From 200b71be028d6d8781a2e31fe42495d1d0788b3e Mon Sep 17 00:00:00 2001 From: SphericalIce Date: Tue, 27 Dec 2022 10:49:57 +0000 Subject: [PATCH] Fix Beat Up's battle script to avoid an out-of-bounds array access --- asm/macros/battle_script.inc | 2 +- data/battle_scripts_1.s | 16 +++++++++------- include/battle.h | 1 + src/battle_main.c | 1 + src/battle_script_commands.c | 5 +++++ src/battle_util.c | 7 ++++--- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 61ad67549..9ad159ef3 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1022,7 +1022,7 @@ .4byte \ptr .endm - .macro trydobeatup endPtr:req, failPtr:req + .macro trydobeatup endPtr=NULL, failPtr=NULL .byte 0xc4 .4byte \endPtr .4byte \failPtr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3b22a684f..244faf2c6 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5183,10 +5183,18 @@ BattleScript_EffectTeleportNew: BattleScript_EffectTeleportNewEnd: goto BattleScript_MoveEnd -.if B_BEAT_UP < GEN_5 BattleScript_EffectBeatUp:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE +.if B_BEAT_UP >= GEN_5 + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + trydobeatup + goto BattleScript_HitFromAtkAnimation +.else attackstring pause B_WAIT_TIME_SHORT ppreduce @@ -5216,12 +5224,6 @@ BattleScript_BeatUpAttack:: goto BattleScript_BeatUpLoop BattleScript_BeatUpEnd:: end -.else -BattleScript_EffectBeatUp:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - addbyte gBattleCommunication, 1 - goto BattleScript_HitFromAtkString .endif BattleScript_EffectSemiInvulnerable:: diff --git a/include/battle.h b/include/battle.h index a38c28db8..cf06a588a 100644 --- a/include/battle.h +++ b/include/battle.h @@ -650,6 +650,7 @@ struct BattleStruct u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. u8 attackerBeforeBounce:2; + u8 beatUpSlot:3; u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching) }; diff --git a/src/battle_main.c b/src/battle_main.c index d138cf231..d7607e37a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3039,6 +3039,7 @@ static void BattleStartClearSetData(void) gBattleStruct->stickyWebUser = 0xFF; gBattleStruct->appearedInBattle = 0; + gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9c780c28e..44cc43227 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12855,6 +12855,10 @@ static void Cmd_trysetfutureattack(void) static void Cmd_trydobeatup(void) { +#if B_BEAT_UP >= GEN_5 + gBattleStruct->beatUpSlot++; + gBattlescriptCurrInstr += 9; +#else struct Pokemon *party; if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) @@ -12898,6 +12902,7 @@ static void Cmd_trydobeatup(void) else gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 5); } +#endif } static void Cmd_setsemiinvulnerablebit(void) diff --git a/src/battle_util.c b/src/battle_util.c index 00e3b869b..75e77a86b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -230,8 +230,9 @@ static u8 CalcBeatUpPower(void) party = gPlayerParty; else party = gEnemyParty; - // Party slot is set in the battle script for Beat Up - species = GetMonData(&party[gBattleCommunication[0] - 1], MON_DATA_SPECIES); + + // Party slot is incremented by the battle script for Beat Up after this damage calculation + species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); basePower = (gSpeciesInfo[species].baseAttack / 10) + 5; return basePower; @@ -3875,7 +3876,7 @@ u8 AtkCanceller_UnableToUseMove(void) gMultiHitCounter++; } - gBattleCommunication[0] = 0; // For later + gBattleStruct->beatUpSlot = 0; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } #endif