diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim.c | 640 |
1 files changed, 637 insertions, 3 deletions
diff --git a/src/battle_anim.c b/src/battle_anim.c index 6c316157f..7a2b7902c 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -13,13 +13,18 @@ #include "bg.h" #include "gpu_regs.h" #include "palette.h" +#include "main.h" // sprites start at 10000 and thus must be subtracted of 10000 to account for the true index. #define GET_TRUE_SPRITE_INDEX(i) ((i - 10000)) + #define SCRIPT_READ_32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) -#define SCRIPT_READ_32_(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) #define SCRIPT_READ_16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) +#define SCRIPT_READ_PTR(ptr) ((const u8*)(SCRIPT_READ_32(ptr))) + #define SCRIPT_READ_16_(ptr) ((ptr)[0] + ((ptr)[1] << 8)) +#define SCRIPT_READ_32_(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) +#define SCRIPT_READ_PTR_(ptr) ((const u8*)(SCRIPT_READ_32_(ptr))) #define ANIM_SPRITE_INDEX_COUNT 8 #define ANIM_ARGS_COUNT 8 @@ -56,7 +61,7 @@ EWRAM_DATA u16 gWeatherMoveAnim = 0; EWRAM_DATA s16 gBattleAnimArgs[ANIM_ARGS_COUNT] = {0}; EWRAM_DATA u16 gSoundAnimFramesToWait = 0; EWRAM_DATA u8 gMonAnimTaskIdArray[2] = {0}; -EWRAM_DATA u8 gUnknown_02038432 = 0; +EWRAM_DATA u8 gAnimMoveTurn = 0; EWRAM_DATA u8 gUnknown_02038433 = 0; EWRAM_DATA u16 gAnimMoveIndex = 0; // set but unused. EWRAM_DATA u8 gAnimBankAttacker = 0; @@ -69,6 +74,7 @@ extern const u16 gUnknown_082C8D64[]; extern const u8 * const gBattleAnims_Moves[]; extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; +extern const struct BattleAnimBackground gBattleAnimBackgroundTable[]; extern void sub_80A8278(void); // rom_80A5C6C.s extern void sub_80A6B30(struct UnknownAnimStruct2*); // rom_80A5C6C.s @@ -76,11 +82,18 @@ extern void sub_80A6B90(struct UnknownAnimStruct2*, u32 arg1); // rom_80A5C6C.s extern u8 sub_80A82E4(u8 bank); // rom_80A5C6C.s extern u8 sub_80A5C6C(u8 bank, u8 attributeId); // rom_80A5C6C.s extern bool8 AnimBankSpriteExists(u8 bank); // rom_80A5C6C.s +extern void sub_80A6C68(u8 arg0); // rom_80A5C6C.s +extern u8 sub_80A6D94(void); // this file's functions void RunAnimScriptCommand(void); void task_pA_ma0A_obj_to_bg_pal(u8 taskId); void sub_80A46A0(void); +void sub_80A4980(u8 taskId); +void sub_80A4BB0(u8 taskId); +void Task_FadeToBg(u8 taskId); +void LoadDefaultBg(void); +void LoadMoveBg(u16 bgId); void ClearBattleAnimationVars(void) { @@ -105,7 +118,7 @@ void ClearBattleAnimationVars(void) gMonAnimTaskIdArray[0] = 0xFF; gMonAnimTaskIdArray[1] = 0xFF; - gUnknown_02038432 = 0; + gAnimMoveTurn = 0; gUnknown_02038433 = 0; gAnimMoveIndex = 0; gAnimBankAttacker = 0; @@ -648,3 +661,624 @@ void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) } } +/*static*/ void sub_80A46A0(void) +{ + s32 i, j; + struct UnknownAnimStruct2 unknownStruct; + u16 *ptr; + + if (IsSpeciesNotUnown(gContestResources->field_18->field_0)) + { + sub_80A6B30(&unknownStruct); + ptr = unknownStruct.unk4; + for (i = 0; i < 8; i++) + { + for (j = 0; j < 4; j++) + { + u16 temp = ptr[j + i * 32]; + + ptr[j + i * 32] = ptr[7 - j + i * 32]; + ptr[7 - j + i * 32] = temp; + } + } + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + ptr[j + i * 32] ^= 0x400; + } + } +} + +void sub_80A4720(u16 a, u16 *b, u32 c, u8 d) +{ + s32 i, j; + s32 var; + + if (d == 0) + var = 32; + else + var = 64; + a <<= 12; + for (i = 0; i < var; i++) + { + for (j = 0; j < 32; j++) + b[j + i * 32] = ((b[j + i * 32] & 0xFFF) | a) + c; + } +} + +void sub_80A477C(bool8 to_BG2) +{ + struct UnknownAnimStruct2 unknownStruct; + sub_80A6B30(&unknownStruct); + + if (!to_BG2 || IsContest()) + { + sub_80A6C68(1); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + } + else + { + sub_80A6C68(2); + gBattle_BG2_X = 0; + gBattle_BG2_Y = 0; + } +} + +/*static*/ void task_pA_ma0A_obj_to_bg_pal(u8 taskId) +{ + u8 r4; + u8 r6; + s16 r3; + s16 r2; + struct UnknownAnimStruct2 unknownStruct; + + r4 = gTasks[taskId].data[0]; + r6 = gTasks[taskId].data[6]; + sub_80A6B30(&unknownStruct); + r3 = gTasks[taskId].data[1] - (gSprites[r4].pos1.x + gSprites[r4].pos2.x); + r2 = gTasks[taskId].data[2] - (gSprites[r4].pos1.y + gSprites[r4].pos2.y); + + if (gTasks[taskId].data[5] == 0) + { + u16 *src; + u16 *dst; + + gBattle_BG1_X = r3 + gTasks[taskId].data[3]; + gBattle_BG1_Y = r2 + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + r6 * 16; + dst = gPlttBufferFaded + 0x100 + unknownStruct.unk8 * 16 - 256; + CpuCopy32(src, dst, 0x20); + } + else + { + u16 *src; + u16 *dst; + + gBattle_BG2_X = r3 + gTasks[taskId].data[3]; + gBattle_BG2_Y = r2 + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + r6 * 16; + dst = gPlttBufferFaded + 0x100 - 112; + CpuCopy32(src, dst, 0x20); + } +} + +/*static*/ void ScriptCmd_clearmonbg(void) +{ + u8 animBankId; + u8 bank; + u8 taskId; + + gBattleAnimScriptPtr++; + animBankId = gBattleAnimScriptPtr[0]; + + if (animBankId == ANIM_BANK_ATTACKER) + animBankId = ANIM_BANK_ATK_PARTNER; + else if (animBankId == ANIM_BANK_TARGET) + animBankId = ANIM_BANK_DEF_PARTNER; + + if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER) + bank = gAnimBankAttacker; + else + bank = gAnimBankTarget; + + if (gMonAnimTaskIdArray[0] != 0xFF) + gSprites[gBankSpriteIds[bank]].invisible = 0; + if (animBankId > 1 && gMonAnimTaskIdArray[1] != 0xFF) + gSprites[gBankSpriteIds[bank ^ BIT_MON]].invisible = 0; + else + animBankId = 0; + + taskId = CreateTask(sub_80A4980, 5); + gTasks[taskId].data[0] = animBankId; + gTasks[taskId].data[2] = bank; + + gBattleAnimScriptPtr++; +} + +/*static*/ void sub_80A4980(u8 taskId) +{ + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] != 1) + { + u8 to_BG2; + u8 identity = GetBankIdentity(gTasks[taskId].data[2]); + if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest()) + to_BG2 = FALSE; + else + to_BG2 = TRUE; + + if (gMonAnimTaskIdArray[0] != 0xFF) + { + sub_80A477C(to_BG2); + DestroyTask(gMonAnimTaskIdArray[0]); + gMonAnimTaskIdArray[0] = 0xFF; + } + if (gTasks[taskId].data[0] > 1) + { + sub_80A477C(to_BG2 ^ 1); + DestroyTask(gMonAnimTaskIdArray[1]); + gMonAnimTaskIdArray[1] = 0xFF; + } + DestroyTask(taskId); + } +} + +/*static*/ void ScriptCmd_monbg_22(void) +{ + bool8 toBG_2; + u8 bank; + u8 animBankId; + + gBattleAnimScriptPtr++; + + animBankId = gBattleAnimScriptPtr[0]; + + if (animBankId == ANIM_BANK_ATTACKER) + animBankId = ANIM_BANK_ATK_PARTNER; + else if (animBankId == ANIM_BANK_TARGET) + animBankId = ANIM_BANK_DEF_PARTNER; + + if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER) + bank = gAnimBankAttacker; + else + bank = gAnimBankTarget; + + if (IsAnimBankSpriteVisible(bank)) + { + u8 identity = GetBankIdentity(bank); + if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest()) + toBG_2 = FALSE; + else + toBG_2 = TRUE; + + sub_80A438C(bank, toBG_2, FALSE); + } + + bank ^= BIT_MON; + if (animBankId > 1 && IsAnimBankSpriteVisible(bank)) + { + u8 identity = GetBankIdentity(bank); + if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest()) + toBG_2 = FALSE; + else + toBG_2 = TRUE; + + sub_80A438C(bank, toBG_2, FALSE); + } + + gBattleAnimScriptPtr++; +} + +/*static*/ void ScriptCmd_clearmonbg_23(void) +{ + u8 animBankId; + u8 bank; + u8 taskId; + + gBattleAnimScriptPtr++; + animBankId = gBattleAnimScriptPtr[0]; + + if (animBankId == ANIM_BANK_ATTACKER) + animBankId = ANIM_BANK_ATK_PARTNER; + else if (animBankId == ANIM_BANK_TARGET) + animBankId = ANIM_BANK_DEF_PARTNER; + + if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER) + bank = gAnimBankAttacker; + else + bank = gAnimBankTarget; + + if (IsAnimBankSpriteVisible(bank)) + gSprites[gBankSpriteIds[bank]].invisible = 0; + if (animBankId > 1 && IsAnimBankSpriteVisible(bank ^ BIT_MON)) + gSprites[gBankSpriteIds[bank ^ BIT_MON]].invisible = 0; + else + animBankId = 0; + + taskId = CreateTask(sub_80A4BB0, 5); + gTasks[taskId].data[0] = animBankId; + gTasks[taskId].data[2] = bank; + + gBattleAnimScriptPtr++; +} + +/*static*/ void sub_80A4BB0(u8 taskId) +{ + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] != 1) + { + bool8 toBG_2; + u8 bank = gTasks[taskId].data[2]; + u8 identity = GetBankIdentity(bank); + if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest()) + toBG_2 = FALSE; + else + toBG_2 = TRUE; + + if (IsAnimBankSpriteVisible(bank)) + sub_80A477C(toBG_2); + if (gTasks[taskId].data[0] > 1 && IsAnimBankSpriteVisible(bank ^ BIT_MON)) + sub_80A477C(toBG_2 ^ 1); + + DestroyTask(taskId); + } +} + +#undef t1_MONBG_BANK +#undef t1_MON_IN_BG2 +#undef t1_CREATE_ANOTHER_TASK +#undef t1_IS_SECONDMON_BG + +#undef t2_BANK_SPRITE_ID +#undef t2_MON_IN_BG2 +#undef t2_MONBG_BANK + +/*static*/ void ScriptCmd_setalpha(void) +{ + u16 half1, half2; + + gBattleAnimScriptPtr++; + half1 = *(gBattleAnimScriptPtr++); + half2 = *(gBattleAnimScriptPtr++) << 8; + SetGpuReg(REG_OFFSET_BLDCNT, 0x3F40); + SetGpuReg(REG_OFFSET_BLDALPHA, half1 | half2); +} + +/*static*/ void ScriptCmd_setbldcnt(void) +{ + u16 half1, half2; + + gBattleAnimScriptPtr++; + half1 = *(gBattleAnimScriptPtr++); + half2 = *(gBattleAnimScriptPtr++) << 8; + SetGpuReg(REG_OFFSET_BLDCNT, half1 | half2); +} + +/*static*/ void ScriptCmd_blendoff(void) +{ + gBattleAnimScriptPtr++; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); +} + +/*static*/ void ScriptCmd_call(void) +{ + gBattleAnimScriptPtr++; + gBattleAnimScriptRetAddr = gBattleAnimScriptPtr + 4; + gBattleAnimScriptPtr = SCRIPT_READ_PTR_(gBattleAnimScriptPtr); +} + +/*static*/ void ScriptCmd_return(void) +{ + gBattleAnimScriptPtr = gBattleAnimScriptRetAddr; +} + +/*static*/ void ScriptCmd_setarg(void) +{ + const u8 *addr = gBattleAnimScriptPtr; + u16 value; + u8 argId; + + gBattleAnimScriptPtr++; + argId = gBattleAnimScriptPtr[0]; + gBattleAnimScriptPtr++; + value = SCRIPT_READ_16(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = addr + 4; + gBattleAnimArgs[argId] = value; +} + +/*static*/ void ScriptCmd_choosetwoturnanim(void) +{ + gBattleAnimScriptPtr++; + if (gAnimMoveTurn & 1) + gBattleAnimScriptPtr += 4; + gBattleAnimScriptPtr = SCRIPT_READ_PTR_(gBattleAnimScriptPtr); +} + +/*static*/ void ScriptCmd_jumpifmoveturn(void) +{ + u8 toCheck; + gBattleAnimScriptPtr++; + toCheck = gBattleAnimScriptPtr[0]; + gBattleAnimScriptPtr++; + + if (toCheck == gAnimMoveTurn) + gBattleAnimScriptPtr = SCRIPT_READ_PTR_(gBattleAnimScriptPtr); + else + gBattleAnimScriptPtr += 4; +} + +/*static*/ void ScriptCmd_jump(void) +{ + gBattleAnimScriptPtr++; + gBattleAnimScriptPtr = SCRIPT_READ_PTR_(gBattleAnimScriptPtr); +} + +// Uses of this function that rely on a TRUE return are expecting inBattle to not be ticked as defined in contest behavior. As a result, if misused, this function cannot reliably discern between field and contest status and could result in undefined behavior. +bool8 IsContest(void) +{ + if (!gMain.inBattle) + return TRUE; + else + return FALSE; +} + +#define tBackgroundId data[0] +#define tState data[10] + +/*static*/ void ScriptCmd_fadetobg(void) +{ + u8 backgroundId; + u8 taskId; + + gBattleAnimScriptPtr++; + backgroundId = gBattleAnimScriptPtr[0]; + gBattleAnimScriptPtr++; + taskId = CreateTask(Task_FadeToBg, 5); + gTasks[taskId].tBackgroundId = backgroundId; + gUnknown_02038433 = 1; +} + +/*static*/ void ScriptCmd_fadetobgfromset(void) +{ + u8 bg1, bg2, bg3; + u8 taskId; + + gBattleAnimScriptPtr++; + bg1 = gBattleAnimScriptPtr[0]; + bg2 = gBattleAnimScriptPtr[1]; + bg3 = gBattleAnimScriptPtr[2]; + gBattleAnimScriptPtr += 3; + taskId = CreateTask(Task_FadeToBg, 5); + + if (IsContest()) + gTasks[taskId].tBackgroundId = bg3; + else if (GetBankSide(gAnimBankTarget) == SIDE_PLAYER) + gTasks[taskId].tBackgroundId = bg2; + else + gTasks[taskId].tBackgroundId = bg1; + + gUnknown_02038433 = 1; +} + +/*static*/ void Task_FadeToBg(u8 taskId) +{ + if (gTasks[taskId].tState == 0) + { + BeginHardwarePaletteFade(0xE8, 0, 0, 16, 0); + gTasks[taskId].tState++; + return; + } + if (gPaletteFade.active) + return; + if (gTasks[taskId].tState == 1) + { + gTasks[taskId].tState++; + gUnknown_02038433 = 2; + } + else if (gTasks[taskId].tState == 2) + { + s16 bgId = (u16)gTasks[taskId].tBackgroundId; + + if (bgId == -1) + LoadDefaultBg(); + else + LoadMoveBg(bgId); + + BeginHardwarePaletteFade(0xE8, 0, 16, 0, 1); + gTasks[taskId].tState++; + return; + } + if (gPaletteFade.active) + return; + if (gTasks[taskId].tState == 3) + { + DestroyTask(taskId); + gUnknown_02038433 = 0; + } +} + +extern u8 gDecompressionBuffer[]; + +/*static*/ void LoadMoveBg(u16 bgId) +{ + if (IsContest()) + { + void *tilemap = gBattleAnimBackgroundTable[bgId].tilemap; + void *dmaSrc; + void *dmaDest; + + LZDecompressWram(tilemap, gDecompressionBuffer); + sub_80A4720(sub_80A6D94(), (void*)(gDecompressionBuffer), 0x100, 0); + dmaSrc = gDecompressionBuffer; + dmaDest = (void *)(VRAM + 0xD000); + DmaCopy32(3, dmaSrc, dmaDest, 0x800); + LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x2000)); + LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, sub_80A6D94() * 16, 32); + } + else + { + LZDecompressVram(gBattleAnimBackgroundTable[bgId].tilemap, (void *)(VRAM + 0xD000)); + LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x8000)); + LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, 32, 32); + } +} + +/*static*/ void LoadDefaultBg(void) +{ + if (IsContest()) + LoadContestBgAfterMoveAnim(); + else + LoadFittingBackgroundForBattle(); +} + +/*static*/ void ScriptCmd_restorebg(void) +{ + u8 taskId; + + gBattleAnimScriptPtr++; + taskId = CreateTask(Task_FadeToBg, 5); + gTasks[taskId].data[0] = 0xFFFF; + gUnknown_02038433 = 1; +} + +/*static*/ void ScriptCmd_waitbgfadeout(void) +{ + if (gUnknown_02038433 == 2) + { + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +/*static*/ void ScriptCmd_waitbgfadein(void) +{ + if (gUnknown_02038433 == 0) + { + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +/*static*/ void ScriptCmd_changebg(void) +{ + gBattleAnimScriptPtr++; + LoadMoveBg(gBattleAnimScriptPtr[0]); + gBattleAnimScriptPtr++; +} + +s8 BattleAnimAdjustPanning(s8 pan) +{ + if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10) + { + if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER) + pan = 63; + else + pan = -64; + } + else if (IsContest()) + { + if (gAnimBankAttacker != gAnimBankTarget || gAnimBankAttacker != 2 || pan != 63) + pan *= -1; + } + else if (GetBankSide(gAnimBankAttacker) == SIDE_PLAYER) + { + if (GetBankSide(gAnimBankTarget) == SIDE_PLAYER) + { + if (pan == 63) + pan = -64; + else if (pan != -64) + pan *= -1; + } + } + else if (GetBankSide(gAnimBankTarget) == SIDE_OPPONENT) + { + if (pan == -64) + pan = 63; + } + else + { + pan *= -1; + } + + if (pan > 63) + pan = 63; + else if (pan < -64) + pan = -64; + + return pan; +} + +s8 BattleAnimAdjustPanning2(s8 pan) +{ + if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10) + { + if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER) + pan = 63; + else + pan = -64; + } + else + { + if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER || IsContest()) + pan = -pan; + } + return pan; +} + +s16 sub_80A52EC(s16 a) +{ + s16 var = a; + + if (var > 63) + var = 63; + else if (var < -64) + var = -64; + + return var; +} + +s16 sub_80A5314(s16 a, s16 b, s16 c) +{ + u16 var; + + if (a < b) + var = ((c < 0) ? -c : c); + else if (a > b) + var = -((c < 0) ? -c : c); + else + var = 0; + + return var; +} + +/*static*/ void ScriptCmd_playsewithpan(void) +{ + u16 songId; + s8 pan; + + gBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(gBattleAnimScriptPtr); + pan = gBattleAnimScriptPtr[2]; + PlaySE12WithPanning(songId, BattleAnimAdjustPanning(pan)); + gBattleAnimScriptPtr += 3; +} + +/*static*/ void ScriptCmd_setpan(void) +{ + s8 pan; + + gBattleAnimScriptPtr++; + pan = gBattleAnimScriptPtr[0]; + SE12PanpotControl(BattleAnimAdjustPanning(pan)); + gBattleAnimScriptPtr++; +} |