From b464fdbbde0ef50e816d203252ecb1f4d76189d4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 13 Feb 2025 15:13:04 -0500 Subject: [PATCH 01/20] Fix collision comparison in PlayerNotOnBikeMoving --- src/field_player_avatar.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index 1f0708af22..6a1df01b47 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -620,9 +620,27 @@ static void PlayerNotOnBikeMoving(u8 direction, u16 heldKeys) } else { - u8 adjustedCollision = collision - COLLISION_STOP_SURFING; - if (adjustedCollision > 3) + // Player collided with something. Certain collisions have special handling that precludes the normal collision effect. + // COLLISION_STOP_SURFING and COLLISION_PUSHED_BOULDER's effects are started by CheckForObjectEventCollision. + // COLLISION_LEDGE_JUMP's effect is handled further up in this function, so it will never reach this point. + // COLLISION_ROTATING_GATE is unusual however, this was probably included by mistake. When the player walks into a + // rotating gate that cannot rotate there is no additional handling, it's just a regular collision. Its exclusion here + // means that the player avatar won't update if they encounter this kind of collision. This has two noticeable effects: + // - Colliding with it head-on stops the player dead, rather than playing the walking animation and playing a bump sound effect + // - Colliding with it by changing direction won't turn the player avatar, their walking animation will just speed up. +#ifdef BUGFIX + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER) +#else + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER + && collision != COLLISION_ROTATING_GATE) +#endif + { PlayerNotOnBikeCollide(direction); + } return; } } From e2e3438674f1c12df631ba13c9df05ddc83653d0 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 20 Jun 2025 15:33:12 -0400 Subject: [PATCH 02/20] Add missing uses of LOCALID_NONE for trainerbattle --- asm/macros/event.inc | 18 +++++++++--------- .../scripts.inc | 2 +- .../MossdeepCity_SpaceCenter_2F/scripts.inc | 4 ++-- data/scripts/trainer_hill.inc | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 6f17460d43..797d549dc9 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -747,11 +747,11 @@ @ When used with an event script, you can also pass in an optional flag to disable music .macro trainerbattle_single trainer:req, intro_text:req, lose_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_SINGLE, \trainer, 0, \intro_text, \lose_text + trainerbattle TRAINER_BATTLE_SINGLE, \trainer, LOCALID_NONE, \intro_text, \lose_text .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, LOCALID_NONE, \intro_text, \lose_text, \event_script .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, LOCALID_NONE, \intro_text, \lose_text, \event_script .endif .endm @@ -759,27 +759,27 @@ @ and an optional event script. When used with an event script you can pass in an optional flag to disable music .macro trainerbattle_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle TRAINER_BATTLE_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script .endif .endm @ Starts a rematch battle. Takes a trainer, intro text and loss text .macro trainerbattle_rematch trainer:req, intro_text:req, lose_text:req - trainerbattle TRAINER_BATTLE_REMATCH, \trainer, 0, \intro_text, \lose_text + trainerbattle TRAINER_BATTLE_REMATCH, \trainer, LOCALID_NONE, \intro_text, \lose_text .endm @ Starts a rematch double battle. Takes a trainer, intro text, loss text, and text for when you have too few pokemon .macro trainerbattle_rematch_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req - trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, \trainer, 0, \lose_text + trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, \trainer, LOCALID_NONE, \lose_text .endm diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index ba9d996706..021f373be2 100644 --- a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc +++ b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc @@ -105,7 +105,7 @@ BattlePyramid_WarpToTop:: @ TRAINER_PHILLIP is used as a placeholder BattlePyramid_TrainerBattle:: - trainerbattle TRAINER_BATTLE_PYRAMID, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + trainerbattle TRAINER_BATTLE_PYRAMID, TRAINER_PHILLIP, LOCALID_NONE, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText pyramid_showhint waitmessage waitbuttonpress diff --git a/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc b/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc index cbb9cba9af..81ae88e42f 100644 --- a/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc +++ b/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc @@ -329,11 +329,11 @@ MossdeepCity_SpaceCenter_2F_EventScript_StevenFacePlayerWest:: return MossdeepCity_SpaceCenter_2F_EventScript_MaxieTrainer:: - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, TRAINER_MAXIE_MOSSDEEP, 0, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand + trainerbattle TRAINER_BATTLE_SET_TRAINER_A, TRAINER_MAXIE_MOSSDEEP, LOCALID_NONE, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand end MossdeepCity_SpaceCenter_2F_EventScript_TabithaTrainer:: - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, TRAINER_TABITHA_MOSSDEEP, 0, MossdeepCity_SpaceCenter_Text_TabithaDefeat, MossdeepCity_SpaceCenter_Text_TabithaDefeat + trainerbattle TRAINER_BATTLE_SET_TRAINER_B, TRAINER_TABITHA_MOSSDEEP, LOCALID_NONE, MossdeepCity_SpaceCenter_Text_TabithaDefeat, MossdeepCity_SpaceCenter_Text_TabithaDefeat end MossdeepCity_SpaceCenter_2F_EventScript_RivalRayquazaCall:: diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 04bbe05e5a..d51d1f5098 100644 --- a/data/scripts/trainer_hill.inc +++ b/data/scripts/trainer_hill.inc @@ -60,7 +60,7 @@ TrainerHill_1F_Movement_SetInvisible:: @ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here TrainerHill_EventScript_TrainerBattle:: - trainerbattle TRAINER_BATTLE_HILL, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + trainerbattle TRAINER_BATTLE_HILL, TRAINER_PHILLIP, LOCALID_NONE, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText trainerhill_postbattletext waitmessage waitbuttonpress From 98670ca30eef505a8007f456bab87e66490c0413 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Fri, 20 Jun 2025 23:04:01 +0100 Subject: [PATCH 03/20] Fixes Neutralizing Gas leaving the field activating unsuppressable abilities again (#7170) --- asm/macros/battle_script.inc | 6 ++++ data/battle_scripts_1.s | 3 ++ src/battle_script_commands.c | 16 +++++++++- src/battle_util.c | 6 +++- test/battle/ability/neutralizing_gas.c | 41 +++++++++++++++++++++++++- 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index c4bfea9a5f..b524104a36 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2465,6 +2465,12 @@ 1: .endm + .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req + callnative BS_JumpIfAbilityCantBeSuppressed + .byte \battler + .4byte \jumpInstr + .endm + .macro setallytonexttarget jumpInstr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e7e494008a..a10dfaa40c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -9520,9 +9520,12 @@ BattleScript_NeutralizingGasExits:: setbyte gBattlerAttacker, 0 BattleScript_NeutralizingGasExitsLoop: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 + jumpifabilitycantbesuppressed BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement + jumpifability BS_TARGET, ABILITY_IMPOSTER, BattleScript_NeutralizingGasExitsLoopIncrement @ Imposter only activates when first entering the field saveattacker switchinabilities BS_TARGET restoreattacker +BattleScript_NeutralizingGasExitsLoopIncrement: addbyte gBattlerAttacker, 1 jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_NeutralizingGasExitsLoop restoreattacker diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4e6109e93b..bd2ef1509e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7653,7 +7653,7 @@ static void Cmd_switchindataupdate(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif @@ -16542,6 +16542,9 @@ static void Cmd_tryworryseed(void) } else { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18742,3 +18745,14 @@ void BS_JumpIfNoWhiteOut(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_JumpIfAbilityCantBeSuppressed(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 715f8bb3da..ebb11c4c7f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3505,7 +3505,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 u32 diagonalBattler = BATTLE_OPPOSITE(battler); if (IsDoubleBattle()) diagonalBattler = BATTLE_PARTNER(diagonalBattler); - if (IsBattlerAlive(diagonalBattler) + + // Imposter only activates when the battler first switches in + if (gDisableStructs[battler].isFirstTurn == 2 + && !gDisableStructs[battler].overwrittenAbility + && IsBattlerAlive(diagonalBattler) && !(gBattleMons[diagonalBattler].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON diff --git a/test/battle/ability/neutralizing_gas.c b/test/battle/ability/neutralizing_gas.c index 6338bfbeca..f83e928c4a 100644 --- a/test/battle/ability/neutralizing_gas.c +++ b/test/battle/ability/neutralizing_gas.c @@ -256,7 +256,8 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Trace from copying it") SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") { GIVEN { - ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN); PLAYER(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); } OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } } WHEN { @@ -271,3 +272,41 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") EXPECT_LT(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); } } + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate abilities that were not suppressed by it again") +{ + u32 species, ability; + // These are the only abilities that could immediately activate again + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + + GIVEN { + ASSUME(gAbilitiesInfo[ability].cantBeSuppressed); + PLAYER(species) { Ability(ability); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(player, ability); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ability); + } +} + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate Imposter even if it did not activate before") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + } +} From 01fc7e76efc6c8e6790e9585fa6e7056a8841478 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 22 Jun 2025 11:26:31 +0200 Subject: [PATCH 04/20] Fix wrong keep temps files directory in makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index f4aecdc77b..354c335235 100644 --- a/Makefile +++ b/Makefile @@ -313,10 +313,10 @@ ifneq ($(KEEP_TEMPS),1) @echo "$(CC1) -o $@ $<" @$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ - else - @$(CPP) $(CPPFLAGS) $< -o $*.i - @$(PREPROC) $*.i charmap.txt | $(CC1) $(CFLAGS) -o $*.s - @echo -e ".text\n\t.align\t2, 0\n" >> $*.s - $(AS) $(ASFLAGS) -o $@ $*.s + @$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i + @$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s + @echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s + $(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s endif $(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.c From 53f8ae11ff3ccc5333cc70d581b2ac5fd4853883 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 01:48:37 +0200 Subject: [PATCH 05/20] Move gTradePlatform_Tilemap to header (#2088) --- include/trade.h | 1 + src/egg_hatch.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/trade.h b/include/trade.h index 33191f0ac6..24de69b036 100644 --- a/include/trade.h +++ b/include/trade.h @@ -7,6 +7,7 @@ extern struct Mail gTradeMail[PARTY_SIZE]; extern u8 gSelectedTradeMonPositions[2]; +extern const u16 gTradePlatform_Tilemap[]; extern const struct WindowTemplate gTradeEvolutionSceneYesNoWindowTemplate; s32 GetGameProgressForLinkTrade(void); diff --git a/src/egg_hatch.c b/src/egg_hatch.c index abf1aff841..5aa955d7e9 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -33,6 +33,7 @@ #include "naming_screen.h" #include "pokemon_storage_system.h" #include "field_screen_effect.h" +#include "trade.h" #include "data.h" #include "battle.h" // to get rid of later #include "constants/rgb.h" @@ -62,7 +63,6 @@ struct EggHatchData u8 textColor[3]; }; -extern const u32 gTradePlatform_Tilemap[]; extern const u8 gText_HatchedFromEgg[]; extern const u8 gText_NicknameHatchPrompt[]; From 6c6daa8b9cd475122a9110043dba69c7e129f7e6 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:02:51 +0100 Subject: [PATCH 06/20] Fixes Rapid Spin description (#7178) (#7181) --- src/data/moves_info.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index d2e80d787b..51f3438952 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -6050,11 +6050,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rapid Spin"), .description = COMPOUND_STRING( - "Spins attack that removes\n" + "User spins and removes some\n" #if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8 - "some effects and ups speed."), + "effects, while upping speed."), #else - "certain effects."), + "effects."), #endif .effect = EFFECT_RAPID_SPIN, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 50 : 20, From 0dae2cea28a2006d61de73e21940b478e38efa6b Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 10:37:49 +0200 Subject: [PATCH 07/20] force sGFRomHeader to always be present (#7186) --- src/rom_header_gf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rom_header_gf.c b/src/rom_header_gf.c index 182d879c83..5613fe6152 100644 --- a/src/rom_header_gf.c +++ b/src/rom_header_gf.c @@ -99,7 +99,7 @@ struct GFRomHeader // This seems to need to be in the text section for some reason. // To avoid a changed section attributes warning it's put in a special .text.consts section. __attribute__((section(".text.consts"))) -static const struct GFRomHeader sGFRomHeader = { +USED static const struct GFRomHeader sGFRomHeader = { .version = GAME_VERSION, .language = GAME_LANGUAGE, .gameName = "pokemon emerald version", From 7fdc5a45b6fbd9734e9b45e2e52cc3ec8cbd08cd Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 10:38:03 +0200 Subject: [PATCH 08/20] force RHH Rom Header to always be present (#7187) --- src/rom_header_rhh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rom_header_rhh.c b/src/rom_header_rhh.c index c323e9eadf..e9310415c3 100644 --- a/src/rom_header_rhh.c +++ b/src/rom_header_rhh.c @@ -28,7 +28,7 @@ struct RHHRomHeader }; __attribute__((section(".text.consts"))) -static const struct RHHRomHeader sRHHRomHeader = +USED static const struct RHHRomHeader sRHHRomHeader = { .rhh_magic = { 'R', 'H', 'H', 'E', 'X', 'P' }, .expansionVersionMajor = EXPANSION_VERSION_MAJOR, From 753eb9f8d895589daa6e63ace3cccac88fcbe533 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:47:26 +0200 Subject: [PATCH 09/20] Fixes Enigma, Kee and Maranga Berry activation timing (#7171) --- src/battle_util.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index ebb11c4c7f..ba63bf4fe9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6409,16 +6409,13 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, ITEMEFFECT_NONE); break; case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move - if (B_BERRIES_INSTANT >= GEN_4) - effect = TrySetEnigmaBerry(battler); + effect = TrySetEnigmaBerry(battler); break; case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move - if (B_BERRIES_INSTANT >= GEN_4) - effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); + effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); break; case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move - if (B_BERRIES_INSTANT >= GEN_4) - effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); + effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); break; case HOLD_EFFECT_RANDOM_STAT_UP: if (B_BERRIES_INSTANT >= GEN_4) From 0ccf797cceddd45790153fd85c3e9c333d1aefda Mon Sep 17 00:00:00 2001 From: i0brendan0 <19826742+i0brendan0@users.noreply.github.com> Date: Mon, 23 Jun 2025 08:05:01 -0500 Subject: [PATCH 10/20] Fixes Roamers not saving shininess (#7185) --- include/global.h | 3 ++- src/roamer.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/global.h b/include/global.h index 057a53b498..b58ef3518b 100644 --- a/include/global.h +++ b/include/global.h @@ -680,7 +680,8 @@ struct Roamer /*0x12*/ u8 tough; /*0x13*/ bool8 active; /*0x14*/ u8 statusB; // Stores frostbite - /*0x14*/ u8 filler[0x7]; + /*0x15*/ bool8 shiny; + /*0x16*/ u8 filler[0x6]; }; struct RamScriptData diff --git a/src/roamer.c b/src/roamer.c index 9bca6fdc45..0fc86b6711 100644 --- a/src/roamer.c +++ b/src/roamer.c @@ -113,6 +113,7 @@ static void CreateInitialRoamerMon(u8 index, u16 species, u8 level) ROAMER(index)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); ROAMER(index)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); ROAMER(index)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); + ROAMER(index)->shiny = GetMonData(&gEnemyParty[0], MON_DATA_IS_SHINY); ROAMER(index)->active = TRUE; sRoamerLocation[index][MAP_GRP] = ROAMER_MAP_GROUP; sRoamerLocation[index][MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; @@ -243,8 +244,6 @@ void CreateRoamerMonInstance(u32 roamerIndex) struct Pokemon *mon = &gEnemyParty[0]; ZeroEnemyPartyMons(); CreateMonWithIVsPersonality(mon, ROAMER(roamerIndex)->species, ROAMER(roamerIndex)->level, ROAMER(roamerIndex)->ivs, ROAMER(roamerIndex)->personality); - // The roamer's status field is u16, but SetMonData expects status to be u32, so will set the roamer's status - // using the status field and the following 3 bytes (cool, beauty, and cute). SetMonData(mon, MON_DATA_STATUS, &status); SetMonData(mon, MON_DATA_HP, &ROAMER(roamerIndex)->hp); SetMonData(mon, MON_DATA_COOL, &ROAMER(roamerIndex)->cool); @@ -252,6 +251,7 @@ void CreateRoamerMonInstance(u32 roamerIndex) SetMonData(mon, MON_DATA_CUTE, &ROAMER(roamerIndex)->cute); SetMonData(mon, MON_DATA_SMART, &ROAMER(roamerIndex)->smart); SetMonData(mon, MON_DATA_TOUGH, &ROAMER(roamerIndex)->tough); + SetMonData(mon, MON_DATA_IS_SHINY, &ROAMER(roamerIndex)->shiny); } bool8 TryStartRoamerEncounter(void) From 456a8f6aa06d86475252d931bbb41250fd14dc9a Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Mon, 23 Jun 2025 06:40:13 -0700 Subject: [PATCH 11/20] Update the description of OW_OBJECT_VANILLA_SHADOWS (#7184) --- include/config/overworld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index 50cad2f5fe..fa87da4d83 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -99,7 +99,7 @@ #define OW_ENABLE_DNS TRUE // If set to TRUE, the overworld will be tinted depending on time of day. // Object Event Shadows -#define OW_OBJECT_VANILLA_SHADOWS FALSE // In vanilla shadows in the overworld are only shown when jumping. +#define OW_OBJECT_VANILLA_SHADOWS FALSE // When FALSE, every object in the overworld has a shadow. WARNING: This means every object will take up two sprites instead of one. When TRUE, an object's shadow is only shown when jumping. // Overworld flags // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. From a75a49710fd4ab25fe9ac548c70f8b971ca21116 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 23 Jun 2025 09:46:49 -0400 Subject: [PATCH 12/20] Fixed debug flag menu sound (#7190) --- src/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index 5a585ef62d..6694266e08 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2527,6 +2527,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) { if (JOY_NEW(A_BUTTON)) { + PlaySE(SE_SELECT); FlagToggle(gTasks[taskId].tInput); } else if (JOY_NEW(B_BUTTON)) @@ -2536,7 +2537,6 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) return; } - PlaySE(SE_SELECT); Debug_HandleInput_Numeric(taskId, 1, FLAGS_COUNT - 1, DEBUG_NUMBER_DIGITS_FLAGS); if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) From e449a612f5c87ba45217aa9009e48621c6ca3b67 Mon Sep 17 00:00:00 2001 From: Pablo Pena Date: Tue, 24 Jun 2025 01:45:12 +0800 Subject: [PATCH 13/20] fix: use BackPickId to calculate player intro ball throw animation palette (#7193) --- src/battle_controller_player.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index f437d8ee13..a0b4e73ece 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2330,7 +2330,8 @@ static void PlayerHandleOneReturnValue_Duplicate(u32 battler) static void PlayerHandleIntroTrainerBallThrow(u32 battler) { - const u16 *trainerPal = gTrainerBacksprites[gSaveBlock2Ptr->playerGender].palette.data; + const u32 paletteIndex = PlayerGetTrainerBackPicId(); + const u16 *trainerPal = gTrainerBacksprites[paletteIndex].palette.data; BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F8, trainerPal, 31, Intro_TryShinyAnimShowHealthbox); } From e1b83d605698f22bee4ebcb1717378a1a10f3717 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 21:31:18 +0200 Subject: [PATCH 14/20] Match graphics declarations with externs (#2089) --- include/graphics.h | 88 ++++++++++++++++----------------- src/data/graphics/intro_scene.h | 2 +- src/graphics.c | 11 +++-- src/intro.c | 29 ++++++----- src/mail.c | 4 +- src/naming_screen.c | 2 +- 6 files changed, 70 insertions(+), 66 deletions(-) diff --git a/include/graphics.h b/include/graphics.h index 7f0eb7bda5..14f2f5e744 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2,7 +2,7 @@ #define GUARD_GRAPHICS_H // overworld -extern const u32 gMessageBox_Gfx[]; +extern const u8 gMessageBox_Gfx[]; extern const u16 gMessageBox_Pal[]; // pokeballs @@ -3286,17 +3286,17 @@ extern const u32 gBattleEnvironmentPalette_StadiumWallace[]; extern const u32 gPokedexInterface_Gfx[]; extern const u16 gPokedexBgHoenn_Pal[]; extern const u32 gPokedexMenu_Gfx[]; -extern const u8 gPokedexList_Tilemap[]; -extern const u8 gPokedexListUnderlay_Tilemap[]; -extern const u8 gPokedexStartMenuMain_Tilemap[]; -extern const u8 gPokedexStartMenuSearchResults_Tilemap[]; +extern const u32 gPokedexList_Tilemap[]; +extern const u32 gPokedexListUnderlay_Tilemap[]; +extern const u32 gPokedexStartMenuMain_Tilemap[]; +extern const u32 gPokedexStartMenuSearchResults_Tilemap[]; extern const u16 gPokedexSearchResults_Pal[]; extern const u16 gPokedexBgNational_Pal[]; -extern const u8 gPokedexInfoScreen_Tilemap[]; -extern const u8 gPokedexCryScreen_Tilemap[]; -extern const u8 gPokedexSizeScreen_Tilemap[]; -extern const u8 gPokedexScreenSelectBarMain_Tilemap[]; -extern const u8 gPokedexScreenSelectBarSubmenu_Tilemap[]; +extern const u32 gPokedexInfoScreen_Tilemap[]; +extern const u32 gPokedexCryScreen_Tilemap[]; +extern const u32 gPokedexSizeScreen_Tilemap[]; +extern const u32 gPokedexScreenSelectBarMain_Tilemap[]; +extern const u32 gPokedexScreenSelectBarSubmenu_Tilemap[]; extern const u16 gPokedexCaughtScreen_Pal[]; extern const u32 gPokedexSearchMenu_Gfx[]; extern const u32 gPokedexSearchMenuHoenn_Tilemap[]; @@ -3893,7 +3893,7 @@ extern const u32 gIntroGroudon_Gfx[]; extern const u32 gIntroGroudon_Tilemap[]; extern const u32 gIntroLegendBg_Gfx[]; extern const u32 gIntroGroudonBg_Tilemap[]; -extern const u8 ALIGNED(2) gIntro3Bg_Pal[0x200]; +extern const u16 gIntro3Bg_Pal[16][16]; extern const u32 gIntroKyogre_Gfx[]; extern const u32 gIntroKyogre_Tilemap[]; extern const u32 gIntroKyogreBg_Tilemap[]; @@ -4066,9 +4066,9 @@ extern const u8 gHealthboxElementsGfxTable[][32]; extern const u16 gNamingScreenMenu_Pal[6][16]; extern const u32 gNamingScreenMenu_Gfx[]; extern const u32 gNamingScreenBackground_Tilemap[]; -extern const u8 gNamingScreenKeyboardUpper_Tilemap[]; -extern const u8 gNamingScreenKeyboardLower_Tilemap[]; -extern const u8 gNamingScreenKeyboardSymbols_Tilemap[]; +extern const u32 gNamingScreenKeyboardUpper_Tilemap[]; +extern const u32 gNamingScreenKeyboardLower_Tilemap[]; +extern const u32 gNamingScreenKeyboardSymbols_Tilemap[]; extern const u32 gNamingScreenPageSwapFrame_Gfx[]; extern const u32 gNamingScreenBackButton_Gfx[]; extern const u32 gNamingScreenOKButton_Gfx[]; @@ -4791,7 +4791,7 @@ extern const u32 gContestAudienceTilemap[]; extern const u32 gContestInterfaceAudiencePalette[]; extern const u32 gContestInterfaceTilemap[]; extern const u32 gContestCurtainTilemap[]; -extern const u32 gContestSliderHeart_Gfx[]; +extern const u8 gContestSliderHeart_Gfx[]; extern const u32 gContestNextTurnGfx[]; extern const u16 gContestPal[]; extern const u32 gContestFaces_Gfx[]; @@ -4817,11 +4817,11 @@ extern const u16 gUsePokeblockGraph_Pal[]; extern const u16 gUsePokeblockNatureWin_Pal[]; // Berry blender -extern const u32 gBerryBlenderPlayerArrow_Gfx[]; -extern const u32 gBerryBlenderStart_Gfx[]; -extern const u32 gBerryBlenderScoreSymbols_Gfx[]; -extern const u32 gBerryBlenderParticles_Gfx[]; -extern const u32 gBerryBlenderCountdownNumbers_Gfx[]; +extern const u8 gBerryBlenderPlayerArrow_Gfx[]; +extern const u8 gBerryBlenderStart_Gfx[]; +extern const u8 gBerryBlenderScoreSymbols_Gfx[]; +extern const u8 gBerryBlenderParticles_Gfx[]; +extern const u8 gBerryBlenderCountdownNumbers_Gfx[]; extern const u16 gBerryBlenderMiscPalette[]; extern const u16 gBerryBlenderArrowPalette[]; extern const u32 gBerryBlenderCenter_Gfx[]; @@ -5042,30 +5042,30 @@ extern const u16 gMailPalette_Tropic[]; extern const u16 gMailPalette_Dream[]; extern const u16 gMailPalette_Fab[]; extern const u16 gMailPalette_Retro[]; -extern const u8 gMailTiles_Orange[]; -extern const u8 gMailTilemap_Orange[]; -extern const u8 gMailTiles_Harbor[]; -extern const u8 gMailTilemap_Harbor[]; -extern const u8 gMailTiles_Glitter[]; -extern const u8 gMailTilemap_Glitter[]; -extern const u8 gMailTiles_Mech[]; -extern const u8 gMailTilemap_Mech[]; -extern const u8 gMailTiles_Wood[]; -extern const u8 gMailTilemap_Wood[]; -extern const u8 gMailTiles_Wave[]; -extern const u8 gMailTilemap_Wave[]; -extern const u8 gMailTiles_Bead[]; -extern const u8 gMailTilemap_Bead[]; -extern const u8 gMailTiles_Shadow[]; -extern const u8 gMailTilemap_Shadow[]; -extern const u8 gMailTiles_Tropic[]; -extern const u8 gMailTilemap_Tropic[]; -extern const u8 gMailTiles_Dream[]; -extern const u8 gMailTilemap_Dream[]; -extern const u8 gMailTiles_Fab[]; -extern const u8 gMailTilemap_Fab[]; -extern const u8 gMailTiles_Retro[]; -extern const u8 gMailTilemap_Retro[]; +extern const u32 gMailTiles_Orange[]; +extern const u32 gMailTilemap_Orange[]; +extern const u32 gMailTiles_Harbor[]; +extern const u32 gMailTilemap_Harbor[]; +extern const u32 gMailTiles_Glitter[]; +extern const u32 gMailTilemap_Glitter[]; +extern const u32 gMailTiles_Mech[]; +extern const u32 gMailTilemap_Mech[]; +extern const u32 gMailTiles_Wood[]; +extern const u32 gMailTilemap_Wood[]; +extern const u32 gMailTiles_Wave[]; +extern const u32 gMailTilemap_Wave[]; +extern const u32 gMailTiles_Bead[]; +extern const u32 gMailTilemap_Bead[]; +extern const u32 gMailTiles_Shadow[]; +extern const u32 gMailTilemap_Shadow[]; +extern const u32 gMailTiles_Tropic[]; +extern const u32 gMailTilemap_Tropic[]; +extern const u32 gMailTiles_Dream[]; +extern const u32 gMailTilemap_Dream[]; +extern const u32 gMailTiles_Fab[]; +extern const u32 gMailTilemap_Fab[]; +extern const u32 gMailTiles_Retro[]; +extern const u32 gMailTilemap_Retro[]; extern const u8 gMonMarkingsMenu_Gfx[]; extern const u16 gMonMarkingsMenu_Pal[]; diff --git a/src/data/graphics/intro_scene.h b/src/data/graphics/intro_scene.h index cb7706c9a3..8b17b00346 100644 --- a/src/data/graphics/intro_scene.h +++ b/src/data/graphics/intro_scene.h @@ -1,6 +1,6 @@ const u16 gIntroGameFreakTextFade_Pal[] = INCBIN_U16("graphics/intro/scene_1/text.gbapal"); // game freak text blue fade const u16 gIntroPlayer_Pal[] = INCBIN_U16("graphics/intro/scene_2/player.gbapal"); -const u16 gIntro3Bg_Pal[] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); +const u16 gIntro3Bg_Pal[16][16] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); const u16 gIntroVolbeat_Pal[] = INCBIN_U16("graphics/intro/scene_2/volbeat.gbapal"); const u16 gIntroTorchic_Pal[] = INCBIN_U16("graphics/intro/scene_2/torchic.gbapal"); const u16 gIntroManectric_Pal[] = INCBIN_U16("graphics/intro/scene_2/manectric.gbapal"); diff --git a/src/graphics.c b/src/graphics.c index 9179b0fd7d..3d7f2fa08b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,4 +1,5 @@ #include "global.h" +#include "graphics.h" const u32 gBattleTextboxTiles[] = INCBIN_U32("graphics/battle_interface/textbox.4bpp.lz"); const u32 gBattleTextboxPalette[] = INCBIN_U32("graphics/battle_interface/textbox.gbapal.lz"); @@ -354,7 +355,7 @@ const u16 gBattleInterface_BallStatusBarPal[] = INCBIN_U16("graphics/battle_inte const u16 gBattleInterface_BallDisplayPal[] = INCBIN_U16("graphics/battle_interface/ball_display.gbapal"); -const u8 gHealthboxElementsGfxTable[] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", +const u8 gHealthboxElementsGfxTable[][32] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", "graphics/battle_interface/expbar.4bpp", "graphics/battle_interface/status.4bpp", "graphics/battle_interface/misc.4bpp", @@ -971,7 +972,7 @@ const u16 gTilesetAnims_BattleDomePals0_3[] = INCBIN_U16("graphics/battle_fronti static const u16 sUnused0[] = {0x13F, 0x119, 0x113, 0x10E}; -const u16 gBattlePyramidFloor_Pal[] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); +const u16 gBattlePyramidFloor_Pal[][16] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); const u32 gMultiBattleIntroBg_Opponent_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_opponent.bin.lz"); const u32 gMultiBattleIntroBg_Player_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_player.bin.lz"); @@ -1514,12 +1515,12 @@ const u16 gTitleScreenPressStartPal[] = INCBIN_U16("graphics/title_screen/p const u32 gTitleScreenPressStartGfx[] = INCBIN_U32("graphics/title_screen/press_start.4bpp.lz"); const u32 gTitleScreenPokemonLogoTilemap[] = INCBIN_U32("graphics/title_screen/pokemon_logo.bin.lz"); -const u16 gFrontierPassBg_Pal[] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 +const u16 gFrontierPassBg_Pal[][16] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 const u32 gFrontierPassBg_Gfx[] = INCBIN_U32("graphics/frontier_pass/bg.4bpp.lz"); const u32 gFrontierPassMapAndCard_Gfx[] = INCBIN_U32("graphics/frontier_pass/map_and_card.8bpp.lz"); const u32 gFrontierPassBg_Tilemap[] = INCBIN_U32("graphics/frontier_pass/bg.bin.lz"); -const u16 gFrontierPassCancelButton_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel.bin"); -const u16 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel_highlighted.bin"); +const u32 gFrontierPassCancelButton_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel.bin"); +const u32 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel_highlighted.bin"); // Berry Crush const u16 gBerryCrush_Crusher_Pal[] = INCBIN_U16("graphics/berry_crush/crusher.gbapal"); diff --git a/src/intro.c b/src/intro.c index 549acc4b7d..169ef002a6 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1866,12 +1866,15 @@ static void Task_Scene3_StartGroudon(u8 taskId) #define tTrigIdx data[6] // Re-used #define tPalIdx data[7] +// Treats gIntro3Bg_Pal as u8* and iterates by 1 +#define INTRO3_RAW_PTR(palId)(((void *) &gIntro3Bg_Pal) + palId) + static void Task_Scene3_Groudon(u8 taskId) { s16 *data = gTasks[taskId].data; tTimer++; - if ((u16)(tState - 1) < 7 && tTimer % 2 == 0) + if ((tState >= 1 && tState <= 7) && tTimer % 2 == 0) tYShake ^= 3; PanFadeAndZoomScreen(tScreenX, tScreenY + tYShake, tZoom, 0); switch (tState) @@ -1890,7 +1893,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EC) tState++; @@ -1907,7 +1910,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) { @@ -2149,7 +2152,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) tState++; @@ -2167,7 +2170,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EE) { @@ -2498,7 +2501,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) sprite->sPalIdx = 0x1C2; sprite->sState++; case 1: - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx += 2; if (sprite->sPalIdx != 0x1CE) break; @@ -2509,7 +2512,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) if (--sprite->sDelay == 0) { sprite->sDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx -= 2; if (sprite->sPalIdx == 0x1C0) DestroySprite(sprite); @@ -2612,7 +2615,7 @@ static void Task_RayquazaAttack(u8 taskId) case 0: if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2627,7 +2630,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2646,7 +2649,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x182 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x182 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2670,9 +2673,9 @@ static void Task_RayquazaAttack(u8 taskId) if (--data[3] != 0) { BlendPalette(BG_PLTT_ID(5), 16, data[3], RGB(9, 10, 10)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[396], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(396), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); } else { diff --git a/src/mail.c b/src/mail.c index 424a286f3f..e1aaa66873 100644 --- a/src/mail.c +++ b/src/mail.c @@ -48,8 +48,8 @@ struct MailLayout struct MailGraphics { const u16 *palette; - const u8 *tiles; - const u8 *tileMap; + const u32 *tiles; + const u32 *tileMap; u32 unused; u16 textColor; u16 textShadow; diff --git a/src/naming_screen.c b/src/naming_screen.c index d8ae7ccd4d..f7f599f5b9 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -1959,7 +1959,7 @@ static void PrintKeyboardKeys(u8 window, u8 page) PutWindowTilemap(window); } -static const u8 *const sNextKeyboardPageTilemaps[] = +static const u32 *const sNextKeyboardPageTilemaps[] = { [KBPAGE_SYMBOLS] = gNamingScreenKeyboardUpper_Tilemap, [KBPAGE_LETTERS_UPPER] = gNamingScreenKeyboardLower_Tilemap, // lower From 2e3e0889f9675bde7ae7ee6fc73c3185ba5f9b26 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 19:13:50 -0700 Subject: [PATCH 15/20] add pablopenna as a contributor for code (#7202) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 11 ++++++++++- CREDITS.md | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5b6d38e32f..c8b79ba30e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -321,7 +321,7 @@ "code" ] }, - { + { "login": "lordraindance2", "name": "lordraindance2", "avatar_url": "https://avatars.githubusercontent.com/u/47706100?v=4", @@ -329,6 +329,15 @@ "contributions": [ "code" ] + }, + { + "login": "pablopenna", + "name": "Pablo Pena", + "avatar_url": "https://avatars.githubusercontent.com/u/11214682?v=4", + "profile": "https://github.com/pablopenna", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 128f26df6f..ab5c596248 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -58,6 +58,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Zatsu
Zatsu

💻 poetahto
poetahto

💻 lordraindance2
lordraindance2

💻 + Pablo Pena
Pablo Pena

💻 From bc95824e8cfa4f15741f832a3ba810a4a303d1b1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 24 Jun 2025 09:04:19 +0200 Subject: [PATCH 16/20] Fixes wrong Future Sight indexing (#7198) --- src/battle_util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index ba63bf4fe9..226b041be0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9582,8 +9582,13 @@ bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; struct Pokemon *party = GetBattlerParty(battlerAtk); - return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] - && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[BATTLE_PARTNER(gBattlerPartyIndexes[battlerAtk])]; + if (IsDoubleBattle()) + { + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] + && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerAtk)]]; + } + + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]]; } s32 CalculateMoveDamage(struct DamageCalculationData *damageCalcData, u32 fixedBasePower) From 93511ceb054979508f3776df7e1443ffee691c9a Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 24 Jun 2025 09:28:26 +0200 Subject: [PATCH 17/20] Fix BtlController_EmitChosenMonReturnValue UB (#7197) --- src/battle_controllers.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 4faec49613..ec3dfa7426 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1415,8 +1415,11 @@ void BtlController_EmitChosenMonReturnValue(u32 battler, u32 bufferId, u8 partyI gBattleResources->transferBuffer[0] = CONTROLLER_CHOSENMONRETURNVALUE; gBattleResources->transferBuffer[1] = partyId; - for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) - gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + if (battlePartyOrder != NULL) + { + for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) + gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + } PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 5); } From 74326023da8daf1c239a7658877f68539a48656c Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Tue, 24 Jun 2025 09:29:20 +0200 Subject: [PATCH 18/20] Backported Safari catch and add to party fix (#7192) Co-authored-by: Hedara --- src/battle_controller_safari.c | 66 +++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 4a1fc3888c..9311c2f7a1 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -11,6 +11,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokeblock.h" #include "pokemon.h" @@ -22,6 +23,7 @@ #include "window.h" #include "line_break.h" #include "constants/battle_anim.h" +#include "constants/party_menu.h" #include "constants/songs.h" #include "constants/trainers.h" #include "constants/rgb.h" @@ -33,6 +35,7 @@ static void SafariHandlePrintString(u32 battler); static void SafariHandlePrintSelectionString(u32 battler); static void SafariHandleChooseAction(u32 battler); static void SafariHandleChooseItem(u32 battler); +static void SafariHandleChoosePokemon(u32 battler); static void SafariHandleStatusIconUpdate(u32 battler); static void SafariHandleFaintingCry(u32 battler); static void SafariHandleIntroTrainerBallThrow(u32 battler); @@ -42,6 +45,7 @@ static void SafariHandleEndLinkBattle(u32 battler); static void SafariBufferRunCommand(u32 battler); static void SafariBufferExecCompleted(u32 battler); static void CompleteWhenChosePokeblock(u32 battler); +static void WaitForMonSelection(u32 battler); static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { @@ -67,7 +71,7 @@ static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, [CONTROLLER_OPENBAG] = SafariHandleChooseItem, - [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, + [CONTROLLER_CHOOSEPOKEMON] = SafariHandleChoosePokemon, [CONTROLLER_23] = BtlController_Empty, [CONTROLLER_HEALTHBARUPDATE] = BtlController_Empty, [CONTROLLER_EXPUPDATE] = BtlController_Empty, @@ -225,6 +229,41 @@ static void CompleteWhenChosePokeblock(u32 battler) } } +static void OpenPartyMenuToChooseMon(u32 battler) +{ + if (!gPaletteFade.active) + { + gBattlerControllerFuncs[battler] = WaitForMonSelection; + u8 caseId = gTasks[gBattleControllerData[battler]].data[0]; + DestroyTask(gBattleControllerData[battler]); + FreeAllWindowBuffers(); + OpenPartyMenuInBattle(caseId); + } +} + +static void WaitForMonSelection(u32 battler) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + if (gPartyMenuUseExitCallback == TRUE) + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, gSelectedMonPartyId, gBattlePartyCurrentOrder); + else + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, PARTY_SIZE, NULL); + + if ((gBattleResources->bufferA[battler][1] & 0xF) == 1) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + BattlePutTextOnWindow(gText_LinkStandby, B_WIN_MSG); + } + } + + SafariBufferExecCompleted(battler); + } +} + static void SafariBufferExecCompleted(u32 battler) { gBattlerControllerFuncs[battler] = SafariBufferRunCommand; @@ -305,6 +344,31 @@ static void SafariHandleChooseItem(u32 battler) gBattlerInMenuId = battler; } +static void SafariHandleChoosePokemon(u32 battler) +{ + for (s32 i = 0; i < ARRAY_COUNT(gBattlePartyCurrentOrder); i++) + gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[battler][4 + i]; + + if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_SEND_MON_TO_BOX) + { + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, gBattlerPartyIndexes[battler] + 1, gBattlePartyCurrentOrder); + SafariBufferExecCompleted(battler); + } + else + { + gBattleControllerData[battler] = CreateTask(TaskDummy, 0xFF); + gTasks[gBattleControllerData[battler]].data[0] = gBattleResources->bufferA[battler][1] & 0xF; + *(&gBattleStruct->battlerPreventingSwitchout) = gBattleResources->bufferA[battler][1] >> 4; + *(&gBattleStruct->prevSelectedPartySlot) = gBattleResources->bufferA[battler][2]; + *(&gBattleStruct->abilityPreventingSwitchout) = (gBattleResources->bufferA[battler][3] & 0xFF) | (gBattleResources->bufferA[battler][7] << 8); + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); + gBattlerControllerFuncs[battler] = OpenPartyMenuToChooseMon; + gBattlerInMenuId = battler; + } +} + static void SafariHandleStatusIconUpdate(u32 battler) { UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], GetBattlerMon(battler), HEALTHBOX_SAFARI_BALLS_TEXT); From b372fa30b66d67cba459e33475d81d156f96ff93 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 24 Jun 2025 15:03:54 -0400 Subject: [PATCH 19/20] Fix AI party count calc being maintained between tests (#7200) --- src/battle_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/battle_main.c b/src/battle_main.c index cc5f281d4e..fec093d166 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -583,6 +583,12 @@ static void CB2_InitBattleInternal(void) TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } + if (TESTING) + { + gPlayerPartyCount = CalculatePartyCount(gPlayerParty); + gEnemyPartyCount = CalculatePartyCount(gEnemyParty); + } + gBattleCommunication[MULTIUSE_STATE] = 0; } From 8d81f603134a5030f47cd28633f5737e76112bf0 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 25 Jun 2025 08:01:31 -0400 Subject: [PATCH 20/20] Fix tests failing with `B_FRIENDSHIP_BOOST` being `TRUE` (#7194) Co-authored-by: hedara90 <90hedara@gmail.com> --- test/pokemon.c | 13 +++++++++++-- test/test_runner_battle.c | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test/pokemon.c b/test/pokemon.c index 4e8a1da7fa..ac57314f9c 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -82,10 +82,14 @@ TEST("Shininess independent from PID and OTID") TEST("Hyper Training increases stats without affecting IVs") { - u32 data, hp, atk, def, speed, spatk, spdef; + u32 data, hp, atk, def, speed, spatk, spdef, friendship = 0; struct Pokemon mon; CreateMon(&mon, SPECIES_WOBBUFFET, 100, 3, TRUE, 0, OT_ID_PRESET, 0); + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&mon, MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&mon); + hp = GetMonData(&mon, MON_DATA_HP); atk = GetMonData(&mon, MON_DATA_ATK); def = GetMonData(&mon, MON_DATA_DEF); @@ -142,8 +146,13 @@ TEST("Status1 round-trips through BoxPokemon") TEST("canhypertrain/hypertrain affect MON_DATA_HYPER_TRAINED_* and recalculate stats") { - u32 atk; + u32 atk, friendship = 0; CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&gPlayerParty[0], MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&gPlayerParty[0]); + atk = GetMonData(&gPlayerParty[0], MON_DATA_ATK); RUN_OVERWORLD_SCRIPT( diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 7884993a1c..20271a588d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1563,6 +1563,13 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species) data = MOVE_NONE; for (i = 0; i < MAX_MON_MOVES; i++) SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data); + data = 0; + if (B_FRIENDSHIP_BOOST) + { + // This way, we avoid the boost affecting tests unless explicitly stated. + SetMonData(DATA.currentMon, MON_DATA_FRIENDSHIP, &data); + CalculateMonStats(DATA.currentMon); + } } // (sNaturePersonalities[i] % NUM_NATURES) == i