diff options
author | DizzyEggg <jajkodizzy@wp.pl> | 2017-10-20 10:49:21 +0200 |
---|---|---|
committer | DizzyEggg <jajkodizzy@wp.pl> | 2017-10-20 10:49:21 +0200 |
commit | b65da491a97e77ed2aa122ab7342c7fb94d35606 (patch) | |
tree | 02e7c17f29426d6bca7bae4d133e1462dc81c355 /src | |
parent | 9ccc472b97b1a7f85703f813665cb4a30f7891b6 (diff) | |
parent | ae5aa3c4dfd81fc25e5abeef1b915bb2da68b8d1 (diff) |
merge with master, fix conflicts
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_2.c | 7 | ||||
-rw-r--r-- | src/battle_ai_switch_items.c | 18 | ||||
-rw-r--r-- | src/battle_anim.c | 1850 | ||||
-rw-r--r-- | src/battle_controllers.c | 1551 | ||||
-rw-r--r-- | src/battle_script_commands.c | 34 | ||||
-rw-r--r-- | src/decompress.c | 2 | ||||
-rw-r--r-- | src/egg_hatch.c | 2 | ||||
-rw-r--r-- | src/safari_zone.c | 2 | ||||
-rw-r--r-- | src/sprite.c | 2 |
9 files changed, 3433 insertions, 35 deletions
diff --git a/src/battle_2.c b/src/battle_2.c index aeba69213..16c07114a 100644 --- a/src/battle_2.c +++ b/src/battle_2.c @@ -204,9 +204,6 @@ extern const u8 BattleScript_ActionSwitch[]; extern const u8 BattleScript_PrintFailedToRunString[]; // functions -extern void HandleLinkBattleSetup(void); // rom_3 -extern void SetUpBattleVarsAndBirchZigzagoon(void); // rom_3 -extern void sub_8032768(void); // rom_3 extern void dp12_8087EA4(void); extern void sub_80356D0(void); extern void GetFrontierTrainerName(u8* dst, u16 trainerId); // battle tower @@ -4083,7 +4080,7 @@ static void HandleTurnActionSelectionState(void) if (gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_MULTIPLETURNS || gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_RECHARGE) { - Emit_x32(0); + EmitCmd50(0); MarkBufferBankForExecution(gActiveBank); return; } @@ -4111,7 +4108,7 @@ static void HandleTurnActionSelectionState(void) { RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 3); } - Emit_x32(0); + EmitCmd50(0); MarkBufferBankForExecution(gActiveBank); return; } diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 661759a98..d86be6fad 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -39,7 +39,7 @@ static bool8 ShouldSwitchIfPerishSong(void) && gDisableStructs[gActiveBank].perishSong1 == 0) { *(gBattleStruct->field_294 + gActiveBank) = 6; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } @@ -121,7 +121,7 @@ static bool8 ShouldSwitchIfWonderGuard(void) { // we found a mon *(gBattleStruct->field_294 + gActiveBank) = i; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } } @@ -221,7 +221,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) { // we found a mon *(gBattleStruct->field_294 + gActiveBank) = i; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } } @@ -241,13 +241,13 @@ static bool8 ShouldSwitchIfNaturalCure(void) if ((gUnknown_02024250[gActiveBank] == 0 || gUnknown_02024250[gActiveBank] == 0xFFFF) && Random() & 1) { *(gBattleStruct->field_294 + gActiveBank) = 6; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } else if (gBattleMoves[gUnknown_02024250[gActiveBank]].power == 0 && Random() & 1) { *(gBattleStruct->field_294 + gActiveBank) = 6; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } @@ -258,7 +258,7 @@ static bool8 ShouldSwitchIfNaturalCure(void) if (Random() & 1) { *(gBattleStruct->field_294 + gActiveBank) = 6; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } @@ -426,7 +426,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent) if (moveFlags & MOVESTATUS_SUPEREFFECTIVE && Random() % moduloPercent == 0) { *(gBattleStruct->field_294 + gActiveBank) = i; - EmitCmd_x21(1, 2, 0); + EmitCmd33(1, 2, 0); return TRUE; } } @@ -611,7 +611,7 @@ void AI_TrySwitchOrUseItem(void) } } - EmitCmd_x21(1, 0, (gActiveBank ^ BIT_SIDE) << 8); + EmitCmd33(1, 0, (gActiveBank ^ BIT_SIDE) << 8); } #define TYPE_FORESIGHT 0xFE @@ -940,7 +940,7 @@ static bool8 ShouldUseItem(void) if (shouldUse) { - EmitCmd_x21(1, 1, 0); + EmitCmd33(1, 1, 0); *(gBattleStruct->field_C0 + (gActiveBank / 2) * 2) = item; gBattleResources->battleHistory->trainerItems[i] = 0; return shouldUse; diff --git a/src/battle_anim.c b/src/battle_anim.c new file mode 100644 index 000000000..765733d39 --- /dev/null +++ b/src/battle_anim.c @@ -0,0 +1,1850 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "sprite.h" +#include "contest.h" +#include "m4a.h" +#include "pokemon.h" +#include "battle_interface.h" +#include "task.h" +#include "decompress.h" +#include "sound.h" +#include "dma3.h" +#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_16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) +#define SCRIPT_READ_32(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) +#define SCRIPT_READ_PTR(ptr) ((const u8*)(SCRIPT_READ_32(ptr))) + +#define ANIM_SPRITE_INDEX_COUNT 8 + +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u16 gBattle_WIN0H; +extern u16 gBattle_WIN0V; +extern u16 gBattle_WIN1H; +extern u16 gBattle_WIN1V; +extern u16 gBattle_BG1_X; +extern u16 gBattle_BG1_Y; +extern u16 gBattle_BG2_X; +extern u16 gBattle_BG2_Y; +extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; +extern u8 gBankSpriteIds[BATTLE_BANKS_COUNT]; +extern struct MusicPlayerInfo gMPlay_BGM; +extern struct MusicPlayerInfo gMPlay_SE1; +extern struct MusicPlayerInfo gMPlay_SE2; +extern u8 gDecompressionBuffer[]; + +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 +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 GetAnimBankSpriteId(u8 wantedBank); // rom_80A5C6C.s +extern u8 sub_80A6D94(void); +extern u8 sub_80A8364(u8); +extern bool8 IsDoubleBattle(void); + +// this file's functions +static void ScriptCmd_loadspritegfx(void); +static void ScriptCmd_unloadspritegfx(void); +static void ScriptCmd_createsprite(void); +static void ScriptCmd_createvisualtask(void); +static void ScriptCmd_delay(void); +static void ScriptCmd_waitforvisualfinish(void); +static void ScriptCmd_hang1(void); +static void ScriptCmd_hang2(void); +static void ScriptCmd_end(void); +static void ScriptCmd_playse(void); +static void ScriptCmd_monbg(void); +static void ScriptCmd_clearmonbg(void); +static void ScriptCmd_setalpha(void); +static void ScriptCmd_blendoff(void); +static void ScriptCmd_call(void); +static void ScriptCmd_return(void); +static void ScriptCmd_setarg(void); +static void ScriptCmd_choosetwoturnanim(void); +static void ScriptCmd_jumpifmoveturn(void); +static void ScriptCmd_jump(void); +static void ScriptCmd_fadetobg(void); +static void ScriptCmd_restorebg(void); +static void ScriptCmd_waitbgfadeout(void); +static void ScriptCmd_waitbgfadein(void); +static void ScriptCmd_changebg(void); +static void ScriptCmd_playsewithpan(void); +static void ScriptCmd_setpan(void); +static void ScriptCmd_panse_1B(void); +static void ScriptCmd_loopsewithpan(void); +static void ScriptCmd_waitplaysewithpan(void); +static void ScriptCmd_setbldcnt(void); +static void ScriptCmd_createsoundtask(void); +static void ScriptCmd_waitsound(void); +static void ScriptCmd_jumpargeq(void); +static void ScriptCmd_monbg_22(void); +static void ScriptCmd_clearmonbg_23(void); +static void ScriptCmd_jumpifcontest(void); +static void ScriptCmd_fadetobgfromset(void); +static void ScriptCmd_panse_26(void); +static void ScriptCmd_panse_27(void); +static void ScriptCmd_monbgprio_28(void); +static void ScriptCmd_monbgprio_29(void); +static void ScriptCmd_monbgprio_2A(void); +static void ScriptCmd_invisible(void); +static void ScriptCmd_visible(void); +static void ScriptCmd_doublebattle_2D(void); +static void ScriptCmd_doublebattle_2E(void); +static void ScriptCmd_stopsound(void); + +static void RunAnimScriptCommand(void); +static void task_pA_ma0A_obj_to_bg_pal(u8 taskId); +static void sub_80A46A0(void); +static void sub_80A4980(u8 taskId); +static void sub_80A4BB0(u8 taskId); +static void Task_FadeToBg(u8 taskId); +static void Task_PanFromInitialToTarget(u8 taskId); +static void Task_LoopAndPlaySE(u8 taskId); +static void Task_WaitAndPlaySE(u8 taskId); +static void LoadDefaultBg(void); +static void LoadMoveBg(u16 bgId); + +// ewram +EWRAM_DATA static const u8 *sBattleAnimScriptPtr = NULL; +EWRAM_DATA static const u8 *sBattleAnimScriptRetAddr = NULL; +EWRAM_DATA void (*gAnimScriptCallback)(void) = NULL; +EWRAM_DATA static s8 gAnimFramesToWait = 0; +EWRAM_DATA bool8 gAnimScriptActive = FALSE; +EWRAM_DATA u8 gAnimVisualTaskCount = 0; +EWRAM_DATA u8 gAnimSoundTaskCount = 0; +EWRAM_DATA struct DisableStruct *gAnimDisableStructPtr = NULL; +EWRAM_DATA u32 gAnimMoveDmg = 0; +EWRAM_DATA u16 gAnimMovePower = 0; +EWRAM_DATA static u16 sAnimSpriteIndexArray[ANIM_SPRITE_INDEX_COUNT] = {0}; +EWRAM_DATA u8 gAnimFriendship = 0; +EWRAM_DATA u16 gWeatherMoveAnim = 0; +EWRAM_DATA s16 gBattleAnimArgs[ANIM_ARGS_COUNT] = {0}; +EWRAM_DATA static u16 sSoundAnimFramesToWait = 0; +EWRAM_DATA static u8 sMonAnimTaskIdArray[2] = {0}; +EWRAM_DATA u8 gAnimMoveTurn = 0; +EWRAM_DATA static u8 sAnimBackgroundFadeState = 0; +EWRAM_DATA static u16 sAnimMoveIndex = 0; // set but unused. +EWRAM_DATA u8 gAnimBankAttacker = 0; +EWRAM_DATA u8 gAnimBankTarget = 0; +EWRAM_DATA u16 gAnimSpeciesByBanks[BATTLE_BANKS_COUNT] = {0}; +EWRAM_DATA u8 gUnknown_02038440 = 0; + +// const rom data +static void (* const sScriptCmdTable[])(void) = +{ + ScriptCmd_loadspritegfx, + ScriptCmd_unloadspritegfx, + ScriptCmd_createsprite, + ScriptCmd_createvisualtask, + ScriptCmd_delay, + ScriptCmd_waitforvisualfinish, + ScriptCmd_hang1, + ScriptCmd_hang2, + ScriptCmd_end, + ScriptCmd_playse, + ScriptCmd_monbg, + ScriptCmd_clearmonbg, + ScriptCmd_setalpha, + ScriptCmd_blendoff, + ScriptCmd_call, + ScriptCmd_return, + ScriptCmd_setarg, + ScriptCmd_choosetwoturnanim, + ScriptCmd_jumpifmoveturn, + ScriptCmd_jump, + ScriptCmd_fadetobg, + ScriptCmd_restorebg, + ScriptCmd_waitbgfadeout, + ScriptCmd_waitbgfadein, + ScriptCmd_changebg, + ScriptCmd_playsewithpan, + ScriptCmd_setpan, + ScriptCmd_panse_1B, + ScriptCmd_loopsewithpan, + ScriptCmd_waitplaysewithpan, + ScriptCmd_setbldcnt, + ScriptCmd_createsoundtask, + ScriptCmd_waitsound, + ScriptCmd_jumpargeq, + ScriptCmd_monbg_22, + ScriptCmd_clearmonbg_23, + ScriptCmd_jumpifcontest, + ScriptCmd_fadetobgfromset, + ScriptCmd_panse_26, + ScriptCmd_panse_27, + ScriptCmd_monbgprio_28, + ScriptCmd_monbgprio_29, + ScriptCmd_monbgprio_2A, + ScriptCmd_invisible, + ScriptCmd_visible, + ScriptCmd_doublebattle_2D, + ScriptCmd_doublebattle_2E, + ScriptCmd_stopsound +}; + +void ClearBattleAnimationVars(void) +{ + s32 i; + + gAnimFramesToWait = 0; + gAnimScriptActive = FALSE; + gAnimVisualTaskCount = 0; + gAnimSoundTaskCount = 0; + gAnimDisableStructPtr = NULL; + gAnimMoveDmg = 0; + gAnimMovePower = 0; + gAnimFriendship = 0; + + // clear index array. + for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) + sAnimSpriteIndexArray[i] |= 0xFFFF; + + // clear anim args. + for (i = 0; i < ANIM_ARGS_COUNT; i++) + gBattleAnimArgs[i] = 0; + + sMonAnimTaskIdArray[0] = 0xFF; + sMonAnimTaskIdArray[1] = 0xFF; + gAnimMoveTurn = 0; + sAnimBackgroundFadeState = 0; + sAnimMoveIndex = 0; + gAnimBankAttacker = 0; + gAnimBankTarget = 0; + gUnknown_02038440 = 0; +} + +void DoMoveAnim(u16 move) +{ + gAnimBankAttacker = gBankAttacker; + gAnimBankTarget = gBankTarget; + DoBattleAnim(gBattleAnims_Moves, move, TRUE); +} + +void DoBattleAnim(const u8 *const animsTable[], u16 tableId, bool8 isMoveAnim) +{ + s32 i; + + if (!IsContest()) + { + sub_80A8278(); + UpdateOamPriorityInAllHealthboxes(0); + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + { + if (GetBankSide(i) != 0) + gAnimSpeciesByBanks[i] = GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_SPECIES); + else + gAnimSpeciesByBanks[i] = GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_SPECIES); + } + } + else + { + for (i = 0; i < 4; i++) + gAnimSpeciesByBanks[i] = gContestResources->field_18->field_0; + } + + if (!isMoveAnim) + sAnimMoveIndex = 0; + else + sAnimMoveIndex = tableId; + + for (i = 0; i < ANIM_ARGS_COUNT; i++) + gBattleAnimArgs[i] = 0; + + sMonAnimTaskIdArray[0] = 0xFF; + sMonAnimTaskIdArray[1] = 0xFF; + sBattleAnimScriptPtr = animsTable[tableId]; + gAnimScriptActive = TRUE; + gAnimFramesToWait = 0; + gAnimScriptCallback = RunAnimScriptCommand; + + for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) + sAnimSpriteIndexArray[i] |= 0xFFFF; + + if (isMoveAnim) + { + for (i = 0; gUnknown_082C8D64[i] != 0xFFFF; i++) + { + if (tableId == gUnknown_082C8D64[i]) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 128); + break; + } + } + } + + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + gBattle_WIN1H = 0; + gBattle_WIN1V = 0; +} + +void DestroyAnimSprite(struct Sprite *sprite) +{ + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gAnimVisualTaskCount--; +} + +void DestroyAnimVisualTask(u8 taskId) +{ + DestroyTask(taskId); + gAnimVisualTaskCount--; +} + +void DestroyAnimSoundTask(u8 taskId) +{ + DestroyTask(taskId); + gAnimSoundTaskCount--; +} + +static void AddSpriteIndex(u16 index) +{ + s32 i; + + for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) + { + if (sAnimSpriteIndexArray[i] == 0xFFFF) + { + sAnimSpriteIndexArray[i] = index; + return; + } + } +} + +static void ClearSpriteIndex(u16 index) +{ + s32 i; + + for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) + { + if (sAnimSpriteIndexArray[i] == index) + { + sAnimSpriteIndexArray[i] |= 0xFFFF; + return; + } + } +} + +static void WaitAnimFrameCount(void) +{ + if (gAnimFramesToWait <= 0) + { + gAnimScriptCallback = RunAnimScriptCommand; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait--; + } +} + +static void RunAnimScriptCommand(void) +{ + do + { + sScriptCmdTable[sBattleAnimScriptPtr[0]](); + } while (gAnimFramesToWait == 0 && gAnimScriptActive); +} + +static void ScriptCmd_loadspritegfx(void) +{ + u16 index; + + sBattleAnimScriptPtr++; + index = SCRIPT_READ_16(sBattleAnimScriptPtr); + LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)]); + LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(index)]); + sBattleAnimScriptPtr += 2; + AddSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); + gAnimFramesToWait = 1; + gAnimScriptCallback = WaitAnimFrameCount; +} + +static void ScriptCmd_unloadspritegfx(void) +{ + u16 index; + + sBattleAnimScriptPtr++; + index = SCRIPT_READ_16(sBattleAnimScriptPtr); + FreeSpriteTilesByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); + FreeSpritePaletteByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); + sBattleAnimScriptPtr += 2; + ClearSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); +} + +static void ScriptCmd_createsprite(void) +{ + s32 i; + const struct SpriteTemplate *template; + u8 argVar; + u8 argsCount; + s16 subpriority; + + sBattleAnimScriptPtr++; + template = (const struct SpriteTemplate *)(SCRIPT_READ_32(sBattleAnimScriptPtr)); + sBattleAnimScriptPtr += 4; + + argVar = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + argsCount = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + for (i = 0; i < argsCount; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + + if (argVar & 0x80) + { + argVar ^= 0x80; + if (argVar >= 0x40) + argVar -= 0x40; + else + argVar *= -1; + + subpriority = sub_80A82E4(gAnimBankTarget) + (s8)(argVar); + } + else + { + if (argVar >= 0x40) + argVar -= 0x40; + else + argVar *= -1; + + subpriority = sub_80A82E4(gAnimBankAttacker) + (s8)(argVar); + } + + if (subpriority < 3) + subpriority = 3; + + CreateSpriteAndAnimate(template, sub_80A5C6C(gAnimBankTarget, 2), sub_80A5C6C(gAnimBankTarget, 3), subpriority); + gAnimVisualTaskCount++; +} + +static void ScriptCmd_createvisualtask(void) +{ + TaskFunc taskFunc; + u8 taskPriority; + u8 taskId; + u8 numArgs; + s32 i; + + sBattleAnimScriptPtr++; + + taskFunc = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 4; + + taskPriority = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + numArgs = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + for (i = 0; i < numArgs; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + + taskId = CreateTask(taskFunc, taskPriority); + taskFunc(taskId); + gAnimVisualTaskCount++; +} + +static void ScriptCmd_delay(void) +{ + sBattleAnimScriptPtr++; + gAnimFramesToWait = sBattleAnimScriptPtr[0]; + if (gAnimFramesToWait == 0) + gAnimFramesToWait = -1; + sBattleAnimScriptPtr++; + gAnimScriptCallback = WaitAnimFrameCount; +} + +// wait for visual tasks to finish. +static void ScriptCmd_waitforvisualfinish(void) +{ + if (gAnimVisualTaskCount == 0) + { + sBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_hang1(void) +{ +} + +static void ScriptCmd_hang2(void) +{ +} + +static void ScriptCmd_end(void) +{ + s32 i; + bool32 continuousAnim = FALSE; + + // keep waiting as long as there is animations to be done. + if (gAnimVisualTaskCount != 0 || gAnimSoundTaskCount != 0 + || sMonAnimTaskIdArray[0] != 0xFF || sMonAnimTaskIdArray[1] != 0xFF) + { + sSoundAnimFramesToWait = 0; + gAnimFramesToWait = 1; + return; + } + + // finish the sound effects. + if (IsSEPlaying()) + { + if (++sSoundAnimFramesToWait <= 90) // wait 90 frames, then halt the sound effect. + { + gAnimFramesToWait = 1; + return; + } + else + { + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + } + } + + // the SE has halted, so set the SE Frame Counter to 0 and continue. + sSoundAnimFramesToWait = 0; + + for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) + { + if (sAnimSpriteIndexArray[i] != 0xFFFF) + { + FreeSpriteTilesByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag); + FreeSpritePaletteByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag); + sAnimSpriteIndexArray[i] |= 0xFFFF; // set terminator. + } + } + + if (!continuousAnim) // may have been used for debug? + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256); + if (!IsContest()) + { + sub_80A8278(); + UpdateOamPriorityInAllHealthboxes(1); + } + gAnimScriptActive = FALSE; + } +} + +static void ScriptCmd_playse(void) +{ + sBattleAnimScriptPtr++; + PlaySE(SCRIPT_READ_16(sBattleAnimScriptPtr)); + sBattleAnimScriptPtr += 2; +} + +#define t1_MONBG_BANK 0 +#define t1_MON_IN_BG2 1 +#define t1_CREATE_ANOTHER_TASK 2 +#define t1_IS_SECONDMON_BG 3 + +#define t2_BANK_SPRITE_ID 0 +#define t2_MON_IN_BG2 5 +#define t2_MONBG_BANK 6 + +static void sub_80A40F4(u8 taskId) +{ + u8 newTaskId; + + s16 *selfData = gTasks[taskId].data; + u8 bankSpriteId = gBankSpriteIds[selfData[t1_MONBG_BANK]]; + gSprites[bankSpriteId].invisible = 1; + + if (!selfData[t1_CREATE_ANOTHER_TASK]) + { + DestroyAnimVisualTask(taskId); + return; + } + + newTaskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10); + gTasks[newTaskId].data[t2_BANK_SPRITE_ID] = bankSpriteId; + gTasks[newTaskId].data[1] = gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x; + gTasks[newTaskId].data[2] = gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y; + + if (!selfData[t1_MON_IN_BG2]) + { + gTasks[newTaskId].data[3] = gBattle_BG1_X; + gTasks[newTaskId].data[4] = gBattle_BG1_Y; + } + else + { + gTasks[newTaskId].data[3] = gBattle_BG2_X; + gTasks[newTaskId].data[4] = gBattle_BG2_Y; + } + + gTasks[newTaskId].data[t2_MON_IN_BG2] = selfData[t1_MON_IN_BG2]; + gTasks[newTaskId].data[t2_MONBG_BANK] = selfData[t1_MONBG_BANK]; + sMonAnimTaskIdArray[selfData[t1_IS_SECONDMON_BG]] = newTaskId; + DestroyAnimVisualTask(taskId); +} + +static void ScriptCmd_monbg(void) +{ + bool8 toBG_2; + u8 taskId; + u8 bank; + u8 animBank; + + sBattleAnimScriptPtr++; + + animBank = sBattleAnimScriptPtr[0]; + if (animBank & ANIM_BANK_TARGET) + bank = gAnimBankTarget; + else + bank = gAnimBankAttacker; + + 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); + taskId = CreateTask(sub_80A40F4, 10); + gAnimVisualTaskCount++; + gTasks[taskId].data[t1_MONBG_BANK] = bank; + gTasks[taskId].data[t1_MON_IN_BG2] = toBG_2; + gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; + gTasks[taskId].data[t1_IS_SECONDMON_BG] = 0; + + } + + bank ^= BIT_MON; + 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); + taskId = CreateTask(sub_80A40F4, 10); + gAnimVisualTaskCount++; + gTasks[taskId].data[0] = bank; + gTasks[taskId].data[1] = toBG_2; + gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; + gTasks[taskId].data[t1_IS_SECONDMON_BG] = 1; + } + + sBattleAnimScriptPtr++; + gAnimFramesToWait = 1; + gAnimScriptCallback = WaitAnimFrameCount; +} + +bool8 IsAnimBankSpriteVisible(u8 bank) +{ + if (IsContest()) + { + if (bank == gAnimBankAttacker) + return TRUE; + else + return FALSE; + } + if (!AnimBankSpriteExists(bank)) + return FALSE; + if (IsContest()) + return TRUE; // this line wont ever be reached. + if (!gBattleSpritesDataPtr->bankData[bank].invisible || !gSprites[gBankSpriteIds[bank]].invisible) + return TRUE; + + return FALSE; +} + +void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) +{ + struct UnknownAnimStruct2 unknownStruct; + u8 bankSpriteId; + + if (!toBG_2) + { + u8 bankIdentity; + + if (IsContest() == TRUE) + { + RequestDma3Fill(0, (void*)(VRAM + 0x8000), 0x2000, 1); + RequestDma3Fill(0xFF, (void*)(VRAM + 0xF000), 0x1000, 0); + } + else + { + RequestDma3Fill(0, (void*)(VRAM + 0x4000), 0x2000, 1); + RequestDma3Fill(0xFF, (void*)(VRAM + 0xe000), 0x1000, 0); + } + + sub_80A6B30(&unknownStruct); + CpuFill16(0, unknownStruct.unk0, 0x1000); + CpuFill16(0xFF, unknownStruct.unk4, 0x800); + + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 1); + SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 0); + + bankSpriteId = gBankSpriteIds[bank]; + + gBattle_BG1_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; + if (IsContest() && IsSpeciesNotUnown(gContestResources->field_18->field_0)) + gBattle_BG1_X--; + + gBattle_BG1_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; + if (setSpriteInvisible) + gSprites[gBankSpriteIds[bank]].invisible = 1; + + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + + LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], unknownStruct.unk8 * 16, 0x20); + CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + unknownStruct.unk8 * 32), 0x20); + + if (IsContest()) + bankIdentity = 0; + else + bankIdentity = GetBankIdentity(bank); + + sub_8118FBC(1, 0, 0, bankIdentity, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA); + + if (IsContest()) + sub_80A46A0(); + } + else + { + 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.unk4 + 0x400, 0x800); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 1); + SetAnimBgAttribute(2, BG_ANIM_AREA_OVERFLOW_MODE, 0); + + bankSpriteId = gBankSpriteIds[bank]; + + gBattle_BG2_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; + gBattle_BG2_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; + + if (setSpriteInvisible) + gSprites[gBankSpriteIds[bank]].invisible = 1; + + SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X); + SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y); + + LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], 0x90, 0x20); + CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + 0x120), 0x20); + + sub_8118FBC(2, 0, 0, GetBankIdentity(bank), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA); + } +} + +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 spriteId, palIndex; + s16 x, y; + struct UnknownAnimStruct2 unknownStruct; + + spriteId = gTasks[taskId].data[0]; + palIndex = gTasks[taskId].data[6]; + sub_80A6B30(&unknownStruct); + x = gTasks[taskId].data[1] - (gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x); + y = gTasks[taskId].data[2] - (gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y); + + if (gTasks[taskId].data[5] == 0) + { + u16 *src; + u16 *dst; + + gBattle_BG1_X = x + gTasks[taskId].data[3]; + gBattle_BG1_Y = y + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + palIndex * 16; + dst = gPlttBufferFaded + 0x100 + unknownStruct.unk8 * 16 - 256; + CpuCopy32(src, dst, 0x20); + } + else + { + u16 *src; + u16 *dst; + + gBattle_BG2_X = x + gTasks[taskId].data[3]; + gBattle_BG2_Y = y + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + palIndex * 16; + dst = gPlttBufferFaded + 0x100 - 112; + CpuCopy32(src, dst, 0x20); + } +} + +static void ScriptCmd_clearmonbg(void) +{ + u8 animBankId; + u8 bank; + u8 taskId; + + sBattleAnimScriptPtr++; + animBankId = sBattleAnimScriptPtr[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 (sMonAnimTaskIdArray[0] != 0xFF) + gSprites[gBankSpriteIds[bank]].invisible = 0; + if (animBankId > 1 && sMonAnimTaskIdArray[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; + + sBattleAnimScriptPtr++; +} + +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 (sMonAnimTaskIdArray[0] != 0xFF) + { + sub_80A477C(to_BG2); + DestroyTask(sMonAnimTaskIdArray[0]); + sMonAnimTaskIdArray[0] = 0xFF; + } + if (gTasks[taskId].data[0] > 1) + { + sub_80A477C(to_BG2 ^ 1); + DestroyTask(sMonAnimTaskIdArray[1]); + sMonAnimTaskIdArray[1] = 0xFF; + } + DestroyTask(taskId); + } +} + +static void ScriptCmd_monbg_22(void) +{ + bool8 toBG_2; + u8 bank; + u8 animBankId; + + sBattleAnimScriptPtr++; + + animBankId = sBattleAnimScriptPtr[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); + } + + sBattleAnimScriptPtr++; +} + +static void ScriptCmd_clearmonbg_23(void) +{ + u8 animBankId; + u8 bank; + u8 taskId; + + sBattleAnimScriptPtr++; + animBankId = sBattleAnimScriptPtr[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; + + sBattleAnimScriptPtr++; +} + +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; + + sBattleAnimScriptPtr++; + half1 = *(sBattleAnimScriptPtr++); + half2 = *(sBattleAnimScriptPtr++) << 8; + SetGpuReg(REG_OFFSET_BLDCNT, 0x3F40); + SetGpuReg(REG_OFFSET_BLDALPHA, half1 | half2); +} + +static void ScriptCmd_setbldcnt(void) +{ + u16 half1, half2; + + sBattleAnimScriptPtr++; + half1 = *(sBattleAnimScriptPtr++); + half2 = *(sBattleAnimScriptPtr++) << 8; + SetGpuReg(REG_OFFSET_BLDCNT, half1 | half2); +} + +static void ScriptCmd_blendoff(void) +{ + sBattleAnimScriptPtr++; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); +} + +static void ScriptCmd_call(void) +{ + sBattleAnimScriptPtr++; + sBattleAnimScriptRetAddr = sBattleAnimScriptPtr + 4; + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); +} + +static void ScriptCmd_return(void) +{ + sBattleAnimScriptPtr = sBattleAnimScriptRetAddr; +} + +static void ScriptCmd_setarg(void) +{ + const u8 *addr = sBattleAnimScriptPtr; + u16 value; + u8 argId; + + sBattleAnimScriptPtr++; + argId = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + value = SCRIPT_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = addr + 4; + gBattleAnimArgs[argId] = value; +} + +static void ScriptCmd_choosetwoturnanim(void) +{ + sBattleAnimScriptPtr++; + if (gAnimMoveTurn & 1) + sBattleAnimScriptPtr += 4; + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); +} + +static void ScriptCmd_jumpifmoveturn(void) +{ + u8 toCheck; + sBattleAnimScriptPtr++; + toCheck = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + if (toCheck == gAnimMoveTurn) + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + else + sBattleAnimScriptPtr += 4; +} + +static void ScriptCmd_jump(void) +{ + sBattleAnimScriptPtr++; + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); +} + +// Uses of this function that rely on a TRUE return are expecting inBattle to not be ticked as defined in contest behavior. As a result, if misused, this function cannot reliably discern between field and contest status and could result in undefined behavior. +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; + + sBattleAnimScriptPtr++; + backgroundId = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + taskId = CreateTask(Task_FadeToBg, 5); + gTasks[taskId].tBackgroundId = backgroundId; + sAnimBackgroundFadeState = 1; +} + +static void ScriptCmd_fadetobgfromset(void) +{ + u8 bg1, bg2, bg3; + u8 taskId; + + sBattleAnimScriptPtr++; + bg1 = sBattleAnimScriptPtr[0]; + bg2 = sBattleAnimScriptPtr[1]; + bg3 = sBattleAnimScriptPtr[2]; + sBattleAnimScriptPtr += 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; + + sAnimBackgroundFadeState = 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++; + sAnimBackgroundFadeState = 2; + } + else if (gTasks[taskId].tState == 2) + { + s16 bgId = 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); + sAnimBackgroundFadeState = 0; + } +} + +static void LoadMoveBg(u16 bgId) +{ + if (IsContest()) + { + const 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 + DrawMainBattleBackground(); +} + +static void ScriptCmd_restorebg(void) +{ + u8 taskId; + + sBattleAnimScriptPtr++; + taskId = CreateTask(Task_FadeToBg, 5); + gTasks[taskId].tBackgroundId = -1; + sAnimBackgroundFadeState = 1; +} + +#undef tBackgroundId +#undef tState + +static void ScriptCmd_waitbgfadeout(void) +{ + if (sAnimBackgroundFadeState == 2) + { + sBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_waitbgfadein(void) +{ + if (sAnimBackgroundFadeState == 0) + { + sBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_changebg(void) +{ + sBattleAnimScriptPtr++; + LoadMoveBg(sBattleAnimScriptPtr[0]); + sBattleAnimScriptPtr++; +} + +s8 BattleAnimAdjustPanning(s8 pan) +{ + if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10) + { + if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER) + pan = PAN_ATTACKER_OPPONENT; + else + pan = PAN_ATTACKER_PLAYER; + } + else if (IsContest()) + { + if (gAnimBankAttacker != gAnimBankTarget || gAnimBankAttacker != 2 || pan != PAN_ATTACKER_OPPONENT) + pan *= -1; + } + else if (GetBankSide(gAnimBankAttacker) == SIDE_PLAYER) + { + if (GetBankSide(gAnimBankTarget) == SIDE_PLAYER) + { + if (pan == PAN_ATTACKER_OPPONENT) + pan = PAN_ATTACKER_PLAYER; + else if (pan != PAN_ATTACKER_PLAYER) + pan *= -1; + } + } + else if (GetBankSide(gAnimBankTarget) == SIDE_OPPONENT) + { + if (pan == PAN_ATTACKER_PLAYER) + pan = PAN_ATTACKER_OPPONENT; + } + else + { + pan *= -1; + } + + if (pan > PAN_ATTACKER_OPPONENT) + pan = PAN_ATTACKER_OPPONENT; + else if (pan < PAN_ATTACKER_PLAYER) + pan = PAN_ATTACKER_PLAYER; + + return pan; +} + +s8 BattleAnimAdjustPanning2(s8 pan) +{ + if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10) + { + if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER) + pan = PAN_ATTACKER_OPPONENT; + else + pan = PAN_ATTACKER_PLAYER; + } + 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 CalculatePanIncrement(s16 sourcePan, s16 targetPan, s16 incrementPan) +{ + s16 ret; + + if (sourcePan < targetPan) + ret = ((incrementPan < 0) ? -incrementPan : incrementPan); + else if (sourcePan > targetPan) + ret = -((incrementPan < 0) ? -incrementPan : incrementPan); + else + ret = 0; + + return ret; +} + +static void ScriptCmd_playsewithpan(void) +{ + u16 songId; + s8 pan; + + sBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + pan = sBattleAnimScriptPtr[2]; + PlaySE12WithPanning(songId, BattleAnimAdjustPanning(pan)); + sBattleAnimScriptPtr += 3; +} + +static void ScriptCmd_setpan(void) +{ + s8 pan; + + sBattleAnimScriptPtr++; + pan = sBattleAnimScriptPtr[0]; + SE12PanpotControl(BattleAnimAdjustPanning(pan)); + sBattleAnimScriptPtr++; +} + +#define tInitialPan data[0] +#define tTargetPan data[1] +#define tIncrementPan data[2] +#define tFramesToWait data[3] +#define tCurrentPan data[4] +#define tFrameCounter data[8] + +static void ScriptCmd_panse_1B(void) +{ + u16 songNum; + s8 currentPanArg, incrementPan, incrementPanArg, currentPan, targetPan; + u8 framesToWait; + u8 taskId; + + sBattleAnimScriptPtr++; + songNum = SCRIPT_READ_16(sBattleAnimScriptPtr); + currentPanArg = sBattleAnimScriptPtr[2]; + incrementPan = sBattleAnimScriptPtr[3]; + incrementPanArg = sBattleAnimScriptPtr[4]; + framesToWait = sBattleAnimScriptPtr[5]; + + currentPan = BattleAnimAdjustPanning(currentPanArg); + targetPan = BattleAnimAdjustPanning(incrementPan); + incrementPan = CalculatePanIncrement(currentPan, targetPan, incrementPanArg); + taskId = CreateTask(Task_PanFromInitialToTarget, 1); + gTasks[taskId].tInitialPan = currentPan; + gTasks[taskId].tTargetPan = targetPan; + gTasks[taskId].tIncrementPan = incrementPan; + gTasks[taskId].tFramesToWait = framesToWait; + gTasks[taskId].tCurrentPan = currentPan; + + PlaySE12WithPanning(songNum, currentPan); + + gAnimSoundTaskCount++; + sBattleAnimScriptPtr += 6; +} + +void Task_PanFromInitialToTarget(u8 taskId) +{ + bool32 destroyTask = FALSE; + if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait) + { + s16 pan; + s16 initialPanning, targetPanning, currentPan, incrementPan; + + gTasks[taskId].tFrameCounter = 0; + initialPanning = gTasks[taskId].tInitialPan; + targetPanning = gTasks[taskId].tTargetPan; + currentPan = gTasks[taskId].tCurrentPan; + incrementPan = gTasks[taskId].tIncrementPan; + pan = currentPan + incrementPan; + gTasks[taskId].tCurrentPan = pan; + + if (incrementPan == 0) // If we're not incrementing, just cancel the task immediately + { + destroyTask = TRUE; + } + else if (initialPanning < targetPanning) // Panning increasing + { + if (pan >= targetPanning) // Target reached + destroyTask = TRUE; + } + else // Panning decreasing + { + if (pan <= targetPanning) // Target reached + destroyTask = TRUE; + } + + if (destroyTask) + { + pan = targetPanning; + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + + SE12PanpotControl(pan); + } +} + +static void ScriptCmd_panse_26(void) +{ + u16 songId; + s8 currentPan, targetPan, incrementPan; + u8 framesToWait; + u8 taskId; + + sBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + currentPan = sBattleAnimScriptPtr[2]; + targetPan = sBattleAnimScriptPtr[3]; + incrementPan = sBattleAnimScriptPtr[4]; + framesToWait = sBattleAnimScriptPtr[5]; + + taskId = CreateTask(Task_PanFromInitialToTarget, 1); + gTasks[taskId].tInitialPan = currentPan; + gTasks[taskId].tTargetPan = targetPan; + gTasks[taskId].tIncrementPan = incrementPan; + gTasks[taskId].tFramesToWait = framesToWait; + gTasks[taskId].tCurrentPan = currentPan; + + PlaySE12WithPanning(songId, currentPan); + + gAnimSoundTaskCount++; + sBattleAnimScriptPtr += 6; +} + +static void ScriptCmd_panse_27(void) +{ + u16 songId; + s8 targetPanArg, incrementPanArg, currentPanArg, currentPan, targetPan, incrementPan; + u8 framesToWait; + u8 taskId; + + sBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + currentPanArg = sBattleAnimScriptPtr[2]; + targetPanArg = sBattleAnimScriptPtr[3]; + incrementPanArg = sBattleAnimScriptPtr[4]; + framesToWait = sBattleAnimScriptPtr[5]; + + currentPan = BattleAnimAdjustPanning2(currentPanArg); + targetPan = BattleAnimAdjustPanning2(targetPanArg); + incrementPan = BattleAnimAdjustPanning2(incrementPanArg); + + taskId = CreateTask(Task_PanFromInitialToTarget, 1); + gTasks[taskId].tInitialPan = currentPan; + gTasks[taskId].tTargetPan = targetPan; + gTasks[taskId].tIncrementPan = incrementPan; + gTasks[taskId].tFramesToWait = framesToWait; + gTasks[taskId].tCurrentPan = currentPan; + + PlaySE12WithPanning(songId, currentPan); + + gAnimSoundTaskCount++; + sBattleAnimScriptPtr += 6; +} + +#undef tInitialPan +#undef tTargetPan +#undef tIncrementPan +#undef tFramesToWait +#undef tCurrentPan +#undef tFrameCounter + +#define tSongId data[0] +#define tPanning data[1] +#define tFramesToWait data[2] +#define tNumberOfPlays data[3] +#define tFrameCounter data[8] + +static void ScriptCmd_loopsewithpan(void) +{ + u16 songId; + s8 panningArg, panning; + u8 framesToWait, numberOfPlays; + u8 taskId; + + sBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + panningArg = sBattleAnimScriptPtr[2]; + framesToWait = sBattleAnimScriptPtr[3]; + numberOfPlays = sBattleAnimScriptPtr[4]; + panning = BattleAnimAdjustPanning(panningArg); + + taskId = CreateTask(Task_LoopAndPlaySE, 1); + gTasks[taskId].tSongId = songId; + gTasks[taskId].tPanning = panning; + gTasks[taskId].tFramesToWait = framesToWait; + gTasks[taskId].tNumberOfPlays = numberOfPlays; + gTasks[taskId].tFrameCounter = framesToWait; + gTasks[taskId].func(taskId); + + gAnimSoundTaskCount++; + sBattleAnimScriptPtr += 5; +} + +static void Task_LoopAndPlaySE(u8 taskId) +{ + if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait) + { + u16 songId; + s8 panning; + u8 numberOfPlays; + + gTasks[taskId].tFrameCounter = 0; + songId = gTasks[taskId].tSongId; + panning = gTasks[taskId].tPanning; + numberOfPlays = --gTasks[taskId].tNumberOfPlays; + PlaySE12WithPanning(songId, panning); + if (numberOfPlays == 0) + { + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + } +} + +#undef tSongId +#undef tPanning +#undef tFramesToWait +#undef tNumberOfPlays +#undef tFrameCounter + +#define tSongId data[0] +#define tPanning data[1] +#define tFramesToWait data[2] + +static void ScriptCmd_waitplaysewithpan(void) +{ + u16 songId; + s8 panningArg, panning; + u8 framesToWait; + u8 taskId; + + sBattleAnimScriptPtr++; + songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + panningArg = sBattleAnimScriptPtr[2]; + framesToWait = sBattleAnimScriptPtr[3]; + panning = BattleAnimAdjustPanning(panningArg); + + taskId = CreateTask(Task_WaitAndPlaySE, 1); + gTasks[taskId].tSongId = songId; + gTasks[taskId].tPanning = panning; + gTasks[taskId].tFramesToWait = framesToWait; + + gAnimSoundTaskCount++; + sBattleAnimScriptPtr += 4; +} + +static void Task_WaitAndPlaySE(u8 taskId) +{ + if (gTasks[taskId].tFramesToWait-- <= 0) + { + PlaySE12WithPanning(gTasks[taskId].tSongId, gTasks[taskId].tPanning); + DestroyTask(taskId); + gAnimSoundTaskCount--; + } +} + +#undef tSongId +#undef tPanning +#undef tFramesToWait + +static void ScriptCmd_createsoundtask(void) +{ + TaskFunc func; + u8 numArgs, taskId; + s32 i; + + sBattleAnimScriptPtr++; + func = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 4; + numArgs = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + for (i = 0; i < numArgs; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + taskId = CreateTask(func, 1); + func(taskId); + gAnimSoundTaskCount++; +} + +static void ScriptCmd_waitsound(void) +{ + if (gAnimSoundTaskCount != 0) + { + sSoundAnimFramesToWait = 0; + gAnimFramesToWait = 1; + } + else if (IsSEPlaying()) + { + if (++sSoundAnimFramesToWait > 90) + { + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + sSoundAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } + } + else + { + sSoundAnimFramesToWait = 0; + sBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } +} + +static void ScriptCmd_jumpargeq(void) +{ + u8 argId; + s16 valueToCheck; + + sBattleAnimScriptPtr++; + argId = sBattleAnimScriptPtr[0]; + valueToCheck = SCRIPT_READ_16(sBattleAnimScriptPtr + 1); + + if (valueToCheck == gBattleAnimArgs[argId]) + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr + 3); + else + sBattleAnimScriptPtr += 7; +} + +static void ScriptCmd_jumpifcontest(void) +{ + sBattleAnimScriptPtr++; + if (IsContest()) + sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + else + sBattleAnimScriptPtr += 4; +} + +static void ScriptCmd_monbgprio_28(void) +{ + u8 wantedBank; + u8 bank; + u8 bankIdentity; + + wantedBank = sBattleAnimScriptPtr[1]; + sBattleAnimScriptPtr += 2; + + if (wantedBank != ANIM_BANK_ATTACKER) + bank = gAnimBankTarget; + else + bank = gAnimBankAttacker; + + bankIdentity = GetBankIdentity(bank); + if (!IsContest() && (bankIdentity == IDENTITY_PLAYER_MON1 || bankIdentity == IDENTITY_OPPONENT_MON2)) + { + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + } +} + +static void ScriptCmd_monbgprio_29(void) +{ + sBattleAnimScriptPtr++; + if (!IsContest()) + { + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + } +} + +static void ScriptCmd_monbgprio_2A(void) +{ + u8 wantedBank; + u8 bankIdentity; + u8 bank; + + wantedBank = sBattleAnimScriptPtr[1]; + sBattleAnimScriptPtr += 2; + if (GetBankSide(gAnimBankAttacker) != GetBankSide(gAnimBankTarget)) + { + if (wantedBank != ANIM_BANK_ATTACKER) + bank = gAnimBankTarget; + else + bank = gAnimBankAttacker; + + bankIdentity = GetBankIdentity(bank); + if (!IsContest() && (bankIdentity == IDENTITY_PLAYER_MON1 || bankIdentity == IDENTITY_OPPONENT_MON2)) + { + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + } + } +} + +static void ScriptCmd_invisible(void) +{ + u8 spriteId; + + spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]); + if (spriteId != 0xFF) + gSprites[spriteId].invisible = 1; + + sBattleAnimScriptPtr += 2; +} + +static void ScriptCmd_visible(void) +{ + u8 spriteId; + + spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]); + if (spriteId != 0xFF) + gSprites[spriteId].invisible = 0; + + sBattleAnimScriptPtr += 2; +} + +static void ScriptCmd_doublebattle_2D(void) +{ + u8 wantedBank; + u8 r4; + u8 spriteId; + + wantedBank = sBattleAnimScriptPtr[1]; + sBattleAnimScriptPtr += 2; + if (!IsContest() && IsDoubleBattle() + && GetBankSide(gAnimBankAttacker) == GetBankSide(gAnimBankTarget)) + { + if (wantedBank == ANIM_BANK_ATTACKER) + { + r4 = sub_80A8364(gAnimBankAttacker); + spriteId = GetAnimBankSpriteId(0); + } + else + { + r4 = sub_80A8364(gAnimBankTarget); + spriteId = GetAnimBankSpriteId(1); + } + if (spriteId != 0xFF) + { + gSprites[spriteId].invisible = FALSE; + if (r4 == 2) + gSprites[spriteId].oam.priority = 3; + + if (r4 == 1) + sub_80A477C(FALSE); + else + sub_80A477C(TRUE); + } + } +} + +static void ScriptCmd_doublebattle_2E(void) +{ + u8 wantedBank; + u8 r4; + u8 spriteId; + + wantedBank = sBattleAnimScriptPtr[1]; + sBattleAnimScriptPtr += 2; + if (!IsContest() && IsDoubleBattle() + && GetBankSide(gAnimBankAttacker) == GetBankSide(gAnimBankTarget)) + { + if (wantedBank == ANIM_BANK_ATTACKER) + { + r4 = sub_80A8364(gAnimBankAttacker); + spriteId = GetAnimBankSpriteId(0); + } + else + { + r4 = sub_80A8364(gAnimBankTarget); + spriteId = GetAnimBankSpriteId(1); + } + + if (spriteId != 0xFF && r4 == 2) + gSprites[spriteId].oam.priority = 2; + } +} + +static void ScriptCmd_stopsound(void) +{ + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + sBattleAnimScriptPtr++; +} diff --git a/src/battle_controllers.c b/src/battle_controllers.c new file mode 100644 index 000000000..9ac18c72f --- /dev/null +++ b/src/battle_controllers.c @@ -0,0 +1,1551 @@ +#include "global.h" +#include "battle.h" +#include "battle_controllers.h" +#include "link.h" +#include "task.h" +#include "battle_ai_script_commands.h" +#include "battle_anim.h" +#include "pokemon.h" +#include "species.h" +#include "recorded_battle.h" +#include "util.h" +#include "abilities.h" +#include "battle_message.h" + +extern u32 gBattleTypeFlags; +extern u32 gBattleExecBuffer; +extern void (*gBattleMainFunc)(void); +extern void (*gBattleBankFunc[BATTLE_BANKS_COUNT])(void); +extern u8 gBanksByIdentity[BATTLE_BANKS_COUNT]; +extern u8 gActionSelectionCursor[BATTLE_BANKS_COUNT]; +extern u8 gMoveSelectionCursor[BATTLE_BANKS_COUNT]; +extern u8 gNoOfAllBanks; +extern u8 gActiveBank; +extern u8 gUnknown_0202428C; +extern u32 gUnknown_02022FF4; +extern u8 gUnknown_0203C7B4; +extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; +extern u8 gBattleBufferA[BATTLE_BANKS_COUNT][0x200]; +extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200]; +extern u8 gBattleBuffersTransferData[0x100]; +extern u8 gUnknown_02022D08; +extern u8 gUnknown_02022D09; +extern u8 gUnknown_02022D0A; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u8 gAbsentBankFlags; +extern u8 gEffectBank; +extern u16 gBattleWeather; +extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT]; +extern u16 gCurrentMove; +extern u16 gLastUsedMove; +extern u16 gLastUsedItem; +extern u8 gBattleOutcome; +extern u8 gLastUsedAbility; +extern u8 gStringBank; + +extern const struct BattleMove gBattleMoves[]; + +extern void task00_08081A90(u8 taskId); // cable_club +extern void sub_81B8D64(u8 bank, u8 arg1); // party_menu + +// this file's funcionts +static void CreateTasksForSendRecvLinkBuffers(void); +static void SetControllersVariablesInLinkBattle(void); +static void SetControllersVariables(void); +static void SetBattlePartyIds(void); +static void Task_HandleSendLinkBuffersData(u8 taskId); +static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId); + +void HandleLinkBattleSetup(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (gLinkVSyncDisabled) + sub_800B488(); + if (!gReceivedRemoteLinkPlayers) + sub_8009734(); + CreateTask(task00_08081A90, 0); + CreateTasksForSendRecvLinkBuffers(); + } +} + +void SetUpBattleVarsAndBirchZigzagoon(void) +{ + s32 i; + + gBattleMainFunc = nullsub_20; + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + { + gBattleBankFunc[i] = nullsub_21; + gBanksByIdentity[i] = 0xFF; + gActionSelectionCursor[i] = 0; + gMoveSelectionCursor[i] = 0; + } + + HandleLinkBattleSetup(); + gBattleExecBuffer = 0; + ClearBattleAnimationVars(); + ClearBattleMonForms(); + BattleAI_HandleItemUseBeforeAISetup(0xF); + + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) + { + ZeroEnemyPartyMons(); + CreateMon(&gEnemyParty[0], SPECIES_ZIGZAGOON, 2, 32, 0, 0, 0, 0); + i = 0; + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &i); + } + + gUnknown_02022FF4 = 0; + gUnknown_0202428C = 0; +} + +void sub_8032768(void) +{ + s32 i; + u8 *data; + + if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + sub_8184DA4(1); + else + sub_8184DA4(2); + + if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + sub_8185EB8(); + + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + SetControllersVariablesInLinkBattle(); + else + SetControllersVariables(); + + SetBattlePartyIds(); + + if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + for (i = 0; i < gNoOfAllBanks; i++) + sub_81B8D64(i, 0); + } + + for (i = 0; i < sizeof(gBattleStruct->field_1A4); i++) + *(gBattleStruct->field_1A4 + i) = 0; + + for (i = 0; i < sizeof(gBattleStruct->field_204); i++) + *(gBattleStruct->field_204 + i) = 0; +} + +static void SetControllersVariables(void) +{ + s32 i; + + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + { + gBattleMainFunc = BeginBattleIntro; + + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) + { + gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToPlayerPartnerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + } + else + { + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToPlayerPartnerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + } + + gNoOfAllBanks = 4; + + sub_81B8D64(0, 0); + sub_81B8D64(1, 0); + sub_81B8D64(2, 1); + sub_81B8D64(3, 1); + + gBattlePartyID[0] = 0; + gBattlePartyID[1] = 0; + gBattlePartyID[2] = 3; + gBattlePartyID[3] = 3; + } + else if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + gBattleMainFunc = BeginBattleIntro; + + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + gBattleBankFunc[0] = SetBankFuncToSafariBufferRunCommand; + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) + gBattleBankFunc[0] = SetBankFuncToWallyBufferRunCommand; + else + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gNoOfAllBanks = 2; + + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) + { + if (gBattleTypeFlags & BATTLE_TYPE_x2000000) + { + if (gBattleTypeFlags & BATTLE_TYPE_x80000000) + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gNoOfAllBanks = 2; + } + else // see how the banks are switched + { + gBattleBankFunc[1] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[0] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1; + + gNoOfAllBanks = 2; + } + } + else + { + gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + } + } + } + else + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + + gNoOfAllBanks = 4; + + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[0] = 0; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = 1; + + gBattleBankFunc[2] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[2] = 2; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = 3; + + gNoOfAllBanks = 4; + + sub_81B8D64(0, 0); + sub_81B8D64(1, 0); + sub_81B8D64(2, 1); + sub_81B8D64(3, 1); + + gBattlePartyID[0] = 0; + gBattlePartyID[1] = 0; + gBattlePartyID[2] = 3; + gBattlePartyID[3] = 3; + } + else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + u8 var; // multiplayer Id in a recorded battle? + + for (var = gUnknown_0203C7B4, i = 0; i < BATTLE_BANKS_COUNT; i++) + { + switch (gLinkPlayers[i].lp_field_18) + { + case 0: + case 3: + sub_81B8D64(gLinkPlayers[i].lp_field_18, 0); + break; + case 1: + case 2: + sub_81B8D64(gLinkPlayers[i].lp_field_18, 1); + break; + } + + if (i == var) + { + gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedPlayerBufferRunCommand; + switch (gLinkPlayers[i].lp_field_18) + { + case 0: + case 3: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON1; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON2; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3; + break; + } + } + else if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[var].lp_field_18 & 1)) + || ((gLinkPlayers[i].lp_field_18 & 1) && (gLinkPlayers[var].lp_field_18 & 1))) + { + gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedPlayerBufferRunCommand; + switch (gLinkPlayers[i].lp_field_18) + { + case 0: + case 3: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON1; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON2; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3; + break; + } + } + else + { + gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedOpponentBufferRunCommand; + switch (gLinkPlayers[i].lp_field_18) + { + case 0: + case 3: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_OPPONENT_MON1; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_OPPONENT_MON2; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3; + break; + } + } + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_WILD) + { + gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[2] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + if (gBattleTypeFlags & BATTLE_TYPE_x2000000) + { + gBattleBankFunc[1] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[3] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + } + else + { + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + } + } + else + { + gBattleBankFunc[1] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[3] = SetBankFuncToRecordedPlayerBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_PLAYER_MON2; + + if (gBattleTypeFlags & BATTLE_TYPE_x2000000) + { + gBattleBankFunc[0] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToRecordedOpponentBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2; + } + else + { + gBattleBankFunc[0] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2; + } + } + } + } +} + +static void SetControllersVariablesInLinkBattle(void) +{ + s32 i; + u8 multiplayerId; + + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + if (gBattleTypeFlags & BATTLE_TYPE_WILD) + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gNoOfAllBanks = 2; + } + else + { + gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1; + + gNoOfAllBanks = 2; + } + } + else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (gBattleTypeFlags & BATTLE_TYPE_WILD) + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + + gNoOfAllBanks = 4; + } + else + { + gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[3] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[2] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2; + + gNoOfAllBanks = 4; + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + { + if (gBattleTypeFlags & BATTLE_TYPE_WILD) + { + gBattleMainFunc = BeginBattleIntro; + + gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToLinkPartnerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + + gNoOfAllBanks = 4; + } + else + { + gBattleBankFunc[0] = SetBankFuncToLinkPartnerBufferRunCommand; + gBanksByIdentity[0] = IDENTITY_PLAYER_MON1; + + gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1; + + gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand; + gBanksByIdentity[2] = IDENTITY_PLAYER_MON2; + + gBattleBankFunc[3] = SetBankFuncToLinkOpponentBufferRunCommand; + gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2; + + gNoOfAllBanks = 4; + } + + sub_81B8D64(0, 0); + sub_81B8D64(1, 0); + sub_81B8D64(2, 1); + sub_81B8D64(3, 1); + gBattlePartyID[0] = 0; + gBattlePartyID[1] = 0; + gBattlePartyID[2] = 3; + gBattlePartyID[3] = 3; + } + else + { + multiplayerId = GetMultiplayerId(); + + if (gBattleTypeFlags & BATTLE_TYPE_WILD) + gBattleMainFunc = BeginBattleIntro; + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + { + switch (gLinkPlayers[i].lp_field_18) + { + case 0: + case 3: + sub_81B8D64(gLinkPlayers[i].lp_field_18, 0); + break; + case 1: + case 2: + sub_81B8D64(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: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 0; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[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: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 0; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[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: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 1; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0; + break; + case 1: + case 2: + gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 3; + gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3; + break; + } + } + } + } + + gNoOfAllBanks = 4; + } +} + +static void SetBattlePartyIds(void) +{ + s32 i, j; + + if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + for (i = 0; i < gNoOfAllBanks; i++) + { + for (j = 0; j < 6; j++) + { + if (i < 2) + { + if (GET_BANK_SIDE2(i) == SIDE_PLAYER) + { + if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 + && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE + && 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) != SPECIES_NONE + && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG + && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0) + { + gBattlePartyID[i] = j; + break; + } + } + } + else + { + if (GET_BANK_SIDE2(i) == SIDE_PLAYER) + { + if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 + && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != SPECIES_NONE // 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) != SPECIES_NONE + && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG + && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0 + && gBattlePartyID[i - 2] != j) + { + gBattlePartyID[i] = j; + break; + } + } + } + } + } + + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + gBattlePartyID[1] = 0, gBattlePartyID[3] = 3; + } +} + +static void PrepareBufferDataTransfer(u8 bufferId, u8 *data, u16 size) +{ + s32 i; + + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + PrepareBufferDataTransferLink(bufferId, size, data); + } + else + { + switch (bufferId) + { + 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; + } + } +} + +static void CreateTasksForSendRecvLinkBuffers(void) +{ + gUnknown_02022D08 = CreateTask(Task_HandleSendLinkBuffersData, 0); + gTasks[gUnknown_02022D08].data[11] = 0; + gTasks[gUnknown_02022D08].data[12] = 0; + gTasks[gUnknown_02022D08].data[13] = 0; + gTasks[gUnknown_02022D08].data[14] = 0; + gTasks[gUnknown_02022D08].data[15] = 0; + + gUnknown_02022D09 = CreateTask(Task_HandleCopyReceivedLinkBuffersData, 0); + gTasks[gUnknown_02022D09].data[12] = 0; + gTasks[gUnknown_02022D09].data[13] = 0; + gTasks[gUnknown_02022D09].data[14] = 0; + gTasks[gUnknown_02022D09].data[15] = 0; + + gUnknown_02022D0A = 0; +} + +enum +{ + LINK_BUFF_BUFFER_ID, + LINK_BUFF_ACTIVE_BANK, + LINK_BUFF_ATTACKER, + LINK_BUFF_TARGET, + LINK_BUFF_SIZE_LO, + LINK_BUFF_SIZE_HI, + LINK_BUFF_ABSENT_BANK_FLAGS, + LINK_BUFF_EFFECT_BANK, + LINK_BUFF_DATA +}; + +void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data) +{ + s32 alignedSize; + s32 i; + + alignedSize = size - size % 4 + 4; + if (gTasks[gUnknown_02022D08].data[14] + alignedSize + LINK_BUFF_DATA + 1 > BATTLE_BUFFER_LINK_SIZE) + { + gTasks[gUnknown_02022D08].data[12] = gTasks[gUnknown_02022D08].data[14]; + gTasks[gUnknown_02022D08].data[14] = 0; + } + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_BUFFER_ID] = bufferId; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ACTIVE_BANK] = gActiveBank; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ATTACKER] = gBankAttacker; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_TARGET] = gBankTarget; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_SIZE_LO] = alignedSize; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_SIZE_HI] = (alignedSize & 0x0000FF00) >> 8; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ABSENT_BANK_FLAGS] = gAbsentBankFlags; + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_EFFECT_BANK] = gEffectBank; + + for (i = 0; i < size; i++) + gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_DATA + i] = data[i]; + + gTasks[gUnknown_02022D08].data[14] = gTasks[gUnknown_02022D08].data[14] + alignedSize + LINK_BUFF_DATA; +} + +static void Task_HandleSendLinkBuffersData(u8 taskId) +{ + u16 var; + u16 blockSize; + + 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: + if (gLinkVSyncDisabled) + { + gTasks[taskId].data[11]++; + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + var = 2; + else + var = (gBattleTypeFlags & BATTLE_TYPE_MULTI) ? 4 : 2; + + if (sub_800ABAC() >= var) + { + if (sub_800ABBC()) + { + sub_800A620(); + gTasks[taskId].data[11]++; + } + else + { + 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; + } + blockSize = (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8)) + LINK_BUFF_DATA; + SendBlock(bitmask_all_link_players_but_self(), &gLinkBattleSendBuffer[gTasks[taskId].data[15]], blockSize); + gTasks[taskId].data[11]++; + } + else + { + gTasks[taskId].data[13]--; + break; + } + } + break; + case 4: + if (sub_800A520()) + { + blockSize = gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8); + gTasks[taskId].data[13] = 1; + gTasks[taskId].data[15] = gTasks[taskId].data[15] + blockSize + LINK_BUFF_DATA; + 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_8033648(void) +{ + u8 i; + s32 j; + u16 r6; + u8 *recvBuffer; + u8 *dest; + u8 *src; + + if (gReceivedRemoteLinkPlayers != 0 && (gBattleTypeFlags & BATTLE_TYPE_20)) + { + sub_8011BD0(); + 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_02022D09].data[14] + 9 + r6 > 0x1000) + { + gTasks[gUnknown_02022D09].data[12] = gTasks[gUnknown_02022D09].data[14]; + gTasks[gUnknown_02022D09].data[14] = 0; + } + + dest = &gLinkBattleRecvBuffer[gTasks[gUnknown_02022D09].data[14]]; + src = recvBuffer; + + for (j = 0; j < r6 + 8; j++) + dest[j] = src[j]; + + gTasks[gUnknown_02022D09].data[14] = gTasks[gUnknown_02022D09].data[14] + r6 + 8; + } + } + } +} + +static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) +{ + u16 blockSize; + u8 bank; + u8 var; + + 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; + } + bank = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BANK]; + blockSize = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8); + + switch (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 0]) + { + case 0: + if (gBattleExecBuffer & gBitTable[bank]) + return; + + memcpy(gBattleBufferA[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); + sub_803F850(bank); + + if (!(gBattleTypeFlags & BATTLE_TYPE_WILD)) + { + gBankAttacker = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 2]; + gBankTarget = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 3]; + gAbsentBankFlags = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 6]; + gEffectBank = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 7]; + } + break; + case 1: + memcpy(gBattleBufferB[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); + break; + case 2: + var = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA]; + gBattleExecBuffer &= ~(gBitTable[bank] << (var * 4)); + break; + } + + gTasks[taskId].data[15] = gTasks[taskId].data[15] + blockSize + LINK_BUFF_DATA; + } +} + +void EmitGetMonData(u8 bufferId, u8 arg1, u8 arg2) +{ + gBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA; + gBattleBuffersTransferData[1] = arg1; + gBattleBuffersTransferData[2] = arg2; + gBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitGetRawMonData(u8 bufferId, u8 monId, u8 bytes) +{ + gBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA; + gBattleBuffersTransferData[1] = monId; + gBattleBuffersTransferData[2] = bytes; + gBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitSetMonData(u8 bufferId, u8 request, u8 c, u8 bytes, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA; + gBattleBuffersTransferData[1] = request; + gBattleBuffersTransferData[2] = c; + for (i = 0; i < bytes; i++) + gBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 3 + bytes); +} + +void EmitSetRawMonData(u8 bufferId, u8 monId, u8 bytes, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA; + gBattleBuffersTransferData[1] = monId; + gBattleBuffersTransferData[2] = bytes; + for (i = 0; i < bytes; i++) + gBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, bytes + 3); +} + +void EmitLoadMonSprite(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE; + gBattleBuffersTransferData[1] = 4; + gBattleBuffersTransferData[2] = 4; + gBattleBuffersTransferData[3] = 4; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitSwitchInAnim(u8 bufferId, u8 partyId, bool8 dontClearSubstituteBit) +{ + gBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM; + gBattleBuffersTransferData[1] = partyId; + gBattleBuffersTransferData[2] = dontClearSubstituteBit; + gBattleBuffersTransferData[3] = 5; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitReturnMonToBall(u8 bufferId, u8 arg1) +{ + gBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL; + gBattleBuffersTransferData[1] = arg1; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitDrawTrainerPic(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC; + gBattleBuffersTransferData[1] = 7; + gBattleBuffersTransferData[2] = 7; + gBattleBuffersTransferData[3] = 7; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitTrainerSlide(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE; + gBattleBuffersTransferData[1] = 8; + gBattleBuffersTransferData[2] = 8; + gBattleBuffersTransferData[3] = 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitTrainerSlideBack(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK; + gBattleBuffersTransferData[1] = 9; + gBattleBuffersTransferData[2] = 9; + gBattleBuffersTransferData[3] = 9; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitFaintAnimation(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION; + gBattleBuffersTransferData[1] = 10; + gBattleBuffersTransferData[2] = 10; + gBattleBuffersTransferData[3] = 10; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd11(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_11; + gBattleBuffersTransferData[1] = 11; + gBattleBuffersTransferData[2] = 11; + gBattleBuffersTransferData[3] = 11; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd12(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_12; + gBattleBuffersTransferData[1] = 12; + gBattleBuffersTransferData[2] = 12; + gBattleBuffersTransferData[3] = 12; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitBallThrow(u8 bufferId, u8 caseId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_BALLTHROW; + gBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitPause(u8 bufferId, u8 toWait, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_PAUSE; + gBattleBuffersTransferData[1] = toWait; + for (i = 0; i < toWait * 3; i++) + gBattleBuffersTransferData[2 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, toWait * 3 + 2); +} + +void EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit) +{ + gBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION; + gBattleBuffersTransferData[1] = move; + gBattleBuffersTransferData[2] = (move & 0xFF00) >> 8; + gBattleBuffersTransferData[3] = turnOfMove; + gBattleBuffersTransferData[4] = movePower; + gBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8; + gBattleBuffersTransferData[6] = dmg; + gBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8; + gBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16; + gBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24; + gBattleBuffersTransferData[10] = friendship; + gBattleBuffersTransferData[11] = multihit; + if (WEATHER_HAS_EFFECT2) + { + gBattleBuffersTransferData[12] = gBattleWeather; + gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8; + } + else + { + gBattleBuffersTransferData[12] = 0; + gBattleBuffersTransferData[13] = 0; + } + gBattleBuffersTransferData[14] = 0; + gBattleBuffersTransferData[15] = 0; + memcpy(&gBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 16 + sizeof(struct DisableStruct)); +} + +void EmitPrintString(u8 bufferId, u16 stringID) +{ + s32 i; + struct StringInfoBattle* stringInfo; + + gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING; + gBattleBuffersTransferData[1] = gBattleOutcome; + gBattleBuffersTransferData[2] = stringID; + gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + + stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo->currentMove = gCurrentMove; + stringInfo->lastMove = gLastUsedMove; + stringInfo->lastItem = gLastUsedItem; + stringInfo->lastAbility = gLastUsedAbility; + stringInfo->scrActive = gBattleScripting.bank; + stringInfo->unk1605E = gBattleStruct->field_52; + stringInfo->hpScale = gBattleStruct->hpScale; + stringInfo->StringBank = gStringBank; + stringInfo->moveType = gBattleMoves[gCurrentMove].type; + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + stringInfo->abilities[i] = gBattleMons[i].ability; + for (i = 0; i < TEXT_BUFF_ARRAY_COUNT; i++) + { + stringInfo->textBuffs[0][i] = gBattleTextBuff1[i]; + stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; + stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; + } + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); +} + +void EmitPrintStringPlayerOnly(u8 bufferId, u16 stringID) +{ + s32 i; + struct StringInfoBattle* stringInfo; + + gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY; + gBattleBuffersTransferData[1] = 17; + gBattleBuffersTransferData[2] = stringID; + gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + + stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo->currentMove = gCurrentMove; + stringInfo->lastMove = gLastUsedMove; + stringInfo->lastItem = gLastUsedItem; + stringInfo->lastAbility = gLastUsedAbility; + stringInfo->scrActive = gBattleScripting.bank; + stringInfo->unk1605E = gBattleStruct->field_52; + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + stringInfo->abilities[i] = gBattleMons[i].ability; + for (i = 0; i < TEXT_BUFF_ARRAY_COUNT; i++) + { + stringInfo->textBuffs[0][i] = gBattleTextBuff1[i]; + stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; + stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; + } + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); +} + +void EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2) +{ + gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION; + gBattleBuffersTransferData[1] = arg1; + gBattleBuffersTransferData[2] = arg2; + gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd19(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_19; + gBattleBuffersTransferData[1] = 19; + gBattleBuffersTransferData[2] = 19; + gBattleBuffersTransferData[3] = 19; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE; + gBattleBuffersTransferData[1] = isDoubleBattle; + gBattleBuffersTransferData[2] = NoPpNumber; + gBattleBuffersTransferData[3] = 0; + for (i = 0; i < sizeof(*movePpData); i++) + gBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(*movePpData) + 4); +} + +void EmitOpenBag(u8 bufferId, u8 *arg1) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_OPENBAG; + for (i = 0; i < 3; i++) + gBattleBuffersTransferData[1 + i] = arg1[i]; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8* arg4) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON; + gBattleBuffersTransferData[1] = caseId; + gBattleBuffersTransferData[2] = arg2; + gBattleBuffersTransferData[3] = abilityId; + for (i = 0; i < 3; i++) + gBattleBuffersTransferData[4 + i] = arg4[i]; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 8); // but only 7 bytes were written +} + +void EmitCmd23(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_23; + gBattleBuffersTransferData[1] = 23; + gBattleBuffersTransferData[2] = 23; + gBattleBuffersTransferData[3] = 23; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +// why is the argument u16 if it's being cast to s16 anyway? +void EmitHealthBarUpdate(u8 bufferId, u16 hpValue) +{ + gBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE; + gBattleBuffersTransferData[1] = 0; + gBattleBuffersTransferData[2] = (s16)hpValue; + gBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +// why is the argument u16 if it's being cast to s16 anyway? +void EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints) +{ + gBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE; + gBattleBuffersTransferData[1] = partyId; + gBattleBuffersTransferData[2] = (s16)expPoints; + gBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2) +{ + gBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE; + gBattleBuffersTransferData[1] = status1; + gBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8; + gBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16; + gBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24; + gBattleBuffersTransferData[5] = status2; + gBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8; + gBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16; + gBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 9); +} + +void EmitStatusAnimation(u8 bufferId, bool8 status2, u32 status) +{ + gBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION; + gBattleBuffersTransferData[1] = status2; + gBattleBuffersTransferData[2] = status; + gBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8; + gBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16; + gBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 6); +} + +void EmitStatusXor(u8 bufferId, u8 b) +{ + gBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR; + gBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitDataTransfer(u8 bufferId, u16 size, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER; + gBattleBuffersTransferData[1] = 29; + gBattleBuffersTransferData[2] = size; + gBattleBuffersTransferData[3] = (size & 0xFF00) >> 8; + for (i = 0; i < size; i++) + gBattleBuffersTransferData[4 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 4); +} + +void EmitDMA3Transfer(u8 bufferId, void *dst, u16 size, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER; + gBattleBuffersTransferData[1] = (u32)(dst); + gBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8; + gBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16; + gBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24; + gBattleBuffersTransferData[5] = size; + gBattleBuffersTransferData[6] = (size & 0xFF00) >> 8; + for (i = 0; i < size; i++) + gBattleBuffersTransferData[7 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 7); +} + +void EmitPlayBGM(u8 bufferId, u16 songId, void *unusedDumbDataParameter) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_31; + gBattleBuffersTransferData[1] = songId; + gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + for (i = 0; i < songId; i++) // ???? + gBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, songId + 3); +} + +void EmitCmd32(u8 bufferId, u16 size, void *data) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_32; + gBattleBuffersTransferData[1] = size; + gBattleBuffersTransferData[2] = (size & 0xFF00) >> 8; + for (i = 0; i < size; i++) + gBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 3); +} + +void EmitCmd33(u8 bufferId, u8 arg1, u16 arg2) +{ + gBattleBuffersTransferData[0] = CONTROLLER_33; + gBattleBuffersTransferData[1] = arg1; + gBattleBuffersTransferData[2] = arg2; + gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd34(u8 bufferId, u8 b, u8 *c) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_34; + gBattleBuffersTransferData[1] = b; + for (i = 0; i < 3; i++) + gBattleBuffersTransferData[2 + i] = c[i]; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 5); +} + +void EmitCmd35(u8 bufferId, u16 b) +{ + gBattleBuffersTransferData[0] = CONTROLLER_35; + gBattleBuffersTransferData[1] = b; + gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; + gBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd36(u8 bufferId, u16 b) +{ + gBattleBuffersTransferData[0] = CONTROLLER_36; + gBattleBuffersTransferData[1] = b; + gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; + gBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd37(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_37; + gBattleBuffersTransferData[1] = 37; + gBattleBuffersTransferData[2] = 37; + gBattleBuffersTransferData[3] = 37; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd38(u8 bufferId, u8 b) +{ + gBattleBuffersTransferData[0] = CONTROLLER_38; + gBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitCmd39(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_39; + gBattleBuffersTransferData[1] = 39; + gBattleBuffersTransferData[2] = 39; + gBattleBuffersTransferData[3] = 39; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd40(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_40; + gBattleBuffersTransferData[1] = 40; + gBattleBuffersTransferData[2] = 40; + gBattleBuffersTransferData[3] = 40; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitHitAnimation(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION; + gBattleBuffersTransferData[1] = 41; + gBattleBuffersTransferData[2] = 41; + gBattleBuffersTransferData[3] = 41; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd42(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_42; + gBattleBuffersTransferData[1] = 42; + gBattleBuffersTransferData[2] = 42; + gBattleBuffersTransferData[3] = 42; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitEffectivenessSound(u8 bufferId, u16 songId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND; + gBattleBuffersTransferData[1] = songId; + gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + gBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitPlayFanfareOrBGM(u8 bufferId, u16 songId, bool8 playBGM) +{ + gBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM; + gBattleBuffersTransferData[1] = songId; + gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + gBattleBuffersTransferData[3] = playBGM; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitFaintingCry(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY; + gBattleBuffersTransferData[1] = 45; + gBattleBuffersTransferData[2] = 45; + gBattleBuffersTransferData[3] = 45; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitIntroSlide(u8 bufferId, u8 terrainId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE; + gBattleBuffersTransferData[1] = terrainId; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitIntroTrainerBallThrow(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW; + gBattleBuffersTransferData[1] = 47; + gBattleBuffersTransferData[2] = 47; + gBattleBuffersTransferData[3] = 47; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitDrawPartyStatusSummary(u8 bufferId, struct HpAndStatus* hpAndStatus, u8 arg2) +{ + s32 i; + + gBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; + gBattleBuffersTransferData[1] = arg2 & 0x7F; + gBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7; + gBattleBuffersTransferData[3] = 48; + for (i = 0; i < (s32)(sizeof(struct HpAndStatus) * 6); i++) + gBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus)); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4); +} + +void EmitCmd49(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_49; + gBattleBuffersTransferData[1] = 49; + gBattleBuffersTransferData[2] = 49; + gBattleBuffersTransferData[3] = 49; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitCmd50(u8 bufferId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_50; + gBattleBuffersTransferData[1] = 50; + gBattleBuffersTransferData[2] = 50; + gBattleBuffersTransferData[3] = 50; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitSpriteInvisibility(u8 bufferId, bool8 isInvisible) +{ + gBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY; + gBattleBuffersTransferData[1] = isInvisible; + gBattleBuffersTransferData[2] = 51; + gBattleBuffersTransferData[3] = 51; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitBattleAnimation(u8 bufferId, u8 animationId, u16 argument) +{ + gBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION; + gBattleBuffersTransferData[1] = animationId; + gBattleBuffersTransferData[2] = argument; + gBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); +} + +void EmitLinkStandbyMsg(u8 bufferId, u8 arg1, bool32 arg2) +{ + bool8 arg2_ = arg2; + gBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG; + gBattleBuffersTransferData[1] = arg1; + + if (arg2_) + gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = sub_81850DC(&gBattleBuffersTransferData[4]); + else + gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = 0; + + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[2] + 4); +} + +void EmitResetActionMoveSelection(u8 bufferId, u8 caseId) +{ + gBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION; + gBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); +} + +void EmitCmd55(u8 bufferId, u8 arg1) +{ + gBattleBuffersTransferData[0] = CONTROLLER_55; + gBattleBuffersTransferData[1] = arg1; + gBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b; + gBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b; + gBattleBuffersTransferData[5] = gBattleBuffersTransferData[4] = sub_81850DC(&gBattleBuffersTransferData[6]); + PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[4] + 6); +} diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fb6a8272b..a1e5767ad 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -349,7 +349,7 @@ static void atk51_switch_handle_order(void); static void atk52_switch_in_effects(void); static void atk53_trainer_slide(void); static void atk54_effectiveness_sound(void); -static void atk55_play_sound(void); +static void atk55_play_fanfare(void); static void atk56_fainting_cry(void); static void atk57(void); static void atk58_return_to_ball(void); @@ -601,7 +601,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = atk52_switch_in_effects, atk53_trainer_slide, atk54_effectiveness_sound, - atk55_play_sound, + atk55_play_fanfare, atk56_fainting_cry, atk57, atk58_return_to_ball, @@ -5308,7 +5308,7 @@ static void atk4B_return_atk_to_ball(void) gActiveBank = gBankAttacker; if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank))) { - EmitReturnPokeToBall(0, 0); + EmitReturnMonToBall(0, 0); MarkBufferBankForExecution(gActiveBank); } gBattlescriptCurrInstr++; @@ -5627,7 +5627,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -5649,7 +5649,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -5670,7 +5670,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -5692,7 +5692,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -5755,7 +5755,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -5771,7 +5771,7 @@ static void atk50_openpartyscreen(void) { gAbsentBankFlags |= gBitTable[gActiveBank]; gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); - Emit_x2A(0); + EmitCmd42(0); MarkBufferBankForExecution(gActiveBank); } else if (!gSpecialStatuses[gActiveBank].flag40) @@ -6031,10 +6031,10 @@ static void atk54_effectiveness_sound(void) gBattlescriptCurrInstr += 3; } -static void atk55_play_sound(void) +static void atk55_play_fanfare(void) { gActiveBank = gBankAttacker; - EmitPlaySound(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), 0); + EmitPlayFanfareOrBGM(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), FALSE); MarkBufferBankForExecution(gActiveBank); gBattlescriptCurrInstr += 3; @@ -6052,7 +6052,7 @@ static void atk56_fainting_cry(void) static void atk57(void) { gActiveBank = GetBankByIdentity(0); - Emit_x37(0, gBattleOutcome); + EmitCmd55(0, gBattleOutcome); MarkBufferBankForExecution(gActiveBank); gBattlescriptCurrInstr += 1; @@ -6061,7 +6061,7 @@ static void atk57(void) static void atk58_return_to_ball(void) { gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]); - EmitReturnPokeToBall(0, 1); + EmitReturnMonToBall(0, 1); MarkBufferBankForExecution(gActiveBank); gBattlescriptCurrInstr += 2; @@ -7137,7 +7137,7 @@ static void atk76_various(void) gDisableStructs[1].truantUnknownBit = 1; break; case 13: - EmitCmd13(0); + EmitCmd19(0); MarkBufferBankForExecution(gActiveBank); break; case 14: @@ -7162,7 +7162,7 @@ static void atk76_various(void) gActiveBank = 1; if (gBattleMons[gActiveBank].hp != 0) { - EmitReturnPokeToBall(0, 0); + EmitReturnMonToBall(0, 0); MarkBufferBankForExecution(gActiveBank); } break; @@ -7172,7 +7172,7 @@ static void atk76_various(void) gActiveBank = 3; if (gBattleMons[gActiveBank].hp != 0) { - EmitReturnPokeToBall(0, 0); + EmitReturnMonToBall(0, 0); MarkBufferBankForExecution(gActiveBank); } } @@ -7197,7 +7197,7 @@ static void atk76_various(void) gBattleOutcome = BATTLE_OPPONENT_TELEPORTED; break; case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC: - EmitPlaySound(0, BGM_KACHI1, 1); + EmitPlayFanfareOrBGM(0, BGM_KACHI1, TRUE); MarkBufferBankForExecution(gActiveBank); break; } diff --git a/src/decompress.c b/src/decompress.c index 2863ff1f5..9210799ec 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -465,7 +465,7 @@ u32 sub_8034974(void* ptr) return (ptr_[3] << 16) | (ptr_[2] << 8) | (ptr_[1]); } -bool8 LoadCompressedObjectPicUsingHeap(struct CompressedSpriteSheet* src) +bool8 LoadCompressedObjectPicUsingHeap(const struct CompressedSpriteSheet* src) { struct SpriteSheet dest; void* buffer; diff --git a/src/egg_hatch.c b/src/egg_hatch.c index a1f187b85..589e8901d 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -462,7 +462,7 @@ static void VBlankCB_EggHatch(void) TransferPlttBuffer(); } -static void EggHatch(void) +void EggHatch(void) { ScriptContext2_Enable(); CreateTask(Task_EggHatch, 10); diff --git a/src/safari_zone.c b/src/safari_zone.c index a1ec38920..77c6bbd61 100644 --- a/src/safari_zone.c +++ b/src/safari_zone.c @@ -139,7 +139,7 @@ static void ClearAllPokeblockFeeders(void) memset(sPokeblockFeeders, 0, sizeof(sPokeblockFeeders)); } -static void GetPokeblockFeederInFront(void) +void GetPokeblockFeederInFront(void) { s16 x, y; u16 i; diff --git a/src/sprite.c b/src/sprite.c index 17b0f181a..daa019019 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -594,7 +594,7 @@ u8 CreateSpriteAt(u8 index, const struct SpriteTemplate *template, s16 x, s16 y, return index; } -u8 CreateSpriteAndAnimate(struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority) +u8 CreateSpriteAndAnimate(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority) { u8 i; |