summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_anim.c8
-rw-r--r--src/battle_anim_80A5C6C.c1742
2 files changed, 1735 insertions, 15 deletions
diff --git a/src/battle_anim.c b/src/battle_anim.c
index fa782d661..4989b0fb2 100644
--- a/src/battle_anim.c
+++ b/src/battle_anim.c
@@ -681,7 +681,7 @@ void sub_80A438C(u8 battlerId, bool8 toBG_2, bool8 setSpriteInvisible)
}
sub_80A6B30(&unknownStruct);
- CpuFill16(0, unknownStruct.unk0, 0x1000);
+ CpuFill16(0, unknownStruct.bgTiles, 0x1000);
CpuFill16(0xFF, unknownStruct.unk4, 0x800);
SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2);
@@ -709,7 +709,7 @@ void sub_80A438C(u8 battlerId, bool8 toBG_2, bool8 setSpriteInvisible)
else
battlerPosition = GetBattlerPosition(battlerId);
- sub_8118FBC(1, 0, 0, battlerPosition, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA);
+ sub_8118FBC(1, 0, 0, battlerPosition, unknownStruct.unk8, unknownStruct.bgTiles, unknownStruct.unk4, unknownStruct.tilesOffset);
if (IsContest())
sub_80A46A0();
@@ -719,7 +719,7 @@ void sub_80A438C(u8 battlerId, bool8 toBG_2, bool8 setSpriteInvisible)
RequestDma3Fill(0, (void*)(VRAM + 0x6000), 0x2000, 1);
RequestDma3Fill(0, (void*)(VRAM + 0xF000), 0x1000, 1);
sub_80A6B90(&unknownStruct, 2);
- CpuFill16(0, unknownStruct.unk0 + 0x1000, 0x1000);
+ CpuFill16(0, unknownStruct.bgTiles + 0x1000, 0x1000);
CpuFill16(0, unknownStruct.unk4 + 0x400, 0x800);
SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2);
SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 1);
@@ -739,7 +739,7 @@ void sub_80A438C(u8 battlerId, bool8 toBG_2, bool8 setSpriteInvisible)
LoadPalette(&gPlttBufferUnfaded[0x100 + battlerId * 16], 0x90, 0x20);
CpuCopy32(&gPlttBufferUnfaded[0x100 + battlerId * 16], (void*)(BG_PLTT + 0x120), 0x20);
- sub_8118FBC(2, 0, 0, GetBattlerPosition(battlerId), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA);
+ sub_8118FBC(2, 0, 0, GetBattlerPosition(battlerId), unknownStruct.unk8, unknownStruct.bgTiles + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.tilesOffset);
}
}
diff --git a/src/battle_anim_80A5C6C.c b/src/battle_anim_80A5C6C.c
index 46e1e5b71..f799b091b 100644
--- a/src/battle_anim_80A5C6C.c
+++ b/src/battle_anim_80A5C6C.c
@@ -14,12 +14,15 @@
#include "trig.h"
#include "util.h"
#include "gpu_regs.h"
+#include "bg.h"
+#include "malloc.h"
+#include "dma3.h"
-#define GET_UNOWN_LETTER(personality) ((\
+#define GET_UNOWN_LETTER(personality) (( \
(((personality & 0x03000000) >> 24) << 6) \
| (((personality & 0x00030000) >> 16) << 4) \
- | (((personality & 0x00000300) >> 8) << 2) \
- | (((personality & 0x00000003) >> 0) << 0) \
+ | (((personality & 0x00000300) >> 8) << 2) \
+ | (((personality & 0x00000003) >> 0) << 0) \
) % 28)
#define IS_DOUBLE_BATTLE() ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
@@ -28,15 +31,37 @@ extern const struct OamData gUnknown_0852497C;
extern const struct MonCoords gMonFrontPicCoords[];
extern const struct MonCoords gMonBackPicCoords[];
extern const u8 gEnemyMonElevation[];
+extern const struct CompressedSpriteSheet gMonFrontPicTable[];
+extern const union AffineAnimCmd *gUnknown_082FF6C0[];
// This file's functions.
void sub_80A64EC(struct Sprite *sprite);
void sub_80A653C(struct Sprite *sprite);
void InitAnimLinearTranslation(struct Sprite *sprite);
-bool8 TranslateAnimLinear(struct Sprite *sprite);
+void sub_80A6E14(struct Sprite *sprite);
+void sub_80A6FB4(struct Sprite *sprite);
+void sub_80A6F98(struct Sprite *sprite);
+void sub_80A7144(struct Sprite *sprite);
+void sub_80A791C(struct Sprite *sprite);
+void sub_80A8DFC(struct Sprite *sprite);
+void sub_80A8E88(struct Sprite *sprite);
+void sub_80A7E6C(u8 spriteId);
+u16 sub_80A7F18(u8 spriteId);
+void AnimTask_BlendMonInAndOutSetup(struct Task *task);
+void sub_80A7AFC(u8 taskId);
+void sub_80A8CAC(u8 taskId);
+void AnimTask_BlendMonInAndOutStep(u8 taskId);
+bool8 sub_80A7238(void);
+void sub_80A8048(s16 *bottom, s16 *top, const void *ptr);
+void *sub_80A8050(s16 bottom, s16 top);
+u8 sub_80A82E4(u8 battlerId);
+void sub_80A8D78(struct Task *task, u8 taskId);
+
+// EWRAM vars
+EWRAM_DATA static union AffineAnimCmd *gUnknown_02038444 = NULL;
// Const rom data
-const struct UCoords8 sBattlerCoords[][4] =
+static const struct UCoords8 sBattlerCoords[][4] =
{
{
{ 72, 80 },
@@ -61,7 +86,7 @@ const struct MonCoords gCastformFrontSpriteCoords[] =
{ 0x86, 8 }, // HAIL
};
-const u8 gCastformElevations[] =
+static const u8 sCastformElevations[] =
{
13, // NORMAL
14, // SUN
@@ -70,7 +95,7 @@ const u8 gCastformElevations[] =
};
// Y position of the backsprite for each of the four Castform forms.
-const u8 gCastformBackSpriteYCoords[] =
+static const u8 sCastformBackSpriteYCoords[] =
{
0, // NORMAL
0, // SUN
@@ -78,7 +103,7 @@ const u8 gCastformBackSpriteYCoords[] =
0, // HAIL
};
-const struct SpriteTemplate gUnknown_08525F90[] =
+static const struct SpriteTemplate sUnknown_08525F90[] =
{
{
.tileTag = 55125,
@@ -100,7 +125,7 @@ const struct SpriteTemplate gUnknown_08525F90[] =
}
};
-const struct SpriteSheet gUnknown_08525FC0[] =
+static const struct SpriteSheet sUnknown_08525FC0[] =
{
{ gMiscBlank_Gfx, 0x800, 55125, },
{ gMiscBlank_Gfx, 0x800, 55126, },
@@ -203,7 +228,7 @@ u8 GetBattlerYDelta(u8 battlerId, u16 species)
}
else if (species == SPECIES_CASTFORM)
{
- ret = gCastformBackSpriteYCoords[gBattleMonForms[battlerId]];
+ ret = sCastformBackSpriteYCoords[gBattleMonForms[battlerId]];
}
else if (species > NUM_SPECIES)
{
@@ -254,7 +279,7 @@ u8 GetBattlerElevation(u8 battlerId, u16 species)
if (!IsContest())
{
if (species == SPECIES_CASTFORM)
- ret = gCastformElevations[gBattleMonForms[battlerId]];
+ ret = sCastformElevations[gBattleMonForms[battlerId]];
else if (species > NUM_SPECIES)
ret = gEnemyMonElevation[0];
else
@@ -739,3 +764,1698 @@ bool8 TranslateAnimArc(struct Sprite *sprite)
sprite->pos2.y += Sin((u8)(sprite->data[7] >> 8), sprite->data[5]);
return FALSE;
}
+
+bool8 sub_80A6934(struct Sprite *sprite)
+{
+ if (TranslateAnimLinear(sprite))
+ return TRUE;
+ sprite->data[7] += sprite->data[6];
+ sprite->pos2.x += Sin((u8)(sprite->data[7] >> 8), sprite->data[5]);
+ 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_80A6980(struct Sprite *sprite, bool8 a2)
+{
+ if (!a2)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, 0);
+ sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, 1);
+ }
+ sub_80A6864(sprite, gBattleAnimArgs[0]);
+ sprite->pos1.y += gBattleAnimArgs[1];
+}
+
+void sub_80A69CC(struct Sprite *sprite, u8 a2)
+{
+ if (!a2)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimAttacker, 0);
+ sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimAttacker, 1);
+ }
+ else
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimAttacker, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimAttacker, 3);
+ }
+ sub_80A6864(sprite, gBattleAnimArgs[0]);
+ sprite->pos1.y += gBattleAnimArgs[1];
+}
+
+u8 GetBattlerSide(u8 battlerId)
+{
+ return GET_BATTLER_SIDE2(battlerId);
+}
+
+u8 GetBattlerPosition(u8 battlerId)
+{
+ return GET_BATTLER_POSITION(battlerId);
+}
+
+u8 GetBattlerAtPosition(u8 position)
+{
+ u8 i;
+
+ for (i = 0; i < gBattlersCount; i++)
+ {
+ if (gBattlerPositions[i] == position)
+ break;
+ }
+ return i;
+}
+
+bool8 IsBattlerSpritePresent(u8 battlerId)
+{
+ if (IsContest())
+ {
+ if (gBattleAnimAttacker == battlerId)
+ return TRUE;
+ else if (gBattleAnimTarget == battlerId)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ {
+ if (gBattlerPositions[battlerId] == 0xff)
+ {
+ return FALSE;
+ }
+ else if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
+ {
+ if (GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) != 0)
+ return TRUE;
+ }
+ else
+ {
+ if (GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) != 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool8 IsDoubleBattle()
+{
+ return IS_DOUBLE_BATTLE();
+}
+
+void sub_80A6B30(struct UnknownAnimStruct2 *unk)
+{
+ if (IsContest())
+ {
+ unk->bgTiles = gUnknown_0202305C;
+ unk->unk4 = (u16 *)gUnknown_02023060;
+ unk->unk8 = 0xe;
+ unk->bgId = 1;
+ unk->tilesOffset = 0;
+ unk->unkC = 0;
+ }
+ else
+ {
+ unk->bgTiles = gUnknown_0202305C;
+ unk->unk4 = (u16 *)gUnknown_02023060;
+ unk->unk8 = 0x8;
+ unk->bgId = 1;
+ unk->tilesOffset = 0x200;
+ unk->unkC = 0;
+ }
+}
+
+void sub_80A6B90(struct UnknownAnimStruct2 *unk, u32 arg1)
+{
+ if (IsContest())
+ {
+ unk->bgTiles = gUnknown_0202305C;
+ unk->unk4 = (u16 *)gUnknown_02023060;
+ unk->unk8 = 0xe;
+ unk->bgId = 1;
+ unk->tilesOffset = 0;
+ unk->unkC = 0;
+ }
+ else if (arg1 == 1)
+ {
+ sub_80A6B30(unk);
+ }
+ else
+ {
+ unk->bgTiles = gUnknown_0202305C;
+ unk->unk4 = (u16 *)gUnknown_02023060;
+ unk->unk8 = 0x9;
+ unk->bgId = 2;
+ unk->tilesOffset = 0x300;
+ unk->unkC = 0;
+ }
+}
+
+void sub_80A6BFC(struct UnknownAnimStruct2 *unk)
+{
+ unk->bgTiles = gUnknown_0202305C;
+ unk->unk4 = (u16 *)gUnknown_02023060;
+ if (IsContest())
+ {
+ unk->unk8 = 0xe;
+ unk->bgId = 1;
+ unk->tilesOffset = 0;
+ unk->unkC = 0;
+ }
+ else if (sub_80A8364(gBattleAnimAttacker) == 1)
+ {
+ unk->unk8 = 8;
+ unk->bgId = 1;
+ unk->tilesOffset = 0x200;
+ unk->unkC = 0;
+ }
+ else
+ {
+ unk->unk8 = 0x9;
+ unk->bgId = 2;
+ unk->tilesOffset = 0x300;
+ unk->unkC = 0;
+ }
+}
+
+void sub_80A6C68(u32 arg0)
+{
+ struct UnknownAnimStruct2 unkStruct;
+
+ sub_80A6B90(&unkStruct, arg0);
+ CpuFill32(0, unkStruct.bgTiles, 0x2000);
+ LoadBgTiles(unkStruct.bgId, unkStruct.bgTiles, 0x2000, unkStruct.tilesOffset);
+ FillBgTilemapBufferRect(unkStruct.bgId, 0, 0, 0, 0x20, 0x40, 0x11);
+ CopyBgTilemapBufferToVram(unkStruct.bgId);
+}
+
+void sub_80A6CC0(u32 bgId, void *src, u32 tilesOffset)
+{
+ CpuFill32(0, gUnknown_0202305C, 0x2000);
+ LZDecompressWram(src, gUnknown_0202305C);
+ LoadBgTiles(bgId, gUnknown_0202305C, 0x2000, tilesOffset);
+}
+
+void sub_80A6D10(u32 bgId, const void *src)
+{
+ FillBgTilemapBufferRect(bgId, 0, 0, 0, 0x20, 0x40, 0x11);
+ CopyToBgTilemapBuffer(bgId, src, 0, 0);
+}
+
+void sub_80A6D48(u32 bgId, const void *src)
+{
+ sub_80A6D10(bgId, src);
+ CopyBgTilemapBufferToVram(bgId);
+}
+
+void sub_80A6D60(struct UnknownAnimStruct2 *unk, const void *src, u32 arg2)
+{
+ sub_80A6D10(unk->bgId, src);
+ if (IsContest() == TRUE)
+ sub_80A4720(unk->unk8, unk->unk4, 0, arg2);
+ CopyBgTilemapBufferToVram(unk->bgId);
+}
+
+u8 sub_80A6D94(void)
+{
+ if (IsContest())
+ return 1;
+ else
+ return 2;
+}
+
+void sub_80A6DAC(bool8 arg0)
+{
+ if (!arg0 || IsContest())
+ {
+ SetAnimBgAttribute(3, BG_ANIM_SCREEN_SIZE, 0);
+ SetAnimBgAttribute(3, BG_ANIM_AREA_OVERFLOW_MODE, 1);
+ }
+ else
+ {
+ SetAnimBgAttribute(3, BG_ANIM_SCREEN_SIZE, 1);
+ SetAnimBgAttribute(3, BG_ANIM_AREA_OVERFLOW_MODE, 0);
+ }
+}
+
+void sub_80A6DEC(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ sub_80A6E14(sprite);
+ sprite->callback = sub_80A65A8;
+ sprite->callback(sprite);
+}
+
+void sub_80A6E14(struct Sprite *sprite)
+{
+ s16 x = (sprite->data[2] - sprite->data[1]) << 8;
+ s16 y = (sprite->data[4] - sprite->data[3]) << 8;
+ sprite->data[1] = x / sprite->data[0];
+ sprite->data[2] = y / sprite->data[0];
+ sprite->data[4] = 0;
+ sprite->data[3] = 0;
+}
+
+void InitAnimLinearTranslation(struct Sprite *sprite)
+{
+ int x = sprite->data[2] - sprite->data[1];
+ int y = sprite->data[4] - sprite->data[3];
+ bool8 movingLeft = x < 0;
+ bool8 movingUp = y < 0;
+ u16 xDelta = abs(x) << 8;
+ u16 yDelta = abs(y) << 8;
+
+ xDelta = xDelta / sprite->data[0];
+ yDelta = yDelta / sprite->data[0];
+
+ if (movingLeft)
+ xDelta |= 1;
+ else
+ xDelta &= ~1;
+
+ if (movingUp)
+ yDelta |= 1;
+ else
+ yDelta &= ~1;
+
+ sprite->data[1] = xDelta;
+ sprite->data[2] = yDelta;
+ sprite->data[4] = 0;
+ sprite->data[3] = 0;
+}
+
+void sub_80A6EEC(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ InitAnimLinearTranslation(sprite);
+ sprite->callback = sub_80A6F98;
+ sprite->callback(sprite);
+}
+
+void sub_80A6F14(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ InitAnimLinearTranslation(sprite);
+ sprite->callback = sub_80A6FB4;
+ sprite->callback(sprite);
+}
+
+bool8 TranslateAnimLinear(struct Sprite *sprite)
+{
+ u16 v1, v2, x, y;
+
+ if (!sprite->data[0])
+ return TRUE;
+
+ v1 = sprite->data[1];
+ v2 = sprite->data[2];
+ x = sprite->data[3];
+ y = sprite->data[4];
+ 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->data[3] = x;
+ sprite->data[4] = y;
+ sprite->data[0]--;
+ return FALSE;
+}
+
+void sub_80A6F98(struct Sprite *sprite)
+{
+ if (TranslateAnimLinear(sprite))
+ SetCallbackToStoredInData6(sprite);
+}
+
+void sub_80A6FB4(struct Sprite *sprite)
+{
+ sub_8039E9C(sprite);
+ if (TranslateAnimLinear(sprite))
+ SetCallbackToStoredInData6(sprite);
+}
+
+void sub_80A6FD4(struct Sprite *sprite)
+{
+ int v1 = abs(sprite->data[2] - sprite->data[1]) << 8;
+ sprite->data[0] = v1 / sprite->data[0];
+ InitAnimLinearTranslation(sprite);
+}
+
+void sub_80A7000(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ sub_80A6FD4(sprite);
+ sprite->callback = sub_80A6F98;
+ sprite->callback(sprite);
+}
+
+void sub_80A7028(struct Sprite *sprite)
+{
+ int x = sprite->data[2] - sprite->data[1];
+ int y = sprite->data[4] - sprite->data[3];
+ bool8 x_sign = x < 0;
+ bool8 y_sign = y < 0;
+ u16 x2 = abs(x) << 4;
+ u16 y2 = abs(y) << 4;
+
+ x2 /= sprite->data[0];
+ y2 /= sprite->data[0];
+
+ if (x_sign)
+ x2 |= 1;
+ else
+ x2 &= ~1;
+
+ if (y_sign)
+ y2 |= 1;
+ else
+ y2 &= ~1;
+
+ sprite->data[1] = x2;
+ sprite->data[2] = y2;
+ sprite->data[4] = 0;
+ sprite->data[3] = 0;
+}
+
+void sub_80A70C0(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ sub_80A7028(sprite);
+ sprite->callback = sub_80A7144;
+ sprite->callback(sprite);
+}
+
+bool8 sub_80A70E8(struct Sprite *sprite)
+{
+ u16 v1, v2, x, y;
+
+ if (!sprite->data[0])
+ return TRUE;
+
+ v1 = sprite->data[1];
+ v2 = sprite->data[2];
+ x = sprite->data[3];
+ y = sprite->data[4];
+ 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->data[3] = x;
+ sprite->data[4] = y;
+ sprite->data[0]--;
+ return FALSE;
+}
+
+void sub_80A7144(struct Sprite *sprite)
+{
+ if (sub_80A70E8(sprite))
+ SetCallbackToStoredInData6(sprite);
+}
+
+void sub_80A7160(struct Sprite *sprite)
+{
+ int v1 = abs(sprite->data[2] - sprite->data[1]) << 4;
+ sprite->data[0] = v1 / sprite->data[0];
+ sub_80A7028(sprite);
+}
+
+void sub_80A718C(struct Sprite *sprite)
+{
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[3] = sprite->pos1.y;
+ sub_80A7160(sprite);
+ sprite->callback = sub_80A7144;
+ sprite->callback(sprite);
+}
+
+void obj_id_set_rotscale(u8 spriteId, 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_80A7238())
+ src.xScale = -src.xScale;
+ i = gSprites[spriteId].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_80A7238(void)
+{
+ if (IsContest())
+ {
+ if (gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].data[2] == SPECIES_UNOWN)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void sub_80A7270(u8 spriteId, u8 objMode)
+{
+ u8 battlerId = gSprites[spriteId].data[0];
+
+ if (IsContest() || IsBattlerSpriteVisible(battlerId))
+ gSprites[spriteId].invisible = FALSE;
+ gSprites[spriteId].oam.objMode = objMode;
+ gSprites[spriteId].affineAnimPaused = TRUE;
+ if (!IsContest() && !gSprites[spriteId].oam.affineMode)
+ gSprites[spriteId].oam.matrixNum = gBattleSpritesDataPtr->healthBoxesData[battlerId].field_6;
+ gSprites[spriteId].oam.affineMode = 3;
+ CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode);
+}
+
+void sub_80A7344(u8 spriteId)
+{
+ obj_id_set_rotscale(spriteId, 0x100, 0x100, 0);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.objMode = 0;
+ gSprites[spriteId].affineAnimPaused = FALSE;
+ CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode);
+}
+
+void sub_80A73A0(u8 spriteId)
+{
+ u16 matrix = gSprites[spriteId].oam.matrixNum;
+ s16 c = gOamMatrices[matrix].c;
+
+ if (c < 0)
+ c = -c;
+ gSprites[spriteId].pos2.y = c >> 3;
+}
+
+// related to obj_id_set_rotscale
+void sub_80A73E0(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_80A7238())
+ 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_80A749C(struct Sprite *sprite)
+{
+ sub_80A73E0(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 ArcTan2Neg(s16 a, s16 b)
+{
+ u16 var = ArcTan2_(a, b);
+ return -var;
+}
+
+void sub_80A750C(u16 a1, bool8 a2)
+{
+ int i;
+ struct PlttData *c;
+ struct PlttData *c2;
+ u16 average;
+
+ a1 *= 0x10;
+
+ if (!a2)
+ {
+ for (i = 0; i < 0x10; i++)
+ {
+ c = (struct PlttData *)&gPlttBufferUnfaded[a1 + i];
+ average = c->r + c->g + c->b;
+ average /= 3;
+
+ c2 = (struct PlttData *)&gPlttBufferFaded[a1 + i];
+ c2->r = average;
+ c2->g = average;
+ c2->b = average;
+ }
+ }
+ else
+ {
+ CpuCopy32(&gPlttBufferUnfaded[a1], &gPlttBufferFaded[a1], 0x20);
+ }
+}
+
+u32 sub_80A75AC(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_80A6D94();
+ }
+ if (a2)
+ {
+ shift = gBattleAnimAttacker + 16;
+ var |= 1 << shift;
+ }
+ if (a3) {
+ shift = gBattleAnimTarget + 16;
+ var |= 1 << shift;
+ }
+ if (a4)
+ {
+ if (IsBattlerSpriteVisible(gBattleAnimAttacker ^ 2))
+ {
+ shift = (gBattleAnimAttacker ^ 2) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a5)
+ {
+ if (IsBattlerSpriteVisible(gBattleAnimTarget ^ 2))
+ {
+ shift = (gBattleAnimTarget ^ 2) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a6)
+ {
+ if (!IsContest())
+ var |= 0x100;
+ else
+ var |= 0x4000;
+ }
+ if (a7)
+ {
+ if (!IsContest())
+ var |= 0x200;
+ }
+ return var;
+}
+
+u32 sub_80A76C4(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 (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)))
+ {
+ var |= 1 << (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) + 16);
+ }
+ }
+ if (a2)
+ {
+ if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)))
+ {
+ shift = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a3)
+ {
+ if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)))
+ {
+ shift = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT) + 16;
+ var |= 1 << shift;
+ }
+ }
+ if (a4)
+ {
+ if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)))
+ {
+ shift = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT) + 16;
+ var |= 1 << shift;
+ }
+ }
+ }
+ return var;
+}
+
+u8 sub_80A77AC(u8 a1)
+{
+ return a1;
+}
+
+u8 sub_80A77B4(u8 position)
+{
+ return GetBattlerAtPosition(position);
+}
+
+void sub_80A77C8(struct Sprite *sprite)
+{
+ bool8 var;
+
+ if (!sprite->data[0])
+ {
+ if (!gBattleAnimArgs[3])
+ var = TRUE;
+ else
+ var = FALSE;
+ if (!gBattleAnimArgs[2])
+ sub_80A69CC(sprite, var);
+ else
+ sub_80A6980(sprite, var);
+ sprite->data[0]++;
+
+ }
+ else if (sprite->animEnded || sprite->affineAnimEnded)
+ {
+ move_anim_8074EE0(sprite);
+ }
+}
+
+// Linearly translates a sprite to a target position on the
+// other mon's sprite.
+// arg 0: initial x offset
+// arg 1: initial y offset
+// arg 2: target x offset
+// arg 3: target y offset
+// arg 4: duration
+// arg 5: lower 8 bits = location on attacking mon, upper 8 bits = location on target mon pick to target
+void TranslateAnimSpriteToTargetMonLocation(struct Sprite *sprite)
+{
+ bool8 v1;
+ u8 attributeId;
+
+ if (!(gBattleAnimArgs[5] & 0xff00))
+ v1 = TRUE;
+ else
+ v1 = FALSE;
+
+ if (!(gBattleAnimArgs[5] & 0xff))
+ attributeId = BATTLER_COORD_3;
+ else
+ attributeId = BATTLER_COORD_Y;
+
+ sub_80A69CC(sprite, v1);
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2];
+ sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, attributeId) + gBattleAnimArgs[3];
+ sprite->callback = sub_80A6EEC;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+void sub_80A78AC(struct Sprite *sprite)
+{
+ sub_80A69CC(sprite, 1);
+ if (GetBattlerSide(gBattleAnimAttacker))
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2];
+ sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3];
+ sprite->data[5] = gBattleAnimArgs[5];
+ sub_80A68D4(sprite);
+ sprite->callback = sub_80A791C;
+}
+
+void sub_80A791C(struct Sprite *sprite)
+{
+ if (TranslateAnimArc(sprite))
+ DestroyAnimSprite(sprite);
+}
+
+void sub_80A7938(struct Sprite *sprite)
+{
+ bool8 r4;
+ u8 battlerId, attributeId;
+
+ if (!gBattleAnimArgs[6])
+ {
+ r4 = TRUE;
+ attributeId = BATTLER_COORD_3;
+ }
+ else
+ {
+ r4 = FALSE;
+ attributeId = BATTLER_COORD_Y;
+ }
+ if (!gBattleAnimArgs[5])
+ {
+ sub_80A69CC(sprite, r4);
+ battlerId = gBattleAnimAttacker;
+ }
+ else
+ {
+ sub_80A6980(sprite, r4);
+ battlerId = gBattleAnimTarget;
+ }
+ if (GetBattlerSide(gBattleAnimAttacker))
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ sub_80A6980(sprite, r4);
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[2] = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X_2) + gBattleAnimArgs[2];
+ sprite->data[4] = GetBattlerSpriteCoord(battlerId, attributeId) + gBattleAnimArgs[3];
+ sprite->callback = sub_80A6EEC;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+s16 duplicate_obj_of_side_rel2move_in_transparent_mode(u8 whichBattler)
+{
+ u16 i;
+ u8 spriteId = GetAnimBattlerSpriteId(whichBattler);
+
+ if (spriteId != 0xff)
+ {
+ for (i = 0; i < MAX_SPRITES; i++)
+ {
+ if (!gSprites[i].inUse)
+ {
+ gSprites[i] = gSprites[spriteId];
+ 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_80A7A74(u8 taskId)
+{
+ 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[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = gBattleAnimArgs[4];
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[3] = gBattleAnimArgs[0];
+ gTasks[taskId].data[4] = gBattleAnimArgs[1];
+ gTasks[taskId].data[5] = v2;
+ gTasks[taskId].data[6] = v1;
+ gTasks[taskId].data[7] = gBattleAnimArgs[2];
+ gTasks[taskId].data[8] = gBattleAnimArgs[3];
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gBattleAnimArgs[0], gBattleAnimArgs[1]));
+ gTasks[taskId].func = sub_80A7AFC;
+}
+
+void sub_80A7AFC(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];
+ }
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4]));
+ if (task->data[3] == task->data[7] && task->data[4] == task->data[8])
+ {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ }
+}
+
+// Linearly blends a mon's sprite colors with a target color with increasing
+// strength, and then blends out to the original color.
+// arg 0: anim bank
+// arg 1: blend color
+// arg 2: target blend coefficient
+// arg 3: initial delay
+// arg 4: number of times to blend in and out
+void AnimTask_BlendMonInAndOut(u8 task)
+{
+ u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
+ if (spriteId == 0xff)
+ {
+ DestroyAnimVisualTask(task);
+ return;
+ }
+ gTasks[task].data[0] = (gSprites[spriteId].oam.paletteNum * 0x10) + 0x101;
+ AnimTask_BlendMonInAndOutSetup(&gTasks[task]);
+}
+
+void AnimTask_BlendMonInAndOutSetup(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 = AnimTask_BlendMonInAndOutStep;
+}
+
+void AnimTask_BlendMonInAndOutStep(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], 15, 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], 15, 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_80A7CB4(u8 task)
+{
+ u8 palette = IndexOfSpritePaletteTag(gBattleAnimArgs[0]);
+
+ if (palette == 0xff)
+ {
+ DestroyAnimVisualTask(task);
+ return;
+ }
+ gTasks[task].data[0] = (palette * 0x10) + 0x101;
+ AnimTask_BlendMonInAndOutSetup(&gTasks[task]);
+}
+
+void sub_80A7CFC(struct Task *task, u8 a2, const 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_80A8048(&task->data[13], &task->data[14], a3);
+ sub_80A7270(a2, 0);
+}
+
+bool8 sub_80A7D34(struct Task *task)
+{
+ gUnknown_02038444 = sub_80A8050(task->data[13], task->data[14]) + (task->data[7] << 3);
+ switch (gUnknown_02038444->type)
+ {
+ default:
+ if (!gUnknown_02038444->frame.duration)
+ {
+ task->data[10] = gUnknown_02038444->frame.xScale;
+ task->data[11] = gUnknown_02038444->frame.yScale;
+ task->data[12] = gUnknown_02038444->frame.rotation;
+ task->data[7]++;
+ gUnknown_02038444++;
+ }
+ task->data[10] += gUnknown_02038444->frame.xScale;
+ task->data[11] += gUnknown_02038444->frame.yScale;
+ task->data[12] += gUnknown_02038444->frame.rotation;
+ obj_id_set_rotscale(task->data[15], task->data[10], task->data[11], task->data[12]);
+ sub_80A7E6C(task->data[15]);
+ if (++task->data[8] >= gUnknown_02038444->frame.duration)
+ {
+ task->data[8] = 0;
+ task->data[7]++;
+ }
+ break;
+ case AFFINEANIMCMDTYPE_JUMP:
+ task->data[7] = gUnknown_02038444->jump.target;
+ break;
+ case AFFINEANIMCMDTYPE_LOOP:
+ if (gUnknown_02038444->loop.count)
+ {
+ if (task->data[9])
+ {
+ if (!--task->data[9])
+ {
+ task->data[7]++;
+ break;
+ }
+ }
+ else
+ {
+ task->data[9] = gUnknown_02038444->loop.count;
+ }
+ if (!task->data[7])
+ {
+ break;
+ }
+ for (;;)
+ {
+ task->data[7]--;
+ gUnknown_02038444--;
+ if (gUnknown_02038444->type == AFFINEANIMCMDTYPE_LOOP)
+ {
+ task->data[7]++;
+ return TRUE;
+ }
+ if (!task->data[7])
+ return TRUE;
+ }
+ }
+ task->data[7]++;
+ break;
+ case AFFINEANIMCMDTYPE_END:
+ gSprites[task->data[15]].pos2.y = 0;
+ sub_80A7344(task->data[15]);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void sub_80A7E6C(u8 spriteId)
+{
+ int var = 0x40 - sub_80A7F18(spriteId) * 2;
+ u16 matrix = gSprites[spriteId].oam.matrixNum;
+ int var2 = (var << 8) / gOamMatrices[matrix].d;
+
+ if (var2 > 0x80)
+ var2 = 0x80;
+ gSprites[spriteId].pos2.y = (var - var2) / 2;
+}
+
+void sub_80A7EC0(u8 spriteId, u8 spriteId2)
+{
+ int var = 0x40 - sub_80A7F18(spriteId2) * 2;
+ u16 matrix = gSprites[spriteId].oam.matrixNum;
+ int var2 = (var << 8) / gOamMatrices[matrix].d;
+
+ if (var2 > 0x80)
+ var2 = 0x80;
+ gSprites[spriteId].pos2.y = (var - var2) / 2;
+}
+
+u16 sub_80A7F18(u8 spriteId)
+{
+ struct BattleSpriteInfo *spriteInfo;
+ u8 battlerId = gSprites[spriteId].data[0];
+ u16 species;
+ u16 i;
+
+ for (i = 0; i < MAX_BATTLERS_COUNT; i++)
+ {
+ if (gBattlerSpriteIds[i] == spriteId)
+ {
+ if (IsContest())
+ {
+ species = shared19348.unk0;
+ return gMonBackPicCoords[species].y_offset;
+ }
+ else
+ {
+ if (GetBattlerSide(i) == B_SIDE_PLAYER)
+ {
+ spriteInfo = gBattleSpritesDataPtr->battlerData;
+ if (!spriteInfo[battlerId].transformSpecies)
+ species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
+ else
+ species = spriteInfo[battlerId].transformSpecies;
+
+ if (species == SPECIES_CASTFORM)
+ return sCastformBackSpriteYCoords[gBattleMonForms[battlerId]];
+ else
+ return gMonBackPicCoords[species].y_offset;
+ }
+ else
+ {
+ spriteInfo = gBattleSpritesDataPtr->battlerData;
+ if (!spriteInfo[battlerId].transformSpecies)
+ species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
+ else
+ species = spriteInfo[battlerId].transformSpecies;
+
+ if (species == SPECIES_CASTFORM)
+ return sCastformElevations[gBattleMonForms[battlerId]];
+ else
+ return gMonFrontPicCoords[species].y_offset;
+ }
+ }
+ }
+ }
+ return 0x40;
+}
+
+void sub_80A8048(s16 *bottom, s16 *top, const void *ptr)
+{
+ *bottom = ((intptr_t) ptr) & 0xffff;
+ *top = (((intptr_t) ptr) >> 16) & 0xffff;
+}
+
+void *sub_80A8050(s16 bottom, s16 top)
+{
+ return (void *)((u16)bottom | ((u16)top << 16));
+}
+
+void sub_80A805C(struct Task *task, u8 a2, s16 a3, s16 a4, s16 a5, s16 a6, u16 a7)
+{
+ task->data[8] = a7;
+ task->data[15] = a2; // spriteId
+ 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_80A80C8(struct Task *task)
+{
+ if (!task->data[8])
+ return 0;
+
+ if (--task->data[8] != 0)
+ {
+ 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_80A7E6C(task->data[15]);
+ else
+ gSprites[task->data[15]].pos2.y = 0;
+ return task->data[8];
+}
+
+void AnimTask_GetFrustrationPowerLevel(u8 taskId)
+{
+ u16 powerLevel;
+
+ if (gAnimFriendship <= 30)
+ powerLevel = 0;
+ else if (gAnimFriendship <= 100)
+ powerLevel = 1;
+ else if (gAnimFriendship <= 200)
+ powerLevel = 2;
+ else
+ powerLevel = 3;
+ gBattleAnimArgs[7] = powerLevel;
+ DestroyAnimVisualTask(taskId);
+}
+
+void sub_80A8174(u8 priority)
+{
+ if (IsBattlerSpriteVisible(gBattleAnimTarget))
+ gSprites[gBattlerSpriteIds[gBattleAnimTarget]].oam.priority = priority;
+ if (IsBattlerSpriteVisible(gBattleAnimAttacker))
+ gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].oam.priority = priority;
+ if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget)))
+ gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimTarget)]].oam.priority = priority;
+ if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker)))
+ gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority = priority;
+}
+
+void sub_80A8278(void)
+{
+ int i;
+
+ for (i = 0; i < gBattlersCount; i++)
+ {
+ if (IsBattlerSpriteVisible(i))
+ {
+ gSprites[gBattlerSpriteIds[i]].subpriority = sub_80A82E4(i);
+ gSprites[gBattlerSpriteIds[i]].oam.priority = 2;
+ }
+ }
+}
+
+u8 sub_80A82E4(u8 battlerId)
+{
+ u8 position;
+ u8 ret;
+
+ if (IsContest())
+ {
+ if (battlerId == 2)
+ return 30;
+ else
+ return 40;
+ }
+ else
+ {
+ position = GetBattlerPosition(battlerId);
+ if (position == B_POSITION_PLAYER_LEFT)
+ ret = 30;
+ else if (position == B_POSITION_PLAYER_RIGHT)
+ ret = 20;
+ else if (position == B_POSITION_OPPONENT_LEFT)
+ ret = 40;
+ else
+ ret = 50;
+ }
+ return ret;
+}
+
+u8 sub_80A8328(u8 battlerId)
+{
+ u8 position = GetBattlerPosition(battlerId);
+
+ if (IsContest())
+ return 2;
+ else if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_OPPONENT_RIGHT)
+ return GetAnimBgAttribute(2, BG_ANIM_PRIORITY);
+ else
+ return GetAnimBgAttribute(1, BG_ANIM_PRIORITY);
+}
+
+u8 sub_80A8364(u8 battlerId)
+{
+ if (!IsContest())
+ {
+ u8 position = GetBattlerPosition(battlerId);
+ if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_OPPONENT_RIGHT)
+ return 2;
+ else
+ return 1;
+ }
+ return 1;
+}
+
+u8 sub_80A8394(u16 species, bool8 isBackpic, u8 a3, s16 x, s16 y, u8 subpriority, u32 personality, u32 trainerId, u32 battlerId, u32 a10)
+{
+ u8 spriteId;
+ u16 sheet = LoadSpriteSheet(&sUnknown_08525FC0[a3]);
+ u16 palette = AllocSpritePalette(sUnknown_08525F90[a3].paletteTag);
+
+ if (gMonSpritesGfxPtr != NULL && gMonSpritesGfxPtr->field_17C == NULL)
+ gMonSpritesGfxPtr->field_17C = AllocZeroed(0x2000);
+ if (!isBackpic)
+ {
+ LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, trainerId, personality), (palette * 0x10) + 0x100, 0x20);
+ if (a10 == 1 || sub_80688F8(5, battlerId) == 1 || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != 0)
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
+ gMonSpritesGfxPtr->field_17C,
+ species,
+ personality,
+ TRUE);
+ else
+ LoadSpecialPokePic_2(&gMonFrontPicTable[species],
+ gMonSpritesGfxPtr->field_17C,
+ species,
+ personality,
+ TRUE);
+ }
+ else
+ {
+ LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, trainerId, personality), (palette * 0x10) + 0x100, 0x20);
+ if (a10 == 1 || sub_80688F8(5, battlerId) == 1 || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != 0)
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species],
+ gMonSpritesGfxPtr->field_17C,
+ species,
+ personality,
+ FALSE);
+ else
+ LoadSpecialPokePic_2(&gMonBackPicTable[species],
+ gMonSpritesGfxPtr->field_17C,
+ species,
+ personality,
+ FALSE);
+ }
+
+ RequestDma3Copy(gMonSpritesGfxPtr->field_17C, (void *)(OBJ_VRAM0 + (sheet * 0x20)), 0x800, 1);
+ FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_17C);
+
+ if (!isBackpic)
+ spriteId = CreateSprite(&sUnknown_08525F90[a3], x, y + gMonFrontPicCoords[species].y_offset, subpriority);
+ else
+ spriteId = CreateSprite(&sUnknown_08525F90[a3], x, y + gMonBackPicCoords[species].y_offset, subpriority);
+
+ if (IsContest())
+ {
+ gSprites[spriteId].affineAnims = gUnknown_082FF6C0;
+ StartSpriteAffineAnim(&gSprites[spriteId], 0);
+ }
+ return spriteId;
+}
+
+void sub_80A8610(struct Sprite *sprite)
+{
+ DestroySpriteAndFreeResources(sprite);
+}
+
+s16 sub_80A861C(u8 battlerId, u8 a2)
+{
+ u16 species;
+ u32 personality;
+ u16 letter;
+ u16 var;
+ int ret;
+ const struct MonCoords *coords;
+ struct BattleSpriteInfo *spriteInfo;
+
+ if (IsContest())
+ {
+ if (shared19348.unk4_0)
+ {
+ species = shared19348.unk2;
+ personality = shared19348.unk10;
+ }
+ else
+ {
+ species = shared19348.unk0;
+ personality = shared19348.unk8;
+ }
+ 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[battlerId]];
+ }
+ else if (species <= SPECIES_EGG)
+ {
+ coords = &gMonBackPicCoords[species];
+ }
+ else
+ {
+ coords = &gMonBackPicCoords[0];
+ }
+ }
+ else
+ {
+ if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
+ {
+ spriteInfo = gBattleSpritesDataPtr->battlerData;
+ if (!spriteInfo[battlerId].transformSpecies)
+ {
+ species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
+ personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY);
+ }
+ else
+ {
+ species = spriteInfo[battlerId].transformSpecies;
+ personality = gTransformedPersonalities[battlerId];
+ }
+ 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
+ {
+ spriteInfo = gBattleSpritesDataPtr->battlerData;
+ if (!spriteInfo[battlerId].transformSpecies)
+ {
+ species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
+ personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY);
+ }
+ else
+ {
+ species = spriteInfo[battlerId].transformSpecies;
+ personality = gTransformedPersonalities[battlerId];
+ }
+ 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[battlerId]];
+ }
+ 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 GetBattlerSpriteCoord(battlerId, 2) - ((coords->coords >> 4) * 4);
+ case 5:
+ return GetBattlerSpriteCoord(battlerId, 2) + ((coords->coords >> 4) * 4);
+ case 2:
+ return GetBattlerSpriteCoord(battlerId, 3) - ((coords->coords & 0xf) * 4);
+ case 3:
+ return GetBattlerSpriteCoord(battlerId, 3) + ((coords->coords & 0xf) * 4);
+ case 6:
+ ret = GetBattlerSpriteCoord(battlerId, 1) + 0x1f;
+ return ret - coords->y_offset;
+ default:
+ return 0;
+ }
+}
+
+void SetAverageBattlerPositions(u8 battlerId, bool8 a2, s16 *x, s16 *y)
+{
+ u8 v1, v2;
+ s16 v3, v4;
+ s16 v5, v6;
+
+ if (!a2)
+ {
+ v1 = 0;
+ v2 = 1;
+ }
+ else
+ {
+ v1 = 2;
+ v2 = 3;
+ }
+ v3 = GetBattlerSpriteCoord(battlerId, v1);
+ v4 = GetBattlerSpriteCoord(battlerId, v2);
+ if (IsDoubleBattle() && !IsContest())
+ {
+ v5 = GetBattlerSpriteCoord(BATTLE_PARTNER(battlerId), v1);
+ v6 = GetBattlerSpriteCoord(BATTLE_PARTNER(battlerId), v2);
+ }
+ else
+ {
+ v5 = v3;
+ v6 = v4;
+ }
+ *x = (v3 + v5) / 2;
+ *y = (v4 + v6) / 2;
+}
+
+u8 sub_80A89C8(int battlerId, u8 spriteId, int species)
+{
+ u8 newSpriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
+ gSprites[newSpriteId] = gSprites[spriteId];
+ gSprites[newSpriteId].usingSheet = TRUE;
+ gSprites[newSpriteId].oam.priority = 0;
+ gSprites[newSpriteId].oam.objMode = 2;
+ gSprites[newSpriteId].oam.tileNum = gSprites[spriteId].oam.tileNum;
+ gSprites[newSpriteId].callback = SpriteCallbackDummy;
+ return newSpriteId;
+}
+
+void sub_80A8A6C(struct Sprite *sprite)
+{
+ sub_80A6838(sprite);
+ if (GetBattlerSide(gBattleAnimAttacker))
+ {
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ sprite->hFlip = TRUE;
+ }
+ else
+ {
+ sprite->pos1.x += gBattleAnimArgs[0];
+ }
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[1] = gBattleAnimArgs[3];
+ sprite->data[3] = gBattleAnimArgs[4];
+ sprite->data[5] = gBattleAnimArgs[5];
+ StoreSpriteCallbackInData6(sprite, move_anim_8074EE0);
+ sprite->callback = sub_80A66DC;
+}
+
+void sub_80A8AEC(struct Sprite *sprite)
+{
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ {
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ gBattleAnimArgs[3] *= -1;
+ }
+ else
+ {
+ sprite->pos1.x += gBattleAnimArgs[0];
+ }
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[1] = gBattleAnimArgs[3];
+ sprite->data[3] = gBattleAnimArgs[4];
+ sprite->data[5] = gBattleAnimArgs[5];
+ StartSpriteAnim(sprite, gBattleAnimArgs[6]);
+ StoreSpriteCallbackInData6(sprite, move_anim_8074EE0);
+ sprite->callback = sub_80A66DC;
+}
+
+void sub_80A8B64(struct Sprite *sprite)
+{
+ sub_80A6838(sprite);
+ if (GetBattlerSide(gBattleAnimAttacker))
+ sprite->pos1.x -= gBattleAnimArgs[0];
+ else
+ sprite->pos1.x += gBattleAnimArgs[0];
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->callback = sub_80A67D8;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+void sub_80A8BC4(u8 taskId)
+{
+ u16 src;
+ u16 dest;
+ struct Task *task = &gTasks[taskId];
+
+ task->data[0] = GetAnimBattlerSpriteId(ANIM_ATTACKER);
+ task->data[1] = ((GetBattlerSide(gBattleAnimAttacker)) != B_SIDE_PLAYER) ? -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_80A82E4(gBattleAnimAttacker);
+ 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, 16, gBattleAnimArgs[1], gBattleAnimArgs[0]);
+ task->func = sub_80A8CAC;
+}
+
+void sub_80A8CAC(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ switch (task->data[2])
+ {
+ case 0:
+ sub_80A8D78(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_80A8D78(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(ANIM_TAG_BENT_SPOON);
+ DestroyAnimVisualTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_80A8D78(struct Task *task, u8 taskId)
+{
+ s16 spriteId = duplicate_obj_of_side_rel2move_in_transparent_mode(0);
+ if (spriteId >= 0)
+ {
+ gSprites[spriteId].oam.priority = task->data[6];
+ gSprites[spriteId].oam.paletteNum = task->data[4];
+ gSprites[spriteId].data[0] = 8;
+ gSprites[spriteId].data[1] = taskId;
+ gSprites[spriteId].data[2] = spriteId;
+ gSprites[spriteId].pos2.x = gSprites[task->data[0]].pos2.x;
+ gSprites[spriteId].callback = sub_80A8DFC;
+ task->data[5]++;
+ }
+}
+
+void sub_80A8DFC(struct Sprite *sprite)
+{
+ if (--sprite->data[0] == 0)
+ {
+ gTasks[sprite->data[1]].data[5]--;
+ obj_delete_but_dont_free_vram(sprite);
+ }
+}
+
+void sub_80A8E30(struct Sprite *sprite)
+{
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_3);
+ if (!GetBattlerSide(gBattleAnimAttacker))
+ sprite->data[0] = 5;
+ else
+ sprite->data[0] = -10;
+ sprite->data[1] = -40;
+ sprite->callback = sub_80A8E88;
+}
+
+void sub_80A8E88(struct Sprite *sprite)
+{
+ sprite->data[2] += sprite->data[0];
+ sprite->data[3] += sprite->data[1];
+ sprite->pos2.x = sprite->data[2] / 10;
+ sprite->pos2.y = sprite->data[3] / 10;
+ if (sprite->data[1] < -20)
+ sprite->data[1]++;
+ if (sprite->pos1.y + sprite->pos2.y < -32)
+ DestroyAnimSprite(sprite);
+}
+
+void sub_80A8EE4(struct Sprite *sprite)
+{
+ int x;
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[4];
+ sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[5];
+ if (!GetBattlerSide(gBattleAnimTarget))
+ {
+ 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_80A6EEC;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}