summaryrefslogtreecommitdiff
path: root/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc')
-rw-r--r--src/misc/de_rom_8040FE0.c272
-rw-r--r--src/misc/rom3.c1168
-rw-r--r--src/misc/rom6.c202
-rw-r--r--src/misc/rom_800D42C.c118
-rw-r--r--src/misc/rom_8077ABC.c2055
-rw-r--r--src/misc/script_pokemon_util_80C4BF0.c714
-rw-r--r--src/misc/script_pokemon_util_80F99CC.c444
-rw-r--r--src/misc/unknown_task.c248
-rw-r--r--src/misc/unused_8124F94.c126
9 files changed, 5347 insertions, 0 deletions
diff --git a/src/misc/de_rom_8040FE0.c b/src/misc/de_rom_8040FE0.c
new file mode 100644
index 000000000..eebcc1437
--- /dev/null
+++ b/src/misc/de_rom_8040FE0.c
@@ -0,0 +1,272 @@
+#include "global.h"
+#include "battle.h"
+
+#if GERMAN
+
+enum {
+ TRAINER_CLASS_NAME_LEADER = 25,
+ TRAINER_CLASS_NAME_SCHOOL_KID = 26,
+ TRAINER_CLASS_NAME_EXPERT = 30,
+ TRAINER_CLASS_NAME_POKEMON_TRAINER_3 = 46,
+};
+
+enum {
+ TRAINER_CLASS_LEADER_F = 26,
+ TRAINER_CLASS_ELITE_FOUR_F = 25,
+ TRAINER_CLASS_SCHOOL_KID_F = 30,
+ TRAINER_CLASS_BIRD_KEEPER = 46,
+ TRAINER_CLASS_MAY_1 = 61,
+ TRAINER_CLASS_MAY_2 = 62,
+ TRAINER_CLASS_MAY_3 = 63,
+};
+
+extern struct SecretBaseRecord gSecretBaseRecord;
+
+extern u8 gTrainerClassNames[][13];
+extern struct Trainer gTrainers[];
+
+u8 *de_sub_8040FE0(u8 gender) {
+ if (gender)
+ {
+ gender++;
+
+ }
+
+ gender = TRAINER_CLASS_NAME_SCHOOL_KID;
+ return gTrainerClassNames[gender];
+}
+
+u8 *de_sub_8040FF4(u8 gender) {
+ if (gender) {
+ gender++;
+ }
+
+ gender = TRAINER_CLASS_NAME_POKEMON_TRAINER_3;
+ return gTrainerClassNames[gender];
+}
+
+u8 *de_sub_804100C(u8 gender) {
+ if (gender) {
+ gender++;
+ }
+
+ gender = TRAINER_CLASS_NAME_LEADER;
+ return gTrainerClassNames[gender];
+}
+
+#ifdef NONMATCHING
+
+u8 de_sub_81364AC(void);
+u8 get_trainer_class_name_index(void);
+u8 de_sub_81364F8(void);
+u8 sub_8135FD8(void);
+
+u8 *de_sub_8041024(s32 arg0, u32 arg1) {
+ u8 nameIndex, trainerClass, gender;
+ struct Trainer *trainer;
+ u8 local2;
+
+ switch (arg0)
+ {
+ case 0x400:
+ nameIndex = GetSecretBaseTrainerNameIndex();
+ gender = gSecretBaseRecord.gender;
+ if (nameIndex == TRAINER_CLASS_NAME_SCHOOL_KID)
+ {
+ return de_sub_8040FE0(gender);
+ }
+
+ return gTrainerClassNames[nameIndex];
+
+ case 0x100:
+ trainerClass = de_sub_81364AC();
+ nameIndex = get_trainer_class_name_index();
+ if (trainerClass == TRAINER_CLASS_SCHOOL_KID_F)
+ {
+ return de_sub_8040FE0(FEMALE);
+ }
+ if (trainerClass == TRAINER_CLASS_MAY_1 || trainerClass == TRAINER_CLASS_MAY_2 || trainerClass == TRAINER_CLASS_MAY_3)
+ {
+ return de_sub_8040FF4(FEMALE);
+ }
+
+ return gTrainerClassNames[nameIndex];
+
+ case 0x800:
+ trainerClass = de_sub_81364F8();
+ nameIndex = sub_8135FD8();
+ if (trainerClass == TRAINER_CLASS_SCHOOL_KID_F)
+ {
+ return de_sub_8040FE0(FEMALE);
+ }
+ if (trainerClass == TRAINER_CLASS_MAY_1 || trainerClass == TRAINER_CLASS_MAY_2 || trainerClass == TRAINER_CLASS_MAY_3)
+ {
+ return de_sub_8040FF4(FEMALE);
+ }
+
+ return gTrainerClassNames[nameIndex];
+
+ default:
+ trainer = &gTrainers[arg1];
+ trainerClass = trainer->trainerClass;
+ local2 = sub_803FC58(arg1);
+
+ if (trainerClass == TRAINER_CLASS_LEADER_F)
+ {
+ return de_sub_8040FE0(local2);
+ }
+
+ if (trainerClass == TRAINER_CLASS_BIRD_KEEPER && local2 == FEMALE)
+ {
+ return de_sub_8040FF4(FEMALE);
+ }
+
+ if (trainerClass == TRAINER_CLASS_ELITE_FOUR_F)
+ {
+ if (gTrainers[arg1].doubleBattle == TRUE)
+ {
+ return de_sub_804100C(FEMALE);
+ }
+ else
+ {
+ return de_sub_804100C(MALE);
+ }
+ }
+
+
+ return gTrainerClassNames[trainerClass];
+ }
+}
+#else
+
+__attribute__((naked))
+void de_sub_8041024(void) {
+ asm(".syntax unified\n\
+ push {r4-r6,lr}\n\
+ adds r2, r0, 0\n\
+ adds r6, r1, 0\n\
+ movs r0, 0x80\n\
+ lsls r0, 3\n\
+ cmp r2, r0\n\
+ beq _0804104A\n\
+ cmp r2, r0\n\
+ bgt _08041040\n\
+ movs r0, 0x80\n\
+ lsls r0, 1\n\
+ cmp r2, r0\n\
+ beq _08041064\n\
+ b _0804109C\n\
+_08041040:\n\
+ movs r0, 0x80\n\
+ lsls r0, 4\n\
+ cmp r2, r0\n\
+ beq _08041086\n\
+ b _0804109C\n\
+_0804104A:\n\
+ bl GetSecretBaseTrainerNameIndex\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ ldr r0, _08041060 @ =0x02017000\n\
+ ldrb r0, [r0, 0x1]\n\
+ lsls r0, 27\n\
+ lsrs r2, r0, 31\n\
+ cmp r5, 0x1A\n\
+ beq _080410B8\n\
+ b _080410F8\n\
+ .align 2, 0\n\
+_08041060: .4byte 0x02017000\n\
+_08041064:\n\
+ bl de_sub_81364AC\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ bl get_trainer_class_name_index\n\
+_08041070:\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ cmp r4, 0x1E\n\
+ beq _08041094\n\
+ adds r0, r4, 0\n\
+ subs r0, 0x3D\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0x2\n\
+ bls _080410CC\n\
+ b _080410F8\n\
+_08041086:\n\
+ bl de_sub_81364F8\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ bl sub_8135FD8\n\
+ b _08041070\n\
+_08041094:\n\
+ movs r0, 0x1\n\
+ bl de_sub_8040FE0\n\
+ b _08041102\n\
+_0804109C:\n\
+ ldr r1, _080410C0 @ =gTrainers\n\
+ lsls r4, r6, 2\n\
+ adds r0, r4, r6\n\
+ lsls r0, 3\n\
+ adds r0, r1\n\
+ ldrb r5, [r0, 0x1]\n\
+ lsls r0, r6, 16\n\
+ lsrs r0, 16\n\
+ bl sub_803FC58\n\
+ lsls r0, 24\n\
+ lsrs r2, r0, 24\n\
+ cmp r5, 0x1A\n\
+ bne _080410C4\n\
+_080410B8:\n\
+ adds r0, r2, 0\n\
+ bl de_sub_8040FE0\n\
+ b _08041102\n\
+ .align 2, 0\n\
+_080410C0: .4byte gTrainers\n\
+_080410C4:\n\
+ cmp r5, 0x2E\n\
+ bne _080410D4\n\
+ cmp r2, 0x1\n\
+ bne _080410D4\n\
+_080410CC:\n\
+ movs r0, 0x1\n\
+ bl de_sub_8040FF4\n\
+ b _08041102\n\
+_080410D4:\n\
+ cmp r5, 0x19\n\
+ bne _080410F8\n\
+ ldr r0, _080410F4 @ =gTrainers\n\
+ adds r1, r4, r6\n\
+ lsls r1, 3\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x18]\n\
+ movs r2, 0\n\
+ cmp r0, 0x1\n\
+ bne _080410EA\n\
+ movs r2, 0x1\n\
+_080410EA:\n\
+ adds r0, r2, 0\n\
+ bl de_sub_804100C\n\
+ b _08041102\n\
+ .align 2, 0\n\
+_080410F4: .4byte gTrainers\n\
+_080410F8:\n\
+ movs r0, 0xD\n\
+ adds r1, r5, 0\n\
+ muls r1, r0\n\
+ ldr r0, _08041108 @ =gTrainerClassNames\n\
+ adds r0, r1, r0\n\
+_08041102:\n\
+ pop {r4-r6}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .align 2, 0\n\
+_08041108: .4byte gTrainerClassNames\n\
+ .syntax divided\n");
+}
+#endif
+
+u32 de_sub_804110C(u32 arg0, u32 arg1) {
+ return arg1;
+}
+
+#endif
diff --git a/src/misc/rom3.c b/src/misc/rom3.c
new file mode 100644
index 000000000..3f4860ecc
--- /dev/null
+++ b/src/misc/rom3.c
@@ -0,0 +1,1168 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_811DA74.h"
+#include "battle_ai.h"
+#include "battle_anim.h"
+#include "battle_anim_81258BC.h"
+#include "battle_anim_8137220.h"
+#include "cable_club.h"
+#include "items.h"
+#include "link.h"
+#include "pokemon.h"
+#include "rom3.h"
+#include "rom_8094928.h"
+#include "species.h"
+#include "task.h"
+#include "util.h"
+#include "battle_message.h"
+#include "data2.h"
+
+extern u8 unk_2000000[];
+
+#define EWRAM_14000 ((u8 *)(unk_2000000 + 0x14000))
+#define EWRAM_15000 ((u8 *)(unk_2000000 + 0x15000))
+
+extern u16 gBattleTypeFlags;
+extern u16 gBattleWeather;
+extern struct BattlePokemon gBattleMons[];
+
+static EWRAM_DATA u8 gUnknown_020238C4 = 0;
+static EWRAM_DATA u8 gUnknown_020238C5 = 0;
+static EWRAM_DATA u8 gUnknown_020238C6 = 0;
+
+extern u32 gUnknown_020239FC;
+extern u8 gBattleBufferA[][0x200];
+extern u8 gBattleBufferB[][0x200];
+extern u8 gActiveBank;
+extern u32 gBattleExecBuffer;
+extern u8 gNoOfAllBanks;
+extern u16 gBattlePartyID[];
+extern u8 gBanksBySide[];
+extern u16 gCurrentMove;
+extern u16 gUnknown_02024BE8;
+extern u16 gLastUsedItem;
+extern u8 gLastUsedAbility;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gEffectBank;
+extern u8 gStringBank;
+extern u8 gAbsentBankFlags;
+extern u8 gMultiHitCounter;
+extern u8 gUnknown_02024C78;
+extern u8 gBattleOutcome;
+extern u8 gActionSelectionCursor[];
+extern u8 gMoveSelectionCursor[];
+extern u8 gBattleTextBuff1[];
+extern u8 gBattleTextBuff2[];
+extern u8 gBattleTextBuff3[];
+extern void (*gBattleMainFunc)(void);
+extern void (*gBattleBankFunc[])(void);
+
+u8 gBattleBuffersTransferData[0x170];
+
+void sub_800B858(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ OpenLink();
+ CreateTask(sub_8083C50, 0);
+ sub_800BF28();
+ }
+}
+
+void setup_poochyena_battle(void)
+{
+ s32 i;
+
+ gBattleMainFunc = nullsub_41;
+ for (i = 0; i < 4; i++)
+ {
+ gBattleBankFunc[i] = nullsub_91;
+ gBanksBySide[i] = 0xFF;
+ gActionSelectionCursor[i] = 0;
+ gMoveSelectionCursor[i] = 0;
+ }
+ sub_800B858();
+ gBattleExecBuffer = 0;
+ battle_anim_clear_some_data();
+ ClearBattleMonForms();
+ BattleAI_HandleItemUseBeforeAISetup();
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ ZeroEnemyPartyMons();
+ CreateMon(&gEnemyParty[0], SPECIES_POOCHYENA, 2, 32, 0, 0, 0, 0);
+ i = ITEM_NONE;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, (u8 *)&i);
+ }
+ gUnknown_020239FC = 0;
+ gUnknown_02024C78 = 0;
+}
+
+void sub_800B950(void)
+{
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ sub_800BA78();
+ else
+ sub_800B9A8();
+ sub_800BD54();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ sub_8094978(i, 0);
+ }
+}
+
+void sub_800B9A8(void)
+{
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gBattleMainFunc = sub_8010800;
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ gBattleBankFunc[0] = SetBankFuncToSafariBufferRunCommand;
+ else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
+ gBattleBankFunc[0] = SetBankFuncToWallyBufferRunCommand;
+ else
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[0] = 0;
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksBySide[1] = 1;
+ gNoOfAllBanks = 2;
+ }
+ else
+ {
+ gBattleMainFunc = sub_8010800;
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[0] = 0;
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksBySide[1] = 1;
+ gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[2] = 2;
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksBySide[3] = 3;
+ gNoOfAllBanks = 4;
+ }
+}
+
+void sub_800BA78(void)
+{
+ u8 multiplayerId;
+ int i;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleMainFunc = sub_8010800;
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[0] = 0;
+ gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[1] = 1;
+ gNoOfAllBanks = 2;
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[1] = 0;
+ gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[0] = 1;
+ gNoOfAllBanks = 2;
+ }
+ return;
+ }
+ if ((gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_DOUBLE)) == BATTLE_TYPE_DOUBLE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleMainFunc = sub_8010800;
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[0] = 0;
+ gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[1] = 1;
+ gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[2] = 2;
+ gBattleBankFunc[3] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[3] = 3;
+ gNoOfAllBanks = 4;
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[1] = 0;
+ gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[0] = 1;
+ gBattleBankFunc[3] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksBySide[3] = 2;
+ gBattleBankFunc[2] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksBySide[2] = 3;
+ gNoOfAllBanks = 4;
+
+ }
+ return;
+ }
+ multiplayerId = GetMultiplayerId();
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ gBattleMainFunc = sub_8010800;
+ for (i = 0; i < 4; i++)
+ {
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ sub_8094978(gLinkPlayers[i].lp_field_18, 0);
+ break;
+ case 1:
+ case 2:
+ sub_8094978(gLinkPlayers[i].lp_field_18, 1);
+ break;
+ }
+
+ if (i == multiplayerId)
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToPlayerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 0;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[multiplayerId].lp_field_18 & 1))
+ || ((gLinkPlayers[i].lp_field_18 & 1) && (gLinkPlayers[multiplayerId].lp_field_18 & 1)))
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToLinkPartnerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 0;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToLinkOpponentBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 1;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksBySide[gLinkPlayers[i].lp_field_18] = 3;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ }
+ }
+ gNoOfAllBanks = 4;
+}
+
+void sub_800BD54(void)
+{
+ int i;
+ int j;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ for (j = 0; j < 6; j++)
+ {
+ if (i < 2)
+ {
+ if (!(gBanksBySide[i] & 1))
+ {
+ if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != 0
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ else
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!(gBanksBySide[i] & 1))
+ {
+ if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != 0 //Probably a typo by Game Freak. The rest use SPECIES2
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0
+ && gBattlePartyID[i - 2] != j)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ else
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0
+ && gBattlePartyID[i - 2] != j)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void PrepareBufferDataTransfer(u8 a, u8 *data, u16 size)
+{
+ int i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ PrepareBufferDataTransferLink(a, size, data);
+ }
+ else
+ {
+ switch (a)
+ {
+ case 0:
+ for (i = 0; i < size; i++)
+ {
+ gBattleBufferA[gActiveBank][i] = *data;
+ data++;
+ }
+ break;
+ case 1:
+ for (i = 0; i < size; i++)
+ {
+ gBattleBufferB[gActiveBank][i] = *data;
+ data++;
+ }
+ break;
+ }
+ }
+}
+
+void sub_800BF28(void)
+{
+ gUnknown_020238C4 = CreateTask(sub_800C1A8, 0);
+ gTasks[gUnknown_020238C4].data[11] = 0;
+ gTasks[gUnknown_020238C4].data[12] = 0;
+ gTasks[gUnknown_020238C4].data[13] = 0;
+ gTasks[gUnknown_020238C4].data[14] = 0;
+ gTasks[gUnknown_020238C4].data[15] = 0;
+ gUnknown_020238C5 = CreateTask(sub_800C47C, 0);
+ gTasks[gUnknown_020238C5].data[12] = 0;
+ gTasks[gUnknown_020238C5].data[13] = 0;
+ gTasks[gUnknown_020238C5].data[14] = 0;
+ gTasks[gUnknown_020238C5].data[15] = 0;
+ gUnknown_020238C6 = 0;
+ CpuFill16(0, EWRAM_14000, 0x2000);
+}
+
+void PrepareBufferDataTransferLink(u8 a, u16 size, u8 *data)
+{
+ s32 r9;
+ int i;
+
+ r9 = size - size % 4 + 4;
+ if (gTasks[gUnknown_020238C4].data[14] + r9 + 9 > 0x1000)
+ {
+ gTasks[gUnknown_020238C4].data[12] = gTasks[gUnknown_020238C4].data[14];
+ gTasks[gUnknown_020238C4].data[14] = 0;
+ }
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14000] = a;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14001] = gActiveBank;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14002] = gBankAttacker;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14003] = gBankTarget;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14004] = r9;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14005] = (r9 & 0x0000FF00) >> 8;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14006] = gAbsentBankFlags;
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14007] = gEffectBank;
+ for (i = 0; i < size; i++)
+ unk_2000000[gTasks[gUnknown_020238C4].data[14] + 0x14008 + i] = data[i];
+ gTasks[gUnknown_020238C4].data[14] = gTasks[gUnknown_020238C4].data[14] + r9 + 8;
+}
+
+void sub_800C1A8(u8 taskId)
+{
+ u16 var;
+
+ switch (gTasks[taskId].data[11])
+ {
+ case 0:
+ gTasks[taskId].data[10] = 100;
+ gTasks[taskId].data[11]++;
+ break;
+ case 1:
+ gTasks[taskId].data[10]--;
+ if (gTasks[taskId].data[10] == 0)
+ gTasks[taskId].data[11]++;
+ break;
+ case 2:
+ GetLinkPlayerCount_2();
+ if (IsLinkMaster())
+ {
+ sub_8007F4C();
+ gTasks[taskId].data[11]++;
+ break;
+ }
+ gTasks[taskId].data[11]++;
+ break;
+ case 3:
+ if (gTasks[taskId].data[15] != gTasks[taskId].data[14])
+ {
+ if (gTasks[taskId].data[13] == 0)
+ {
+ if (gTasks[taskId].data[15] > gTasks[taskId].data[14]
+ && gTasks[taskId].data[15] == gTasks[taskId].data[12])
+ {
+ gTasks[taskId].data[12] = 0;
+ gTasks[taskId].data[15] = 0;
+ }
+ var = (unk_2000000[gTasks[taskId].data[15] + 0x14004] | (unk_2000000[gTasks[taskId].data[15] + 0x14005] << 8)) + 8;
+ SendBlock(bitmask_all_link_players_but_self(), &unk_2000000[gTasks[taskId].data[15] + 0x14000], var);
+ gTasks[taskId].data[11]++;
+ }
+ else
+ {
+ gTasks[taskId].data[13]--;
+ break;
+ }
+ }
+ break;
+ case 4:
+ if (sub_8007ECC())
+ {
+ var = unk_2000000[gTasks[taskId].data[15] + 0x14004] | (unk_2000000[gTasks[taskId].data[15] + 0x14005] << 8);
+ gTasks[taskId].data[13] = 1;
+ gTasks[taskId].data[15] = gTasks[taskId].data[15] + var + 8;
+ gTasks[taskId].data[11] = 3;
+ }
+ break;
+ case 5:
+ gTasks[taskId].data[13]--;
+ if (gTasks[taskId].data[13] == 0)
+ {
+ gTasks[taskId].data[13] = 1;
+ gTasks[taskId].data[11] = 3;
+ }
+ break;
+ }
+}
+
+//fix me
+void sub_800C35C(void)
+{
+ u8 i; //r4
+ s32 j; //r2
+ u16 r6; //r6
+ u8 *recvBuffer; //r3
+ u8 *dest; //r5
+ u8 *src; //r4
+
+ if (gReceivedRemoteLinkPlayers != 0 && (gBattleTypeFlags & 0x20) && gLinkPlayers[0].linkType == 0x2211)
+ {
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ if (GetBlockReceivedStatus() & gBitTable[i])
+ {
+ ResetBlockReceivedFlag(i);
+ recvBuffer = (u8 *)&gBlockRecvBuffer[i];
+#ifndef NONMATCHING
+ asm("");
+ recvBuffer = (u8 *)&gBlockRecvBuffer[i];
+#endif
+ r6 = gBlockRecvBuffer[i][2];
+ if (gTasks[gUnknown_020238C5].data[14] + 9 + r6 > 0x1000)
+ {
+ gTasks[gUnknown_020238C5].data[12] = gTasks[gUnknown_020238C5].data[14];
+ gTasks[gUnknown_020238C5].data[14] = 0;
+ }
+ //_0800C402
+ dest = EWRAM_15000 + gTasks[gUnknown_020238C5].data[14];
+ src = recvBuffer;
+ for (j = 0; j < r6 + 8; j++)
+ dest[j] = src[j];
+ gTasks[gUnknown_020238C5].data[14] = gTasks[gUnknown_020238C5].data[14] + r6 + 8;
+ }
+ //_0800C446
+ }
+ }
+}
+
+void sub_800C47C(u8 taskId)
+{
+ u16 r7;
+ u8 r4;
+ u8 r2;
+
+ if (gTasks[taskId].data[15] != gTasks[taskId].data[14])
+ {
+ if (gTasks[taskId].data[15] > gTasks[taskId].data[14]
+ && gTasks[taskId].data[15] == gTasks[taskId].data[12])
+ {
+ gTasks[taskId].data[12] = 0;
+ gTasks[taskId].data[15] = 0;
+ }
+ r4 = unk_2000000[0x15000 + gTasks[taskId].data[15] + 1];
+ r7 = unk_2000000[0x15000 + gTasks[taskId].data[15] + 4] | (unk_2000000[0x15000 + gTasks[taskId].data[15] + 5] << 8);
+ switch (unk_2000000[0x15000 + gTasks[taskId].data[15] + 0])
+ {
+ case 0:
+ if (gBattleExecBuffer & gBitTable[r4])
+ return;
+ memcpy(gBattleBufferA[r4], &unk_2000000[0x15000 + gTasks[taskId].data[15] + 8], r7);
+ sub_80155A4(r4);
+ if (!(gBattleTypeFlags & BATTLE_TYPE_WILD))
+ {
+ gBankAttacker = unk_2000000[0x15000 + gTasks[taskId].data[15] + 2];
+ gBankTarget = unk_2000000[0x15000 + gTasks[taskId].data[15] + 3];
+ gAbsentBankFlags = unk_2000000[0x15000 + gTasks[taskId].data[15] + 6];
+ gEffectBank = unk_2000000[0x15000 + gTasks[taskId].data[15] + 7];
+ }
+ break;
+ case 1:
+ memcpy(gBattleBufferB[r4], &unk_2000000[0x15000 + gTasks[taskId].data[15] + 8], r7);
+ break;
+ case 2:
+ r2 = unk_2000000[0x15000 + gTasks[taskId].data[15] + 8];
+ gBattleExecBuffer &= ~(gBitTable[r4] << (r2 * 4));
+ break;
+ }
+ gTasks[taskId].data[15] = gTasks[taskId].data[15] + r7 + 8;
+ }
+}
+
+void EmitGetAttributes(u8 a, u8 b, u8 c)
+{
+ gBattleBuffersTransferData[0] = 0;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd1(u8 a, u8 b, u8 c)
+{
+ gBattleBuffersTransferData[0] = 1;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitSetAttributes(u8 a, u8 b, u8 c, u8 d, void *e)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 2;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ for (i = 0; i < d; i++)
+ gBattleBuffersTransferData[3 + i] = *(u8*)(e++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, d + 3);
+}
+
+void Emitcmd3(u8 a, u8 b, u8 c, u8 *d)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 3;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ for (i = 0; i < c; i++)
+ gBattleBuffersTransferData[3 + i] = *(d++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, c + 3);
+}
+
+void EmitLoadPokeSprite(u8 a)
+{
+ gBattleBuffersTransferData[0] = 4;
+ gBattleBuffersTransferData[1] = 4;
+ gBattleBuffersTransferData[2] = 4;
+ gBattleBuffersTransferData[3] = 4;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitSendOutPoke(u8 a, u8 b, u8 c)
+{
+ gBattleBuffersTransferData[0] = 5;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = 5;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitReturnPokeToBall(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 6;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void EmitTrainerThrow(u8 a)
+{
+ gBattleBuffersTransferData[0] = 7;
+ gBattleBuffersTransferData[1] = 7;
+ gBattleBuffersTransferData[2] = 7;
+ gBattleBuffersTransferData[3] = 7;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitTrainerSlide(u8 a)
+{
+ gBattleBuffersTransferData[0] = 8;
+ gBattleBuffersTransferData[1] = 8;
+ gBattleBuffersTransferData[2] = 8;
+ gBattleBuffersTransferData[3] = 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitTrainerSlideBack(u8 a)
+{
+ gBattleBuffersTransferData[0] = 9;
+ gBattleBuffersTransferData[1] = 9;
+ gBattleBuffersTransferData[2] = 9;
+ gBattleBuffersTransferData[3] = 9;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd10(u8 a)
+{
+ gBattleBuffersTransferData[0] = 10;
+ gBattleBuffersTransferData[1] = 10;
+ gBattleBuffersTransferData[2] = 10;
+ gBattleBuffersTransferData[3] = 10;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd11(u8 a)
+{
+ gBattleBuffersTransferData[0] = 11;
+ gBattleBuffersTransferData[1] = 11;
+ gBattleBuffersTransferData[2] = 11;
+ gBattleBuffersTransferData[3] = 11;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd12(u8 a)
+{
+ gBattleBuffersTransferData[0] = 12;
+ gBattleBuffersTransferData[1] = 12;
+ gBattleBuffersTransferData[2] = 12;
+ gBattleBuffersTransferData[3] = 12;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitBallThrow(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 13;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void EmitPuase(u8 a, u8 b, u8 *c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 14;
+ gBattleBuffersTransferData[1] = b;
+ for (i = 0; i < b * 3; i++)
+ gBattleBuffersTransferData[2 + i] = *(c++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, b * 3 + 2);
+}
+
+void EmitMoveAnimation(u8 a, u16 b, u8 c, u16 d, s32 e, u8 f, struct DisableStruct *g)
+{
+ gBattleBuffersTransferData[0] = 15;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = c;
+ gBattleBuffersTransferData[4] = d;
+ gBattleBuffersTransferData[5] = (d & 0xFF00) >> 8;
+ gBattleBuffersTransferData[6] = e;
+ gBattleBuffersTransferData[7] = (e & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[8] = (e & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[9] = (e & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[10] = f;
+ gBattleBuffersTransferData[11] = gMultiHitCounter;
+ if (AbilityBattleEffects(14, 0, 13, 0, 0) == 0 && AbilityBattleEffects(14, 0, 0x4D, 0, 0) == 0)
+ {
+ gBattleBuffersTransferData[12] = gBattleWeather;
+ gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8;
+ }
+ else
+ {
+ gBattleBuffersTransferData[12] = 0;
+ gBattleBuffersTransferData[13] = 0;
+ }
+ gBattleBuffersTransferData[14] = 0;
+ gBattleBuffersTransferData[15] = 0;
+ memcpy(&gBattleBuffersTransferData[16], g, sizeof(*g));
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 0x2C);
+}
+
+void EmitPrintString(u8 a, u16 stringID)
+{
+ s32 i;
+ struct StringInfoBattle* stringInfo;
+
+ gBattleBuffersTransferData[0] = 16;
+ gBattleBuffersTransferData[1] = gBattleOutcome;
+ gBattleBuffersTransferData[2] = stringID;
+ gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+
+ stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo->currentMove = gCurrentMove;
+ stringInfo->lastMove = gUnknown_02024BE8;
+ stringInfo->lastItem = gLastUsedItem;
+ stringInfo->lastAbility = gLastUsedAbility;
+ stringInfo->scrActive = BATTLE_STRUCT->scriptingActive;
+ stringInfo->unk1605E = BATTLE_STRUCT->unk1605E;
+ stringInfo->hpScale = BATTLE_STRUCT->hpScale;
+ stringInfo->StringBank = gStringBank;
+ stringInfo->moveType = gBattleMoves[gCurrentMove].type;
+
+ for (i = 0; i < 4; i++)
+ stringInfo->abilities[i] = gBattleMons[i].ability;
+ for (i = 0; i < 0x10; i++)
+ {
+ stringInfo->textBuffs[0][i] = gBattleTextBuff1[i];
+ stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
+ stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
+ }
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+}
+
+void EmitPrintStringPlayerOnly(u8 a, u16 stringID)
+{
+ s32 i;
+ struct StringInfoBattle* stringInfo;
+
+ gBattleBuffersTransferData[0] = 17;
+ gBattleBuffersTransferData[1] = 17;
+ gBattleBuffersTransferData[2] = stringID;
+ gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+
+ stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo->currentMove = gCurrentMove;
+ stringInfo->lastMove = gUnknown_02024BE8;
+ stringInfo->lastItem = gLastUsedItem;
+ stringInfo->lastAbility = gLastUsedAbility;
+ stringInfo->scrActive = BATTLE_STRUCT->scriptingActive;
+ stringInfo->unk1605E = BATTLE_STRUCT->unk1605E;
+
+ for (i = 0; i < 4; i++)
+ stringInfo->abilities[i] = gBattleMons[i].ability;
+ for (i = 0; i < 0x10; i++)
+ {
+ stringInfo->textBuffs[0][i] = gBattleTextBuff1[i];
+ stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
+ stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
+ }
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+}
+
+void Emitcmd18(u8 a, u8 b, u16 c)
+{
+ gBattleBuffersTransferData[0] = 18;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = (c & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd19(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 19;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void Emitcmd20(u8 a, u8 b, u8 c, u8 *d)
+{
+ u32 i;
+
+ gBattleBuffersTransferData[0] = 20;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = 0;
+ for (i = 0; i < 20; i++)
+ gBattleBuffersTransferData[4 + i] = d[i];
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 24);
+}
+
+void EmitOpenBag(u8 a, u8 *b)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 21;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[1 + i] = b[i];
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitChoosePokemon(u8 a, u8 b, u8 c, u8 d, u8 *e)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 22;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = d;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[4 + i] = e[i];
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 8); //but only 7 bytes were written
+}
+
+void Emitcmd23(u8 a)
+{
+ gBattleBuffersTransferData[0] = 23;
+ gBattleBuffersTransferData[1] = 23;
+ gBattleBuffersTransferData[2] = 23;
+ gBattleBuffersTransferData[3] = 23;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+// FIXME: I think this function is supposed to take s16 as its second argument,
+// but battle_4.c expects u16
+void EmitHealthBarUpdate(u8 a, u16 b)
+{
+ gBattleBuffersTransferData[0] = 24;
+ gBattleBuffersTransferData[1] = 0;
+ gBattleBuffersTransferData[2] = (s16)b;
+ gBattleBuffersTransferData[3] = ((s16)b & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+// FIXME: I think this function is supposed to take s16 as its third argument,
+// but battle_4.c expects u16
+void EmitExpBarUpdate(u8 a, u8 b, u16 c)
+{
+ gBattleBuffersTransferData[0] = 25;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (s16)c;
+ gBattleBuffersTransferData[3] = ((s16)c & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitStatusIconUpdate(u8 a, u32 b, u32 c)
+{
+ gBattleBuffersTransferData[0] = 26;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[3] = (b & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[4] = (b & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[5] = c;
+ gBattleBuffersTransferData[6] = (c & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[7] = (c & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[8] = (c & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 9);
+}
+
+void EmitStatusAnimation(u8 a, u8 b, u32 c)
+{
+ gBattleBuffersTransferData[0] = 27;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = (c & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[4] = (c & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[5] = (c & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 6);
+}
+
+void EmitStatusXor(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 28;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void Emitcmd29(u8 a, u16 b, u8 *c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 29;
+ gBattleBuffersTransferData[1] = 29;
+ gBattleBuffersTransferData[2] = b;
+ gBattleBuffersTransferData[3] = (b & 0xFF00) >> 8;
+ for (i = 0; i < b; i++)
+ gBattleBuffersTransferData[4 + i] = *(c++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, b + 4);
+}
+
+void EmitDMATransfer(u8 a, u32 b, u16 c, u8 *d)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 30;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[3] = (b & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[4] = (b & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[5] = c;
+ gBattleBuffersTransferData[6] = (c & 0xFF00) >> 8;
+ for (i = 0; i < c; i++)
+ gBattleBuffersTransferData[7 + i] = *(d++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, c + 7);
+}
+
+void Emitcmd31(u8 a, u16 b, u8 *c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 31;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ for (i = 0; i < b; i++)
+ gBattleBuffersTransferData[3 + i] = *(c++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, b + 3);
+}
+
+void Emitcmd32(u8 a, u16 b, u8 *c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 32;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ for (i = 0; i < b; i++)
+ gBattleBuffersTransferData[3 + i] = *(c++);
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, b + 3);
+}
+
+void Emitcmd33(u8 a, u8 b, u16 c)
+{
+ gBattleBuffersTransferData[0] = 33;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = (c & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd34(u8 a, u8 b, u8 *c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 34;
+ gBattleBuffersTransferData[1] = b;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[2 + i] = c[i];
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 5);
+}
+
+void Emitcmd35(u8 a, u16 b)
+{
+ gBattleBuffersTransferData[0] = 35;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd36(u8 a, u16 b)
+{
+ gBattleBuffersTransferData[0] = 36;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd37(u8 a)
+{
+ gBattleBuffersTransferData[0] = 37;
+ gBattleBuffersTransferData[1] = 37;
+ gBattleBuffersTransferData[2] = 37;
+ gBattleBuffersTransferData[3] = 37;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd38(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 38;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void Emitcmd39(u8 a)
+{
+ gBattleBuffersTransferData[0] = 39;
+ gBattleBuffersTransferData[1] = 39;
+ gBattleBuffersTransferData[2] = 39;
+ gBattleBuffersTransferData[3] = 39;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd40(u8 a)
+{
+ gBattleBuffersTransferData[0] = 40;
+ gBattleBuffersTransferData[1] = 40;
+ gBattleBuffersTransferData[2] = 40;
+ gBattleBuffersTransferData[3] = 40;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitHitAnimation(u8 a)
+{
+ gBattleBuffersTransferData[0] = 41;
+ gBattleBuffersTransferData[1] = 41;
+ gBattleBuffersTransferData[2] = 41;
+ gBattleBuffersTransferData[3] = 41;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd42(u8 a)
+{
+ gBattleBuffersTransferData[0] = 42;
+ gBattleBuffersTransferData[1] = 42;
+ gBattleBuffersTransferData[2] = 42;
+ gBattleBuffersTransferData[3] = 42;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitEffectivenessSound(u8 a, u16 b)
+{
+ gBattleBuffersTransferData[0] = 43;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd44(u8 a, u16 b)
+{
+ gBattleBuffersTransferData[0] = 44;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitFaintingCry(u8 a)
+{
+ gBattleBuffersTransferData[0] = 45;
+ gBattleBuffersTransferData[1] = 45;
+ gBattleBuffersTransferData[2] = 45;
+ gBattleBuffersTransferData[3] = 45;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitIntroSlide(u8 a, u8 battleTerrain)
+{
+ gBattleBuffersTransferData[0] = 46;
+ gBattleBuffersTransferData[1] = battleTerrain;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void EmitTrainerBallThrow(u8 a)
+{
+ gBattleBuffersTransferData[0] = 47;
+ gBattleBuffersTransferData[1] = 47;
+ gBattleBuffersTransferData[2] = 47;
+ gBattleBuffersTransferData[3] = 47;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd48(u8 a, u8 *b, u8 c)
+{
+ int i;
+
+ gBattleBuffersTransferData[0] = 48;
+ gBattleBuffersTransferData[1] = c & 0x7F;
+ gBattleBuffersTransferData[2] = (c & 0x80) >> 7;
+ gBattleBuffersTransferData[3] = 48;
+ for (i = 0; i < 48; i++)
+ gBattleBuffersTransferData[4 + i] = b[i];
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 52);
+}
+
+void Emitcmd49(u8 a)
+{
+ gBattleBuffersTransferData[0] = 49;
+ gBattleBuffersTransferData[1] = 49;
+ gBattleBuffersTransferData[2] = 49;
+ gBattleBuffersTransferData[3] = 49;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void Emitcmd50(u8 a)
+{
+ gBattleBuffersTransferData[0] = 50;
+ gBattleBuffersTransferData[1] = 50;
+ gBattleBuffersTransferData[2] = 50;
+ gBattleBuffersTransferData[3] = 50;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitSpriteInvisibility(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 51;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = 51;
+ gBattleBuffersTransferData[3] = 51;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitBattleAnimation(u8 a, u8 b, u16 c)
+{
+ gBattleBuffersTransferData[0] = 52;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = c;
+ gBattleBuffersTransferData[3] = (c & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 4);
+}
+
+void EmitLinkStandbyMsg(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 53;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void EmitResetActionMoveSelection(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 54;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
+
+void Emitcmd55(u8 a, u8 b)
+{
+ gBattleBuffersTransferData[0] = 55;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(a, gBattleBuffersTransferData, 2);
+}
diff --git a/src/misc/rom6.c b/src/misc/rom6.c
new file mode 100644
index 000000000..3a5071034
--- /dev/null
+++ b/src/misc/rom6.c
@@ -0,0 +1,202 @@
+#include "global.h"
+#include "rom6.h"
+#include "braille_puzzles.h"
+#include "field_effect.h"
+#include "field_map_obj.h"
+#include "field_player_avatar.h"
+#include "item_use.h"
+#include "pokemon_menu.h"
+#include "overworld.h"
+#include "script.h"
+#include "songs.h"
+#include "sound.h"
+#include "sprite.h"
+#include "task.h"
+
+extern u16 gScriptLastTalked;
+extern void (*gFieldCallback)(void);
+extern u8 gLastFieldPokeMenuOpened;
+extern void (*gUnknown_03005CE4)(void);
+extern u8 S_UseRockSmash[];
+
+EWRAM_DATA struct MapPosition gUnknown_0203923C = {0};
+
+static void task08_080C9820(u8);
+static void sub_810B3DC(u8);
+static void sub_810B428(u8);
+static void sub_810B4CC(u8);
+static void sub_810B53C(void);
+static void sub_810B58C(void);
+static void sub_810B5D8(void);
+static void sub_810B634(void);
+
+bool8 npc_before_player_of_type(u8 a)
+{
+ u8 mapObjId;
+
+ GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203923C.x, &gUnknown_0203923C.y);
+ gUnknown_0203923C.height = PlayerGetZCoord();
+ mapObjId = GetFieldObjectIdByXYZ(gUnknown_0203923C.x, gUnknown_0203923C.y, gUnknown_0203923C.height);
+ if (gMapObjects[mapObjId].graphicsId != a)
+ {
+ return FALSE;
+ }
+ else
+ {
+ gScriptLastTalked = gMapObjects[mapObjId].localId;
+ return TRUE;
+ }
+}
+
+u8 oei_task_add(void)
+{
+ GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203923C.x, &gUnknown_0203923C.y);
+ return CreateTask(task08_080C9820, 8);
+}
+
+static void task08_080C9820(u8 taskId)
+{
+ u8 mapObjId;
+
+ ScriptContext2_Enable();
+ gPlayerAvatar.unk6 = 1;
+ 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_810B428;
+ }
+ else
+ {
+ sub_8059BF4();
+ FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], 0x39);
+ gTasks[taskId].func = sub_810B3DC;
+ }
+ }
+}
+
+static void sub_810B3DC(u8 taskId)
+{
+ if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[gPlayerAvatar.mapObjectId]) == TRUE)
+ {
+ FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT);
+ gTasks[taskId].func = sub_810B428;
+ }
+}
+
+static void sub_810B428(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;
+ sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByCurrentState());
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], gFieldEffectArguments[2]);
+ FieldEffectActiveListRemove(6);
+ gTasks[taskId].func = sub_810B4CC;
+ }
+}
+
+static void sub_810B4CC(u8 taskId)
+{
+ void (*func)(void) = (void (*)(void))(((u16)gTasks[taskId].data[8] << 16) | (u16)gTasks[taskId].data[9]);
+
+ func();
+ gPlayerAvatar.unk6 = 0;
+ DestroyTask(taskId);
+}
+
+bool8 SetUpFieldMove_RockSmash(void)
+{
+ if (npc_before_player_of_type(0x56) == TRUE)
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_810B53C;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static void sub_810B53C(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ ScriptContext1_SetupScript(S_UseRockSmash);
+}
+
+int FldEff_RockSmash(void)
+{
+ u8 taskId = oei_task_add();
+
+ gTasks[taskId].data[8] = (u32)sub_810B58C >> 16;
+ gTasks[taskId].data[9] = (u32)sub_810B58C;
+ IncrementGameStat(0x13);
+ return 0;
+}
+
+static void sub_810B58C(void)
+{
+ PlaySE(SE_W088);
+ FieldEffectActiveListRemove(FLDEFF_USE_ROCK_SMASH);
+ EnableBothScriptContexts();
+}
+
+int SetUpFieldMove_Dig(void)
+{
+ if (CanUseEscapeRopeOnCurrMap() == TRUE)
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_810B5D8;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static void sub_810B5D8(void)
+{
+ sub_8053014();
+ FieldEffectStart(FLDEFF_USE_DIG);
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+}
+
+int FldEff_UseDig(void)
+{
+ u8 taskId = oei_task_add();
+
+ gTasks[taskId].data[8] = (u32)sub_810B634 >> 16;
+ gTasks[taskId].data[9] = (u32)sub_810B634;
+ if (!ShouldDoBrailleDigEffect())
+ SetPlayerAvatarTransitionFlags(1);
+ return 0;
+}
+
+static void sub_810B634(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/misc/rom_800D42C.c b/src/misc/rom_800D42C.c
new file mode 100644
index 000000000..f51779e65
--- /dev/null
+++ b/src/misc/rom_800D42C.c
@@ -0,0 +1,118 @@
+#include "global.h"
+#include "battle.h"
+#include "link.h"
+#include "text.h"
+
+extern u16 gBattleTypeFlags;
+extern u8 gBattleOutcome;
+
+extern struct Window gUnknown_03004210;
+
+extern u8 BattleText_Win[];
+extern u8 BattleText_Loss[];
+extern u8 BattleText_Tie[];
+
+#if ENGLISH
+#define LEFT_MESSAGE_X 6
+#define RIGHT_MESSAGE_X 21
+#define TILE_OFFSET_LOSS 168
+#elif GERMAN
+#define LEFT_MESSAGE_X 5
+#define RIGHT_MESSAGE_X 20
+#define TILE_OFFSET_LOSS 172
+#endif
+#define TILE_OFFSET_WIN 160
+#define CENTER_MESSAGE_X 13
+#define MESSAGE_Y 2
+
+#define PRINT_MESSAGE(text, tileDataStartOffset, x) \
+{ \
+ InitWindow(&gUnknown_03004210, text, tileDataStartOffset, x, MESSAGE_Y); \
+ sub_8002F44(&gUnknown_03004210); \
+}
+
+#define PRINT_MESSAGE_LEFT(text, tileDataStartOffset) PRINT_MESSAGE(text, tileDataStartOffset, LEFT_MESSAGE_X)
+#define PRINT_MESSAGE_RIGHT(text, tileDataStartOffset) PRINT_MESSAGE(text, tileDataStartOffset, RIGHT_MESSAGE_X)
+
+void PrintLinkBattleWinLossTie(void)
+{
+
+ if (gBattleOutcome == 3)
+ {
+ PRINT_MESSAGE(BattleText_Tie, TILE_OFFSET_WIN, CENTER_MESSAGE_X);
+ return;
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ // Double battle?
+
+ if (gBattleOutcome == 1)
+ {
+
+ // lp_field_18 = player position?
+ switch (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18)
+ {
+ case 0:
+ case 2:
+ PRINT_MESSAGE_LEFT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_RIGHT(BattleText_Loss, TILE_OFFSET_LOSS);
+ return;
+
+ case 1:
+ case 3:
+ PRINT_MESSAGE_RIGHT(BattleText_Win, TILE_OFFSET_WIN)
+ PRINT_MESSAGE_LEFT(BattleText_Loss, TILE_OFFSET_LOSS)
+ return;
+ }
+ }
+ else
+ {
+
+ switch (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18)
+ {
+ case 1:
+ case 3:
+ PRINT_MESSAGE_LEFT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_RIGHT(BattleText_Loss, TILE_OFFSET_LOSS);
+ return;
+
+ case 0:
+ case 2:
+ PRINT_MESSAGE_RIGHT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_LEFT(BattleText_Loss, TILE_OFFSET_LOSS);
+ return;
+ }
+ }
+
+ return;
+ }
+
+
+ if (gBattleOutcome == 1)
+ {
+ if (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18 != 0)
+ {
+ PRINT_MESSAGE_RIGHT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_LEFT(BattleText_Loss, TILE_OFFSET_LOSS);
+ }
+ else
+ {
+ PRINT_MESSAGE_LEFT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_RIGHT(BattleText_Loss, TILE_OFFSET_LOSS);
+ }
+ }
+ else
+ {
+ if (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18 != 0)
+ {
+ PRINT_MESSAGE_LEFT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_RIGHT(BattleText_Loss, TILE_OFFSET_LOSS);
+ }
+ else
+ {
+ PRINT_MESSAGE_RIGHT(BattleText_Win, TILE_OFFSET_WIN);
+ PRINT_MESSAGE_LEFT(BattleText_Loss, TILE_OFFSET_LOSS);
+ }
+ }
+}
diff --git a/src/misc/rom_8077ABC.c b/src/misc/rom_8077ABC.c
new file mode 100644
index 000000000..172233e6d
--- /dev/null
+++ b/src/misc/rom_8077ABC.c
@@ -0,0 +1,2055 @@
+#include "global.h"
+#include "rom_8077ABC.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "blend_palette.h"
+#include "data2.h"
+#include "decompress.h"
+#include "palette.h"
+#include "pokemon_icon.h"
+#include "species.h"
+#include "sprite.h"
+#include "task.h"
+#include "trig.h"
+#include "util.h"
+
+#define GET_UNOWN_LETTER(personality) ((\
+ (((personality & 0x03000000) >> 24) << 6) \
+ | (((personality & 0x00030000) >> 16) << 4) \
+ | (((personality & 0x00000300) >> 8) << 2) \
+ | (((personality & 0x00000003) >> 0) << 0) \
+) % 28)
+
+#define IS_DOUBLE_BATTLE() ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? TRUE : FALSE)
+
+#define NUM_BATTLE_SLOTS 4
+
+#define gBattleMonPartyPositions gBattlePartyID
+#define gCastformElevations gUnknownCastformData_0837F5A8
+#define gCastformBackSpriteYCoords gUnknown_0837F5AC
+#define gTransformPersonalities gPID_perBank
+#define gBattleMonSprites gObjectBankIDs
+
+
+struct Struct_unk_2019348 {
+ u16 field_0;
+ u16 field_2;
+ u8 field_4;
+ u32 field_8;
+ u32 field_c;
+ u32 field_10;
+};
+
+struct TransformStatus {
+ u16 unknown;
+ u16 species;
+};
+
+struct Struct_gUnknown_0837F578 {
+ u8 field_0;
+ u8 field_1;
+};
+
+struct OamMatrix {
+ s16 a;
+ s16 b;
+ s16 c;
+ s16 d;
+};
+
+struct Struct_2017810 {
+ u8 filler_0[6];
+ u8 field_6;
+ u8 filler_7[5];
+};
+
+struct Color {
+ u16 r:5;
+ u16 g:5;
+ u16 b:5;
+};
+
+struct Struct_sub_8078914 {
+ u8 *field_0;
+ u8 *field_4;
+ u8 field_8;
+};
+
+struct BGCnt {
+ u16 priority:2;
+ u16 charBase:2;
+ u16 unused:2;
+ u16 mosaic:1;
+ u16 colorMode:1;
+ u16 screenBase:5;
+ u16 overflow:1;
+ u16 size:2;
+};
+
+#define BG1CNT (*(volatile struct BGCnt*)REG_ADDR_BG1CNT)
+#define BG2CNT (*(volatile struct BGCnt*)REG_ADDR_BG2CNT)
+#define BG3CNT (*(volatile struct BGCnt*)REG_ADDR_BG3CNT)
+
+extern struct OamData gOamData_837DF9C[];
+extern const union AnimCmd *const gDummySpriteAnimTable[];
+extern const union AffineAnimCmd *const gDummySpriteAffineAnimTable[];
+
+extern struct Struct_unk_2019348 unk_2019348;
+extern struct TransformStatus gTransformStatuses[];
+extern u16 gBattleMonPartyPositions[];
+extern u16 gBattleTypeFlags;
+extern u32 gTransformPersonalities[NUM_BATTLE_SLOTS];
+extern u8 gBattleMonForms[NUM_BATTLE_SLOTS];
+extern u16 gUnknown_0202F7CA[];
+extern u8 gBattleMonSprites[NUM_BATTLE_SLOTS];
+extern u8 gBattleAnimBankAttacker;
+extern u8 gBattleAnimBankTarget;
+extern s16 gBattleAnimArgs[8];
+extern u8 gBanksBySide[NUM_BATTLE_SLOTS];
+extern u8 gNoOfAllBanks; // gNumBattleMons?
+extern struct OamMatrix gOamMatrices[];
+extern struct Struct_2017810 unk_2017810[];
+extern u8 gHappinessMoveAnim;
+
+EWRAM_DATA union AffineAnimCmd *gUnknown_0202F7D4 = NULL;
+EWRAM_DATA u32 filler_0202F7D8[3] = {0};
+
+const struct Struct_gUnknown_0837F578 gUnknown_0837F578[][4] = {
+ {
+ { 72, 80 },
+ { 176, 40 },
+ { 48, 40 },
+ { 112, 80 },
+ },
+ {
+ { 32, 80 },
+ { 200, 40 },
+ { 90, 88 },
+ { 152, 32 },
+ },
+};
+
+// One entry for each of the four Castform forms.
+// Coords are probably front pic coords or back pic coords, but this data does not seem to be
+// used during battle, party summary, or pokedex screens.
+const struct MonCoords gCastformFrontSpriteCoords[] = {
+ { 0x44, 17 }, // NORMAL
+ { 0x66, 9 }, // SUN
+ { 0x46, 9 }, // RAIN
+ { 0x86, 8 }, // HAIL
+};
+
+const u8 gCastformElevations[] = {
+ 13, // NORMAL
+ 14, // SUN
+ 13, // RAIN
+ 13, // HAIL
+};
+
+// Y position of the backsprite for each of the four Castform forms.
+const u8 gCastformBackSpriteYCoords[] = {
+ 0, // NORMAL
+ 0, // SUN
+ 0, // RAIN
+ 0, // HAIL
+};
+
+const struct SpriteTemplate gSpriteTemplate_837F5B0[] = {
+ {
+ .tileTag = 55125,
+ .paletteTag = 55125,
+ .oam = gOamData_837DF9C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+ }, {
+ .tileTag = 55126,
+ .paletteTag = 55126,
+ .oam = gOamData_837DF9C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+ }
+};
+
+const struct SpriteSheet gUnknown_0837F5E0[] = {
+ { gMiscBlank_Gfx, 0x800, 55125, },
+ { gMiscBlank_Gfx, 0x800, 55126, },
+};
+
+
+u8 sub_8077ABC(u8 slot, u8 a2) {
+ u8 var;
+ u16 species;
+ struct TransformStatus *transform;
+
+ if (IsContest()) {
+ if (a2 == 3 && slot == 3) {
+ a2 = 1;
+ }
+ }
+ switch (a2) {
+ case 0:
+ case 2:
+ var = gUnknown_0837F578[IS_DOUBLE_BATTLE()][GetBankIdentity(slot)].field_0;
+ break;
+ case 1:
+ var = gUnknown_0837F578[IS_DOUBLE_BATTLE()][GetBankIdentity(slot)].field_1;
+ break;
+ case 3:
+ case 4:
+ default:
+ if (IsContest()) {
+ if (unk_2019348.field_4 & 1) {
+ species = unk_2019348.field_2;
+ } else {
+ species = unk_2019348.field_0;
+ }
+ } else {
+ if (GetBankSide(slot)) {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ } else {
+ species = transform->species;
+ }
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ } else {
+ species = transform->species;
+ }
+ }
+ }
+ if (a2 == 3) {
+ var = sub_8077E44(slot, species, 1);
+ } else {
+ var = sub_8077E44(slot, species, 0);
+ }
+ break;
+ }
+ return var;
+}
+
+u8 sub_8077BFC(u8 slot, u16 species) {
+ u16 letter;
+ u32 personality;
+ struct TransformStatus *transform;
+ u8 ret;
+ u16 var;
+
+ if (!GetBankSide(slot) || IsContest()) {
+ if (species == SPECIES_UNOWN) {
+ if (IsContest()) {
+ if (unk_2019348.field_4 & 1) {
+ personality = unk_2019348.field_10;
+ } else {
+ personality = unk_2019348.field_8;
+ }
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ personality = GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_PERSONALITY);
+ } else {
+ personality = gTransformPersonalities[slot];
+ }
+ }
+ letter = GET_UNOWN_LETTER(personality);
+ if (!letter) {
+ var = species;
+ } else {
+ var = letter + SPECIES_UNOWN_B - 1;
+ }
+ ret = gMonBackPicCoords[var].y_offset;
+ } else if (species == SPECIES_CASTFORM) {
+ ret = gCastformBackSpriteYCoords[gBattleMonForms[slot]];
+ } else if (species > NUM_SPECIES) {
+ ret = gMonBackPicCoords[0].y_offset;
+ } else {
+ ret = gMonBackPicCoords[species].y_offset;
+ }
+ } else {
+ if (species == SPECIES_UNOWN) {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ personality = GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_PERSONALITY);
+ } else {
+ personality = gTransformPersonalities[slot];
+ }
+ letter = GET_UNOWN_LETTER(personality);
+ if (!letter) {
+ var = species;
+ } else {
+ var = letter + SPECIES_UNOWN_B - 1;
+ }
+ ret = gMonFrontPicCoords[var].y_offset;
+ } else if (species == SPECIES_CASTFORM) {
+ ret = gCastformFrontSpriteCoords[gBattleMonForms[slot]].y_offset;
+ } else if (species > NUM_SPECIES) {
+ ret = gMonFrontPicCoords[0].y_offset;
+ } else {
+ ret = gMonFrontPicCoords[species].y_offset;
+ }
+ }
+ return ret;
+}
+
+u8 sub_8077DD8(u8 slot, u16 species) {
+ u8 ret = 0;
+ if (GetBankSide(slot) == 1) {
+ if (!IsContest()) {
+ if (species == SPECIES_CASTFORM) {
+ ret = gCastformElevations[gBattleMonForms[slot]];
+ } else if (species > NUM_SPECIES) {
+ ret = gEnemyMonElevation[0];
+ } else {
+ ret = gEnemyMonElevation[species];
+ }
+ }
+ }
+ return ret;
+}
+
+u8 sub_8077E44(u8 slot, u16 species, u8 a3) {
+ u16 offset;
+ u8 y;
+ if (GetBankSide(slot) == 0 || IsContest()) {
+ offset = sub_8077BFC(slot, species);
+ } else {
+ offset = sub_8077BFC(slot, species);
+ offset -= sub_8077DD8(slot, species);
+ }
+ y = offset + gUnknown_0837F578[IS_DOUBLE_BATTLE()][GetBankIdentity(slot)].field_1;
+ if (a3) {
+ if (GetBankSide(slot) == 0) {
+ y += 8;
+ }
+ if (y > 104) y = 104;
+ }
+ return y;
+}
+
+u8 sub_8077EE4(u8 slot, u8 a2) {
+ u16 species;
+ struct TransformStatus *transform;
+ if (a2 == 3 || a2 == 4) {
+ if (IsContest()) {
+ if (unk_2019348.field_4 & 1) {
+ species = unk_2019348.field_2;
+ } else {
+ species = unk_2019348.field_0;
+ }
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = gUnknown_0202F7CA[slot];
+ } else {
+ species = transform->species;
+ }
+ }
+ if (a2 == 3) {
+ return sub_8077E44(slot, species, 1);
+ } else {
+ return sub_8077E44(slot, species, 0);
+ }
+ } else {
+ return sub_8077ABC(slot, a2);
+ }
+}
+
+u8 sub_8077F68(u8 slot) {
+ return sub_8077ABC(slot, 4);
+}
+
+u8 sub_8077F7C(u8 slot) {
+ u16 var;
+ if (GetBankSide(slot)) {
+ var = sub_8077ABC(slot, 1) + 16;
+ } else {
+ var = sub_8077ABC(slot, 1) + 17;
+ }
+ return var;
+}
+
+u8 sub_8077FC0(u8 slot) {
+ u16 var;
+ u8 r6;
+ struct TransformStatus *transform;
+ r6 = sub_8077ABC(slot, 1);
+ if (!IsContest()) {
+ if (GetBankSide(slot)) {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ var = GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ } else {
+ var = transform->species;
+ }
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ var = GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ } else {
+ var = transform->species;
+ }
+ }
+ if (GetBankSide(slot)) {
+ r6 -= sub_8077DD8(slot, var);
+ }
+ }
+ return r6;
+}
+
+u8 GetAnimBankSpriteId(u8 whichBank) {
+ u8 *sprites;
+ if (whichBank == ANIM_BANK_ATK) {
+ if (AnimBankSpriteExists(gBattleAnimBankAttacker)) {
+ sprites = gBattleMonSprites;
+ return sprites[gBattleAnimBankAttacker];
+ } else {
+ return 0xff;
+ }
+ } else if (whichBank == ANIM_BANK_DEF) {
+ if (AnimBankSpriteExists(gBattleAnimBankTarget)) {
+ sprites = gBattleMonSprites;
+ return sprites[gBattleAnimBankTarget];
+ } else {
+ return 0xff;
+ }
+ } else if (whichBank == ANIM_BANK_ATK_PARTNER) {
+ if (!IsAnimBankSpriteVisible(gBattleAnimBankAttacker ^ 2)) {
+ return 0xff;
+ } else {
+ return gBattleMonSprites[gBattleAnimBankAttacker ^ 2];
+ }
+ } else {
+ if (IsAnimBankSpriteVisible(gBattleAnimBankTarget ^ 2)) {
+ return gBattleMonSprites[gBattleAnimBankTarget ^ 2];
+ } else {
+ return 0xff;
+ }
+ }
+}
+
+void StoreSpriteCallbackInData6(struct Sprite *sprite, void (*callback)(struct Sprite*)) {
+ sprite->data6 = (u32)(callback) & 0xffff;
+ sprite->data7 = (u32)(callback) >> 16;
+}
+
+void SetCallbackToStoredInData6(struct Sprite *sprite) {
+ u32 callback = (u16)sprite->data6 | (sprite->data7 << 16);
+ sprite->callback = (void (*)(struct Sprite *))callback;
+}
+
+void sub_8078114(struct Sprite *sprite) {
+ if (sprite->data3) {
+ sprite->pos2.x = Sin(sprite->data0, sprite->data1);
+ sprite->pos2.y = Cos(sprite->data0, sprite->data1);
+ sprite->data0 += sprite->data2;
+ if (sprite->data0 >= 0x100) {
+ sprite->data0 -= 0x100;
+ } else if (sprite->data0 < 0) {
+ sprite->data0 += 0x100;
+ }
+ sprite->data3--;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078174(struct Sprite *sprite) {
+ if (sprite->data3) {
+ sprite->pos2.x = Sin(sprite->data0, (sprite->data5 >> 8) + sprite->data1);
+ sprite->pos2.y = Cos(sprite->data0, (sprite->data5 >> 8) + sprite->data1);
+ sprite->data0 += sprite->data2;
+ sprite->data5 += sprite->data4;
+ if (sprite->data0 >= 0x100) {
+ sprite->data0 -= 0x100;
+ } else if (sprite->data0 < 0) {
+ sprite->data0 += 0x100;
+ }
+ sprite->data3--;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void unref_sub_80781F0(struct Sprite *sprite) {
+ if (sprite->data3) {
+ sprite->pos2.x = Sin(sprite->data0, sprite->data1);
+ sprite->pos2.y = Cos(sprite->data4, sprite->data1);
+ sprite->data0 += sprite->data2;
+ sprite->data4 += sprite->data5;
+ if (sprite->data0 >= 0x100) {
+ sprite->data0 -= 0x100;
+ } else if (sprite->data0 < 0) {
+ sprite->data0 += 0x100;
+ }
+ if (sprite->data4 >= 0x100) {
+ sprite->data4 -= 0x100;
+ } else if (sprite->data4 < 0) {
+ sprite->data4 += 0x100;
+ }
+ sprite->data3--;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078278(struct Sprite *sprite) {
+ if (sprite->data3) {
+ sprite->pos2.x = Sin(sprite->data0, sprite->data1);
+ sprite->pos2.y = Cos(sprite->data0, sprite->data4);
+ sprite->data0 += sprite->data2;
+ if (sprite->data0 >= 0x100) {
+ sprite->data0 -= 0x100;
+ } else if (sprite->data0 < 0) {
+ sprite->data0 += 0x100;
+ }
+ sprite->data3--;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_80782D8(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_80782F8(struct Sprite *sprite) {
+ sub_8078314(sprite);
+ sprite->callback = sub_8078364;
+ sprite->callback(sprite);
+}
+
+void sub_8078314(struct Sprite *sprite) {
+ s16 old;
+ int v1;
+ if (sprite->data1 > sprite->data2) {
+ sprite->data0 = -sprite->data0;
+ }
+ v1 = sprite->data2 - sprite->data1;
+ old = sprite->data0;
+ sprite->data0 = abs(v1 / sprite->data0);
+ sprite->data2 = (sprite->data4 - sprite->data3) / sprite->data0;
+ sprite->data1 = old;
+}
+
+void sub_8078364(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ sprite->pos2.x += sprite->data1;
+ sprite->pos2.y += sprite->data2;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078394(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ sprite->data3 += sprite->data1;
+ sprite->data4 += sprite->data2;
+ sprite->pos2.x = sprite->data3 >> 8;
+ sprite->pos2.y = sprite->data4 >> 8;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_80783D0(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ sprite->data3 += sprite->data1;
+ sprite->data4 += sprite->data2;
+ sprite->pos2.x = sprite->data3 >> 8;
+ sprite->pos2.y = sprite->data4 >> 8;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+ UpdateMonIconFrame(sprite);
+}
+
+void unref_sub_8078414(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x + sprite->pos2.x;
+ sprite->data3 = sprite->pos1.y + sprite->pos2.y;
+ sprite->data2 = sub_8077ABC(gBattleAnimBankTarget, 2);
+ sprite->data4 = sub_8077ABC(gBattleAnimBankTarget, 3);
+ sprite->callback = sub_80782F8;
+}
+
+void sub_8078458(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ gSprites[sprite->data3].pos2.x += sprite->data1;
+ gSprites[sprite->data3].pos2.y += sprite->data2;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_80784A8(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ sprite->data3 += sprite->data1;
+ sprite->data4 += sprite->data2;
+ gSprites[sprite->data5].pos2.x = sprite->data3 >> 8;
+ gSprites[sprite->data5].pos2.y = sprite->data4 >> 8;
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078504(struct Sprite *sprite) {
+ if (sprite->data0 > 0) {
+ sprite->data0--;
+ sprite->pos2.x = sprite->data2 >> 8;
+ sprite->data2 += sprite->data1;
+ sprite->pos2.y = sprite->data4 >> 8;
+ sprite->data4 += sprite->data3;
+ if (sprite->data0 % sprite->data5 == 0) {
+ if (sprite->data5) {
+ sprite->invisible ^= 1;
+ }
+ }
+ } else {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void move_anim_8074EE0(struct Sprite *sprite) {
+ FreeSpriteOamMatrix(sprite);
+ move_anim_8072740(sprite);
+}
+
+void unref_sub_8078588(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x + sprite->pos2.x;
+ sprite->data3 = sprite->pos1.y + sprite->pos2.y;
+ sprite->data2 = sub_8077ABC(gBattleAnimBankAttacker, 2);
+ sprite->data4 = sub_8077ABC(gBattleAnimBankAttacker, 3);
+ sprite->callback = sub_80782F8;
+}
+
+void unref_sub_80785CC(struct Sprite *sprite) {
+ ResetPaletteStructByUid(sprite->data5);
+ move_anim_8074EE0(sprite);
+}
+
+void sub_80785E4(struct Sprite *sprite) {
+ if (sprite->affineAnimEnded) {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078600(struct Sprite *sprite) {
+ if (sprite->animEnded) {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_807861C(struct Sprite *sprite) {
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ move_anim_8072740(sprite);
+}
+
+void sub_8078634(u8 task) {
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ DestroyAnimVisualTask(task);
+}
+
+void sub_8078650(struct Sprite *sprite) {
+ sprite->pos1.x = sub_8077ABC(gBattleAnimBankAttacker, 2);
+ sprite->pos1.y = sub_8077ABC(gBattleAnimBankAttacker, 3);
+}
+
+void sub_807867C(struct Sprite *sprite, s16 a2) {
+ u16 v1 = sub_8077ABC(gBattleAnimBankAttacker, 0);
+ u16 v2 = sub_8077ABC(gBattleAnimBankTarget, 0);
+ if (v1 > v2) {
+ sprite->pos1.x -= a2;
+ } else if (v1 < v2) {
+ sprite->pos1.x += a2;
+ } else {
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ sprite->pos1.x -= a2;
+ } else {
+ sprite->pos1.x += a2;
+ }
+ }
+}
+
+void sub_80786EC(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ obj_translate_based_on_private_1_2_3_4(sprite);
+ sprite->data6 = 0x8000 / sprite->data0;
+ sprite->data7 = 0;
+}
+
+bool8 sub_8078718(struct Sprite *sprite) {
+ if (sub_8078B5C(sprite)) {
+ return TRUE;
+ }
+ sprite->data7 += sprite->data6;
+ sprite->pos2.y += Sin((u8)(sprite->data7 >> 8), sprite->data5);
+ return FALSE;
+}
+
+void oamt_add_pos2_onto_pos1(struct Sprite *sprite) {
+ sprite->pos1.x += sprite->pos2.x;
+ sprite->pos1.y += sprite->pos2.y;
+ sprite->pos2.x = 0;
+ sprite->pos2.y = 0;
+}
+
+void sub_8078764(struct Sprite *sprite, u8 a2) {
+ if (!a2) {
+ sprite->pos1.x = sub_8077EE4(gBattleAnimBankTarget, 0);
+ sprite->pos1.y = sub_8077EE4(gBattleAnimBankTarget, 1);
+ }
+ sub_807867C(sprite, gBattleAnimArgs[0]);
+ sprite->pos1.y += gBattleAnimArgs[1];
+}
+
+void sub_80787B0(struct Sprite *sprite, u8 a2) {
+ if (!a2) {
+ sprite->pos1.x = sub_8077EE4(gBattleAnimBankAttacker, 0);
+ sprite->pos1.y = sub_8077EE4(gBattleAnimBankAttacker, 1);
+ } else {
+ sprite->pos1.x = sub_8077EE4(gBattleAnimBankAttacker, 2);
+ sprite->pos1.y = sub_8077EE4(gBattleAnimBankAttacker, 3);
+ }
+ sub_807867C(sprite, gBattleAnimArgs[0]);
+ sprite->pos1.y += gBattleAnimArgs[1];
+}
+
+u8 GetBankSide(u8 slot) {
+ return gBanksBySide[slot] & 1;
+}
+
+u8 GetBankIdentity(u8 slot) {
+ return gBanksBySide[slot];
+}
+
+u8 GetBankByPlayerAI(u8 slot) {
+ u8 i;
+ for (i = 0; i < gNoOfAllBanks; i++) {
+ if (gBanksBySide[i] == slot) {
+ break;
+ }
+ }
+ return i;
+}
+
+bool8 AnimBankSpriteExists(u8 slot) {
+ if (IsContest()) {
+ if (gBattleAnimBankAttacker == slot) {
+ return TRUE;
+ }
+ if (gBattleAnimBankTarget == slot) {
+ return TRUE;
+ }
+ return FALSE;
+ } else {
+ if (gBanksBySide[slot] == 0xff) {
+ return FALSE;
+ }
+ if (GetBankSide(slot)) {
+ if (GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_HP) != 0) {
+ return TRUE;
+ }
+ } else {
+ if (GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_HP) != 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+}
+
+bool8 IsDoubleBattle() {
+ return IS_DOUBLE_BATTLE();
+}
+
+void sub_8078914(struct Struct_sub_8078914 *unk) {
+ if (IsContest()) {
+ unk->field_0 = (u8 *)0x6008000;
+ unk->field_4 = (u8 *)0x600f000;
+ unk->field_8 = 0xe;
+ } else {
+ unk->field_0 = (u8 *)0x6004000;
+ unk->field_4 = (u8 *)0x600e000;
+ unk->field_8 = 0x8;
+ }
+}
+
+void sub_8078954(struct Struct_sub_8078914 *unk) {
+ if (IsContest()) {
+ unk->field_0 = (u8 *)0x6008000;
+ unk->field_4 = (u8 *)0x600f000;
+ unk->field_8 = 0xe;
+ } else if (GetBankIdentity_permutated(gBattleAnimBankAttacker) == 1) {
+ unk->field_0 = (u8 *)0x6004000;
+ unk->field_4 = (u8 *)0x600e000;
+ unk->field_8 = 0x8;
+ } else {
+ unk->field_0 = (u8 *)0x6006000;
+ unk->field_4 = (u8 *)0x600f000;
+ unk->field_8 = 0x9;
+ }
+}
+
+u8 sub_80789BC() {
+ if (IsContest()) {
+ return 1;
+ }
+ return 2;
+}
+
+void sub_80789D4(bool8 a1) {
+ if (!a1) {
+ BG3CNT.size = 0;
+ BG3CNT.overflow = 1;
+ } else if (IsContest()) {
+ BG3CNT.size = 0;
+ BG3CNT.overflow = 1;
+ } else {
+ BG3CNT.size = 1;
+ BG3CNT.overflow = 0;
+ }
+}
+
+void sub_8078A34(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ sub_8078A5C(sprite);
+ sprite->callback = sub_80783D0;
+ sprite->callback(sprite);
+}
+
+void sub_8078A5C(struct Sprite *sprite) {
+ s16 x = (sprite->data2 - sprite->data1) << 8;
+ s16 y = (sprite->data4 - sprite->data3) << 8;
+ sprite->data1 = x / sprite->data0;
+ sprite->data2 = y / sprite->data0;
+ sprite->data4 = 0;
+ sprite->data3 = 0;
+}
+
+void obj_translate_based_on_private_1_2_3_4(struct Sprite *sprite) {
+ int x = sprite->data2 - sprite->data1;
+ int y = sprite->data4 - sprite->data3;
+ bool8 r8 = x < 0;
+ bool8 r9 = y < 0;
+ u16 x2 = abs(x) << 8;
+ u16 y2 = abs(y) << 8;
+ x2 = x2 / sprite->data0;
+ y2 = y2 / sprite->data0;
+ if (r8) {
+ x2 |= 1;
+ } else {
+ x2 &= ~1;
+ }
+ if (r9) {
+ y2 |= 1;
+ } else {
+ y2 &= ~1;
+ }
+ sprite->data1 = x2;
+ sprite->data2 = y2;
+ sprite->data4 = 0;
+ sprite->data3 = 0;
+}
+
+void sub_8078B34(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ obj_translate_based_on_private_1_2_3_4(sprite);
+ sprite->callback = sub_8078BB8;
+ sprite->callback(sprite);
+}
+
+bool8 sub_8078B5C(struct Sprite *sprite) {
+ u16 v1, v2, x, y;
+ if (!sprite->data0) {
+ return TRUE;
+ }
+ v1 = sprite->data1;
+ v2 = sprite->data2;
+ x = sprite->data3;
+ y = sprite->data4;
+ x += v1;
+ y += v2;
+ if (v1 & 1) {
+ sprite->pos2.x = -(x >> 8);
+ } else {
+ sprite->pos2.x = x >> 8;
+ }
+ if (v2 & 1) {
+ sprite->pos2.y = -(y >> 8);
+ } else {
+ sprite->pos2.y = y >> 8;
+ }
+ sprite->data3 = x;
+ sprite->data4 = y;
+ sprite->data0--;
+ return FALSE;
+}
+
+void sub_8078BB8(struct Sprite *sprite) {
+ if (sub_8078B5C(sprite)) {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078BD4(struct Sprite *sprite) {
+ int v1 = abs(sprite->data2 - sprite->data1) << 8;
+ sprite->data0 = v1 / sprite->data0;
+ obj_translate_based_on_private_1_2_3_4(sprite);
+}
+
+void sub_8078C00(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ sub_8078BD4(sprite);
+ sprite->callback = sub_8078BB8;
+ sprite->callback(sprite);
+}
+
+void sub_8078C28(struct Sprite *sprite) {
+ int x = sprite->data2 - sprite->data1;
+ int y = sprite->data4 - sprite->data3;
+ bool8 x_sign = x < 0;
+ bool8 y_sign = y < 0;
+ u16 x2 = abs(x) << 4;
+ u16 y2 = abs(y) << 4;
+ x2 /= sprite->data0;
+ y2 /= sprite->data0;
+ if (x_sign) {
+ x2 |= 1;
+ } else {
+ x2 &= ~1;
+ }
+ if (y_sign) {
+ y2 |= 1;
+ } else {
+ y2 &= ~1;
+ }
+ sprite->data1 = x2;
+ sprite->data2 = y2;
+ sprite->data4 = 0;
+ sprite->data3 = 0;
+}
+
+void sub_8078CC0(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ sub_8078C28(sprite);
+ sprite->callback = sub_8078D44;
+ sprite->callback(sprite);
+}
+
+bool8 sub_8078CE8(struct Sprite *sprite) {
+ u16 v1, v2, x, y;
+ if (!sprite->data0) {
+ return TRUE;
+ }
+ v1 = sprite->data1;
+ v2 = sprite->data2;
+ x = sprite->data3;
+ y = sprite->data4;
+ x += v1;
+ y += v2;
+ if (v1 & 1) {
+ sprite->pos2.x = -(x >> 4);
+ } else {
+ sprite->pos2.x = x >> 4;
+ }
+ if (v2 & 1) {
+ sprite->pos2.y = -(y >> 4);
+ } else {
+ sprite->pos2.y = y >> 4;
+ }
+ sprite->data3 = x;
+ sprite->data4 = y;
+ sprite->data0--;
+ return FALSE;
+}
+
+void sub_8078D44(struct Sprite *sprite) {
+ if (sub_8078CE8(sprite)) {
+ SetCallbackToStoredInData6(sprite);
+ }
+}
+
+void sub_8078D60(struct Sprite *sprite) {
+ int v1 = abs(sprite->data2 - sprite->data1) << 4;
+ sprite->data0 = v1 / sprite->data0;
+ sub_8078C28(sprite);
+}
+
+void sub_8078D8C(struct Sprite *sprite) {
+ sprite->data1 = sprite->pos1.x;
+ sprite->data3 = sprite->pos1.y;
+ sub_8078D60(sprite);
+ sprite->callback = sub_8078D44;
+ sprite->callback(sprite);
+}
+
+void obj_id_set_rotscale(u8 sprite, s16 xScale, s16 yScale, u16 rotation) {
+ int i;
+ struct ObjAffineSrcData src;
+ struct OamMatrix matrix;
+ src.xScale = xScale;
+ src.yScale = yScale;
+ src.rotation = rotation;
+ if (sub_8078E38()) {
+ src.xScale = -src.xScale;
+ }
+ i = gSprites[sprite].oam.matrixNum;
+ ObjAffineSet(&src, &matrix, 1, 2);
+ gOamMatrices[i].a = matrix.a;
+ gOamMatrices[i].b = matrix.b;
+ gOamMatrices[i].c = matrix.c;
+ gOamMatrices[i].d = matrix.d;
+}
+
+bool8 sub_8078E38() {
+ if (IsContest()) {
+ if (gSprites[GetAnimBankSpriteId(0)].data2 == 0xc9 /* XXX SPECIES_UNOWN? */) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_8078E70(u8 sprite, u8 a2) {
+ struct Struct_2017810 *unk;
+ u8 r7 = gSprites[sprite].data0;
+ if (IsContest() || IsAnimBankSpriteVisible(r7)) {
+ gSprites[sprite].invisible = FALSE;
+ }
+ gSprites[sprite].oam.objMode = a2;
+ gSprites[sprite].affineAnimPaused = TRUE;
+ if (!IsContest() && !gSprites[sprite].oam.affineMode) {
+ unk = &unk_2017810[r7];
+ gSprites[sprite].oam.matrixNum = unk->field_6;
+ }
+ gSprites[sprite].oam.affineMode = 3;
+ CalcCenterToCornerVec(&gSprites[sprite], gSprites[sprite].oam.shape, gSprites[sprite].oam.size, gSprites[sprite].oam.affineMode);
+}
+
+void sub_8078F40(u8 sprite) {
+ obj_id_set_rotscale(sprite, 0x100, 0x100, 0);
+ gSprites[sprite].oam.affineMode = 1;
+ gSprites[sprite].oam.objMode = 0;
+ gSprites[sprite].affineAnimPaused = FALSE;
+ CalcCenterToCornerVec(&gSprites[sprite], gSprites[sprite].oam.shape, gSprites[sprite].oam.size, gSprites[sprite].oam.affineMode);
+}
+
+void sub_8078F9C(u8 sprite) {
+ u16 matrix = gSprites[sprite].oam.matrixNum;
+ s16 c = gOamMatrices[matrix].c;
+ if (c < 0) {
+ c = -c;
+ }
+ gSprites[sprite].pos2.y = c >> 3;
+}
+
+// related to obj_id_set_rotscale
+void sub_8078FDC(struct Sprite *sprite, bool8 a2, s16 xScale, s16 yScale, u16 rotation) {
+ int i;
+ struct ObjAffineSrcData src;
+ struct OamMatrix matrix;
+ if (sprite->oam.affineMode & 1) {
+ sprite->affineAnimPaused = TRUE;
+ if (a2) {
+ CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode);
+ }
+ src.xScale = xScale;
+ src.yScale = yScale;
+ src.rotation = rotation;
+ if (sub_8078E38()) {
+ src.xScale = -src.xScale;
+ }
+ i = sprite->oam.matrixNum;
+ ObjAffineSet(&src, &matrix, 1, 2);
+ gOamMatrices[i].a = matrix.a;
+ gOamMatrices[i].b = matrix.b;
+ gOamMatrices[i].c = matrix.c;
+ gOamMatrices[i].d = matrix.d;
+ }
+}
+
+void sub_8079098(struct Sprite *sprite) {
+ sub_8078FDC(sprite, TRUE, 0x100, 0x100, 0);
+ sprite->affineAnimPaused = FALSE;
+ CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode);
+}
+
+static u16 ArcTan2_(s16 a, s16 b) {
+ return ArcTan2(a, b);
+}
+
+u16 sub_80790F0(s16 a, s16 b) {
+ u16 var = ArcTan2_(a, b);
+ return -var;
+}
+
+void sub_8079108(u16 a1, bool8 a2) {
+ int i;
+ struct Color *c;
+ struct Color *c2;
+ u16 average;
+
+ a1 *= 0x10;
+
+ if (!a2) {
+ for (i = 0; i < 0x10; i++) {
+ c = (struct Color *)&gPlttBufferUnfaded[a1 + i];
+ average = c->r + c->g + c->b;
+ average /= 3;
+
+ c2 = (struct Color *)&gPlttBufferFaded[a1 + i];
+ c2->r = average;
+ c2->g = average;
+ c2->b = average;
+ }
+ } else {
+ CpuCopy32(&gPlttBufferUnfaded[a1], &gPlttBufferFaded[a1], 0x20);
+ }
+}
+
+u32 sub_80791A8(u8 a1, u8 a2, u8 a3, u8 a4, u8 a5, u8 a6, u8 a7) {
+ u32 var = 0;
+ u32 shift;
+ if (a1) {
+ if (!IsContest()) {
+ var = 0xe;
+ } else {
+ var = 1 << sub_80789BC();
+ }
+ }
+ if (a2) {
+ shift = gBattleAnimBankAttacker + 16;
+ var |= 1 << shift;
+ }
+ if (a3) {
+ shift = gBattleAnimBankTarget + 16;
+ var |= 1 << shift;
+ }
+ if (a4) {
+ if (IsAnimBankSpriteVisible(gBattleAnimBankAttacker ^ 2)) {
+ shift = (gBattleAnimBankAttacker ^ 2) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a5) {
+ if (IsAnimBankSpriteVisible(gBattleAnimBankTarget ^ 2)) {
+ shift = (gBattleAnimBankTarget ^ 2) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a6) {
+ if (!IsContest()) {
+ var |= 0x100;
+ } else {
+ var |= 0x4000;
+ }
+ }
+ if (a7) {
+ if (!IsContest()) {
+ var |= 0x200;
+ }
+ }
+ return var;
+}
+
+u32 sub_80792C0(u8 a1, u8 a2, u8 a3, u8 a4) {
+ u32 var = 0;
+ u32 shift;
+ if (IsContest()) {
+ if (a1) {
+ var |= 1 << 18;
+ return var;
+ }
+ } else {
+ if (a1) {
+ if (IsAnimBankSpriteVisible(GetBankByPlayerAI(0))) {
+ var |= 1 << (GetBankByPlayerAI(0) + 16);
+ }
+ }
+ if (a2) {
+ if (IsAnimBankSpriteVisible(GetBankByPlayerAI(2))) {
+ shift = GetBankByPlayerAI(2) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a3) {
+ if (IsAnimBankSpriteVisible(GetBankByPlayerAI(1))) {
+ shift = GetBankByPlayerAI(1) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a4) {
+ if (IsAnimBankSpriteVisible(GetBankByPlayerAI(3))) {
+ shift = GetBankByPlayerAI(3) + 16;
+ var |= 1 << shift;
+ }
+ }
+ }
+ return var;
+}
+
+u8 sub_80793A8(u8 a1) {
+ return a1;
+}
+
+u8 unref_sub_80793B0(u8 a1) {
+ return GetBankByPlayerAI(a1);
+}
+
+void sub_80793C4(struct Sprite *sprite) {
+ bool8 var;
+ if (!sprite->data0) {
+ if (!gBattleAnimArgs[3]) {
+ var = TRUE;
+ } else {
+ var = FALSE;
+ }
+ if (!gBattleAnimArgs[2]) {
+ sub_80787B0(sprite, var);
+ } else {
+ sub_8078764(sprite, var);
+ }
+ sprite->data0++;
+
+ } else if (sprite->animEnded || sprite->affineAnimEnded) {
+ move_anim_8074EE0(sprite);
+ }
+}
+
+void sub_807941C(struct Sprite *sprite) {
+ bool8 v1;
+ u8 v2;
+ if (!(gBattleAnimArgs[5] & 0xff00)) {
+ v1 = TRUE;
+ } else {
+ v1 = FALSE;
+ }
+ if (!(gBattleAnimArgs[5] & 0xff)) {
+ v2 = 3;
+ } else {
+ v2 = 1;
+ }
+ sub_80787B0(sprite, v1);
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ }
+ sprite->data0 = gBattleAnimArgs[4];
+ sprite->data2 = sub_8077ABC(gBattleAnimBankTarget, 2) + gBattleAnimArgs[2];
+ sprite->data4 = sub_8077ABC(gBattleAnimBankTarget, v2) + gBattleAnimArgs[3];
+ sprite->callback = sub_8078B34;
+ StoreSpriteCallbackInData6(sprite, move_anim_8072740);
+}
+
+void sub_80794A8(struct Sprite *sprite) {
+ sub_80787B0(sprite, 1);
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ }
+ sprite->data0 = gBattleAnimArgs[4];
+ sprite->data2 = sub_8077ABC(gBattleAnimBankTarget, 2) + gBattleAnimArgs[2];
+ sprite->data4 = sub_8077ABC(gBattleAnimBankTarget, 3) + gBattleAnimArgs[3];
+ sprite->data5 = gBattleAnimArgs[5];
+ sub_80786EC(sprite);
+ sprite->callback = sub_8079518;
+}
+
+void sub_8079518(struct Sprite *sprite) {
+ if (sub_8078718(sprite)) {
+ move_anim_8072740(sprite);
+ }
+}
+
+void sub_8079534(struct Sprite *sprite) {
+ u8 r4, slot, r7;
+ if (!gBattleAnimArgs[6]) {
+ r4 = 1;
+ r7 = 3;
+ } else {
+ r4 = 0;
+ r7 = 1;
+ }
+ if (!gBattleAnimArgs[5]) {
+ sub_80787B0(sprite, r4);
+ slot = gBattleAnimBankAttacker;
+ } else {
+ sub_8078764(sprite, r4);
+ slot = gBattleAnimBankTarget;
+ }
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ }
+ sub_8078764(sprite, r4);
+ sprite->data0 = gBattleAnimArgs[4];
+ sprite->data2 = sub_8077ABC(slot, 2) + gBattleAnimArgs[2];
+ sprite->data4 = sub_8077ABC(slot, r7) + gBattleAnimArgs[3];
+ sprite->callback = sub_8078B34;
+ StoreSpriteCallbackInData6(sprite, move_anim_8072740);
+}
+
+s16 duplicate_obj_of_side_rel2move_in_transparent_mode(u8 a1) {
+ u16 i;
+ u8 sprite = GetAnimBankSpriteId(a1);
+ if (sprite != 0xff) {
+ for (i = 0; i < 0x40; i++) {
+ if (gSprites[i].inUse) {
+ continue;
+ }
+ gSprites[i] = gSprites[sprite];
+ gSprites[i].oam.objMode = 1;
+ gSprites[i].invisible = FALSE;
+ return i;
+ }
+ }
+ return -1;
+}
+
+void obj_delete_but_dont_free_vram(struct Sprite *sprite) {
+ sprite->usingSheet = TRUE;
+ DestroySprite(sprite);
+}
+
+void sub_8079670(u8 task) {
+ s16 v1 = 0;
+ s16 v2 = 0;
+ if (gBattleAnimArgs[2] > gBattleAnimArgs[0]) {
+ v2 = 1;
+ }
+ if (gBattleAnimArgs[2] < gBattleAnimArgs[0]) {
+ v2 = -1;
+ }
+ if (gBattleAnimArgs[3] > gBattleAnimArgs[1]) {
+ v1 = 1;
+ }
+ if (gBattleAnimArgs[3] < gBattleAnimArgs[1]) {
+ v1 = -1;
+ }
+ gTasks[task].data[0] = 0;
+ gTasks[task].data[1] = gBattleAnimArgs[4];
+ gTasks[task].data[2] = 0;
+ gTasks[task].data[3] = gBattleAnimArgs[0];
+ gTasks[task].data[4] = gBattleAnimArgs[1];
+ gTasks[task].data[5] = v2;
+ gTasks[task].data[6] = v1;
+ gTasks[task].data[7] = gBattleAnimArgs[2];
+ gTasks[task].data[8] = gBattleAnimArgs[3];
+ REG_BLDALPHA = (gBattleAnimArgs[1] << 8) | gBattleAnimArgs[0];
+ gTasks[task].func = sub_80796F8;
+}
+
+void sub_80796F8(u8 taskId) {
+ struct Task *task = &gTasks[taskId];
+ if (++task->data[0] > task->data[1]) {
+ task->data[0] = 0;
+ if (++task->data[2] & 1) {
+ if (task->data[3] != task->data[7]) {
+ task->data[3] += task->data[5];
+ }
+ } else {
+ if (task->data[4] != task->data[8]) {
+ task->data[4] += task->data[6];
+ }
+ }
+ REG_BLDALPHA = (task->data[4] << 8) | task->data[3];
+ if (task->data[3] == task->data[7] && task->data[4] == task->data[8]) {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ }
+}
+
+void sub_8079790(u8 task) {
+ u8 sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+ if (sprite == 0xff) {
+ DestroyAnimVisualTask(task);
+ return;
+ }
+ gTasks[task].data[0] = (gSprites[sprite].oam.paletteNum * 0x10) + 0x101;
+ sub_80797EC(&gTasks[task]);
+}
+
+void sub_80797EC(struct Task *task) {
+ task->data[1] = gBattleAnimArgs[1];
+ task->data[2] = 0;
+ task->data[3] = gBattleAnimArgs[2];
+ task->data[4] = 0;
+ task->data[5] = gBattleAnimArgs[3];
+ task->data[6] = 0;
+ task->data[7] = gBattleAnimArgs[4];
+ task->func = sub_8079814;
+}
+
+void sub_8079814(u8 taskId) {
+ struct Task *task = &gTasks[taskId];
+ if (++task->data[4] >= task->data[5]) {
+ task->data[4] = 0;
+ if (!task->data[6]) {
+ task->data[2]++;
+ BlendPalette(task->data[0], 0xf, task->data[2], task->data[1]);
+ if (task->data[2] == task->data[3]) {
+ task->data[6] = 1;
+ }
+ } else {
+ task->data[2]--;
+ BlendPalette(task->data[0], 0xf, task->data[2], task->data[1]);
+ if (!task->data[2]) {
+ if (--task->data[7]) {
+ task->data[4] = 0;
+ task->data[6] = 0;
+ } else {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void sub_80798AC(u8 task) {
+ u8 palette = IndexOfSpritePaletteTag(gBattleAnimArgs[0]);
+ if (palette == 0xff) {
+ DestroyAnimVisualTask(task);
+ return;
+ }
+ gTasks[task].data[0] = (palette * 0x10) + 0x101;
+ sub_80797EC(&gTasks[task]);
+}
+
+void sub_80798F4(struct Task *task, u8 a2, void *a3) {
+ task->data[7] = 0;
+ task->data[8] = 0;
+ task->data[9] = 0;
+ task->data[15] = a2;
+ task->data[10] = 0x100;
+ task->data[11] = 0x100;
+ task->data[12] = 0;
+ sub_8079BF4(&task->data[13], &task->data[14], a3);
+ sub_8078E70(a2, 0);
+}
+
+bool8 sub_807992C(struct Task *task) {
+ gUnknown_0202F7D4 = sub_8079BFC(task->data[13], task->data[14]) + (task->data[7] << 3);
+ switch (gUnknown_0202F7D4->type) {
+ default:
+ if (!gUnknown_0202F7D4->frame.duration) {
+ task->data[10] = gUnknown_0202F7D4->frame.xScale;
+ task->data[11] = gUnknown_0202F7D4->frame.yScale;
+ task->data[12] = gUnknown_0202F7D4->frame.rotation;
+ task->data[7]++;
+ gUnknown_0202F7D4++;
+ }
+ task->data[10] += gUnknown_0202F7D4->frame.xScale;
+ task->data[11] += gUnknown_0202F7D4->frame.yScale;
+ task->data[12] += gUnknown_0202F7D4->frame.rotation;
+ obj_id_set_rotscale(task->data[15], task->data[10], task->data[11], task->data[12]);
+ sub_8079A64(task->data[15]);
+ if (++task->data[8] >= gUnknown_0202F7D4->frame.duration) {
+ task->data[8] = 0;
+ task->data[7]++;
+ }
+ break;
+
+ case AFFINEANIMCMDTYPE_JUMP:
+ task->data[7] = gUnknown_0202F7D4->jump.target;
+ break;
+
+ case AFFINEANIMCMDTYPE_LOOP:
+ if (gUnknown_0202F7D4->loop.count) {
+ if (task->data[9]) {
+ if (!--task->data[9]) {
+ task->data[7]++;
+ break;
+ }
+ } else {
+ task->data[9] = gUnknown_0202F7D4->loop.count;
+ }
+ if (!task->data[7]) {
+ break;
+ }
+ for (;;) {
+ task->data[7]--;
+ gUnknown_0202F7D4--;
+ if (gUnknown_0202F7D4->type == AFFINEANIMCMDTYPE_LOOP) {
+ task->data[7]++;
+ return TRUE;
+ }
+ if (!task->data[7]) {
+ return TRUE;
+ }
+ }
+ }
+ task->data[7]++;
+ break;
+
+ case 0x7fff:
+ gSprites[task->data[15]].pos2.y = 0;
+ sub_8078F40(task->data[15]);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void sub_8079A64(u8 sprite) {
+ int var = 0x40 - sub_8079B10(sprite) * 2;
+ u16 matrix = gSprites[sprite].oam.matrixNum;
+ int var2 = (var << 8) / gOamMatrices[matrix].d;
+ if (var2 > 0x80) {
+ var2 = 0x80;
+ }
+ gSprites[sprite].pos2.y = (var - var2) / 2;
+}
+
+void sub_8079AB8(u8 sprite, u8 sprite2) {
+ int var = 0x40 - sub_8079B10(sprite2) * 2;
+ u16 matrix = gSprites[sprite].oam.matrixNum;
+ int var2 = (var << 8) / gOamMatrices[matrix].d;
+ if (var2 > 0x80) {
+ var2 = 0x80;
+ }
+ gSprites[sprite].pos2.y = (var - var2) / 2;
+}
+
+u16 sub_8079B10(u8 sprite) {
+ struct TransformStatus *transform;
+ u8 slot = gSprites[sprite].data0;
+ u16 species;
+ u16 i;
+ for (i = 0; i < (sizeof(gBattleMonSprites) / sizeof(u8)); i++) {
+ if (gBattleMonSprites[i] == sprite) {
+ if (IsContest()) {
+ species = unk_2019348.field_0;
+ return gMonBackPicCoords[species].y_offset;
+ } else {
+ if (!GetBankSide(i)) {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gPlayerParty[gBattleMonPartyPositions[i]], MON_DATA_SPECIES);
+ } else {
+ species = transform->species;
+ }
+ return gMonBackPicCoords[species].y_offset;
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gEnemyParty[gBattleMonPartyPositions[i]], MON_DATA_SPECIES);
+ } else {
+ species = transform->species;
+ }
+ return gMonFrontPicCoords[species].y_offset;
+ }
+ }
+ }
+ }
+ return 0x40;
+}
+
+void sub_8079BF4(s16 *bottom, s16 *top, void *ptr) {
+ *bottom = ((intptr_t) ptr) & 0xffff;
+ *top = (((intptr_t) ptr) >> 16) & 0xffff;
+}
+
+void *sub_8079BFC(s16 bottom, s16 top) {
+ return (void *)((u16)bottom | ((u16)top << 16));
+}
+
+
+// possible new file
+
+void sub_8079C08(struct Task *task, u8 a2, s16 a3, s16 a4, s16 a5, s16 a6, u16 a7) {
+ task->data[8] = a7;
+ task->data[15] = a2;
+ task->data[9] = a3;
+ task->data[10] = a4;
+ task->data[13] = a5;
+ task->data[14] = a6;
+ task->data[11] = (a5 - a3) / a7;
+ task->data[12] = (a6 - a4) / a7;
+}
+
+u8 sub_8079C74(struct Task *task) {
+ if (!task->data[8]) {
+ return 0;
+ }
+ if (--task->data[8]) {
+ task->data[9] += task->data[11];
+ task->data[10] += task->data[12];
+ } else {
+ task->data[9] = task->data[13];
+ task->data[10] = task->data[14];
+ }
+ obj_id_set_rotscale(task->data[15], task->data[9], task->data[10], 0);
+ if (task->data[8]) {
+ sub_8079A64(task->data[15]);
+ } else {
+ gSprites[task->data[15]].pos2.y = 0;
+ }
+ return task->data[8];
+}
+
+void sub_8079CEC(u8 task) {
+ u16 v1;
+ if (gHappinessMoveAnim <= 30) {
+ v1 = 0;
+ } else if (gHappinessMoveAnim <= 100) {
+ v1 = 1;
+ } else if (gHappinessMoveAnim <= 200) {
+ v1 = 2;
+ } else {
+ v1 = 3;
+ }
+ gBattleAnimArgs[7] = v1;
+ DestroyAnimVisualTask(task);
+}
+
+void unref_sub_8079D20(u8 priority) {
+ if (IsAnimBankSpriteVisible(gBattleAnimBankTarget)) {
+ gSprites[gBattleMonSprites[gBattleAnimBankTarget]].oam.priority = priority;
+ }
+ if (IsAnimBankSpriteVisible(gBattleAnimBankAttacker)) {
+ gSprites[gBattleMonSprites[gBattleAnimBankAttacker]].oam.priority = priority;
+ }
+ if (IsAnimBankSpriteVisible(gBattleAnimBankTarget ^ 2)) {
+ gSprites[gBattleMonSprites[gBattleAnimBankTarget ^ 2]].oam.priority = priority;
+ }
+ if (IsAnimBankSpriteVisible(gBattleAnimBankAttacker ^ 2)) {
+ gSprites[gBattleMonSprites[gBattleAnimBankAttacker ^ 2]].oam.priority = priority;
+ }
+}
+
+void sub_8079E24() {
+ int i;
+ for (i = 0; i < gNoOfAllBanks; i++) {
+ if (IsAnimBankSpriteVisible(i)) {
+ gSprites[gBattleMonSprites[i]].subpriority = sub_8079E90(i);
+ gSprites[gBattleMonSprites[i]].oam.priority = 2;
+ }
+ }
+}
+
+u8 sub_8079E90(u8 slot) {
+ u8 status;
+ u8 ret;
+ if (IsContest()) {
+ if (slot == 2) {
+ return 30;
+ } else {
+ return 40;
+ }
+ } else {
+ status = GetBankIdentity(slot);
+ if (status == 0) {
+ ret = 30;
+ } else if (status == 2) {
+ ret = 20;
+ } else if (status == 1) {
+ ret = 40;
+ } else {
+ ret = 50;
+ }
+ }
+ return ret;
+}
+
+u8 sub_8079ED4(u8 slot) {
+ u8 status = GetBankIdentity(slot);
+ if (IsContest()) {
+ return 2;
+ }
+ if (status == 0 || status == 3) {
+ return BG2CNT.priority;
+ } else {
+ return BG1CNT.priority;
+ }
+}
+
+u8 GetBankIdentity_permutated(u8 slot) {
+ u8 status;
+ if (!IsContest()) {
+ status = GetBankIdentity(slot);
+ if (status == 0 || status == 3) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+ return 1;
+}
+
+u8 sub_8079F44(u16 species, u8 isBackpic, u8 a3, s16 a4, s16 a5, u8 a6, u32 a7, u32 a8) {
+ void *src;
+ void *dest;
+ int size;
+
+ u8 sprite;
+ u16 sheet = LoadSpriteSheet(&gUnknown_0837F5E0[a3]);
+ u16 palette = AllocSpritePalette(gSpriteTemplate_837F5B0[a3].paletteTag);
+ if (!isBackpic) {
+ LoadCompressedPalette(GetMonSpritePalFromOtIdPersonality(species, a8, a7), (palette * 0x10) + 0x100, 0x20);
+ LoadSpecialPokePic(
+ &gMonFrontPicTable[species],
+ gMonFrontPicCoords[species].coords,
+ gMonFrontPicCoords[species].y_offset,
+ 0x2000000,
+ (void *)0x2000000,
+ species,
+ a7,
+ 1
+ );
+ } else {
+ LoadCompressedPalette(
+ GetMonSpritePalFromOtIdPersonality(species, a8, a7), (palette * 0x10) + 0x100, 0x20);
+ LoadSpecialPokePic(
+ &gMonBackPicTable[species],
+ gMonBackPicCoords[species].coords,
+ gMonBackPicCoords[species].y_offset,
+ 0x2000000,
+ (void *)0x2000000,
+ species,
+ a7,
+ 0
+ );
+ }
+
+ src = (void *)0x2000000;
+ dest = (void *)(0x6010000 + (sheet * 0x20));
+ size = 0x800;
+ DmaCopy32(3, src, dest, size);
+
+ if (!isBackpic) {
+ sprite = CreateSprite(&gSpriteTemplate_837F5B0[a3], a4, a5 + gMonFrontPicCoords[species].y_offset, a6);
+ } else {
+ sprite = CreateSprite(&gSpriteTemplate_837F5B0[a3], a4, a5 + gMonBackPicCoords[species].y_offset, a6);
+ }
+ if (IsContest()) {
+ gSprites[sprite].affineAnims = &gSpriteAffineAnimTable_81E7C18;
+ StartSpriteAffineAnim(&gSprites[sprite], 0);
+ }
+ return sprite;
+}
+
+void sub_807A0F4(struct Sprite *sprite) {
+ DestroySpriteAndFreeResources(sprite);
+}
+
+int sub_807A100(u8 slot, u8 a2) {
+ u16 species;
+ u32 personality;
+ u16 letter;
+ u16 var;
+ int ret;
+ const struct MonCoords *coords;
+ struct TransformStatus *transform;
+ if (IsContest()) {
+ if (unk_2019348.field_4 & 1) {
+ species = unk_2019348.field_2;
+ personality = unk_2019348.field_10;
+ } else {
+ species = unk_2019348.field_0;
+ personality = unk_2019348.field_8;
+ }
+ if (species == SPECIES_UNOWN) {
+ letter = GET_UNOWN_LETTER(personality);
+ if (!letter) {
+ var = SPECIES_UNOWN;
+ } else {
+ var = letter + SPECIES_UNOWN_B - 1;
+ }
+ coords = &gMonBackPicCoords[var];
+ } else if (species == SPECIES_CASTFORM) {
+ coords = &gCastformFrontSpriteCoords[gBattleMonForms[slot]];
+ } else if (species <= SPECIES_EGG) {
+ coords = &gMonBackPicCoords[species];
+ } else {
+ coords = &gMonBackPicCoords[0];
+ }
+ } else {
+ if (!GetBankSide(slot)) {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ personality = GetMonData(&gPlayerParty[gBattleMonPartyPositions[slot]], MON_DATA_PERSONALITY);
+ } else {
+ species = transform->species;
+ personality = gTransformPersonalities[slot];
+ }
+ if (species == SPECIES_UNOWN) {
+ letter = GET_UNOWN_LETTER(personality);
+ if (!letter) {
+ var = SPECIES_UNOWN;
+ } else {
+ var = letter + SPECIES_UNOWN_B - 1;
+ }
+ coords = &gMonBackPicCoords[var];
+ } else if (species > SPECIES_EGG) {
+ coords = &gMonBackPicCoords[0];
+ } else {
+ coords = &gMonBackPicCoords[species];
+ }
+ } else {
+ transform = &gTransformStatuses[slot];
+ if (!transform->species) {
+ species = GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_SPECIES);
+ personality = GetMonData(&gEnemyParty[gBattleMonPartyPositions[slot]], MON_DATA_PERSONALITY);
+ } else {
+ species = transform->species;
+ personality = gTransformPersonalities[slot];
+ }
+ if (species == SPECIES_UNOWN) {
+ letter = GET_UNOWN_LETTER(personality);
+ if (!letter) {
+ var = SPECIES_UNOWN;
+ } else {
+ var = letter + SPECIES_UNOWN_B - 1;
+ }
+ coords = &gMonFrontPicCoords[var];
+ } else if (species == SPECIES_CASTFORM) {
+ coords = &gCastformFrontSpriteCoords[gBattleMonForms[slot]];
+ } else if (species > SPECIES_EGG) {
+ coords = &gMonFrontPicCoords[0];
+ } else {
+ coords = &gMonFrontPicCoords[species];
+ }
+ }
+ }
+
+ switch (a2) {
+ case 0:
+ return (coords->coords & 0xf) * 8;
+ case 1:
+ return (coords->coords >> 4) * 8;
+ case 4:
+ return sub_8077ABC(slot, 2) - ((coords->coords >> 4) * 4);
+ case 5:
+ return sub_8077ABC(slot, 2) + ((coords->coords >> 4) * 4);
+ case 2:
+ return sub_8077ABC(slot, 3) - ((coords->coords & 0xf) * 4);
+ case 3:
+ return sub_8077ABC(slot, 3) + ((coords->coords & 0xf) * 4);
+ case 6:
+ ret = sub_8077ABC(slot, 1) + 0x1f;
+ return ret - coords->y_offset;
+ default:
+ return 0;
+ }
+}
+
+void sub_807A3FC(u8 slot, u8 a2, s16 *a3, s16 *a4) {
+ u8 v1, v2;
+ s16 v3, v4;
+ s16 v5, v6;
+ if (!a2) {
+ v1 = 0;
+ v2 = 1;
+ } else {
+ v1 = 2;
+ v2 = 3;
+ }
+ v3 = sub_8077ABC(slot, v1);
+ v4 = sub_8077ABC(slot, v2);
+ if (IsDoubleBattle() && !IsContest()) {
+ v5 = sub_8077ABC(slot ^ 2, v1);
+ v6 = sub_8077ABC(slot ^ 2, v2);
+ } else {
+ v5 = v3;
+ v6 = v4;
+ }
+ *a3 = (v3 + v5) / 2;
+ *a4 = (v4 + v6) / 2;
+}
+
+u8 sub_807A4A0(int a1, u8 sprite, int a3) {
+ u8 new_sprite = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
+ gSprites[new_sprite] = gSprites[sprite];
+ gSprites[new_sprite].usingSheet = TRUE;
+ gSprites[new_sprite].oam.priority = 0;
+ gSprites[new_sprite].oam.objMode = 2;
+ gSprites[new_sprite].oam.tileNum = gSprites[sprite].oam.tileNum;
+ gSprites[new_sprite].callback = SpriteCallbackDummy;
+ return new_sprite;
+}
+
+void sub_807A544(struct Sprite *sprite) {
+ sub_8078650(sprite);
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ sprite->hFlip = TRUE;
+ } else {
+ sprite->pos1.x += gBattleAnimArgs[0];
+ }
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data0 = gBattleAnimArgs[2];
+ sprite->data1 = gBattleAnimArgs[3];
+ sprite->data3 = gBattleAnimArgs[4];
+ sprite->data5 = gBattleAnimArgs[5];
+ StoreSpriteCallbackInData6(sprite, move_anim_8074EE0);
+ sprite->callback = sub_8078504;
+}
+
+void sub_807A5C4(struct Sprite *sprite) {
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ gBattleAnimArgs[3] *= -1;
+ } else {
+ sprite->pos1.x += gBattleAnimArgs[0];
+ }
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data0 = gBattleAnimArgs[2];
+ sprite->data1 = gBattleAnimArgs[3];
+ sprite->data3 = gBattleAnimArgs[4];
+ sprite->data5 = gBattleAnimArgs[5];
+ StartSpriteAnim(sprite, gBattleAnimArgs[6]);
+ StoreSpriteCallbackInData6(sprite, move_anim_8074EE0);
+ sprite->callback = sub_8078504;
+}
+
+void sub_807A63C(struct Sprite *sprite) {
+ sub_8078650(sprite);
+ if (GetBankSide(gBattleAnimBankAttacker)) {
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ } else {
+ sprite->pos1.x += gBattleAnimArgs[0];
+ }
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->callback = sub_8078600;
+ StoreSpriteCallbackInData6(sprite, move_anim_8072740);
+}
+
+void sub_807A69C(u8 taskId) {
+ u16 src;
+ u16 dest;
+ struct Task *task = &gTasks[taskId];
+ task->data[0] = GetAnimBankSpriteId(0);
+ task->data[1] = (GetBankSide(gBattleAnimBankAttacker)) ? -8 : 8;
+ task->data[2] = 0;
+ task->data[3] = 0;
+ gSprites[task->data[0]].pos2.x -= task->data[0];
+ task->data[4] = AllocSpritePalette(10097);
+ task->data[5] = 0;
+
+ dest = (task->data[4] + 0x10) * 0x10;
+ src = (gSprites[task->data[0]].oam.paletteNum + 0x10) * 0x10;
+ task->data[6] = sub_8079E90(gBattleAnimBankAttacker);
+ if (task->data[6] == 20 || task->data[6] == 40) {
+ task->data[6] = 2;
+ } else {
+ task->data[6] = 3;
+ }
+ CpuCopy32(&gPlttBufferUnfaded[src], &gPlttBufferFaded[dest], 0x20);
+ BlendPalette(dest, 0x10, gBattleAnimArgs[1], gBattleAnimArgs[0]);
+ task->func = sub_807A784;
+}
+
+void sub_807A784(u8 taskId) {
+ struct Task *task = &gTasks[taskId];
+ switch (task->data[2]) {
+ case 0:
+ sub_807A850(task, taskId);
+ gSprites[task->data[0]].pos2.x += task->data[1];
+ if (++task->data[3] == 5) {
+ task->data[3]--;
+ task->data[2]++;
+ }
+ break;
+ case 1:
+ sub_807A850(task, taskId);
+ gSprites[task->data[0]].pos2.x -= task->data[1];
+ if (--task->data[3] == 0) {
+ gSprites[task->data[0]].pos2.x = 0;
+ task->data[2]++;
+ }
+ break;
+ case 2:
+ if (!task->data[5]) {
+ FreeSpritePaletteByTag(10097);
+ DestroyAnimVisualTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_807A850(struct Task *task, u8 taskId) {
+ s16 sprite = duplicate_obj_of_side_rel2move_in_transparent_mode(0);
+ if (sprite >= 0) {
+ gSprites[sprite].oam.priority = task->data[6];
+ gSprites[sprite].oam.paletteNum = task->data[4];
+ gSprites[sprite].data0 = 8;
+ gSprites[sprite].data1 = taskId;
+ gSprites[sprite].data2 = sprite;
+ gSprites[sprite].pos2.x = gSprites[task->data[0]].pos2.x;
+ gSprites[sprite].callback = sub_807A8D4;
+ task->data[5]++;
+ }
+}
+
+void sub_807A8D4(struct Sprite *sprite) {
+ if (--sprite->data0 == 0) {
+ gTasks[sprite->data1].data[5]--;
+ obj_delete_but_dont_free_vram(sprite);
+ }
+}
+
+void sub_807A908(struct Sprite *sprite) {
+ sprite->pos1.x = sub_8077ABC(gBattleAnimBankAttacker, 2);
+ sprite->pos1.y = sub_8077ABC(gBattleAnimBankAttacker, 3);
+ if (!GetBankSide(gBattleAnimBankAttacker)) {
+ sprite->data0 = 5;
+ } else {
+ sprite->data0 = -10;
+ }
+ sprite->data1 = -40;
+ sprite->callback = sub_807A960;
+}
+
+void sub_807A960(struct Sprite *sprite) {
+ sprite->data2 += sprite->data0;
+ sprite->data3 += sprite->data1;
+ sprite->pos2.x = sprite->data2 / 10;
+ sprite->pos2.y = sprite->data3 / 10;
+ if (sprite->data1 < -20) {
+ sprite->data1++;
+ }
+ if ((sprite->pos1.y + sprite->pos2.y) < -32) {
+ move_anim_8072740(sprite);
+ }
+}
+
+void sub_807A9BC(struct Sprite *sprite) {
+ int x;
+ sprite->data0 = gBattleAnimArgs[2];
+ sprite->data2 = sprite->pos1.x + gBattleAnimArgs[4];
+ sprite->data4 = sprite->pos1.y + gBattleAnimArgs[5];
+ if (!GetBankSide(gBattleAnimBankTarget)) {
+ x = (u16)gBattleAnimArgs[4] + 30;
+ sprite->pos1.x += x;
+ sprite->pos1.y = gBattleAnimArgs[5] - 20;
+ } else {
+ x = (u16)gBattleAnimArgs[4] - 30;
+ sprite->pos1.x += x;
+ sprite->pos1.y = gBattleAnimArgs[5] - 80;
+ }
+ sprite->callback = sub_8078B34;
+ StoreSpriteCallbackInData6(sprite, move_anim_8072740);
+}
diff --git a/src/misc/script_pokemon_util_80C4BF0.c b/src/misc/script_pokemon_util_80C4BF0.c
new file mode 100644
index 000000000..f98293a90
--- /dev/null
+++ b/src/misc/script_pokemon_util_80C4BF0.c
@@ -0,0 +1,714 @@
+#include "global.h"
+#include "battle.h"
+#include "berry.h"
+#include "choose_party.h"
+#include "contest.h"
+#include "contest_link_80C2020.h"
+#include "contest_painting.h"
+#include "data2.h"
+#include "daycare.h"
+#include "debug.h"
+#include "decompress.h"
+#include "event_data.h"
+#include "items.h"
+#include "link.h"
+#include "load_save.h"
+#include "main.h"
+#include "menu.h"
+#include "pokedex.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "overworld.h"
+#include "script_pokemon_80C4.h"
+#include "species.h"
+#include "task.h"
+
+#define CONTEST_ENTRY_PIC_LEFT 10
+#define CONTEST_ENTRY_PIC_TOP 3
+
+extern struct SpriteTemplate gUnknown_02024E8C;
+
+extern u8 gContestPlayerMonIndex;
+extern u8 gIsLinkContest;
+extern u8 gPlayerPartyCount;
+extern u8 gSelectedOrderFromParty[];
+
+extern u16 gSpecialVar_0x8004;
+extern u16 gSpecialVar_0x8005;
+extern u16 gSpecialVar_0x8006;
+
+extern u16 gScriptContestCategory;
+extern u16 gScriptContestRank;
+extern u16 gScriptResult;
+
+extern u32 gUnknown_03005D28;
+
+extern u8 gUnknown_02038694;
+extern u8 gUnknown_0203856C;
+extern u8 gUnknown_02038690[];
+extern u16 gUnknown_02038678[];
+
+void sub_80C4BF0(void)
+{
+ gSaveBlock1.vars[0x10] = gContestMons[0].unk16;
+ gSaveBlock1.vars[0x11] = gContestMons[1].unk16;
+ gSaveBlock1.vars[0x12] = gContestMons[2].unk16;
+}
+
+void sub_80C4C28(void)
+{
+ u16 var;
+ u8 specialVar = gSpecialVar_0x8005;
+
+ switch(specialVar)
+ {
+ case 0:
+ var = 3;
+ break;
+ case 1:
+ var = 4;
+ break;
+ case 2:
+ var = 5;
+ break;
+ default:
+ var = 100;
+ break;
+ }
+ gSpecialVar_0x8004 = var;
+}
+
+void sub_80C4C64(void)
+{
+ sub_80C46EC();
+ sub_80C4740();
+ sub_80C48F4();
+}
+
+void sub_80C4C78(void)
+{
+ u16 var;
+ u16 returnVar;
+
+ switch(gScriptContestCategory)
+ {
+ case 0:
+ var = 8;
+ break;
+ case 1:
+ var = 9;
+ break;
+ case 2:
+ var = 10;
+ break;
+ case 3:
+ var = 11;
+ break;
+ case 4:
+ default:
+ var = 12;
+ break;
+ }
+
+ returnVar = gSaveBlock1.sbStruct.unkSB2.sb1_2EFC_struct2[var].var;
+
+ if(returnVar == 0)
+ gSpecialVar_0x8004 = returnVar;
+ else
+ gSpecialVar_0x8004 = 1;
+}
+
+void sub_80C4CEC(void)
+{
+ sub_80B2A7C(0xFF);
+}
+
+void sub_80C4CF8(void)
+{
+ if(!gUnknown_02038690[gContestPlayerMonIndex]
+ && gScriptContestRank == 3
+ && (s16)gUnknown_02038678[gContestPlayerMonIndex] >= 800)
+ {
+ gSpecialVar_0x8004 = 1;
+ }
+ else
+ {
+ gSpecialVar_0x8004 = 0;
+ }
+}
+
+u8 sub_80C4D50(void)
+{
+ u8 retVar = 0;
+ int i;
+
+ for (i = 0; i < 5; i++)
+ if (gSaveBlock1.sbStruct.unkSB2.sb1_2EFC_struct2[i + 8].var)
+ retVar++;
+
+ return retVar;
+}
+
+// nope. too hard
+__attribute__((naked))
+void sub_80C4D80(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\
+ sub sp, 0x8\n\
+ ldr r0, _080C4EA0 @ =gUnknown_02038670\n\
+ mov r12, r0\n\
+ ldr r1, _080C4EA4 @ =gSpecialVar_0x8006\n\
+ mov r8, r1\n\
+ ldr r2, _080C4EA8 @ =gStringVar1\n\
+ mov r9, r2\n\
+ mov r2, r12\n\
+ mov r1, sp\n\
+ movs r6, 0x3\n\
+_080C4D9E:\n\
+ ldrh r0, [r2]\n\
+ strh r0, [r1]\n\
+ adds r2, 0x2\n\
+ adds r1, 0x2\n\
+ subs r6, 0x1\n\
+ cmp r6, 0\n\
+ bge _080C4D9E\n\
+ movs r6, 0\n\
+_080C4DAE:\n\
+ movs r1, 0x3\n\
+ cmp r1, r6\n\
+ ble _080C4DD8\n\
+_080C4DB4:\n\
+ subs r4, r1, 0x1\n\
+ lsls r0, r4, 1\n\
+ mov r5, sp\n\
+ adds r3, r5, r0\n\
+ lsls r0, r1, 1\n\
+ adds r2, r5, r0\n\
+ ldrh r5, [r3]\n\
+ movs r7, 0\n\
+ ldrsh r1, [r3, r7]\n\
+ movs r7, 0\n\
+ ldrsh r0, [r2, r7]\n\
+ cmp r1, r0\n\
+ bge _080C4DD2\n\
+ strh r5, [r2]\n\
+ strh r0, [r3]\n\
+_080C4DD2:\n\
+ adds r1, r4, 0\n\
+ cmp r1, r6\n\
+ bgt _080C4DB4\n\
+_080C4DD8:\n\
+ adds r6, 0x1\n\
+ cmp r6, 0x2\n\
+ ble _080C4DAE\n\
+ mov r2, r8\n\
+ ldrh r0, [r2]\n\
+ lsls r0, 1\n\
+ add r0, sp\n\
+ ldrh r0, [r0]\n\
+ movs r2, 0\n\
+ movs r7, 0\n\
+ movs r6, 0\n\
+ lsls r0, 16\n\
+ asrs r4, r0, 16\n\
+ adds r3, r0, 0\n\
+ mov r1, sp\n\
+_080C4DF6:\n\
+ movs r5, 0\n\
+ ldrsh r0, [r1, r5]\n\
+ cmp r0, r4\n\
+ bne _080C4E12\n\
+ lsls r0, r2, 24\n\
+ movs r2, 0x80\n\
+ lsls r2, 17\n\
+ adds r0, r2\n\
+ lsrs r2, r0, 24\n\
+ mov r5, r8\n\
+ ldrh r5, [r5]\n\
+ cmp r6, r5\n\
+ bne _080C4E12\n\
+ adds r7, r2, 0\n\
+_080C4E12:\n\
+ adds r1, 0x2\n\
+ adds r6, 0x1\n\
+ cmp r6, 0x3\n\
+ ble _080C4DF6\n\
+ movs r6, 0\n\
+ mov r0, sp\n\
+ movs r1, 0\n\
+ ldrsh r0, [r0, r1]\n\
+ asrs r1, r3, 16\n\
+ lsls r2, 24\n\
+ mov r10, r2\n\
+ cmp r0, r1\n\
+ beq _080C4E40\n\
+ adds r2, r1, 0\n\
+ mov r1, sp\n\
+_080C4E30:\n\
+ adds r1, 0x2\n\
+ adds r6, 0x1\n\
+ cmp r6, 0x3\n\
+ bgt _080C4E40\n\
+ movs r4, 0\n\
+ ldrsh r0, [r1, r4]\n\
+ cmp r0, r2\n\
+ bne _080C4E30\n\
+_080C4E40:\n\
+ lsls r0, r6, 24\n\
+ lsrs r4, r0, 24\n\
+ adds r2, r7, 0\n\
+ movs r6, 0\n\
+ asrs r5, r3, 16\n\
+ mov r8, r5\n\
+ mov r1, r12\n\
+ movs r5, 0\n\
+ ldrsh r0, [r1, r5]\n\
+ cmp r8, r0\n\
+ bne _080C4E60\n\
+ cmp r7, 0x1\n\
+ beq _080C4E78\n\
+_080C4E5A:\n\
+ subs r0, r2, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r2, r0, 24\n\
+_080C4E60:\n\
+ adds r6, 0x1\n\
+ cmp r6, 0x3\n\
+ bgt _080C4E78\n\
+ lsls r0, r6, 1\n\
+ add r0, r12\n\
+ asrs r1, r3, 16\n\
+ movs r5, 0\n\
+ ldrsh r0, [r0, r5]\n\
+ cmp r1, r0\n\
+ bne _080C4E60\n\
+ cmp r2, 0x1\n\
+ bne _080C4E5A\n\
+_080C4E78:\n\
+ lsls r1, r6, 24\n\
+ lsrs r1, 24\n\
+ mov r0, r9\n\
+ bl sub_80C4698\n\
+ ldr r0, _080C4EAC @ =gIsLinkContest\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _080C4EB8\n\
+ ldr r0, _080C4EB0 @ =gStringVar2\n\
+ lsls r1, r6, 3\n\
+ subs r1, r6\n\
+ lsls r1, 2\n\
+ ldr r2, _080C4EB4 @ =gLinkPlayers + 0x8\n\
+ adds r1, r2\n\
+ bl sub_80C4674\n\
+ b _080C4EC4\n\
+ .align 2, 0\n\
+_080C4EA0: .4byte gUnknown_02038670\n\
+_080C4EA4: .4byte gSpecialVar_0x8006\n\
+_080C4EA8: .4byte gStringVar1\n\
+_080C4EAC: .4byte gIsLinkContest\n\
+_080C4EB0: .4byte gStringVar2\n\
+_080C4EB4: .4byte gLinkPlayers + 0x8\n\
+_080C4EB8:\n\
+ ldr r0, _080C4ED8 @ =gStringVar2\n\
+ lsls r1, r6, 6\n\
+ ldr r2, _080C4EDC @ =gUnknown_0203857D\n\
+ adds r1, r2\n\
+ bl sub_80C4674\n\
+_080C4EC4:\n\
+ mov r1, r10\n\
+ asrs r0, r1, 24\n\
+ cmp r0, 0x1\n\
+ beq _080C4ED0\n\
+ cmp r7, r0\n\
+ bne _080C4EE4\n\
+_080C4ED0:\n\
+ ldr r0, _080C4EE0 @ =gSpecialVar_0x8006\n\
+ strh r4, [r0]\n\
+ b _080C4EEA\n\
+ .align 2, 0\n\
+_080C4ED8: .4byte gStringVar2\n\
+_080C4EDC: .4byte gUnknown_0203857D\n\
+_080C4EE0: .4byte gSpecialVar_0x8006\n\
+_080C4EE4:\n\
+ ldr r1, _080C4EFC @ =gSpecialVar_0x8006\n\
+ adds r0, r4, 0x4\n\
+ strh r0, [r1]\n\
+_080C4EEA:\n\
+ add sp, 0x8\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\
+ .align 2, 0\n\
+_080C4EFC: .4byte gSpecialVar_0x8006\n\
+ .syntax divided");
+}
+
+void ShowContestWinnerCleanup(void)
+{
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void ShowContestWinner(void)
+{
+ if(gUnknown_0203856C)
+ {
+ sub_80AAF30();
+ BATTLE_STRUCT->unk15DDF = 1;
+ BATTLE_STRUCT->unk15DDE = sub_80B2C4C(254, 0);
+ sub_80B2A7C(3);
+ gUnknown_0203856C = 0;
+ }
+ SetMainCallback2(CB2_ContestPainting);
+ gMain.savedCallback = ShowContestWinnerCleanup;
+}
+
+void sub_80C4F70(void)
+{
+ VarSet(0x4010, gContestMons[0].unk16);
+ VarSet(0x4011, gContestMons[1].unk16);
+ VarSet(0x4012, gContestMons[2].unk16);
+ VarSet(0x4013, gContestMons[3].unk16);
+}
+
+bool8 GiveMonArtistRibbon(void)
+{
+ u8 ribbon = GetMonData(&gPlayerParty[gUnknown_02038694], MON_DATA_ARTIST_RIBBON);
+
+ if(ribbon == FALSE
+ && gUnknown_02038690[gContestPlayerMonIndex] == 0
+ && gScriptContestRank == 3
+ && (s16)gUnknown_02038678[gContestPlayerMonIndex] >= 800)
+ {
+ ribbon = TRUE;
+ SetMonData(&gPlayerParty[gUnknown_02038694], MON_DATA_ARTIST_RIBBON, &ribbon);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+u8 sub_80C5044(void)
+{
+ return gUnknown_0203856C;
+}
+
+void ShowContestEntryMonPic(void)
+{
+ const struct CompressedSpritePalette *palette;
+ u32 var1, var2;
+ u16 species;
+ u8 spriteId;
+ u8 taskId;
+
+ if(FindTaskIdByFunc(sub_80C5190) == 0xFF)
+ {
+ u8 left = CONTEST_ENTRY_PIC_LEFT;
+ u8 top = CONTEST_ENTRY_PIC_TOP;
+
+ MenuDrawTextWindow(left, top, 19, 13);
+ species = gContestMons[gSpecialVar_0x8006].species;
+ var1 = gContestMons[gSpecialVar_0x8006].unk38; // v2
+ var2 = gContestMons[gSpecialVar_0x8006].unk3C; // v3
+ taskId = CreateTask(sub_80C5190, 0x50);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = species;
+ HandleLoadSpecialPokePic(
+ &gMonFrontPicTable[species],
+ gMonFrontPicCoords[species].coords,
+ gMonFrontPicCoords[species].y_offset,
+ (u32)gUnknown_081FAF4C[0],
+ gUnknown_081FAF4C[1],
+ species,
+ var1);
+ palette = GetMonSpritePalStructFromOtIdPersonality(species, var2, var1);
+ LoadCompressedObjectPalette(palette);
+ GetMonSpriteTemplate_803C56C(species, 1);
+ gUnknown_02024E8C.paletteTag = palette->tag;
+ spriteId = CreateSprite(&gUnknown_02024E8C, 0x78, 0x40, 0);
+ gTasks[taskId].data[2] = spriteId;
+ gTasks[taskId].data[3] = left;
+ gTasks[taskId].data[4] = top;
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ gSprites[spriteId].oam.priority = 0;
+ }
+}
+
+void sub_80C5164(void)
+{
+ u8 taskId = FindTaskIdByFunc(sub_80C5190);
+
+ if(taskId != 0xFF)
+ gTasks[taskId].data[0]++;
+}
+
+void sub_80C5190(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ struct Sprite *sprite;
+
+ switch(task->data[0])
+ {
+ case 2:
+ sprite = &gSprites[task->data[2]];
+ FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum));
+
+ if(sprite->oam.affineMode)
+ FreeOamMatrix(sprite->oam.matrixNum);
+
+ DestroySprite(sprite);
+ task->data[0]++;
+ break;
+ case 0:
+ task->data[0]++;
+ break;
+ case 3:
+ MenuZeroFillWindowRect(task->data[3], task->data[4], task->data[3] + 9, task->data[4] + 10);
+ DestroyTask(taskId);
+ break;
+ case 1:
+ default:
+ break;
+ }
+}
+
+void ScriptGetMultiplayerId(void)
+{
+ if(gIsLinkContest & 1)
+ gScriptResult = GetMultiplayerId();
+ else
+ gScriptResult = 4;
+}
+
+void ScriptRandom(void)
+{
+ u16 random;
+ u16 *scriptPtr;
+
+ if(gIsLinkContest & 1)
+ {
+ gUnknown_03005D28 = 1103515245 * gUnknown_03005D28 + 24691;
+ random = gUnknown_03005D28 >> 16;
+ scriptPtr = &gScriptResult;
+ }
+ else
+ {
+ scriptPtr = &gScriptResult;
+ random = Random();
+ }
+ *scriptPtr = random % *scriptPtr;
+}
+
+void ScrSpecial_HealPlayerParty(void)
+{
+ u8 i, j;
+ u8 ppBonuses;
+ u8 arg[4];
+
+ // restore HP.
+ for(i = 0; i < gPlayerPartyCount; i++)
+ {
+ u16 maxHP = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP);
+ arg[0] = maxHP;
+ arg[1] = maxHP >> 8;
+ SetMonData(&gPlayerParty[i], MON_DATA_HP, arg);
+ ppBonuses = GetMonData(&gPlayerParty[i], MON_DATA_PP_BONUSES);
+
+ // restore PP.
+ for(j = 0; j < 4; j++)
+ {
+ arg[0] = CalculatePPWithBonus(GetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j), ppBonuses, j);
+ SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, arg);
+ }
+
+ // since status is u32, the four 0 assignments here are probably for safety to prevent undefined data from reaching SetMonData.
+ arg[0] = 0;
+ arg[1] = 0;
+ arg[2] = 0;
+ arg[3] = 0;
+ SetMonData(&gPlayerParty[i], MON_DATA_STATUS, arg);
+ }
+}
+
+u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 unused3)
+{
+ u16 nationalDexNum;
+ int sentToPc;
+ u8 heldItem[2];
+ struct Pokemon mon;
+
+ CreateMon(&mon, species, level, 32, 0, 0, 0, 0);
+ heldItem[0] = item;
+ heldItem[1] = item >> 8;
+ SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem);
+ sentToPc = GiveMonToPlayer(&mon);
+ nationalDexNum = SpeciesToNationalPokedexNum(species);
+
+ switch(sentToPc)
+ {
+ case 0:
+ case 1:
+ GetSetPokedexFlag(nationalDexNum, 2);
+ GetSetPokedexFlag(nationalDexNum, 3);
+ break;
+ }
+ return sentToPc;
+}
+
+u8 ScriptGiveEgg(u16 species)
+{
+ struct Pokemon mon;
+ u8 isEgg;
+
+ sub_8042044(&mon, species, 1);
+ isEgg = TRUE;
+ SetMonData(&mon, MON_DATA_IS_EGG, &isEgg);
+
+ return GiveMonToPlayer(&mon);
+}
+
+void CheckForAlivePartyMons(void)
+{
+ u8 var = sub_803DAA0();
+
+ switch(var)
+ {
+ case 1:
+ gScriptResult = var;
+ break;
+ case 0:
+ gScriptResult = var;
+ break;
+ case 2:
+ gScriptResult = var;
+ break;
+ }
+}
+
+bool8 CheckPartyMonHasHeldItem(u16 item)
+{
+ int i;
+
+ for(i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ if(species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM) == item)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 GetNameOfEnigmaBerryInPlayerParty(void)
+{
+ bool8 hasItem = CheckPartyMonHasHeldItem(ITEM_ENIGMA_BERRY);
+
+ if(hasItem == TRUE)
+ GetBerryNameByBerryType(ItemIdToBerryType(ITEM_ENIGMA_BERRY), gStringVar1);
+
+ return hasItem;
+}
+
+void CreateScriptedWildMon(u16 species, u8 level, u16 item)
+{
+ u8 heldItem[2];
+
+ ZeroEnemyPartyMons();
+ CreateMon(&gEnemyParty[0], species, level, 0x20, 0, 0, 0, 0);
+
+ if(item)
+ {
+ heldItem[0] = item;
+ heldItem[1] = item >> 8;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem);
+ }
+}
+
+void ScriptSetMonMoveSlot(u8 monIndex, u16 move, u8 slot)
+{
+ if(monIndex > 6)
+ monIndex = gPlayerPartyCount - 1;
+
+ SetMonMoveSlot(&gPlayerParty[monIndex], move, slot);
+}
+
+void sub_80C5568(void)
+{
+ gMain.savedCallback = sub_80C5580;
+ sub_8121E10();
+}
+
+void sub_80C5580(void)
+{
+ u8 var = gSelectedOrderFromParty[0];
+
+ switch(var)
+ {
+ case 0:
+ gScriptResult = 0;
+ break;
+ default:
+ gScriptResult = 1;
+ break;
+ }
+
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void ChooseBattleTowerPlayerParty(void)
+{
+ gMain.savedCallback = SetBattleTowerPlayerParty;
+ sub_8121E34();
+}
+
+void SetBattleTowerPlayerParty(void)
+{
+ u8 var = gSelectedOrderFromParty[0];
+
+ switch(var)
+ {
+ case 0: // player quit battle tower?
+ LoadPlayerParty();
+ gScriptResult = 0;
+ break;
+ default: // load battle tower.
+ ReducePlayerPartyToThree();
+ gScriptResult = 1;
+ break;
+ }
+
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void ReducePlayerPartyToThree(void)
+{
+ struct Pokemon party[3];
+ int i;
+
+ CpuFill32(0, party, sizeof party);
+
+ // copy the selected pokemon according to the order.
+ for(i = 0; i < 3; i++)
+ if(gSelectedOrderFromParty[i]) // as long as the order keeps going (did the player select 1 mon? 2? 3?), do not stop
+ party[i] = gPlayerParty[gSelectedOrderFromParty[i] - 1]; // index is 0 based, not literal
+
+ // delete the last 3 pokemon
+ CpuFill32(0, gPlayerParty, sizeof gPlayerParty);
+
+ // overwrite the first 3 with the order copied to.
+ for(i = 0; i < 3; i++)
+ gPlayerParty[i] = party[i];
+
+ CalculatePlayerPartyCount();
+}
diff --git a/src/misc/script_pokemon_util_80F99CC.c b/src/misc/script_pokemon_util_80F99CC.c
new file mode 100644
index 000000000..f930df8e2
--- /dev/null
+++ b/src/misc/script_pokemon_util_80F99CC.c
@@ -0,0 +1,444 @@
+#include "global.h"
+#include "battle_party_menu.h"
+#include "choose_party.h"
+#include "contest.h"
+#include "data2.h"
+#include "party_menu.h"
+#include "field_fadetransition.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "pokemon.h"
+#include "pokemon_summary_screen.h"
+#include "overworld.h"
+#include "script.h"
+#include "script_pokemon_80F9.h"
+#include "songs.h"
+#include "sound.h"
+#include "string_util.h"
+#include "task.h"
+#include "text.h"
+
+extern u8 gPlayerPartyCount;
+extern u16 gSpecialVar_0x8004;
+extern u16 gSpecialVar_0x8005;
+extern u8 gUnknown_02038694;
+extern u16 gScriptResult;
+
+extern void (*gFieldCallback)(void);
+
+void sub_80F99CC(void)
+{
+ u8 taskId;
+
+ ScriptContext2_Enable();
+ taskId = CreateTask((void *)sub_80F9A8C, 0xA);
+ gTasks[taskId].data[0] = 2;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+}
+
+void sub_80F9A0C(void)
+{
+ u8 taskId;
+
+ ScriptContext2_Enable();
+ taskId = CreateTask((void *)sub_80F9A8C, 0xA);
+ gTasks[taskId].data[0] = 3;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+}
+
+void sub_80F9A4C(void)
+{
+ u8 taskId;
+
+ ScriptContext2_Enable();
+ taskId = CreateTask((void *)sub_80F9A8C, 0xA);
+ gTasks[taskId].data[0] = 7;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+}
+
+void sub_80F9A8C(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gPaletteFade.bufferTransferDisabled = 1;
+ OpenPartyMenu((u8) gTasks[taskId].data[0], 0);
+ DestroyTask(taskId);
+ }
+}
+
+bool8 sub_80F9ACC(void)
+{
+ switch (EWRAM_1B000.unk264)
+ {
+ case 0:
+ if (EWRAM_1B000.unk266 < gPlayerPartyCount)
+ {
+ TryCreatePartyMenuMonIcon(EWRAM_1B000.unk260, EWRAM_1B000.unk266, &gPlayerParty[EWRAM_1B000.unk266]);
+ EWRAM_1B000.unk266++;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264++;
+ }
+ break;
+ case 1:
+ LoadHeldItemIconGraphics();
+ EWRAM_1B000.unk264++;
+ break;
+ case 2:
+ CreateHeldItemIcons_806DC34(EWRAM_1B000.unk260);
+ EWRAM_1B000.unk264++;
+ break;
+ case 3:
+ if (sub_806BD58(EWRAM_1B000.unk260, EWRAM_1B000.unk266) != 1)
+ {
+ EWRAM_1B000.unk266++;
+ break;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264++;
+ break;
+ }
+ case 4:
+ PartyMenuPrintMonsLevelOrStatus();
+ EWRAM_1B000.unk264++;
+ break;
+ case 5:
+ PrintPartyMenuMonNicknames();
+ EWRAM_1B000.unk264++;
+ break;
+ case 6:
+ sub_80F9C00();
+ EWRAM_1B000.unk264++;
+ break;
+ case 7: // the only case that can return true.
+ if (sub_806B58C(EWRAM_1B000.unk266) != 1)
+ {
+ EWRAM_1B000.unk266++;
+ break;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264 = 0;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_80F9C00(void)
+{
+ u8 i;
+
+ for (i = 0; i < gPlayerPartyCount; i++)
+ {
+ switch (sub_80AE47C(&gPlayerParty[i]))
+ {
+ case 0:
+ case 3:
+ case 4:
+ sub_806BC3C(i, 0x7E);
+ break;
+ case 1:
+ case 2:
+ sub_806BC3C(i, 0x70);
+ break;
+ }
+ }
+}
+
+void sub_80F9C6C(u8 var)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (sub_806BD80(var))
+ {
+ case 1:
+ PlaySE(SE_SELECT);
+ gUnknown_02038694 = sub_806CA38(var);
+ gSpecialVar_0x8004 = gUnknown_02038694;
+ sub_8123138(var);
+ break;
+ case 2:
+ PlaySE(SE_SELECT);
+ gUnknown_02038694 = 0xFF;
+ gSpecialVar_0x8004 = 0xFF;
+ sub_8123138(var);
+ break;
+ }
+ }
+}
+
+bool8 sub_80F9CE8(void) // this is the same function as sub_80F9ACC except case 6 calls a different function. why
+{
+ switch (EWRAM_1B000.unk264)
+ {
+ case 0:
+ if (EWRAM_1B000.unk266 < gPlayerPartyCount)
+ {
+ TryCreatePartyMenuMonIcon(EWRAM_1B000.unk260, EWRAM_1B000.unk266, &gPlayerParty[EWRAM_1B000.unk266]);
+ EWRAM_1B000.unk266++;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264++;
+ }
+ break;
+ case 1:
+ LoadHeldItemIconGraphics();
+ EWRAM_1B000.unk264++;
+ break;
+ case 2:
+ CreateHeldItemIcons_806DC34(EWRAM_1B000.unk260);
+ EWRAM_1B000.unk264++;
+ break;
+ case 3:
+ if (sub_806BD58(EWRAM_1B000.unk260, EWRAM_1B000.unk266) != 1)
+ {
+ EWRAM_1B000.unk266++;
+ break;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264++;
+ break;
+ }
+ case 4:
+ PartyMenuPrintMonsLevelOrStatus();
+ EWRAM_1B000.unk264++;
+ break;
+ case 5:
+ PrintPartyMenuMonNicknames();
+ EWRAM_1B000.unk264++;
+ break;
+ case 6:
+ sub_80F9E1C();
+ EWRAM_1B000.unk264++;
+ break;
+ case 7: // the only case that can return true.
+ if (sub_806B58C(EWRAM_1B000.unk266) != 1)
+ {
+ EWRAM_1B000.unk266++;
+ break;
+ }
+ else
+ {
+ EWRAM_1B000.unk266 = 0;
+ EWRAM_1B000.unk264 = 0;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_80F9E1C(void)
+{
+ u8 i;
+
+ for (i = 0; i < gPlayerPartyCount; i++)
+ {
+ if (!sub_8040574(&gPlayerParty[i]))
+ sub_806BC3C(i, 0x9A);
+ else
+ sub_806BC3C(i, 0x8C);
+ }
+}
+
+void sub_80F9E64(u8 var)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (sub_806BD80(var))
+ {
+ case 1:
+ PlaySE(SE_SELECT);
+ gSpecialVar_0x8004 = sub_806CA38(var);
+ gSpecialVar_0x8005 = sub_8040574(&gPlayerParty[gSpecialVar_0x8004]);
+ sub_8123138(var);
+ break;
+ case 2:
+ PlaySE(SE_SELECT);
+ gSpecialVar_0x8004 = 0xFF;
+ sub_8123138(var);
+ }
+ }
+}
+
+void sub_80F9EEC(void)
+{
+ sub_809D9F0(&gPlayerParty[0], gSpecialVar_0x8004, gPlayerPartyCount - 1, c2_exit_to_overworld_2_switch, 0);
+ unk_2018000.unk8 = 3;
+ gFieldCallback = sub_8080990;
+}
+
+void ScrSpecial_CountPokemonMoves(void) // count pokemon moves
+{
+ u8 i;
+
+ gScriptResult = 0;
+
+ for (i = 0; i < 4; i++) // checks MOVE1-MOVE4
+ if (GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_MOVE1 + i))
+ gScriptResult++;
+}
+
+void ScrSpecial_GetPokemonNicknameAndMoveName(void)
+{
+ struct Pokemon *pkmn = &gPlayerParty[gSpecialVar_0x8004];
+ u16 data = GetMonData(pkmn, MON_DATA_MOVE1 + gSpecialVar_0x8005);
+
+ GetMonNickname(pkmn, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[data]);
+}
+
+// no. hard
+__attribute__((naked))
+void sub_80F9FDC(struct Pokemon *party, u8 var, u8 var2)
+{
+ 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, 0x20\n\
+ mov r8, r0\n\
+ adds r5, r1, 0\n\
+ adds r4, r2, 0\n\
+ lsls r5, 24\n\
+ lsrs r5, 24\n\
+ lsls r4, 24\n\
+ lsrs r4, 24\n\
+ adds r0, r5, 0\n\
+ adds r0, 0xD\n\
+ str r0, [sp, 0x8]\n\
+ mov r0, r8\n\
+ ldr r1, [sp, 0x8]\n\
+ bl GetMonData\n\
+ mov r1, sp\n\
+ adds r1, 0x2\n\
+ str r1, [sp, 0x14]\n\
+ strh r0, [r1]\n\
+ adds r3, r4, 0\n\
+ adds r3, 0xD\n\
+ str r3, [sp, 0xC]\n\
+ mov r0, r8\n\
+ adds r1, r3, 0\n\
+ bl GetMonData\n\
+ mov r1, sp\n\
+ strh r0, [r1]\n\
+ adds r7, r5, 0\n\
+ adds r7, 0x11\n\
+ str r7, [sp, 0x10]\n\
+ mov r0, r8\n\
+ adds r1, r7, 0\n\
+ bl GetMonData\n\
+ mov r1, sp\n\
+ adds r1, 0x5\n\
+ str r1, [sp, 0x18]\n\
+ strb r0, [r1]\n\
+ adds r3, r4, 0\n\
+ adds r3, 0x11\n\
+ str r3, [sp, 0x1C]\n\
+ mov r0, r8\n\
+ adds r1, r3, 0\n\
+ bl GetMonData\n\
+ add r7, sp, 0x4\n\
+ mov r10, r7\n\
+ strb r0, [r7]\n\
+ mov r0, r8\n\
+ movs r1, 0x15\n\
+ bl GetMonData\n\
+ mov r6, sp\n\
+ adds r6, 0x6\n\
+ strb r0, [r6]\n\
+ ldr r1, _080FA0D8 @ =gUnknown_08208238\n\
+ adds r0, r5, r1\n\
+ ldrb r0, [r0]\n\
+ mov r9, r0\n\
+ ldrb r0, [r6]\n\
+ adds r2, r0, 0\n\
+ mov r3, r9\n\
+ ands r2, r3\n\
+ lsls r5, 1\n\
+ asrs r2, r5\n\
+ lsls r2, 24\n\
+ lsrs r2, 24\n\
+ adds r1, r4, r1\n\
+ ldrb r3, [r1]\n\
+ adds r1, r0, 0\n\
+ ands r1, r3\n\
+ lsls r4, 1\n\
+ asrs r1, r4\n\
+ lsls r1, 24\n\
+ lsrs r1, 24\n\
+ mov r7, r9\n\
+ bics r0, r7\n\
+ strb r0, [r6]\n\
+ ldrb r0, [r6]\n\
+ bics r0, r3\n\
+ strb r0, [r6]\n\
+ lsls r2, r4\n\
+ lsls r1, r5\n\
+ adds r2, r1\n\
+ ldrb r0, [r6]\n\
+ orrs r0, r2\n\
+ strb r0, [r6]\n\
+ mov r0, r8\n\
+ ldr r1, [sp, 0x8]\n\
+ mov r2, sp\n\
+ bl SetMonData\n\
+ mov r0, r8\n\
+ ldr r1, [sp, 0xC]\n\
+ ldr r2, [sp, 0x14]\n\
+ bl SetMonData\n\
+ mov r0, r8\n\
+ ldr r1, [sp, 0x10]\n\
+ mov r2, r10\n\
+ bl SetMonData\n\
+ mov r0, r8\n\
+ ldr r1, [sp, 0x1C]\n\
+ ldr r2, [sp, 0x18]\n\
+ bl SetMonData\n\
+ mov r0, r8\n\
+ movs r1, 0x15\n\
+ adds r2, r6, 0\n\
+ bl SetMonData\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\
+ .align 2, 0\n\
+_080FA0D8: .4byte gUnknown_08208238\n\
+ .syntax divided");
+}
+
+void sub_80FA0DC(void)
+{
+ u16 i;
+
+ SetMonMoveSlot(&gPlayerParty[gSpecialVar_0x8004], 0, gSpecialVar_0x8005);
+ RemoveMonPPBonus(&gPlayerParty[gSpecialVar_0x8004], gSpecialVar_0x8005);
+
+ for (i = gSpecialVar_0x8005; i < 3; i++)
+ sub_80F9FDC(&gPlayerParty[gSpecialVar_0x8004], i, i + 1);
+}
+
+void sub_80FA148(void)
+{
+ struct Pokemon *party = &gPlayerParty[gSpecialVar_0x8004];
+ gScriptResult = 0;
+
+ if (GetMonData(party, MON_DATA_IS_EGG))
+ gScriptResult = 1;
+}
diff --git a/src/misc/unknown_task.c b/src/misc/unknown_task.c
new file mode 100644
index 000000000..5ec7fa6bc
--- /dev/null
+++ b/src/misc/unknown_task.c
@@ -0,0 +1,248 @@
+#include "global.h"
+#include "data2.h"
+#include "task.h"
+#include "trig.h"
+#include "unknown_task.h"
+
+struct UnknownStruct1
+{
+ void *src[2];
+ volatile void *dest;
+ u32 unkC;
+ void (*unk10)(void);
+ u8 srcBank;
+ u8 unk15;
+ u8 unk16;
+ u8 unk17;
+ u8 taskId;
+ u8 filler19[0x7];
+};
+
+static void sub_80896F4(void);
+static void sub_8089714(void);
+
+extern u16 gUnknown_030041B0;
+extern u16 gUnknown_030041B4;
+extern u16 gUnknown_030041B8;
+extern u16 gUnknown_03004280;
+extern u16 gUnknown_03004288;
+extern u16 gUnknown_030042A0;
+extern u16 gUnknown_030042A4;
+extern u16 gUnknown_030042C0;
+
+extern u8 gUnknown_0202FFA4;
+
+extern struct UnknownStruct1 gUnknown_03004DC0;
+
+extern u16 gUnknown_03004DE0[][0x3C0];
+
+void remove_some_task(void)
+{
+ gUnknown_03004DC0.unk15 = 0;
+ DmaStop(0);
+ if (gUnknown_03004DC0.taskId != 0xFF)
+ {
+ DestroyTask(gUnknown_03004DC0.taskId);
+ gUnknown_03004DC0.taskId = 0xFF;
+ }
+}
+
+void dp12_8087EA4(void)
+{
+ CpuFill16(0, gUnknown_03004DE0, 0x780 * 2);
+ gUnknown_03004DC0.src[0] = 0;
+ gUnknown_03004DC0.src[1] = 0;
+ gUnknown_03004DC0.dest = 0;
+ gUnknown_03004DC0.unkC = 0;
+ gUnknown_03004DC0.srcBank = 0;
+ gUnknown_03004DC0.unk15 = 0;
+ gUnknown_03004DC0.unk16 = 0;
+ gUnknown_03004DC0.unk17 = 0;
+ gUnknown_03004DC0.taskId = 0xFF;
+}
+
+void sub_80895F8(struct UnknownTaskStruct unk)
+{
+ if (unk.control == (((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1))
+ {
+ gUnknown_03004DC0.src[0] = &gUnknown_03004DE0[0][1];
+ gUnknown_03004DC0.src[1] = &gUnknown_03004DE0[1][1];
+ gUnknown_03004DC0.unk10 = sub_80896F4;
+ }
+ else
+ {
+ gUnknown_03004DC0.src[0] = &gUnknown_03004DE0[0][2];
+ gUnknown_03004DC0.src[1] = &gUnknown_03004DE0[1][2];
+ gUnknown_03004DC0.unk10 = sub_8089714;
+ }
+
+ gUnknown_03004DC0.unkC = unk.control;
+ gUnknown_03004DC0.dest = unk.dest;
+ gUnknown_03004DC0.unk15 = unk.unk8;
+ gUnknown_03004DC0.unk16 = unk.unk9;
+ gUnknown_03004DC0.unk17 = unk.unk9;
+}
+
+void sub_8089668(void)
+{
+ if (gUnknown_03004DC0.unk15)
+ {
+ if (gUnknown_03004DC0.unk15 == 3)
+ {
+ gUnknown_03004DC0.unk15 = 0;
+ DmaStop(0);
+ gUnknown_0202FFA4 = 1;
+ }
+ else
+ {
+ DmaStop(0);
+ DmaSet(0, gUnknown_03004DC0.src[gUnknown_03004DC0.srcBank], gUnknown_03004DC0.dest, gUnknown_03004DC0.unkC);
+ gUnknown_03004DC0.unk10();
+ gUnknown_03004DC0.srcBank ^= 1;
+ }
+ }
+}
+
+static void sub_80896F4(void)
+{
+ u16 *dest = (u16 *)gUnknown_03004DC0.dest;
+ u16 *src = (u16 *)&gUnknown_03004DE0[gUnknown_03004DC0.srcBank];
+ *dest = *src;
+}
+
+static void sub_8089714(void)
+{
+ u32 *dest = (u32 *)gUnknown_03004DC0.dest;
+ u32 *src = (u32 *)&gUnknown_03004DE0[gUnknown_03004DC0.srcBank];
+ *dest = *src;
+}
+
+static void task00_for_dp12(u8 taskId)
+{
+ int value = 0;
+
+ if (gUnknown_0202FFA4)
+ {
+ DestroyTask(taskId);
+ gUnknown_03004DC0.taskId = 0xFF;
+ }
+ else
+ {
+ if (gTasks[taskId].data[7])
+ {
+ switch (gTasks[taskId].data[6])
+ {
+ case 0x0:
+ value = gUnknown_030042A4;
+ break;
+ case 0x2:
+ value = gUnknown_030042A0;
+ break;
+ case 0x4:
+ value = gUnknown_030042C0;
+ break;
+ case 0x6:
+ value = gUnknown_030041B4;
+ break;
+ case 0x8:
+ value = gUnknown_03004288;
+ break;
+ case 0xA:
+ value = gUnknown_03004280;
+ break;
+ case 0xC:
+ value = gUnknown_030041B0;
+ break;
+ case 0xE:
+ value = gUnknown_030041B8;
+ break;
+ }
+ }
+ if (gTasks[taskId].data[4])
+ {
+ int i;
+ int offset;
+ gTasks[taskId].data[4]--;
+ offset = gTasks[taskId].data[3] + 320;
+ for (i = gTasks[taskId].data[0]; i < gTasks[taskId].data[1]; i++)
+ {
+ gUnknown_03004DE0[gUnknown_03004DC0.srcBank][i] = gUnknown_03004DE0[0][offset] + value;
+ offset++;
+ }
+ }
+ else
+ {
+ int i;
+ int offset;
+ gTasks[taskId].data[4] = gTasks[taskId].data[5];
+ offset = gTasks[taskId].data[3] + 320;
+ for (i = gTasks[taskId].data[0]; i < gTasks[taskId].data[1]; i++)
+ {
+ gUnknown_03004DE0[gUnknown_03004DC0.srcBank][i] = gUnknown_03004DE0[0][offset] + value;
+ offset++;
+ }
+ gTasks[taskId].data[3]++;
+ if (gTasks[taskId].data[3] == gTasks[taskId].data[2])
+ {
+ gTasks[taskId].data[3] = 0;
+ }
+ }
+ }
+}
+
+static void sub_80898FC(u16 *a1, u8 a2, u8 a3, u8 a4)
+{
+ u16 i = 0;
+ u8 offset = 0;
+
+ while (i < 0x100)
+ {
+ a1[i] = (gSineTable[offset] * a3) / 256;
+ offset += a2;
+ i++;
+ }
+}
+
+u8 sub_8089944(u8 a1, u8 a2, u8 a3, u8 a4, u8 a5, u8 a6, u8 a7)
+{
+ int i;
+ int offset;
+ struct UnknownTaskStruct unk;
+ u8 taskId;
+
+ dp12_8087EA4();
+
+ unk.dest = (void *)(REG_ADDR_BG0HOFS + a6);
+ unk.control = ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1;
+ unk.unk8 = 1;
+ unk.unk9 = 0;
+
+ sub_80895F8(unk);
+
+ taskId = CreateTask(task00_for_dp12, 0);
+
+ gTasks[taskId].data[0] = a1;
+ gTasks[taskId].data[1] = a2;
+ gTasks[taskId].data[2] = 256 / a3;
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].data[4] = a5;
+ gTasks[taskId].data[5] = a5;
+ gTasks[taskId].data[6] = a6;
+ gTasks[taskId].data[7] = a7;
+
+ gUnknown_03004DC0.taskId = taskId;
+ gUnknown_0202FFA4 = 0;
+
+ sub_80898FC(&gUnknown_03004DE0[0][320], a3, a4, a2 - a1);
+
+ offset = 320;
+
+ for (i = a1; i < a2; i++)
+ {
+ gUnknown_03004DE0[0][i] = gUnknown_03004DE0[0][offset];
+ gUnknown_03004DE0[1][i] = gUnknown_03004DE0[0][offset];
+ offset++;
+ }
+
+ return taskId;
+}
diff --git a/src/misc/unused_8124F94.c b/src/misc/unused_8124F94.c
new file mode 100644
index 000000000..5f76fa92e
--- /dev/null
+++ b/src/misc/unused_8124F94.c
@@ -0,0 +1,126 @@
+#include "global.h"
+#include "decompress.h"
+#include "palette.h"
+
+struct UnknownStruct2
+{
+ void *src;
+ u8 unk4;
+ u8 unk5;
+ u8 unk6;
+ u16 unk8;
+};
+
+struct UnknownStruct3
+{
+ u16 *paletteSrc;
+ u8 unk4;
+ u8 paletteCount;
+};
+
+struct UnknownStruct1
+{
+ u8 paletteNum;
+ u8 unk1;
+ u16 unk2;
+ u8 *dest;
+ struct UnknownStruct3 unk8[16];
+ struct UnknownStruct2 unk88[32];
+};
+
+void unref_sub_8124F94(struct UnknownStruct1 *a)
+{
+ a->unk1 = 0;
+ a->paletteNum = 0;
+ a->unk2 = 0;
+ a->dest = (void *)VRAM;
+ DmaFill16(3, 0, a->unk8, sizeof(a->unk8));
+ DmaFill16(3, 0, a->unk88, sizeof(a->unk88));
+}
+
+u8 unref_sub_8124FD8(struct UnknownStruct1 *a, const struct UnknownStruct2 *b)
+{
+ while (1)
+ {
+ s32 r6;
+ s32 temp;
+
+ // Couldn't get it to match any other way
+ if (a->unk1 < 32 && b->src == NULL)
+ return 0;
+ if (a->unk1 >= 32)
+ break;
+
+ a->unk88[a->unk1].src = b->src;
+ a->unk88[a->unk1].unk6 = b->unk6;
+ a->unk88[a->unk1].unk4 = b->unk4;
+ a->unk88[a->unk1].unk5 = b->unk5;
+ r6 = b->unk4 * b->unk5;
+ if (a->unk2 + r6 > 0x400)
+ return 2;
+ if (b->unk8 == 0)
+ {
+ DmaCopy16(3, b->src, a->dest + a->unk2 * 64, r6 * 32);
+ }
+ else
+ {
+ LZDecompressWram(b->src, a->dest + a->unk2 * 64);
+ }
+ a->unk88[a->unk1].unk8 = a->unk2;
+ temp = r6 + a->unk2;
+ a->unk2 = temp;
+ a->unk1++;
+ b++;
+ }
+ return 1;
+}
+
+u8 unref_sub_81250A4(struct UnknownStruct1 *a, struct UnknownStruct3 *b)
+{
+ while (1)
+ {
+ // Couldn't get it to match any other way
+ if (a->paletteNum < 16 && b->paletteSrc == NULL)
+ return 0;
+ if (a->paletteNum >= 16)
+ break;
+
+ a->unk8[a->paletteNum].paletteSrc = b->paletteSrc;
+ a->unk8[a->paletteNum].unk4 = b->unk4;
+ if (b->paletteCount == 0)
+ {
+ LoadPalette(b->paletteSrc, a->paletteNum * 16, 32);
+ }
+ else
+ {
+ u16 palette[16];
+
+ LZDecompressWram(b->paletteSrc, palette);
+ LoadPalette(palette, a->paletteNum * 16, 32);
+ }
+ a->unk8[a->paletteNum].paletteCount = a->paletteNum;
+ a->paletteNum = a->paletteNum + 1;
+ b++;
+ }
+ return 1;
+}
+
+u8 unref_sub_8125118(struct UnknownStruct1 *a, struct UnknownStruct3 *b)
+{
+ u16 palettes[16][16] = {0};
+ u8 r7 = b->paletteCount;
+ u8 i;
+
+ LZDecompressWram(b->paletteSrc, palettes);
+ for (i = a->paletteNum; i < r7; i++)
+ {
+ if (a->paletteNum + i >= 16)
+ return 1;
+ a->unk8[i].paletteSrc = b->paletteSrc;
+ a->unk8[i].unk4 = b->unk4 + i;
+ a->unk8[i].paletteCount = a->paletteNum;
+ LoadPalette(palettes[i], a->paletteNum * 16, sizeof(palettes[i]));
+ a->paletteNum++;
+ }
+ return 0;
+}