summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiegoisawesome <diego@domoreaweso.me>2017-10-09 13:32:26 -0500
committerDiegoisawesome <diego@domoreaweso.me>2017-10-09 13:32:26 -0500
commit41db0259759c8e4c3c31c5cf09daed9f85ab5b63 (patch)
treeab77e37580ab0eb0ee18c28f749d8c8da15dbcf7 /src
parentae06c13e99162cebd3617f5aafb135bdd8b3f237 (diff)
parent96c5966ff3676eb1b3463808b83b42e13e1591fd (diff)
Merge remote-tracking branch 'pret/master' into baserom_extraction
Diffstat (limited to 'src')
-rw-r--r--src/battle_1.c17
-rw-r--r--src/battle_2.c5653
-rw-r--r--src/battle_ai_script_commands.c6
-rw-r--r--src/battle_script_commands.c133
-rw-r--r--src/battle_util.c (renamed from src/battle_3.c)358
-rw-r--r--src/berry_blender.c18
-rwxr-xr-xsrc/braille_puzzles.c583
-rwxr-xr-xsrc/diploma.c218
-rw-r--r--src/dma3_manager.c18
-rw-r--r--src/egg_hatch.c12
-rw-r--r--src/field_camera.c28
-rw-r--r--src/field_effect.c15
-rw-r--r--src/field_screen.c15
-rw-r--r--src/fldeff_cut.c19
-rw-r--r--src/link.c56
-rw-r--r--src/main.c2
-rw-r--r--src/main_menu.c15
-rw-r--r--src/malloc.c1
-rw-r--r--src/palette.c75
-rw-r--r--src/pokemon_2.c12
-rw-r--r--src/pokemon_3.c6
-rw-r--r--src/pokemon_storage_system.c15
-rw-r--r--src/record_mixing.c28
-rw-r--r--src/rom4.c19
-rw-r--r--src/save.c3
-rwxr-xr-xsrc/save_failed_screen.c426
-rwxr-xr-xsrc/save_location.c145
-rw-r--r--src/scrcmd.c15
-rw-r--r--src/script_menu.c16
-rw-r--r--src/text.c14
-rw-r--r--src/tileset_anims.c1411
-rw-r--r--src/unk_text_util_2.c219
-rw-r--r--src/window.c2
33 files changed, 9369 insertions, 204 deletions
diff --git a/src/battle_1.c b/src/battle_1.c
new file mode 100644
index 000000000..5e4ef5583
--- /dev/null
+++ b/src/battle_1.c
@@ -0,0 +1,17 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u32 gUnknown_03000DD4;
+IWRAM_DATA u32 gUnknown_03000DD8;
+IWRAM_DATA u32 gUnknown_03000DDC;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/battle_2.c b/src/battle_2.c
new file mode 100644
index 000000000..0462615b8
--- /dev/null
+++ b/src/battle_2.c
@@ -0,0 +1,5653 @@
+#include "global.h"
+#include "battle.h"
+#include "recorded_battle.h"
+#include "main.h"
+#include "load_save.h"
+#include "gpu_regs.h"
+#include "unknown_task.h"
+#include "battle_setup.h"
+#include "pokemon.h"
+#include "palette.h"
+#include "task.h"
+#include "event_data.h"
+#include "species.h"
+#include "berry.h"
+#include "text.h"
+#include "item.h"
+#include "items.h"
+#include "hold_effects.h"
+#include "link.h"
+#include "bg.h"
+#include "dma3.h"
+#include "string_util.h"
+#include "malloc.h"
+#include "event_data.h"
+#include "m4a.h"
+#include "window.h"
+#include "rng.h"
+#include "songs.h"
+#include "sound.h"
+#include "battle_message.h"
+#include "sprite.h"
+#include "util.h"
+#include "trig.h"
+#include "battle_ai_script_commands.h"
+#include "battle_move_effects.h"
+#include "battle_controllers.h"
+#include "pokedex.h"
+#include "abilities.h"
+#include "moves.h"
+#include "trainer_classes.h"
+#include "evolution_scene.h"
+#include "roamer.h"
+#include "safari_zone.h"
+
+struct UnknownStruct6
+{
+ u16 unk0[0xA0];
+ u8 fillerA0[0x640];
+ u16 unk780[0xA0];
+};
+
+struct UnknownPokemonStruct2
+{
+ /*0x00*/ u16 species;
+ /*0x02*/ u16 heldItem;
+ /*0x04*/ u8 nickname[POKEMON_NAME_LENGTH + 1];
+ /*0x0F*/ u8 level;
+ /*0x10*/ u16 hp;
+ /*0x12*/ u16 maxhp;
+ /*0x14*/ u32 status;
+ /*0x18*/ u32 personality;
+ /*0x1C*/ u8 gender;
+ /*0x1D*/ u8 language;
+};
+
+extern u32 gBattleTypeFlags;
+extern u8 gBattleCommunication[];
+extern u8 gBattleTerrain;
+extern u16 gBattle_BG0_X;
+extern u16 gBattle_BG0_Y;
+extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gBattle_BG3_X;
+extern u16 gBattle_BG3_Y;
+extern u16 gPartnerTrainerId;
+extern u16 gBattle_WIN0H;
+extern u16 gBattle_WIN0V;
+extern u16 gBattle_WIN1H;
+extern u16 gBattle_WIN1V;
+extern u16 gTrainerBattleOpponent_A;
+extern u16 gTrainerBattleOpponent_B;
+extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT];
+extern void (*gPreBattleCallback1)(void);
+extern void (*gBattleMainFunc)(void);
+extern void (*gUnknown_030061E8)(void);
+extern struct UnknownPokemonStruct2 gUnknown_02022FF8[3]; // what is it used for?
+extern struct UnknownPokemonStruct2* gUnknown_02023058; // what is it used for?
+extern u8 gBattleOutcome;
+extern u8 gUnknown_02039B28[]; // possibly a struct?
+extern struct UnknownStruct6 gUnknown_02038C28; // todo: identify & document
+extern struct MusicPlayerInfo gMPlay_SE1;
+extern struct MusicPlayerInfo gMPlay_SE2;
+extern u8 gDecompressionBuffer[];
+extern u16 gUnknown_020243FC;
+extern u8 gHealthBoxesIds[BATTLE_BANKS_COUNT];
+extern void (*gBattleBankFunc[BATTLE_BANKS_COUNT])(void);
+extern u8 gBattleBufferA[BATTLE_BANKS_COUNT][0x200];
+extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
+extern u8 gStringBank;
+extern u32 gUnknown_02022F88;
+extern u32 gHitMarker;
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gBattleMonForms[BATTLE_BANKS_COUNT];
+extern u8 gBankSpriteIds[BATTLE_BANKS_COUNT];
+extern u16 gPaydayMoney;
+extern u16 gBattleWeather;
+extern u16 gPauseCounterBattle;
+extern u16 gRandomTurnNumber;
+extern u8 gActiveBank;
+extern u8 gNoOfAllBanks;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gLeveledUpInBattle;
+extern u8 gAbsentBankFlags;
+extern u32 gBattleExecBuffer;
+extern u8 gMultiHitCounter;
+extern u8 gBattleMoveFlags;
+extern s32 gBattleMoveDamage;
+extern const u8* gUnknown_02024230[BATTLE_BANKS_COUNT];
+extern u16 gUnknownMovesUsedByBanks[BATTLE_BANKS_COUNT];
+extern u16 gLastUsedMovesByBanks[BATTLE_BANKS_COUNT];
+extern u16 gUnknown_02024250[BATTLE_BANKS_COUNT];
+extern u16 gUnknown_02024258[BATTLE_BANKS_COUNT];
+extern u16 gUnknown_02024260[BATTLE_BANKS_COUNT];
+extern u16 gLockedMoves[BATTLE_BANKS_COUNT];
+extern u8 gUnknown_02024270[BATTLE_BANKS_COUNT];
+extern u8 gUnknown_02024284[BATTLE_BANKS_COUNT];
+extern u32 gStatuses3[BATTLE_BANKS_COUNT];
+extern u16 gSideAffecting[2];
+extern u16 gCurrentMove;
+extern u8 gActionSelectionCursor[BATTLE_BANKS_COUNT];
+extern u8 gMoveSelectionCursor[BATTLE_BANKS_COUNT];
+extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
+extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT];
+extern u8 gActionForBanks[BATTLE_BANKS_COUNT];
+extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
+extern u8 gCurrentActionFuncId;
+extern u8 gLastUsedAbility;
+extern u16 gLastUsedItem;
+extern u8 gUnknown_0203CF00[];
+extern const u8* gBattlescriptPtrsForSelection[BATTLE_BANKS_COUNT];
+extern const u8* gBattlescriptCurrInstr;
+extern u32 gBattlePalaceMoveSelectionRngValue;
+extern u8 gActionsByTurnOrder[BATTLE_BANKS_COUNT];
+extern u8 gCurrentTurnActionNumber;
+extern u16 gDynamicBasePower;
+extern u8 gCritMultiplier;
+extern u8 gCurrMovePos;
+extern u8 gUnknown_020241E9;
+extern u16 gLastUsedMove;
+
+extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
+extern const struct BattleMove gBattleMoves[];
+extern const u16 gUnknown_08C004E0[]; // battle textbox palette
+extern const struct BgTemplate gUnknown_0831AA08[];
+extern const struct WindowTemplate * const gUnknown_0831ABA0[];
+extern const u8 gUnknown_0831ACE0[];
+extern const u8 gStatStageRatios[][2];
+extern const u8 * const gBattleScriptsForMoveEffects[];
+extern const u8 * const gBattlescriptsForBallThrow[];
+extern const u8 * const gBattlescriptsForRunningByItem[];
+extern const u8 * const gUnknown_082DBD3C[];
+extern const u8 * const gBattlescriptsForSafariActions[];
+
+// strings
+extern const u8 gText_LinkStandby3[];
+extern const u8 gText_RecordBattleToPass[];
+extern const u8 gText_BattleYesNoChoice[];
+extern const u8 gText_BattleRecordCouldntBeSaved[];
+extern const u8 gText_BattleRecordedOnPass[];
+extern const u8 gText_ShedinjaJapaneseName[];
+extern const u8 gText_EmptyString3[];
+extern const u8 gText_Poison[];
+extern const u8 gText_Sleep[];
+extern const u8 gText_Paralysis[];
+extern const u8 gText_Burn[];
+extern const u8 gText_Ice[];
+extern const u8 gText_Confusion[];
+extern const u8 gText_Love[];
+
+// battlescripts
+extern const u8 gUnknown_082DB8BE[];
+extern const u8 gUnknown_082DB881[];
+extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[];
+extern const u8 gUnknown_082DAB11[];
+extern const u8 gUnknown_082DB9BA[];
+extern const u8 gUnknown_082DAAFE[];
+extern const u8 gUnknown_082DAB0B[];
+extern const u8 BattleScript_FocusPunchSetUp[];
+extern const u8 BattleScript_LinkBattleWonOrLost[];
+extern const u8 BattleScript_FrontierTrainerBattleWon[];
+extern const u8 BattleScript_LocalTrainerBattleWon[];
+extern const u8 BattleScript_PayDayMoneyAndPickUpItems[];
+extern const u8 BattleScript_LocalBattleLost[];
+extern const u8 gUnknown_082DB9C8[];
+extern const u8 gUnknown_082DAA0B[];
+extern const u8 gUnknown_082DB9C1[];
+extern const u8 BattleScript_RanAwayUsingMonAbility[];
+extern const u8 BattleScript_SmokeBallEscape[];
+extern const u8 BattleScript_GotAwaySafely[];
+extern const u8 BattleScript_WildMonFled[];
+extern const u8 BattleScript_MoveUsedLoafingAround[];
+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
+extern void sub_8166188(void); // battle tower, sets link battle mons level but why?
+extern void sub_8165B88(u8* dst, u16 trainerId); // battle tower, gets language
+extern void sub_81DB4DC(u8* dst, u8 arg2); //
+extern void sub_81B9150(void);
+extern void sub_800AC34(void);
+extern void sub_80B3AF8(u8 taskId); // cable club
+extern void sub_8076918(u8 bank);
+extern void sub_80729D0(u8 healthoxSpriteId);
+extern void sub_81A56B4(void); // battle frontier 2
+extern u8 sub_81A9E28(void); // battle frontier 2
+extern void sub_81A56E8(u8 bank); // battle frontier 2
+extern void sub_81B8FB0(u8, u8); // party menu
+extern u8 pokemon_order_func(u8); // party menu
+extern void sub_80EC728(void); // tv
+extern void sub_80EE184(void); // tv
+extern bool8 InBattlePyramid(void);
+
+// this file's functions
+static void CB2_InitBattleInternal(void);
+static void CB2_PreInitMultiBattle(void);
+static void CB2_PreInitIngamePlayerPartnerBattle(void);
+static void CB2_HandleStartMultiPartnerBattle(void);
+static void CB2_HandleStartMultiBattle(void);
+static void CB2_HandleStartBattle(void);
+static void TryCorrectShedinjaLanguage(struct Pokemon *mon);
+static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer);
+static void BattleMainCB1(void);
+static void sub_8038538(struct Sprite *sprite);
+static void sub_8038F14(void);
+static void sub_8038F34(void);
+static void sub_80392A8(void);
+static void sub_803937C(void);
+static void sub_803939C(void);
+void oac_poke_opponent(struct Sprite *sprite);
+static void sub_803980C(struct Sprite *sprite);
+static void sub_8039838(struct Sprite *sprite);
+static void sub_8039894(struct Sprite *sprite);
+static void sub_80398D0(struct Sprite *sprite);
+static void sub_8039A48(struct Sprite *sprite);
+static void sub_8039AF4(struct Sprite *sprite);
+static void SpriteCallbackDummy_3(struct Sprite *sprite);
+static void oac_poke_ally_(struct Sprite *sprite);
+static void SpecialStatusesClear(void);
+static void TurnValuesCleanUp(bool8 var0);
+static void SpriteCB_HealthBoxBounce(struct Sprite *sprite);
+static void BattleStartClearSetData(void);
+static void BattleIntroGetMonsData(void);
+static void BattleIntroPrepareBackgroundSlide(void);
+static void BattleIntroDrawTrainersOrMonsSprites(void);
+static void BattleIntroDrawPartySummaryScreens(void);
+static void BattleIntroPrintTrainerWantsToBattle(void);
+static void BattleIntroPrintWildMonAttacked(void);
+static void BattleIntroPrintOpponentSendsOut(void);
+static void BattleIntroPrintPlayerSendsOut(void);
+static void BattleIntroOpponent1SendsOutMonAnimation(void);
+static void BattleIntroOpponent2SendsOutMonAnimation(void);
+static void BattleIntroRecordMonsToDex(void);
+static void BattleIntroPlayer1SendsOutMonAnimation(void);
+static void TryDoEventsBeforeFirstTurn(void);
+static void HandleTurnActionSelectionState(void);
+static void RunTurnActionsFunctions(void);
+static void SetActionsAndBanksTurnOrder(void);
+static void sub_803CDF8(void);
+static bool8 sub_803CDB8(void);
+static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void);
+static void FreeResetData_ReturnToOvOrDoEvolutions(void);
+static void ReturnFromBattleToOverworld(void);
+static void TryEvolvePokemon(void);
+static void WaitForEvoSceneToFinish(void);
+static void HandleEndTurn_ContinueBattle(void);
+static void HandleEndTurn_BattleWon(void);
+static void HandleEndTurn_BattleLost(void);
+static void HandleEndTurn_RanFromBattle(void);
+static void HandleEndTurn_MonFled(void);
+static void HandleEndTurn_FinishBattle(void);
+static void HandleAction_UseMove(void);
+static void HandleAction_Switch(void);
+static void HandleAction_UseItem(void);
+static void HandleAction_Run(void);
+static void HandleAction_WatchesCarefully(void);
+static void HandleAction_SafariZoneBallThrow(void);
+static void HandleAction_ThrowPokeblock(void);
+static void HandleAction_GoNear(void);
+static void HandleAction_SafriZoneRun(void);
+static void HandleAction_Action9(void);
+static void HandleAction_Action11(void);
+static void HandleAction_NothingIsFainted(void);
+static void HandleAction_ActionFinished(void);
+
+// rom const data
+static void (* const sTurnActionsFuncsTable[])(void) =
+{
+ HandleAction_UseMove, // ACTION_USE_MOVE
+ HandleAction_UseItem, // ACTION_USE_ITEM
+ HandleAction_Switch, // ACTION_SWITCH
+ HandleAction_Run, // ACTION_RUN
+ HandleAction_WatchesCarefully, // ACTION_WATCHES_CAREFULLY
+ HandleAction_SafariZoneBallThrow, // ACTION_SAFARI_ZONE_BALL
+ HandleAction_ThrowPokeblock, // ACTION_POKEBLOCK_CASE
+ HandleAction_GoNear, // ACTION_GO_NEAR
+ HandleAction_SafriZoneRun, // ACTION_SAFARI_ZONE_RUN
+ HandleAction_Action9, // ACTION_9
+ HandleAction_RunBattleScript, // ACTION_RUN_BATTLESCRIPT
+ HandleAction_Action11, // not sure about this one
+ HandleAction_ActionFinished, // ACTION_FINISHED
+ HandleAction_NothingIsFainted, // ACTION_NOTHING_FAINTED
+};
+
+static void (* const sEndTurnFuncsTable[])(void) =
+{
+ HandleEndTurn_ContinueBattle, // battle outcome 0
+ HandleEndTurn_BattleWon, // BATTLE_WON
+ HandleEndTurn_BattleLost, // BATTLE_LOST
+ HandleEndTurn_BattleLost, // BATTLE_DREW
+ HandleEndTurn_RanFromBattle, // BATTLE_RAN
+ HandleEndTurn_FinishBattle, // BATTLE_PLAYER_TELEPORTED
+ HandleEndTurn_MonFled, // BATTLE_POKE_FLED
+ HandleEndTurn_FinishBattle, // BATTLE_CAUGHT
+ HandleEndTurn_FinishBattle, // battle outcome 8
+ HandleEndTurn_FinishBattle, // BATTLE_FORFEITED
+ HandleEndTurn_FinishBattle, // BATTLE_OPPONENT_TELEPORTED
+};
+
+const u8 gStatusConditionString_PoisonJpn[8] = _("どく$$$$$");
+const u8 gStatusConditionString_SleepJpn[8] = _("ねむり$$$$");
+const u8 gStatusConditionString_ParalysisJpn[8] = _("まひ$$$$$");
+const u8 gStatusConditionString_BurnJpn[8] = _("やけど$$$$");
+const u8 gStatusConditionString_IceJpn[8] = _("こおり$$$$");
+const u8 gStatusConditionString_ConfusionJpn[8] = _("こんらん$$$");
+const u8 gStatusConditionString_LoveJpn[8] = _("メロメロ$$$");
+
+const u8 * const gStatusConditionStringsTable[][2] =
+{
+ {gStatusConditionString_PoisonJpn, gText_Poison},
+ {gStatusConditionString_SleepJpn, gText_Sleep},
+ {gStatusConditionString_ParalysisJpn, gText_Paralysis},
+ {gStatusConditionString_BurnJpn, gText_Burn},
+ {gStatusConditionString_IceJpn, gText_Ice},
+ {gStatusConditionString_ConfusionJpn, gText_Confusion},
+ {gStatusConditionString_LoveJpn, gText_Love}
+};
+
+static const u8 sUnknown_0831BCE0[][3] = {{0, 0, 0}, {3, 5, 0}, {2, 3, 0}, {1, 2, 0}, {1, 1, 0}};
+static const u8 sUnknown_0831BCEF[] = {4, 3, 2, 1};
+static const u8 sUnknown_0831BCF3[] = {4, 4, 4, 4};
+
+void CB2_InitBattle(void)
+{
+ MoveSaveBlocks_ResetHeap();
+ AllocateBattleResrouces();
+ AllocateBattleSpritesData();
+ AllocateMonSpritesGfx();
+ sub_8185F84();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ CB2_InitBattleInternal();
+ }
+ else if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER))
+ {
+ HandleLinkBattleSetup();
+ SetMainCallback2(CB2_PreInitMultiBattle);
+ }
+ else
+ {
+ SetMainCallback2(CB2_PreInitIngamePlayerPartnerBattle);
+ }
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ }
+ else
+ {
+ CB2_InitBattleInternal();
+ }
+}
+
+static void CB2_InitBattleInternal(void)
+{
+ s32 i;
+
+ SetHBlankCallback(NULL);
+ SetVBlankCallback(NULL);
+
+ CpuFill32(0, (void*)(VRAM), VRAM_SIZE);
+
+ SetGpuReg(REG_OFFSET_MOSAIC, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, 240);
+ SetGpuReg(REG_OFFSET_WIN0V, 0x5051);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+
+ gBattle_WIN0H = 240;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != STEVEN_PARTNER_ID)
+ {
+ gBattle_WIN0V = 159;
+ gBattle_WIN1H = 240;
+ gBattle_WIN1V = 32;
+ }
+ else
+ {
+ gBattle_WIN0V = 0x5051;
+ dp12_8087EA4();
+
+ for (i = 0; i < 80; i++)
+ {
+ gUnknown_02038C28.unk0[i] = 0xF0;
+ gUnknown_02038C28.unk780[i] = 0xF0;
+ }
+ for (i = 80; i < 160; i++)
+ {
+ #ifndef NONMATCHING
+ asm(""::"r"(i)); // needed to match
+ #endif // NONMATCHING
+
+ gUnknown_02038C28.unk0[i] = 0xFF10;
+ gUnknown_02038C28.unk780[i] = 0xFF10;
+ }
+
+ sub_80BA038(gUnknown_0831AC70);
+ }
+
+ ResetPaletteFade();
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+
+ gBattleTerrain = BattleSetup_GetTerrainId();
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ gBattleTerrain = BATTLE_TERRAIN_INSIDE;
+
+ sub_80356D0();
+ LoadBattleTextboxAndBackground();
+ ResetSpriteData();
+ ResetTasks();
+ LoadBattleEntryBackground();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 4;
+ SetVBlankCallback(VBlankCB_Battle);
+ SetUpBattleVarsAndBirchZigzagoon();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ SetMainCallback2(CB2_HandleStartMultiPartnerBattle);
+ else if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ SetMainCallback2(CB2_HandleStartMultiPartnerBattle);
+ else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ SetMainCallback2(CB2_HandleStartMultiBattle);
+ else
+ SetMainCallback2(CB2_HandleStartBattle);
+
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED)))
+ {
+ CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE);
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ CreateNPCTrainerParty(&gEnemyParty[3], gTrainerBattleOpponent_B, FALSE);
+ SetWildMonHeldItem();
+ }
+
+ gMain.inBattle = TRUE;
+ gSaveBlock2Ptr->field_CA9_b = 0;
+
+ for (i = 0; i < 6; i++)
+ AdjustFriendship(&gPlayerParty[i], 3);
+
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+}
+
+static void sub_8036A5C(void)
+{
+ u16 r6 = 0;
+ u16 species = 0;
+ u16 hp = 0;
+ u32 status = 0;
+ s32 i;
+
+ for (i = 0; i < 6; i++)
+ {
+ species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r6 |= 1 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r6 |= 2 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r6 |= 3 << i * 2;
+ }
+
+ gBattleStruct->field_182 = r6;
+ *(&gBattleStruct->field_183) = r6 >> 8;
+ gBattleStruct->field_183 |= FlagGet(SYS_FRONTIER_PASS) << 7;
+}
+
+static void SetPlayerBerryDataInBattleStruct(void)
+{
+ s32 i;
+ struct BattleStruct *battleStruct = gBattleStruct;
+ struct BattleEnigmaBerry *battleBerry = &battleStruct->battleEnigmaBerry;
+
+ if (IsEnigmaBerryValid() == TRUE)
+ {
+ for (i = 0; i < BERRY_NAME_COUNT - 1; i++)
+ battleBerry->name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ battleBerry->name[i] = EOS;
+
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; i++)
+ battleBerry->itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+
+ battleBerry->holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ battleBerry->holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ }
+ else
+ {
+ const struct Berry* berryData = GetBerryInfo(ItemIdToBerryType(ITEM_ENIGMA_BERRY));
+
+ for (i = 0; i < BERRY_NAME_COUNT - 1; i++)
+ battleBerry->name[i] = berryData->name[i];
+ battleBerry->name[i] = EOS;
+
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; i++)
+ battleBerry->itemEffect[i] = 0;
+
+ battleBerry->holdEffect = HOLD_EFFECT_NONE;
+ battleBerry->holdEffectParam = 0;
+ }
+}
+
+static void SetAllPlayersBerryData(void)
+{
+ s32 i;
+ s32 j;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ if (IsEnigmaBerryValid() == TRUE)
+ {
+ for (i = 0; i < BERRY_NAME_COUNT - 1; i++)
+ {
+ gEnigmaBerries[0].name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ gEnigmaBerries[2].name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ }
+ gEnigmaBerries[0].name[i] = EOS;
+ gEnigmaBerries[2].name[i] = EOS;
+
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; i++)
+ {
+ gEnigmaBerries[0].itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+ gEnigmaBerries[2].itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+ }
+
+ gEnigmaBerries[0].holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ gEnigmaBerries[2].holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ gEnigmaBerries[0].holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ gEnigmaBerries[2].holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ }
+ else
+ {
+ const struct Berry* berryData = GetBerryInfo(ItemIdToBerryType(ITEM_ENIGMA_BERRY));
+
+ for (i = 0; i < BERRY_NAME_COUNT - 1; i++)
+ {
+ gEnigmaBerries[0].name[i] = berryData->name[i];
+ gEnigmaBerries[2].name[i] = berryData->name[i];
+ }
+ gEnigmaBerries[0].name[i] = EOS;
+ gEnigmaBerries[2].name[i] = EOS;
+
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; i++)
+ {
+ gEnigmaBerries[0].itemEffect[i] = 0;
+ gEnigmaBerries[2].itemEffect[i] = 0;
+ }
+
+ gEnigmaBerries[0].holdEffect = 0;
+ gEnigmaBerries[2].holdEffect = 0;
+ gEnigmaBerries[0].holdEffectParam = 0;
+ gEnigmaBerries[2].holdEffectParam = 0;
+ }
+ }
+ else
+ {
+ s32 numPlayers;
+ struct BattleEnigmaBerry *src;
+ u8 r4;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ numPlayers = 2;
+ else
+ numPlayers = 4;
+
+ for (i = 0; i < numPlayers; i++)
+ {
+ src = (struct BattleEnigmaBerry *)(gBlockRecvBuffer[i] + 2);
+ r4 = gLinkPlayers[i].lp_field_18;
+
+ for (j = 0; j < BERRY_NAME_COUNT - 1; j++)
+ gEnigmaBerries[r4].name[j] = src->name[j];
+ gEnigmaBerries[r4].name[j] = EOS;
+
+ for (j = 0; j < BERRY_ITEM_EFFECT_COUNT; j++)
+ gEnigmaBerries[r4].itemEffect[j] = src->itemEffect[j];
+
+ gEnigmaBerries[r4].holdEffect = src->holdEffect;
+ gEnigmaBerries[r4].holdEffectParam = src->holdEffectParam;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 2; i++)
+ {
+ src = (struct BattleEnigmaBerry *)(gBlockRecvBuffer[i] + 2);
+
+ for (j = 0; j < BERRY_NAME_COUNT - 1; j++)
+ {
+ gEnigmaBerries[i].name[j] = src->name[j];
+ gEnigmaBerries[i + 2].name[j] = src->name[j];
+ }
+ gEnigmaBerries[i].name[j] = EOS;
+ gEnigmaBerries[i + 2].name[j] = EOS;
+
+ for (j = 0; j < BERRY_ITEM_EFFECT_COUNT; j++)
+ {
+ gEnigmaBerries[i].itemEffect[j] = src->itemEffect[j];
+ gEnigmaBerries[i + 2].itemEffect[j] = src->itemEffect[j];
+ }
+
+ gEnigmaBerries[i].holdEffect = src->holdEffect;
+ gEnigmaBerries[i + 2].holdEffect = src->holdEffect;
+ gEnigmaBerries[i].holdEffectParam = src->holdEffectParam;
+ gEnigmaBerries[i + 2].holdEffectParam = src->holdEffectParam;
+ }
+ }
+ }
+}
+
+static void sub_8036EB8(u8 arg0, u8 arg1)
+{
+ u8 var = 0;
+
+ if (gBlockRecvBuffer[0][0] == 256)
+ {
+ if (arg1 == 0)
+ gBattleTypeFlags |= BATTLE_TYPE_WILD | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ var++;
+ }
+
+ if (var == 0)
+ {
+ s32 i;
+
+ for (i = 0; i < arg0; i++)
+ {
+ if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0])
+ break;
+ }
+
+ if (i == arg0)
+ {
+ if (arg1 == 0)
+ gBattleTypeFlags |= BATTLE_TYPE_WILD | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ var++;
+ }
+
+ if (var == 0)
+ {
+ for (i = 0; i < arg0; i++)
+ {
+ if (gBlockRecvBuffer[i][0] == 0x300)
+ {
+ if (i != arg1 && i < arg1)
+ break;
+ }
+ if (gBlockRecvBuffer[i][0] > 0x300 && i != arg1)
+ break;
+ }
+
+ if (i == arg0)
+ gBattleTypeFlags |= BATTLE_TYPE_WILD | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ }
+ }
+}
+
+static void CB2_HandleStartBattle(void)
+{
+ u8 playerMultiplayerId;
+ u8 enemyMultiplayerId;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ playerMultiplayerId = GetMultiplayerId();
+ gBattleScripting.multiplayerId = playerMultiplayerId;
+ enemyMultiplayerId = playerMultiplayerId ^ BIT_SIDE;
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ sub_805EF14();
+ gBattleCommunication[MULTIUSE_STATE] = 1;
+ }
+ if (gLinkVSyncDisabled)
+ sub_800E0E8();
+ break;
+ case 1:
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ if (sub_800A520())
+ {
+ *(&gBattleStruct->field_180) = 0;
+ *(&gBattleStruct->field_181) = 3;
+ sub_8036A5C();
+ SetPlayerBerryDataInBattleStruct();
+
+ if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00)
+ {
+ gLinkPlayers[0].lp_field_18 = 0;
+ gLinkPlayers[1].lp_field_18 = 1;
+ }
+
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32);
+ gBattleCommunication[MULTIUSE_STATE] = 2;
+ }
+ if (gLinkVSyncDisabled)
+ sub_800DFB4(0, 0);
+ }
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ gBattleTypeFlags |= BATTLE_TYPE_WILD;
+ gBattleCommunication[MULTIUSE_STATE] = 15;
+ SetAllPlayersBerryData();
+ }
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ u8 taskId;
+
+ ResetBlockReceivedFlags();
+ sub_8036EB8(2, playerMultiplayerId);
+ SetAllPlayersBerryData();
+ taskId = CreateTask(task00_0800F6FC, 0);
+ gTasks[taskId].data[1] = 0x10E;
+ gTasks[taskId].data[2] = 0x5A;
+ gTasks[taskId].data[5] = 0;
+ gTasks[taskId].data[3] = gBattleStruct->field_182 | (gBattleStruct->field_183 << 8);
+ gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1];
+ sub_8185F90(gBlockRecvBuffer[playerMultiplayerId][1]);
+ sub_8185F90(gBlockRecvBuffer[enemyMultiplayerId][1]);
+ sub_8068AA4();
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 3:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 4:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 7:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 2, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 8:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty + 2, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 11:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 4, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 12:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty + 4, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ TryCorrectShedinjaLanguage(&gEnemyParty[0]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[1]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[2]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[3]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[4]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[5]);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 15:
+ sub_8032768();
+ sub_8184E58();
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE2] = 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ s32 i;
+
+ for (i = 0; i < 2 && (gLinkPlayers[i].version & 0xFF) == 3; i++);
+
+ if (i == 2)
+ gBattleCommunication[MULTIUSE_STATE] = 16;
+ else
+ gBattleCommunication[MULTIUSE_STATE] = 18;
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 18;
+ }
+ break;
+ case 16:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), &gRecordedBattleRngSeed, sizeof(gRecordedBattleRngSeed));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 17:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_WILD))
+ memcpy(&gRecordedBattleRngSeed, gBlockRecvBuffer[enemyMultiplayerId], sizeof(gRecordedBattleRngSeed));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 18:
+ if (BattleInitAllSprites(&gBattleCommunication[SPRITES_INIT_STATE1], &gBattleCommunication[SPRITES_INIT_STATE2]))
+ {
+ gPreBattleCallback1 = gMain.callback1;
+ gMain.callback1 = BattleMainCB1;
+ SetMainCallback2(BattleMainCB2);
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleTypeFlags |= BATTLE_TYPE_20;
+ }
+ }
+ break;
+ case 5:
+ case 9:
+ case 13:
+ gBattleCommunication[MULTIUSE_STATE]++;
+ gBattleCommunication[1] = 1;
+ case 6:
+ case 10:
+ case 14:
+ if (--gBattleCommunication[1] == 0)
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ }
+}
+
+static void CB2_HandleStartMultiPartnerBattle(void)
+{
+ u8 playerMultiplayerId;
+ u8 enemyMultiplayerId;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ playerMultiplayerId = GetMultiplayerId();
+ gBattleScripting.multiplayerId = playerMultiplayerId;
+ enemyMultiplayerId = playerMultiplayerId ^ BIT_SIDE;
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ sub_805EF14();
+ gBattleCommunication[MULTIUSE_STATE] = 1;
+ }
+ if (gLinkVSyncDisabled)
+ sub_800E0E8();
+ // fall through
+ case 1:
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ u8 language;
+
+ gLinkPlayers[0].lp_field_18 = 0;
+ gLinkPlayers[1].lp_field_18 = 2;
+ gLinkPlayers[2].lp_field_18 = 1;
+ gLinkPlayers[3].lp_field_18 = 3;
+ GetFrontierTrainerName(gLinkPlayers[2].name, gTrainerBattleOpponent_A);
+ GetFrontierTrainerName(gLinkPlayers[3].name, gTrainerBattleOpponent_B);
+ sub_8165B88(&language, gTrainerBattleOpponent_A);
+ gLinkPlayers[2].language = language;
+ sub_8165B88(&language, gTrainerBattleOpponent_B);
+ gLinkPlayers[3].language = language;
+
+ if (sub_800A520())
+ {
+ *(&gBattleStruct->field_180) = 0;
+ *(&gBattleStruct->field_181) = 3;
+ sub_8036A5C();
+ SetPlayerBerryDataInBattleStruct();
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32);
+ gBattleCommunication[MULTIUSE_STATE] = 2;
+ }
+
+ if (gLinkVSyncDisabled)
+ sub_800DFB4(0, 0);
+ }
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ gBattleTypeFlags |= BATTLE_TYPE_WILD;
+ gBattleCommunication[MULTIUSE_STATE] = 13;
+ SetAllPlayersBerryData();
+ }
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ u8 taskId;
+
+ ResetBlockReceivedFlags();
+ sub_8036EB8(2, playerMultiplayerId);
+ SetAllPlayersBerryData();
+ taskId = CreateTask(task00_0800F6FC, 0);
+ gTasks[taskId].data[1] = 0x10E;
+ gTasks[taskId].data[2] = 0x5A;
+ gTasks[taskId].data[5] = 0;
+ gTasks[taskId].data[3] = 0x145;
+ gTasks[taskId].data[4] = 0x145;
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 3:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 4:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (gLinkPlayers[playerMultiplayerId].lp_field_18 != 0)
+ {
+ memcpy(gPlayerParty, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[playerMultiplayerId], sizeof(struct Pokemon) * 2);
+ }
+ else
+ {
+ memcpy(gPlayerParty, gBlockRecvBuffer[playerMultiplayerId], sizeof(struct Pokemon) * 2);
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 5:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 2, sizeof(struct Pokemon));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 6:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (gLinkPlayers[playerMultiplayerId].lp_field_18 != 0)
+ {
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon));
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[playerMultiplayerId], sizeof(struct Pokemon));
+ }
+ else
+ {
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[playerMultiplayerId], sizeof(struct Pokemon));
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon));
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 7:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gEnemyParty, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 8:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (GetMultiplayerId() != 0)
+ {
+ memcpy(gEnemyParty, gBlockRecvBuffer[0], sizeof(struct Pokemon) * 2);
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 9:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gEnemyParty + 2, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 10:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (GetMultiplayerId() != 0)
+ {
+ memcpy(gEnemyParty + 2, gBlockRecvBuffer[0], sizeof(struct Pokemon) * 2);
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 11:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gEnemyParty + 4, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 12:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (GetMultiplayerId() != 0)
+ memcpy(gEnemyParty + 4, gBlockRecvBuffer[0], sizeof(struct Pokemon) * 2);
+ TryCorrectShedinjaLanguage(&gPlayerParty[0]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[1]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[2]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[3]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[4]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[5]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[0]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[1]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[2]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[3]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[4]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[5]);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 13:
+ sub_8032768();
+ sub_8184E58();
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE2] = 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 14;
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 16;
+ }
+ break;
+ case 14:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), &gRecordedBattleRngSeed, sizeof(gRecordedBattleRngSeed));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 15:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_WILD))
+ memcpy(&gRecordedBattleRngSeed, gBlockRecvBuffer[enemyMultiplayerId], sizeof(gRecordedBattleRngSeed));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 16:
+ if (BattleInitAllSprites(&gBattleCommunication[SPRITES_INIT_STATE1], &gBattleCommunication[SPRITES_INIT_STATE2]))
+ {
+ sub_8166188();
+ gPreBattleCallback1 = gMain.callback1;
+ gMain.callback1 = BattleMainCB1;
+ SetMainCallback2(BattleMainCB2);
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleTypeFlags |= BATTLE_TYPE_20;
+ }
+ }
+ break;
+ }
+}
+
+static void sub_80379F8(u8 arrayIdPlus)
+{
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ gUnknown_02022FF8[i].species = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_SPECIES);
+ gUnknown_02022FF8[i].heldItem = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_HELD_ITEM);
+ GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_NICKNAME, gUnknown_02022FF8[i].nickname);
+ gUnknown_02022FF8[i].level = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_LEVEL);
+ gUnknown_02022FF8[i].hp = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_HP);
+ gUnknown_02022FF8[i].maxhp = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_MAX_HP);
+ gUnknown_02022FF8[i].status = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_STATUS);
+ gUnknown_02022FF8[i].personality = GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_PERSONALITY);
+ gUnknown_02022FF8[i].gender = GetMonGender(&gPlayerParty[arrayIdPlus + i]);
+ StripExtCtrlCodes(gUnknown_02022FF8[i].nickname);
+ if (GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_LANGUAGE) != LANGUAGE_JAPANESE)
+ sub_81DB4DC(gUnknown_02022FF8[i].nickname, 0);
+ }
+ memcpy(gUnknown_02023058, gUnknown_02022FF8, sizeof(gUnknown_02022FF8));
+}
+
+static void CB2_PreInitMultiBattle(void)
+{
+ s32 i;
+ u8 playerMultiplierId;
+ s32 numPlayers = 4;
+ u8 r4 = 0xF;
+ u32* savedBattleTypeFlags;
+ void (**savedCallback)(void);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ {
+ numPlayers = 2;
+ r4 = 3;
+ }
+
+ playerMultiplierId = GetMultiplayerId();
+ gBattleScripting.multiplayerId = playerMultiplierId;
+ savedCallback = &gBattleStruct->savedCallback;
+ savedBattleTypeFlags = &gBattleStruct->savedBattleTypeFlags;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (gReceivedRemoteLinkPlayers != 0 && sub_800A520())
+ {
+ gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3);
+ sub_80379F8(0);
+ SendBlock(bitmask_all_link_players_but_self(), gUnknown_02023058, sizeof(struct UnknownPokemonStruct2) * 3);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 1:
+ if ((GetBlockReceivedStatus() & r4) == r4)
+ {
+ ResetBlockReceivedFlags();
+ for (i = 0; i < numPlayers; i++)
+ {
+ if (i == playerMultiplierId)
+ continue;
+
+ if (numPlayers == 4)
+ {
+ if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[playerMultiplierId].lp_field_18 & 1))
+ || (gLinkPlayers[i].lp_field_18 & 1 && gLinkPlayers[playerMultiplierId].lp_field_18 & 1))
+ {
+ memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3);
+ }
+ }
+ else
+ {
+ memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3);
+ }
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ *savedCallback = gMain.savedCallback;
+ *savedBattleTypeFlags = gBattleTypeFlags;
+ gMain.savedCallback = CB2_PreInitMultiBattle;
+ sub_81B9150();
+ }
+ break;
+ case 2:
+ if (sub_800A520() && !gPaletteFade.active)
+ {
+ gBattleCommunication[MULTIUSE_STATE]++;
+ if (gLinkVSyncDisabled)
+ sub_800ADF8();
+ else
+ sub_800AC34();
+ }
+ break;
+ case 3:
+ if (gLinkVSyncDisabled)
+ {
+ if (sub_8010500())
+ {
+ gBattleTypeFlags = *savedBattleTypeFlags;
+ gMain.savedCallback = *savedCallback;
+ SetMainCallback2(CB2_InitBattleInternal);
+ Free(gUnknown_02023058);
+ gUnknown_02023058 = NULL;
+ }
+ }
+ else if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gBattleTypeFlags = *savedBattleTypeFlags;
+ gMain.savedCallback = *savedCallback;
+ SetMainCallback2(CB2_InitBattleInternal);
+ Free(gUnknown_02023058);
+ gUnknown_02023058 = NULL;
+ }
+ break;
+ }
+}
+
+static void CB2_PreInitIngamePlayerPartnerBattle(void)
+{
+ u32* savedBattleTypeFlags;
+ void (**savedCallback)(void);
+
+ savedCallback = &gBattleStruct->savedCallback;
+ savedBattleTypeFlags = &gBattleStruct->savedBattleTypeFlags;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3);
+ sub_80379F8(3);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ *savedCallback = gMain.savedCallback;
+ *savedBattleTypeFlags = gBattleTypeFlags;
+ gMain.savedCallback = CB2_PreInitIngamePlayerPartnerBattle;
+ sub_81B9150();
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 2;
+ gBattleTypeFlags = *savedBattleTypeFlags;
+ gMain.savedCallback = *savedCallback;
+ SetMainCallback2(CB2_InitBattleInternal);
+ Free(gUnknown_02023058);
+ gUnknown_02023058 = NULL;
+ }
+ break;
+ }
+}
+
+static void CB2_HandleStartMultiBattle(void)
+{
+ u8 playerMultiplayerId;
+ s32 id;
+ u8 var;
+
+ playerMultiplayerId = GetMultiplayerId();
+ gBattleScripting.multiplayerId = playerMultiplayerId;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ sub_805EF14();
+ gBattleCommunication[MULTIUSE_STATE] = 1;
+ }
+ if (gLinkVSyncDisabled)
+ sub_800E0E8();
+ break;
+ case 1:
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ if (sub_800A520())
+ {
+ *(&gBattleStruct->field_180) = 0;
+ *(&gBattleStruct->field_181) = 3;
+ sub_8036A5C();
+ SetPlayerBerryDataInBattleStruct();
+
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ if (gLinkVSyncDisabled)
+ sub_800DFB4(0, 0);
+ }
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ gBattleTypeFlags |= BATTLE_TYPE_WILD;
+ gBattleCommunication[MULTIUSE_STATE] = 7;
+ SetAllPlayersBerryData();
+ }
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ sub_8036EB8(4, playerMultiplayerId);
+ SetAllPlayersBerryData();
+ sub_8068AA4();
+ var = CreateTask(task00_0800F6FC, 0);
+ gTasks[var].data[1] = 0x10E;
+ gTasks[var].data[2] = 0x5A;
+ gTasks[var].data[5] = 0;
+ gTasks[var].data[3] = 0;
+ gTasks[var].data[4] = 0;
+
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ {
+ sub_8185F90(gBlockRecvBuffer[id][1]);
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ gTasks[var].data[3] |= gBlockRecvBuffer[id][1] & 0x3F;
+ break;
+ case 1:
+ gTasks[var].data[4] |= gBlockRecvBuffer[id][1] & 0x3F;
+ break;
+ case 2:
+ gTasks[var].data[3] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6;
+ break;
+ case 3:
+ gTasks[var].data[4] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6;
+ break;
+ }
+ }
+ ZeroEnemyPartyMons();
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ else
+ break;
+ // fall through
+ case 3:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty, sizeof(struct Pokemon) * 2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 4:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ {
+ if (id == playerMultiplayerId)
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[id].lp_field_18 & 1) && !(gLinkPlayers[playerMultiplayerId].lp_field_18 & 1))
+ || ((gLinkPlayers[id].lp_field_18 & 1) && (gLinkPlayers[playerMultiplayerId].lp_field_18 & 1)))
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ else
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gEnemyParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gEnemyParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ }
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 5:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 2, sizeof(struct Pokemon));
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 6:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ {
+ if (id == playerMultiplayerId)
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[id].lp_field_18 & 1) && !(gLinkPlayers[playerMultiplayerId].lp_field_18 & 1))
+ || ((gLinkPlayers[id].lp_field_18 & 1) && (gLinkPlayers[playerMultiplayerId].lp_field_18 & 1)))
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ else
+ {
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ memcpy(gEnemyParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gEnemyParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ }
+ }
+ TryCorrectShedinjaLanguage(&gPlayerParty[0]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[1]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[2]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[3]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[4]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[5]);
+
+ TryCorrectShedinjaLanguage(&gEnemyParty[0]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[1]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[2]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[3]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[4]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[5]);
+
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 7:
+ sub_8032768();
+ sub_8184E58();
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE2] = 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ for (id = 0; id < 4 && (gLinkPlayers[id].version & 0xFF) == 3; id++);
+
+ if (id == 4)
+ gBattleCommunication[MULTIUSE_STATE] = 8;
+ else
+ gBattleCommunication[MULTIUSE_STATE] = 10;
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 10;
+ }
+ break;
+ case 8:
+ if (sub_800A520())
+ {
+ u32* ptr = (u32*)(&gBattleStruct->field_180);
+ ptr[0] = gBattleTypeFlags;
+ ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data
+ SendBlock(bitmask_all_link_players_but_self(), ptr, 8);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 9:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ for (var = 0; var < 4; var++)
+ {
+ u32 blockValue = gBlockRecvBuffer[var][0];
+ if (blockValue & 4)
+ {
+ memcpy(&gRecordedBattleRngSeed, &gBlockRecvBuffer[var][2], sizeof(gRecordedBattleRngSeed));
+ break;
+ }
+ }
+
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 10:
+ if (BattleInitAllSprites(&gBattleCommunication[SPRITES_INIT_STATE1], &gBattleCommunication[SPRITES_INIT_STATE2]))
+ {
+ gPreBattleCallback1 = gMain.callback1;
+ gMain.callback1 = BattleMainCB1;
+ SetMainCallback2(BattleMainCB2);
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gTrainerBattleOpponent_A = TRAINER_OPPONENT_800;
+ gBattleTypeFlags |= BATTLE_TYPE_20;
+ }
+ }
+ break;
+ }
+}
+
+void BattleMainCB2(void)
+{
+ AnimateSprites();
+ BuildOamBuffer();
+ RunTextPrinters();
+ UpdatePaletteFade();
+ RunTasks();
+
+ if (gMain.heldKeys & B_BUTTON && gBattleTypeFlags & BATTLE_TYPE_RECORDED && sub_8186450())
+ {
+ gScriptResult = gBattleOutcome = BATTLE_PLAYER_TELEPORTED;
+ ResetPaletteFadeControl();
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ SetMainCallback2(CB2_QuitRecordedBattle);
+ }
+}
+
+static void FreeRestoreBattleData(void)
+{
+ gMain.callback1 = gPreBattleCallback1;
+ gUnknown_02039B28[0x15] = 3;
+ gMain.inBattle = 0;
+ ZeroEnemyPartyMons();
+ m4aSongNumStop(0x5A);
+ FreeMonSpritesGfx();
+ FreeBattleSpritesData();
+ FreeBattleResources();
+}
+
+void CB2_QuitRecordedBattle(void)
+{
+ UpdatePaletteFade();
+ if (!gPaletteFade.active)
+ {
+ m4aMPlayStop(&gMPlay_SE1);
+ m4aMPlayStop(&gMPlay_SE2);
+ FreeRestoreBattleData();
+ FreeAllWindowBuffers();
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+void sub_8038528(struct Sprite* sprite)
+{
+ sprite->data0 = 0;
+ sprite->callback = sub_8038538;
+}
+
+static void sub_8038538(struct Sprite *sprite)
+{
+ u16 *arr = (u16*)(gDecompressionBuffer);
+
+ switch (sprite->data0)
+ {
+ case 0:
+ sprite->data0++;
+ sprite->data1 = 0;
+ sprite->data2 = 0x281;
+ sprite->data3 = 0;
+ sprite->data4 = 1;
+ // fall through
+ case 1:
+ sprite->data4--;
+ if (sprite->data4 == 0)
+ {
+ s32 i;
+ s32 r2;
+ s32 r0;
+
+ sprite->data4 = 2;
+ r2 = sprite->data1 + sprite->data3 * 32;
+ r0 = sprite->data2 - sprite->data3 * 32;
+ for (i = 0; i < 29; i += 2)
+ {
+ arr[r2 + i] = 0x3D;
+ arr[r0 + i] = 0x3D;
+ }
+ sprite->data3++;
+ if (sprite->data3 == 21)
+ {
+ sprite->data0++;
+ sprite->data1 = 32;
+ }
+ }
+ break;
+ case 2:
+ sprite->data1--;
+ if (sprite->data1 == 20)
+ SetMainCallback2(CB2_InitBattle);
+ break;
+ }
+}
+
+static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer)
+{
+ u32 nameHash = 0;
+ u32 personalityValue;
+ u8 fixedIV;
+ s32 i, j;
+ u8 monsCount;
+
+ if (trainerNum == SECRET_BASE_OPPONENT)
+ return 0;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_x4000000)))
+ {
+ if (firstTrainer == TRUE)
+ ZeroEnemyPartyMons();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ {
+ if (gTrainers[trainerNum].partySize > 3)
+ monsCount = 3;
+ else
+ monsCount = gTrainers[trainerNum].partySize;
+ }
+ else
+ {
+ monsCount = gTrainers[trainerNum].partySize;
+ }
+
+ for (i = 0; i < monsCount; i++)
+ {
+
+ if (gTrainers[trainerNum].doubleBattle == TRUE)
+ personalityValue = 0x80;
+ else if (gTrainers[trainerNum].encounterMusic_gender & 0x80)
+ personalityValue = 0x78;
+ else
+ personalityValue = 0x88;
+
+ for (j = 0; gTrainers[trainerNum].trainerName[j] != 0xFF; j++)
+ nameHash += gTrainers[trainerNum].trainerName[j];
+
+ switch (gTrainers[trainerNum].partyFlags)
+ {
+ case 0:
+ {
+ const struct TrainerMonNoItemDefaultMoves *partyData = gTrainers[trainerNum].party.NoItemDefaultMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
+ break;
+ }
+ case PARTY_FLAG_CUSTOM_MOVES:
+ {
+ const struct TrainerMonNoItemCustomMoves *partyData = gTrainers[trainerNum].party.NoItemCustomMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, 2, 0);
+
+ for (j = 0; j < 4; j++)
+ {
+ SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
+ SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
+ }
+ break;
+ }
+ case PARTY_FLAG_HAS_ITEM:
+ {
+ const struct TrainerMonItemDefaultMoves *partyData = gTrainers[trainerNum].party.ItemDefaultMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, 2, 0);
+
+ SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
+ break;
+ }
+ case PARTY_FLAG_CUSTOM_MOVES | PARTY_FLAG_HAS_ITEM:
+ {
+ const struct TrainerMonItemCustomMoves *partyData = gTrainers[trainerNum].party.ItemCustomMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, 2, 0);
+
+ SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
+
+ for (j = 0; j < 4; j++)
+ {
+ SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
+ SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
+ }
+ break;
+ }
+ }
+ }
+
+ gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;
+ }
+
+ return gTrainers[trainerNum].partySize;
+}
+
+void sub_8038A04(void) // unused
+{
+ if (REG_VCOUNT < 0xA0 && REG_VCOUNT >= 0x6F)
+ SetGpuReg(REG_OFFSET_BG0CNT, 0x9800);
+}
+
+void VBlankCB_Battle(void)
+{
+ // change gRngSeed every vblank unless the battle could be recorded
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_RECORDED)))
+ Random();
+
+ SetGpuReg(REG_OFFSET_BG0HOFS, gBattle_BG0_X);
+ SetGpuReg(REG_OFFSET_BG0VOFS, gBattle_BG0_Y);
+ SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X);
+ SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
+ SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X);
+ SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y);
+ SetGpuReg(REG_OFFSET_BG3HOFS, gBattle_BG3_X);
+ SetGpuReg(REG_OFFSET_BG3VOFS, gBattle_BG3_Y);
+ SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H);
+ SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V);
+ SetGpuReg(REG_OFFSET_WIN1H, gBattle_WIN1H);
+ SetGpuReg(REG_OFFSET_WIN1V, gBattle_WIN1V);
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+ sub_80BA0A8();
+}
+
+void nullsub_17(void)
+{
+
+}
+
+static void sub_8038B04(struct Sprite *sprite)
+{
+ if (sprite->data0 != 0)
+ sprite->pos1.x = sprite->data1 + ((sprite->data2 & 0xFF00) >> 8);
+ else
+ sprite->pos1.x = sprite->data1 - ((sprite->data2 & 0xFF00) >> 8);
+
+ sprite->data2 += 0x180;
+
+ if (sprite->affineAnimEnded)
+ {
+ FreeSpriteTilesByTag(0x2710);
+ FreeSpritePaletteByTag(0x2710);
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+ }
+}
+
+void sub_8038B74(struct Sprite *sprite)
+{
+ StartSpriteAffineAnim(sprite, 1);
+ sprite->callback = sub_8038B04;
+ PlaySE(SE_BT_START);
+}
+
+static void sub_8038B94(u8 taskId)
+{
+ struct Pokemon *sp4 = NULL;
+ struct Pokemon *sp8 = NULL;
+ u8 r2 = gBattleScripting.multiplayerId;
+ u32 r7;
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ switch (gLinkPlayers[r2].lp_field_18)
+ {
+ case 0:
+ case 2:
+ sp4 = gPlayerParty;
+ sp8 = gEnemyParty;
+ break;
+ case 1:
+ case 3:
+ sp4 = gEnemyParty;
+ sp8 = gPlayerParty;
+ break;
+ }
+ }
+ else
+ {
+ sp4 = gPlayerParty;
+ sp8 = gEnemyParty;
+ }
+
+ r7 = 0;
+ for (i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&sp4[i], MON_DATA_SPECIES2);
+ u16 hp = GetMonData(&sp4[i], MON_DATA_HP);
+ u32 status = GetMonData(&sp4[i], MON_DATA_STATUS);
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r7 |= 1 << i * 2;
+
+ if (species == 0)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r7 |= 2 << i * 2;
+
+ if (species == 0)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r7 |= 3 << i * 2;
+ }
+ gTasks[taskId].data[3] = r7;
+
+ r7 = 0;
+ for (i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&sp8[i], MON_DATA_SPECIES2);
+ u16 hp = GetMonData(&sp8[i], MON_DATA_HP);
+ u32 status = GetMonData(&sp8[i], MON_DATA_STATUS);
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r7 |= 1 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r7 |= 2 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r7 |= 3 << i * 2;
+ }
+ gTasks[taskId].data[4] = r7;
+}
+
+void sub_8038D64(void)
+{
+ s32 i;
+ u8 taskId;
+
+ SetHBlankCallback(NULL);
+ SetVBlankCallback(NULL);
+ gBattleTypeFlags &= ~(BATTLE_TYPE_20);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ {
+ SetMainCallback2(gMain.savedCallback);
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ FreeMonSpritesGfx();
+ }
+ else
+ {
+ CpuFill32(0, (void*)(VRAM), VRAM_SIZE);
+ SetGpuReg(REG_OFFSET_MOSAIC, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0xF0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0x5051);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ gBattle_WIN0H = 0xF0;
+ gBattle_WIN0V = 0x5051;
+ dp12_8087EA4();
+
+ for (i = 0; i < 80; i++)
+ {
+ gUnknown_02038C28.unk0[i] = 0xF0;
+ gUnknown_02038C28.unk780[i] = 0xF0;
+ }
+ for (i = 80; i < 160; i++)
+ {
+ asm(""::"r"(i)); // Needed to stop the compiler from optimizing out the loop counter
+ gUnknown_02038C28.unk0[i] = 0xFF10;
+ gUnknown_02038C28.unk780[i] = 0xFF10;
+ }
+
+ ResetPaletteFade();
+
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+
+ sub_80356D0();
+ LoadCompressedPalette(gUnknown_08C004E0, 0, 64);
+ ApplyPlayerChosenFrameToBattleMenu();
+ ResetSpriteData();
+ ResetTasks();
+ LoadBattleEntryBackground();
+ SetGpuReg(REG_OFFSET_WINOUT, 0x37);
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 4;
+ SetVBlankCallback(VBlankCB_Battle);
+
+ taskId = CreateTask(task00_0800F6FC, 0);
+ gTasks[taskId].data[1] = 0x10E;
+ gTasks[taskId].data[2] = 0x5A;
+ gTasks[taskId].data[5] = 1;
+ sub_8038B94(taskId);
+ SetMainCallback2(sub_8038F14);
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ }
+}
+
+static void sub_8038F14(void)
+{
+ sub_8038F34();
+ AnimateSprites();
+ BuildOamBuffer();
+ RunTextPrinters();
+ UpdatePaletteFade();
+ RunTasks();
+}
+
+static void sub_8038F34(void)
+{
+ s32 i;
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ gBattleCommunication[1] = 0xFF;
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 1:
+ if (--gBattleCommunication[1] == 0)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ u8 monsCount;
+
+ gMain.field_439_x4 = sub_8185FAC();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ monsCount = 4;
+ else
+ monsCount = 2;
+
+ for (i = 0; i < monsCount && (gLinkPlayers[i].version & 0xFF) == 3; i++);
+
+ if (!gSaveBlock2Ptr->field_CA9_b && i == monsCount)
+ {
+ if (FlagGet(SYS_FRONTIER_PASS))
+ {
+ FreeAllWindowBuffers();
+ SetMainCallback2(sub_80392A8);
+ }
+ else if (!gMain.field_439_x4)
+ {
+ SetMainCallback2(gMain.savedCallback);
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ FreeMonSpritesGfx();
+ }
+ else if (gReceivedRemoteLinkPlayers == 0)
+ {
+ CreateTask(sub_80B3AF8, 5);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ }
+ else
+ {
+ SetMainCallback2(gMain.savedCallback);
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ FreeMonSpritesGfx();
+ }
+ }
+ break;
+ case 3:
+ CpuFill32(0, (void*)(VRAM), VRAM_SIZE);
+
+ for (i = 0; i < 2; i++)
+ LoadChosenBattleElement(i);
+
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 4:
+ if (!gPaletteFade.active)
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 5:
+ if (!FuncIsActiveTask(sub_80B3AF8))
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 6:
+ if (sub_800A520() == TRUE)
+ {
+ sub_800ADF8();
+ sub_814F9EC(gText_LinkStandby3, 0);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 7:
+ if (!IsTextPrinterActive(0))
+ {
+ if (sub_800A520() == TRUE)
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 8:
+ if (!gLinkVSyncDisabled)
+ sub_800AC34();
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 9:
+ if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1)
+ {
+ gMain.field_439_x4 = 0;
+ SetMainCallback2(gMain.savedCallback);
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ FreeMonSpritesGfx();
+ }
+ break;
+ }
+}
+
+u32 sub_80391E0(u8 arrayId, u8 caseId)
+{
+ u32 ret = 0;
+
+ switch (caseId)
+ {
+ case 0:
+ ret = gUnknown_0831AA08[arrayId].bg;
+ break;
+ case 1:
+ ret = gUnknown_0831AA08[arrayId].charBaseIndex;
+ break;
+ case 2:
+ ret = gUnknown_0831AA08[arrayId].mapBaseIndex;
+ break;
+ case 3:
+ ret = gUnknown_0831AA08[arrayId].screenSize;
+ break;
+ case 4:
+ ret = gUnknown_0831AA08[arrayId].paletteMode;
+ break;
+ case 5:
+ ret = gUnknown_0831AA08[arrayId].priority;
+ break;
+ case 6:
+ ret = gUnknown_0831AA08[arrayId].baseTile;
+ break;
+ }
+
+ return ret;
+}
+
+static void sub_80392A8(void)
+{
+ s32 i;
+
+ SetHBlankCallback(NULL);
+ SetVBlankCallback(NULL);
+ CpuFill32(0, (void*)(VRAM), VRAM_SIZE);
+ ResetPaletteFade();
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+ sub_80356D0();
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ ApplyPlayerChosenFrameToBattleMenu();
+
+ for (i = 0; i < 2; i++)
+ LoadChosenBattleElement(i);
+
+ ResetSpriteData();
+ ResetTasks();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 4;
+ SetVBlankCallback(VBlankCB_Battle);
+ SetMainCallback2(sub_803937C);
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+}
+
+static void sub_803937C(void)
+{
+ sub_803939C();
+ AnimateSprites();
+ BuildOamBuffer();
+ RunTextPrinters();
+ UpdatePaletteFade();
+ RunTasks();
+}
+
+static void sub_803939C(void)
+{
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 1:
+ if (gMain.field_439_x4 && gReceivedRemoteLinkPlayers == 0)
+ CreateTask(sub_80B3AF8, 5);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 2:
+ if (!FuncIsActiveTask(sub_80B3AF8))
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 3:
+ if (!gPaletteFade.active)
+ {
+ sub_814F9EC(gText_RecordBattleToPass, 0);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 4:
+ if (!IsTextPrinterActive(0))
+ {
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 0);
+ sub_814F9EC(gText_BattleYesNoChoice, 0xC);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 5:
+ if (gMain.newKeys & DPAD_UP)
+ {
+ if (gBattleCommunication[CURSOR_POSITION] != 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ }
+ }
+ else if (gMain.newKeys & DPAD_DOWN)
+ {
+ if (gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ }
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ if (gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 1);
+ gBattleCommunication[1] = MoveRecordedBattleToSaveData();
+ gBattleCommunication[MULTIUSE_STATE] = 10;
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 6:
+ if (sub_800A520() == TRUE)
+ {
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 1);
+ if (gMain.field_439_x4)
+ {
+ sub_800ADF8();
+ sub_814F9EC(gText_LinkStandby3, 0);
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 8:
+ if (--gBattleCommunication[1] == 0)
+ {
+ if (gMain.field_439_x4 && !gLinkVSyncDisabled)
+ sub_800AC34();
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 9:
+ if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1)
+ {
+ gMain.field_439_x4 = 0;
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(gMain.savedCallback);
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ FreeMonSpritesGfx();
+ }
+ }
+ break;
+ case 10:
+ if (gBattleCommunication[1] == 1)
+ {
+ PlaySE(SE_SAVE);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_BattleRecordedOnPass);
+ sub_814F9EC(gDisplayedStringBattle, 0);
+ gBattleCommunication[1] = 0x80;
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ else
+ {
+ BattleStringExpandPlaceholdersToDisplayedString(gText_BattleRecordCouldntBeSaved);
+ sub_814F9EC(gDisplayedStringBattle, 0);
+ gBattleCommunication[1] = 0x80;
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 11:
+ if (sub_800A520() == TRUE && !IsTextPrinterActive(0) && --gBattleCommunication[1] == 0)
+ {
+ if (gMain.field_439_x4)
+ {
+ sub_800ADF8();
+ sub_814F9EC(gText_LinkStandby3, 0);
+ }
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 12:
+ case 7:
+ if (!IsTextPrinterActive(0))
+ {
+ if (gMain.field_439_x4)
+ {
+ if (sub_800A520() == TRUE)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gBattleCommunication[1] = 0x20;
+ gBattleCommunication[MULTIUSE_STATE] = 8;
+ }
+
+ }
+ else
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gBattleCommunication[1] = 0x20;
+ gBattleCommunication[MULTIUSE_STATE] = 8;
+ }
+ }
+ break;
+ }
+}
+
+static void TryCorrectShedinjaLanguage(struct Pokemon *mon)
+{
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+ u8 language = LANGUAGE_JAPANESE;
+
+ if (GetMonData(mon, MON_DATA_SPECIES) == SPECIES_SHEDINJA
+ && GetMonData(mon, MON_DATA_LANGUAGE) != language)
+ {
+ GetMonData(mon, MON_DATA_NICKNAME, nickname);
+ if (StringCompareWithoutExtCtrlCodes(nickname, gText_ShedinjaJapaneseName) == 0)
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ }
+}
+
+u32 sub_80397C4(u32 setId, u32 tableId)
+{
+ return gUnknown_0831ABA0[setId][tableId].width * 8;
+}
+
+#define tBank data0
+#define tSpeciesId data2
+
+void oac_poke_opponent(struct Sprite *sprite)
+{
+ sprite->callback = sub_803980C;
+ StartSpriteAnimIfDifferent(sprite, 0);
+ BeginNormalPaletteFade(0x20000, 0, 10, 10, 0x2108);
+}
+
+static void sub_803980C(struct Sprite *sprite)
+{
+ if ((gUnknown_020243FC & 1) == 0)
+ {
+ sprite->pos2.x += 2;
+ if (sprite->pos2.x == 0)
+ {
+ sprite->callback = sub_8039838;
+ }
+ }
+}
+
+static void sub_8039838(struct Sprite *sprite)
+{
+ if (sprite->animEnded)
+ {
+ sub_8076918(sprite->tBank);
+ sub_80729D0(gHealthBoxesIds[sprite->tBank]);
+ sprite->callback = sub_8039894;
+ StartSpriteAnimIfDifferent(sprite, 0);
+ BeginNormalPaletteFade(0x20000, 0, 10, 0, 0x2108);
+ }
+}
+
+static void sub_8039894(struct Sprite *sprite)
+{
+ if (!gPaletteFade.active)
+ {
+ BattleAnimateFrontSprite(sprite, sprite->tSpeciesId, FALSE, 1);
+ }
+}
+
+void SpriteCallbackDummy_2(struct Sprite *sprite)
+{
+
+}
+
+static void sub_80398BC(struct Sprite *sprite) // unused?
+{
+ sprite->data3 = 6;
+ sprite->data4 = 1;
+ sprite->callback = sub_80398D0;
+}
+
+static void sub_80398D0(struct Sprite *sprite)
+{
+ sprite->data4--;
+ if (sprite->data4 == 0)
+ {
+ sprite->data4 = 8;
+ sprite->invisible ^= 1;
+ sprite->data3--;
+ if (sprite->data3 == 0)
+ {
+ sprite->invisible = FALSE;
+ sprite->callback = SpriteCallbackDummy_2;
+ gUnknown_02022F88 = 0;
+ }
+ }
+}
+
+// to get rid of once the struct is declared in a header
+struct MonCoords
+{
+ // This would use a bitfield, but sub_8079F44
+ // uses it as a u8 and casting won't match.
+ u8 coords; // u8 x:4, y:4;
+ u8 y_offset;
+};
+
+extern const struct MonCoords gMonFrontPicCoords[];
+extern const struct MonCoords gCastformFrontSpriteCoords[];
+
+void sub_8039934(struct Sprite *sprite)
+{
+ u8 bank = sprite->tBank;
+ u16 species;
+ u8 yOffset;
+
+ if (gBattleSpritesDataPtr->bankData[bank].transformSpecies != 0)
+ species = gBattleSpritesDataPtr->bankData[bank].transformSpecies;
+ else
+ species = sprite->tSpeciesId;
+
+ GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_PERSONALITY); // Unused return value
+
+ if (species == SPECIES_UNOWN)
+ {
+ u32 personalityValue = GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_PERSONALITY);
+ u16 unownForm = ((((personalityValue & 0x3000000) >> 18) | ((personalityValue & 0x30000) >> 12) | ((personalityValue & 0x300) >> 6) | (personalityValue & 3)) % 0x1C);
+ u16 unownSpecies;
+
+ if (unownForm == 0)
+ unownSpecies = SPECIES_UNOWN; // Use the A Unown form
+ else
+ unownSpecies = NUM_SPECIES + unownForm; // Use one of the other Unown letters
+
+ yOffset = gMonFrontPicCoords[unownSpecies].y_offset;
+ }
+ else if (species == SPECIES_CASTFORM)
+ {
+ yOffset = gCastformFrontSpriteCoords[gBattleMonForms[bank]].y_offset;
+ }
+ else if (species > NUM_SPECIES)
+ {
+ yOffset = gMonFrontPicCoords[SPECIES_NONE].y_offset;
+ }
+ else
+ {
+ yOffset = gMonFrontPicCoords[species].y_offset;
+ }
+
+ sprite->data3 = 8 - yOffset / 8;
+ sprite->data4 = 1;
+ sprite->callback = sub_8039A48;
+}
+
+static void sub_8039A48(struct Sprite *sprite)
+{
+ s32 i;
+
+ sprite->data4--;
+ if (sprite->data4 == 0)
+ {
+ sprite->data4 = 2;
+ sprite->pos2.y += 8;
+ sprite->data3--;
+ if (sprite->data3 < 0)
+ {
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+ }
+ else
+ {
+ u8 *dst = (u8 *)gMonSpritesGfxPtr->sprites[GetBankIdentity(sprite->tBank)] + (gBattleMonForms[sprite->tBank] << 11) + (sprite->data3 << 8);
+
+ for (i = 0; i < 0x100; i++)
+ *(dst++) = 0;
+
+ StartSpriteAnim(sprite, gBattleMonForms[sprite->tBank]);
+ }
+ }
+}
+
+void sub_8039AD8(struct Sprite *sprite)
+{
+ sprite->data3 = 8;
+ sprite->data4 = sprite->invisible;
+ sprite->callback = sub_8039AF4;
+}
+
+static void sub_8039AF4(struct Sprite *sprite)
+{
+ sprite->data3--;
+ if (sprite->data3 == 0)
+ {
+ sprite->invisible ^= 1;
+ sprite->data3 = 8;
+ }
+}
+
+void sub_8039B2C(struct Sprite *sprite)
+{
+ sprite->invisible = sprite->data4;
+ sprite->data4 = FALSE;
+ sprite->callback = SpriteCallbackDummy_2;
+}
+
+void sub_8039B58(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ if (!(gHitMarker & HITMARKER_NO_ANIMATIONS) || gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ {
+ if (HasTwoFramesAnimation(sprite->tSpeciesId))
+ StartSpriteAnim(sprite, 1);
+ }
+ BattleAnimateFrontSprite(sprite, sprite->tSpeciesId, TRUE, 1);
+ }
+}
+
+void sub_8039BB4(struct Sprite *sprite)
+{
+ sprite->callback = oac_poke_ally_;
+}
+
+static void oac_poke_ally_(struct Sprite *sprite)
+{
+ if ((gUnknown_020243FC & 1) == 0)
+ {
+ sprite->pos2.x -= 2;
+ if (sprite->pos2.x == 0)
+ {
+ sprite->callback = SpriteCallbackDummy_3;
+ sprite->data1 = 0;
+ }
+ }
+}
+
+void sub_80105DC(struct Sprite *sprite)
+{
+ sprite->callback = SpriteCallbackDummy_3;
+}
+
+static void SpriteCallbackDummy_3(struct Sprite *sprite)
+{
+}
+
+void sub_8039C00(struct Sprite *sprite)
+{
+ if (!(gUnknown_020243FC & 1))
+ {
+ sprite->pos2.x += sprite->data1;
+ sprite->pos2.y += sprite->data2;
+ }
+}
+
+void dp11b_obj_instanciate(u8 bank, u8 b, s8 c, s8 d)
+{
+ u8 bounceHealthBoxSpriteId;
+ u8 spriteId2;
+
+ if (b)
+ {
+ if (gBattleSpritesDataPtr->healthBoxesData[bank].flag_x2)
+ return;
+ }
+ else
+ {
+ if (gBattleSpritesDataPtr->healthBoxesData[bank].flag_x4)
+ return;
+ }
+
+ bounceHealthBoxSpriteId = CreateInvisibleSpriteWithCallback(SpriteCB_HealthBoxBounce);
+ if (b == TRUE)
+ {
+ spriteId2 = gHealthBoxesIds[bank];
+ gBattleSpritesDataPtr->healthBoxesData[bank].field_2 = bounceHealthBoxSpriteId;
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x2 = 1;
+ gSprites[bounceHealthBoxSpriteId].data0 = 0x80;
+ }
+ else
+ {
+ spriteId2 = gBankSpriteIds[bank];
+ gBattleSpritesDataPtr->healthBoxesData[bank].field_3 = bounceHealthBoxSpriteId;
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x4 = 1;
+ gSprites[bounceHealthBoxSpriteId].data0 = 0xC0;
+ }
+ gSprites[bounceHealthBoxSpriteId].data1 = c;
+ gSprites[bounceHealthBoxSpriteId].data2 = d;
+ gSprites[bounceHealthBoxSpriteId].data3 = spriteId2;
+ gSprites[bounceHealthBoxSpriteId].data4 = b;
+ gSprites[spriteId2].pos2.x = 0;
+ gSprites[spriteId2].pos2.y = 0;
+}
+
+void dp11b_obj_free(u8 bank, bool8 b)
+{
+ u8 r4;
+
+ if (b == TRUE)
+ {
+ if (!gBattleSpritesDataPtr->healthBoxesData[bank].flag_x2)
+ return;
+
+ r4 = gSprites[gBattleSpritesDataPtr->healthBoxesData[bank].field_2].data3;
+ DestroySprite(&gSprites[gBattleSpritesDataPtr->healthBoxesData[bank].field_2]);
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x2 = 0;
+ }
+ else
+ {
+ if (!gBattleSpritesDataPtr->healthBoxesData[bank].flag_x4)
+ return;
+
+ r4 = gSprites[gBattleSpritesDataPtr->healthBoxesData[bank].field_3].data3;
+ DestroySprite(&gSprites[gBattleSpritesDataPtr->healthBoxesData[bank].field_3]);
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x4 = 0;
+ }
+ gSprites[r4].pos2.x = 0;
+ gSprites[r4].pos2.y = 0;
+}
+
+static void SpriteCB_HealthBoxBounce(struct Sprite *sprite)
+{
+ u8 spriteId = sprite->data3;
+ s32 var;
+
+ if (sprite->data4 == 1)
+ var = sprite->data0;
+ else
+ var = sprite->data0;
+
+ gSprites[spriteId].pos2.y = Sin(var, sprite->data2) + sprite->data2;
+ sprite->data0 = (sprite->data0 + sprite->data1) & 0xFF;
+}
+
+void sub_8039E44(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ BattleAnimateBackSprite(sprite, sprite->tSpeciesId);
+}
+
+void sub_8039E60(struct Sprite *sprite)
+{
+ sub_8039E9C(sprite);
+ if (sprite->animEnded)
+ sprite->callback = SpriteCallbackDummy_3;
+}
+
+void sub_8039E84(struct Sprite *sprite)
+{
+ StartSpriteAnim(sprite, 1);
+ sprite->callback = sub_8039E60;
+}
+
+void sub_8039E9C(struct Sprite *sprite)
+{
+ if (sprite->animDelayCounter == 0)
+ sprite->centerToCornerVecX = gUnknown_0831ACE0[sprite->animCmdIndex];
+}
+
+void nullsub_20(void)
+{
+
+}
+
+void BeginBattleIntro(void)
+{
+ BattleStartClearSetData();
+ gBattleCommunication[1] = 0;
+ gBattleMainFunc = BattleIntroGetMonsData;
+}
+
+static void BattleMainCB1(void)
+{
+ gBattleMainFunc();
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ gBattleBankFunc[gActiveBank]();
+}
+
+static void BattleStartClearSetData(void)
+{
+ s32 i;
+ u32 j;
+ u8 *dataPtr;
+
+ TurnValuesCleanUp(FALSE);
+ SpecialStatusesClear();
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ gStatuses3[i] = 0;
+
+ dataPtr = (u8 *)&gDisableStructs[i];
+ for (j = 0; j < sizeof(struct DisableStruct); j++)
+ dataPtr[j] = 0;
+
+ gDisableStructs[i].isFirstTurn= 2;
+ gUnknown_02024284[i] = 0;
+ gLastUsedMovesByBanks[i] = 0;
+ gUnknown_02024250[i] = 0;
+ gUnknown_02024258[i] = 0;
+ gUnknown_02024260[i] = 0;
+ gUnknown_02024270[i] = 0xFF;
+ gLockedMoves[i] = 0;
+ gUnknownMovesUsedByBanks[i] = 0;
+ gBattleResources->flags->flags[i] = 0;
+ gUnknown_02024230[i] = 0;
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ gSideAffecting[i] = 0;
+
+ dataPtr = (u8 *)&gSideTimers[i];
+ for (j = 0; j < sizeof(struct SideTimer); j++)
+ dataPtr[j] = 0;
+ }
+
+ gBankAttacker = 0;
+ gBankTarget = 0;
+ gBattleWeather = 0;
+
+ dataPtr = (u8 *)&gWishFutureKnock;
+ for (i = 0; i < sizeof(struct WishFutureKnock); i++)
+ dataPtr[i] = 0;
+
+ gHitMarker = 0;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) && gSaveBlock2Ptr->optionsBattleSceneOff == TRUE)
+ gHitMarker |= HITMARKER_NO_ANIMATIONS;
+ }
+ else if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) && sub_8185FB8())
+ gHitMarker |= HITMARKER_NO_ANIMATIONS;
+
+ gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle;
+
+ gMultiHitCounter = 0;
+ gBattleOutcome = 0;
+ gBattleExecBuffer = 0;
+ gPaydayMoney = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+ gBattleResources->battleCallbackStack->size = 0;
+
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++)
+ gBattleCommunication[i] = 0;
+
+ gPauseCounterBattle = 0;
+ gBattleMoveDamage = 0;
+ gUnknown_020243FC = 0;
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gLeveledUpInBattle = 0;
+ gAbsentBankFlags = 0;
+ gBattleStruct->runTries = 0;
+ gBattleStruct->field_79 = 0;
+ gBattleStruct->field_7A = 0;
+ *(&gBattleStruct->field_7C) = gBaseStats[GetMonData(&gEnemyParty[0], MON_DATA_SPECIES)].catchRate * 100 / 1275;
+ gBattleStruct->field_7B = 3;
+ gBattleStruct->wildVictorySong = 0;
+ gBattleStruct->moneyMultiplier = 1;
+
+ for (i = 0; i < 8; i++)
+ {
+ *((u8 *)gBattleStruct->mirrorMoves + i) = 0;
+ *((u8 *)gBattleStruct->usedHeldItems + i) = 0;
+ *((u8 *)gBattleStruct->choicedMove + i) = 0;
+ *((u8 *)gBattleStruct->changedItems + i) = 0;
+ *(i + 0 * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(i + 1 * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(i + 2 * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(i + 3 * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ *(gBattleStruct->field_294 + i) = 6;
+ }
+
+ gBattleStruct->field_DF = 0;
+ gBattleStruct->field_92 = 0;
+
+ gRandomTurnNumber = Random();
+
+ dataPtr = (u8 *)(&gBattleResults);
+ for (i = 0; i < sizeof(struct BattleResults); i++)
+ dataPtr[i] = 0;
+
+ gBattleResults.unk5_6 = IsMonShiny(&gEnemyParty[0]);
+
+ gBattleStruct->field_2A0 = 0;
+ gBattleStruct->field_2A1 = 0;
+}
+
+void SwitchInClearSetData(void)
+{
+ struct DisableStruct disableStructCopy = gDisableStructs[gActiveBank];
+ s32 i;
+ u8 *ptr;
+
+ if (gBattleMoves[gCurrentMove].effect != EFFECT_BATON_PASS)
+ {
+ for (i = 0; i < BATTLE_STATS_NO; i++)
+ gBattleMons[gActiveBank].statStages[i] = 6;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].bankPreventingEscape == gActiveBank)
+ gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION;
+ if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].bankWithSureHit == gActiveBank)
+ {
+ gStatuses3[i] &= ~STATUS3_ALWAYS_HITS;
+ gDisableStructs[i].bankWithSureHit = 0;
+ }
+ }
+ }
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
+ {
+ gBattleMons[gActiveBank].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED);
+ gStatuses3[gActiveBank] &= (STATUS3_LEECHSEED_BANK | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_MUDSPORT | STATUS3_WATERSPORT);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (GetBankSide(gActiveBank) != GetBankSide(i)
+ && (gStatuses3[i] & STATUS3_ALWAYS_HITS) != 0
+ && (gDisableStructs[i].bankWithSureHit == gActiveBank))
+ {
+ gStatuses3[i] &= ~STATUS3_ALWAYS_HITS;
+ gStatuses3[i] |= 0x10;
+ }
+ }
+ }
+ else
+ {
+ gBattleMons[gActiveBank].status2 = 0;
+ gStatuses3[gActiveBank] = 0;
+ }
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(gActiveBank))
+ gBattleMons[i].status2 &= ~(STATUS2_INFATUATED_WITH(gActiveBank));
+ if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == gActiveBank)
+ gBattleMons[i].status2 &= ~(STATUS2_WRAPPED);
+ }
+
+ gActionSelectionCursor[gActiveBank] = 0;
+ gMoveSelectionCursor[gActiveBank] = 0;
+
+ ptr = (u8 *)&gDisableStructs[gActiveBank];
+ for (i = 0; i < sizeof(struct DisableStruct); i++)
+ ptr[i] = 0;
+
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
+ {
+ gDisableStructs[gActiveBank].substituteHP = disableStructCopy.substituteHP;
+ gDisableStructs[gActiveBank].bankWithSureHit = disableStructCopy.bankWithSureHit;
+ gDisableStructs[gActiveBank].perishSong1 = disableStructCopy.perishSong1;
+ gDisableStructs[gActiveBank].perishSong2 = disableStructCopy.perishSong2;
+ gDisableStructs[gActiveBank].bankPreventingEscape = disableStructCopy.bankPreventingEscape;
+ }
+
+ gBattleMoveFlags = 0;
+ gDisableStructs[gActiveBank].isFirstTurn= 2;
+ gDisableStructs[gActiveBank].truantUnknownBit = disableStructCopy.truantUnknownBit;
+ gLastUsedMovesByBanks[gActiveBank] = 0;
+ gUnknown_02024250[gActiveBank] = 0;
+ gUnknown_02024258[gActiveBank] = 0;
+ gUnknown_02024260[gActiveBank] = 0;
+ gUnknownMovesUsedByBanks[gActiveBank] = 0;
+ gUnknown_02024270[gActiveBank] = 0xFF;
+
+ *(gBattleStruct->mirrorMoves + gActiveBank * 2 + 0) = 0;
+ *(gBattleStruct->mirrorMoves + gActiveBank * 2 + 1) = 0;
+ *(0 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(0 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(1 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(1 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(2 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(2 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(3 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(3 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+
+ gBattleStruct->field_92 &= ~(gBitTable[gActiveBank]);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (i != gActiveBank && GetBankSide(i) != GetBankSide(gActiveBank))
+ {
+ *(gBattleStruct->mirrorMoves + i * 2 + 0) = 0;
+ *(gBattleStruct->mirrorMoves + i * 2 + 1) = 0;
+ }
+ *(i * 8 + gActiveBank * 2 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(i * 8 + gActiveBank * 2 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ }
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gActiveBank]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gActiveBank]) + 1) = 0;
+
+ gBattleResources->flags->flags[gActiveBank] = 0;
+ gCurrentMove = 0;
+ gBattleStruct->field_DA = 0xFF;
+
+ ClearBankMoveHistory(gActiveBank);
+ ClearBankAbilityHistory(gActiveBank);
+}
+
+void FaintClearSetData(void)
+{
+ s32 i;
+ u8 *ptr;
+
+ for (i = 0; i < BATTLE_STATS_NO; i++)
+ gBattleMons[gActiveBank].statStages[i] = 6;
+
+ gBattleMons[gActiveBank].status2 = 0;
+ gStatuses3[gActiveBank] = 0;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].bankPreventingEscape == gActiveBank)
+ gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION;
+ if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(gActiveBank))
+ gBattleMons[i].status2 &= ~(STATUS2_INFATUATED_WITH(gActiveBank));
+ if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == gActiveBank)
+ gBattleMons[i].status2 &= ~(STATUS2_WRAPPED);
+ }
+
+ gActionSelectionCursor[gActiveBank] = 0;
+ gMoveSelectionCursor[gActiveBank] = 0;
+
+ ptr = (u8 *)&gDisableStructs[gActiveBank];
+ for (i = 0; i < sizeof(struct DisableStruct); i++)
+ ptr[i] = 0;
+
+ gProtectStructs[gActiveBank].protected = 0;
+ gProtectStructs[gActiveBank].endured = 0;
+ gProtectStructs[gActiveBank].onlyStruggle = 0;
+ gProtectStructs[gActiveBank].helpingHand = 0;
+ gProtectStructs[gActiveBank].bounceMove = 0;
+ gProtectStructs[gActiveBank].stealMove = 0;
+ gProtectStructs[gActiveBank].flag0Unknown = 0;
+ gProtectStructs[gActiveBank].prlzImmobility = 0;
+ gProtectStructs[gActiveBank].confusionSelfDmg = 0;
+ gProtectStructs[gActiveBank].targetNotAffected = 0;
+ gProtectStructs[gActiveBank].chargingTurn = 0;
+ gProtectStructs[gActiveBank].fleeFlag = 0;
+ gProtectStructs[gActiveBank].usedImprisionedMove = 0;
+ gProtectStructs[gActiveBank].loveImmobility = 0;
+ gProtectStructs[gActiveBank].usedDisabledMove = 0;
+ gProtectStructs[gActiveBank].usedTauntedMove = 0;
+ gProtectStructs[gActiveBank].flag2Unknown = 0;
+ gProtectStructs[gActiveBank].flinchImmobility = 0;
+ gProtectStructs[gActiveBank].notFirstStrike = 0;
+
+ gDisableStructs[gActiveBank].isFirstTurn = 2;
+
+ gLastUsedMovesByBanks[gActiveBank] = 0;
+ gUnknown_02024250[gActiveBank] = 0;
+ gUnknown_02024258[gActiveBank] = 0;
+ gUnknown_02024260[gActiveBank] = 0;
+ gUnknownMovesUsedByBanks[gActiveBank] = 0;
+ gUnknown_02024270[gActiveBank] = 0xFF;
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gActiveBank]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gActiveBank]) + 1) = 0;
+
+ *(gBattleStruct->mirrorMoves + gActiveBank * 2 + 0) = 0;
+ *(gBattleStruct->mirrorMoves + gActiveBank * 2 + 1) = 0;
+ *(0 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(0 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(1 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(1 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(2 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(2 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ *(3 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(3 * 2 + gActiveBank * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+
+ gBattleStruct->field_92 &= ~(gBitTable[gActiveBank]);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (i != gActiveBank && GetBankSide(i) != GetBankSide(gActiveBank))
+ {
+ *(gBattleStruct->mirrorMoves + i * 2 + 0) = 0;
+ *(gBattleStruct->mirrorMoves + i * 2 + 1) = 0;
+ }
+ *(i * 8 + gActiveBank * 2 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = 0;
+ *(i * 8 + gActiveBank * 2 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = 0;
+ }
+
+ gBattleResources->flags->flags[gActiveBank] = 0;
+
+ gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1;
+ gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2;
+
+ ClearBankMoveHistory(gActiveBank);
+ ClearBankAbilityHistory(gActiveBank);
+}
+
+static void BattleIntroGetMonsData(void)
+{
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ gActiveBank = gBattleCommunication[1];
+ EmitGetMonData(0, 0, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ break;
+ case 1:
+ if (gBattleExecBuffer == 0)
+ {
+ gBattleCommunication[1]++;
+ if (gBattleCommunication[1] == gNoOfAllBanks)
+ gBattleMainFunc = BattleIntroPrepareBackgroundSlide;
+ else
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ }
+ break;
+ }
+}
+
+static void BattleIntroPrepareBackgroundSlide(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBankByIdentity(0);
+ EmitIntroSlide(0, gBattleTerrain);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleMainFunc = BattleIntroDrawTrainersOrMonsSprites;
+ gBattleCommunication[0] = 0;
+ gBattleCommunication[1] = 0;
+ }
+}
+
+static void BattleIntroDrawTrainersOrMonsSprites(void)
+{
+ u8 *ptr;
+ s32 i;
+
+ if (gBattleExecBuffer)
+ return;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ && GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ ptr = (u8 *)&gBattleMons[gActiveBank];
+ for (i = 0; i < sizeof(struct BattlePokemon); i++)
+ ptr[i] = 0;
+ }
+ else
+ {
+ u16* hpOnSwitchout;
+
+ ptr = (u8 *)&gBattleMons[gActiveBank];
+ for (i = 0; i < sizeof(struct BattlePokemon); i++)
+ ptr[i] = gBattleBufferB[gActiveBank][4 + i];
+
+ gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1;
+ gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2;
+ gBattleMons[gActiveBank].ability = GetAbilityBySpecies(gBattleMons[gActiveBank].species, gBattleMons[gActiveBank].altAbility);
+ hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBankSide(gActiveBank)];
+ *hpOnSwitchout = gBattleMons[gActiveBank].hp;
+ for (i = 0; i < BATTLE_STATS_NO; i++)
+ gBattleMons[gActiveBank].statStages[i] = 6;
+ gBattleMons[gActiveBank].status2 = 0;
+ }
+
+ if (GetBankIdentity(gActiveBank) == IDENTITY_PLAYER_MON1)
+ {
+ EmitDrawTrainerPic(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ if (GetBankIdentity(gActiveBank) == IDENTITY_OPPONENT_MON1)
+ {
+ EmitDrawTrainerPic(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_x4000000)))
+ {
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), FLAG_SET_SEEN, gBattleMons[gActiveBank].personality);
+ }
+ }
+ else
+ {
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
+ {
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_x4000000)))
+ {
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), FLAG_SET_SEEN, gBattleMons[gActiveBank].personality);
+ }
+ EmitLoadMonSprite(0);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES, NULL);
+ }
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (GetBankIdentity(gActiveBank) == IDENTITY_PLAYER_MON2
+ || GetBankIdentity(gActiveBank) == IDENTITY_OPPONENT_MON2)
+ {
+ EmitDrawTrainerPic(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBankIdentity(gActiveBank) == IDENTITY_OPPONENT_MON2)
+ {
+ EmitDrawTrainerPic(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ sub_81A56B4();
+ }
+ gBattleMainFunc = BattleIntroDrawPartySummaryScreens;
+}
+
+static void BattleIntroDrawPartySummaryScreens(void)
+{
+ s32 i;
+ struct HpAndStatus hpStatus[6];
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
+ || GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
+ {
+ hpStatus[i].hp = 0xFFFF;
+ hpStatus[i].status = 0;
+ }
+ else
+ {
+ hpStatus[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP);
+ hpStatus[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS);
+ }
+ }
+ gActiveBank = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
+ MarkBufferBankForExecution(gActiveBank);
+
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
+ || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
+ {
+ hpStatus[i].hp = 0xFFFF;
+ hpStatus[i].status = 0;
+ }
+ else
+ {
+ hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+ }
+ }
+ gActiveBank = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattleMainFunc = BattleIntroPrintTrainerWantsToBattle;
+ }
+ else
+ {
+ // The struct gets set here, but nothing is ever done with it since
+ // wild battles don't show the party summary.
+ // Still, there's no point in having dead code.
+
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
+ || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
+ {
+ hpStatus[i].hp = 0xFFFF;
+ hpStatus[i].status = 0;
+ }
+ else
+ {
+ hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+ }
+ }
+
+ gBattleMainFunc = BattleIntroPrintWildMonAttacked;
+ }
+
+}
+
+static void BattleIntroPrintTrainerWantsToBattle(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ PrepareStringBattle(0, gActiveBank);
+ gBattleMainFunc = BattleIntroPrintOpponentSendsOut;
+ }
+}
+
+static void BattleIntroPrintWildMonAttacked(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+ PrepareStringBattle(0, 0);
+ }
+}
+
+static void BattleIntroPrintOpponentSendsOut(void)
+{
+ u32 identity;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_OPPONENT_MON1;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_OPPONENT_MON1;
+ else
+ identity = IDENTITY_PLAYER_MON1;
+ }
+ else
+ identity = IDENTITY_OPPONENT_MON1;
+
+ PrepareStringBattle(1, GetBankByIdentity(identity));
+ gBattleMainFunc = BattleIntroOpponent1SendsOutMonAnimation;
+}
+
+static void BattleIntroOpponent2SendsOutMonAnimation(void)
+{
+ u32 identity;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_OPPONENT_MON2;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_OPPONENT_MON2;
+ else
+ identity = IDENTITY_PLAYER_MON2;
+ }
+ else
+ identity = IDENTITY_OPPONENT_MON2;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankIdentity(gActiveBank) == identity)
+ {
+ EmitIntroTrainerBallThrow(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+
+ gBattleMainFunc = BattleIntroRecordMonsToDex;
+}
+
+#ifdef NONMATCHING
+static void BattleIntroOpponent1SendsOutMonAnimation(void)
+{
+ u32 identity;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_OPPONENT_MON1;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_OPPONENT_MON1;
+ else
+ identity = IDENTITY_PLAYER_MON1;
+ }
+ else
+ identity = IDENTITY_OPPONENT_MON1;
+
+ if (gBattleExecBuffer)
+ return;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankIdentity(gActiveBank) == identity)
+ {
+ EmitIntroTrainerBallThrow(0);
+ MarkBufferBankForExecution(gActiveBank);
+ if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS))
+ {
+ gBattleMainFunc = BattleIntroOpponent2SendsOutMonAnimation;
+ return;
+ }
+ }
+ }
+
+ gBattleMainFunc = BattleIntroRecordMonsToDex;
+}
+
+#else
+__attribute__((naked))
+static void BattleIntroOpponent1SendsOutMonAnimation(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r6,lr}\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r2, [r0]\n\
+ movs r0, 0x80\n\
+ lsls r0, 17\n\
+ ands r0, r2\n\
+ cmp r0, 0\n\
+ beq _0803B298\n\
+ movs r0, 0x80\n\
+ lsls r0, 18\n\
+ ands r0, r2\n\
+ cmp r0, 0\n\
+ beq _0803B298\n\
+ movs r1, 0x80\n\
+ lsls r1, 24\n\
+ ands r1, r2\n\
+ negs r0, r1\n\
+ orrs r0, r1\n\
+ lsrs r5, r0, 31\n\
+ b _0803B29A\n\
+ .pool\n\
+_0803B288:\n\
+ ldr r1, =gBattleMainFunc\n\
+ ldr r0, =BattleIntroOpponent2SendsOutMonAnimation\n\
+ b _0803B2F0\n\
+ .pool\n\
+_0803B298:\n\
+ movs r5, 0x1\n\
+_0803B29A:\n\
+ ldr r0, =gBattleExecBuffer\n\
+ ldr r2, [r0]\n\
+ cmp r2, 0\n\
+ bne _0803B2F2\n\
+ ldr r0, =gActiveBank\n\
+ strb r2, [r0]\n\
+ ldr r1, =gNoOfAllBanks\n\
+ adds r4, r0, 0\n\
+ ldrb r1, [r1]\n\
+ cmp r2, r1\n\
+ bcs _0803B2EC\n\
+ adds r6, r4, 0\n\
+_0803B2B2:\n\
+ ldrb r0, [r4]\n\
+ bl GetBankIdentity\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, r5\n\
+ bne _0803B2D8\n\
+ movs r0, 0\n\
+ bl EmitIntroTrainerBallThrow\n\
+ ldrb r0, [r4]\n\
+ bl MarkBufferBankForExecution\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ ldr r1, =0x00008040\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _0803B288\n\
+_0803B2D8:\n\
+ ldrb r0, [r6]\n\
+ adds r0, 0x1\n\
+ strb r0, [r6]\n\
+ ldr r1, =gNoOfAllBanks\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ ldr r4, =gActiveBank\n\
+ ldrb r1, [r1]\n\
+ cmp r0, r1\n\
+ bcc _0803B2B2\n\
+_0803B2EC:\n\
+ ldr r1, =gBattleMainFunc\n\
+ ldr r0, =BattleIntroRecordMonsToDex\n\
+_0803B2F0:\n\
+ str r0, [r1]\n\
+_0803B2F2:\n\
+ pop {r4-r6}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool\n\
+ .syntax divided");
+}
+
+#endif // NONMATCHING
+
+static void BattleIntroRecordMonsToDex(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_x4000000)))
+ {
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), FLAG_SET_SEEN, gBattleMons[gActiveBank].personality);
+ }
+ }
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+ }
+}
+
+void sub_803B3AC(void) // unused
+{
+ if (gBattleExecBuffer == 0)
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+}
+
+static void BattleIntroPrintPlayerSendsOut(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ u8 identity;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_PLAYER_MON1;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_PLAYER_MON1;
+ else
+ identity = IDENTITY_OPPONENT_MON1;
+ }
+ else
+ identity = IDENTITY_PLAYER_MON1;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
+ PrepareStringBattle(1, GetBankByIdentity(identity));
+
+ gBattleMainFunc = BattleIntroPlayer1SendsOutMonAnimation;
+ }
+}
+
+static void BattleIntroPlayer2SendsOutMonAnimation(void)
+{
+ u32 identity;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_PLAYER_MON2;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_PLAYER_MON2;
+ else
+ identity = IDENTITY_OPPONENT_MON2;
+ }
+ else
+ identity = IDENTITY_PLAYER_MON2;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankIdentity(gActiveBank) == identity)
+ {
+ EmitIntroTrainerBallThrow(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+
+ gBattleStruct->switchInAbilitiesCounter = 0;
+ gBattleStruct->switchInItemsCounter = 0;
+ gBattleStruct->overworldWeatherDone = FALSE;
+
+ gBattleMainFunc = TryDoEventsBeforeFirstTurn;
+}
+
+static void BattleIntroPlayer1SendsOutMonAnimation(void)
+{
+ u32 identity;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ identity = IDENTITY_PLAYER_MON1;
+ else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ identity = IDENTITY_PLAYER_MON1;
+ else
+ identity = IDENTITY_OPPONENT_MON1;
+ }
+ else
+ identity = IDENTITY_PLAYER_MON1;
+
+ if (gBattleExecBuffer)
+ return;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankIdentity(gActiveBank) == identity)
+ {
+ EmitIntroTrainerBallThrow(0);
+ MarkBufferBankForExecution(gActiveBank);
+ if (gBattleTypeFlags & (BATTLE_TYPE_MULTI))
+ {
+ gBattleMainFunc = BattleIntroPlayer2SendsOutMonAnimation;
+ return;
+ }
+ }
+ }
+
+ gBattleStruct->switchInAbilitiesCounter = 0;
+ gBattleStruct->switchInItemsCounter = 0;
+ gBattleStruct->overworldWeatherDone = FALSE;
+
+ gBattleMainFunc = TryDoEventsBeforeFirstTurn;
+}
+
+void sub_803B598(void) // unused
+{
+ if (gBattleExecBuffer == 0)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ EmitSwitchInAnim(0, gBattlePartyID[gActiveBank], FALSE);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+
+ gBattleStruct->switchInAbilitiesCounter = 0;
+ gBattleStruct->switchInItemsCounter = 0;
+ gBattleStruct->overworldWeatherDone = FALSE;
+
+ gBattleMainFunc = TryDoEventsBeforeFirstTurn;
+ }
+}
+
+static void TryDoEventsBeforeFirstTurn(void)
+{
+ s32 i;
+ s32 j;
+ u8 effect = 0;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattleStruct->switchInAbilitiesCounter == 0)
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ gBanksByTurnOrder[i] = i;
+ for (i = 0; i < gNoOfAllBanks - 1; i++)
+ {
+ for (j = i + 1; j < gNoOfAllBanks; j++)
+ {
+ if (GetWhoStrikesFirst(gBanksByTurnOrder[i], gBanksByTurnOrder[j], TRUE) != 0)
+ SwapTurnOrder(i, j);
+ }
+ }
+ }
+ if (!gBattleStruct->overworldWeatherDone
+ && AbilityBattleEffects(0, 0, 0, ABILITYEFFECT_SWITCH_IN_WEATHER, 0) != 0)
+ {
+ gBattleStruct->overworldWeatherDone = TRUE;
+ return;
+ }
+ // check all switch in abilities happening from the fastest mon to slowest
+ while (gBattleStruct->switchInAbilitiesCounter < gNoOfAllBanks)
+ {
+ if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBanksByTurnOrder[gBattleStruct->switchInAbilitiesCounter], 0, 0, 0) != 0)
+ effect++;
+
+ gBattleStruct->switchInAbilitiesCounter++;
+
+ if (effect)
+ return;
+ }
+ if (AbilityBattleEffects(ABILITYEFFECT_INTIMIDATE1, 0, 0, 0, 0) != 0)
+ return;
+ if (AbilityBattleEffects(ABILITYEFFECT_TRACE, 0, 0, 0, 0) != 0)
+ return;
+ // check all switch in items having effect from the fastest mon to slowest
+ while (gBattleStruct->switchInItemsCounter < gNoOfAllBanks)
+ {
+ if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, gBanksByTurnOrder[gBattleStruct->switchInItemsCounter], 0) != 0)
+ effect++;
+
+ gBattleStruct->switchInItemsCounter++;
+
+ if (effect)
+ return;
+ }
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ *(gBattleStruct->field_5C + i) = 6;
+ gActionForBanks[i] = ACTION_INIT_VALUE;
+ gChosenMovesByBanks[i] = MOVE_NONE;
+ }
+ TurnValuesCleanUp(FALSE);
+ SpecialStatusesClear();
+ *(&gBattleStruct->field_91) = gAbsentBankFlags;
+ sub_814F9EC(gText_EmptyString3, 0);
+ gBattleMainFunc = HandleTurnActionSelectionState;
+ ResetSentPokesToOpponentValue();
+
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++)
+ gBattleCommunication[i] = 0;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ gBattleMons[i].status2 &= ~(STATUS2_FLINCHED);
+
+ *(&gBattleStruct->turnEffectsTracker) = 0;
+ *(&gBattleStruct->turnEffectsBank) = 0;
+ *(&gBattleStruct->field_1A0) = 0;
+ *(&gBattleStruct->field_1A1) = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleStruct->field_4D = 0;
+ gBattleStruct->turncountersTracker = 0;
+ gBattleMoveFlags = 0;
+
+ gRandomTurnNumber = Random();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ {
+ StopCryAndClearCrySongs();
+ BattleScriptExecute(gUnknown_082DB8BE);
+ }
+}
+
+static void HandleEndTurn_ContinueBattle(void)
+{
+ s32 i;
+
+ if (gBattleExecBuffer == 0)
+ {
+ gBattleMainFunc = BattleTurnPassed;
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++)
+ gBattleCommunication[i] = 0;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ gBattleMons[i].status2 &= ~(STATUS2_FLINCHED);
+ if ((gBattleMons[i].status1 & STATUS_SLEEP) && (gBattleMons[i].status2 & STATUS2_MULTIPLETURNS))
+ CancelMultiTurnMoves(i);
+ }
+ gBattleStruct->turnEffectsTracker = 0;
+ gBattleStruct->turnEffectsBank = 0;
+ gBattleStruct->field_1A0 = 0;
+ gBattleStruct->field_1A1 = 0;
+ gBattleStruct->turncountersTracker = 0;
+ gBattleMoveFlags = 0;
+ }
+}
+
+void BattleTurnPassed(void)
+{
+ s32 i;
+
+ TurnValuesCleanUp(TRUE);
+ if (gBattleOutcome == 0)
+ {
+ if (UpdateTurnCounters() != 0)
+ return;
+ if (TurnBasedEffects() != 0)
+ return;
+ }
+ if (sub_8041728() != 0)
+ return;
+ gBattleStruct->field_4D = 0;
+ if (sub_8041364() != 0)
+ return;
+
+ TurnValuesCleanUp(FALSE);
+ gHitMarker &= ~(HITMARKER_NO_ATTACKSTRING);
+ gHitMarker &= ~(HITMARKER_UNABLE_TO_USE_MOVE);
+ gHitMarker &= ~(HITMARKER_x400000);
+ gHitMarker &= ~(HITMARKER_x100000);
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleMoveDamage = 0;
+ gBattleMoveFlags = 0;
+
+ for (i = 0; i < 5; i++)
+ gBattleCommunication[i] = 0;
+
+ if (gBattleOutcome != 0)
+ {
+ gCurrentActionFuncId = 12;
+ gBattleMainFunc = RunTurnActionsFunctions;
+ return;
+ }
+
+ if (gBattleResults.battleTurnCounter < 0xFF)
+ {
+ gBattleResults.battleTurnCounter++;
+ gBattleStruct->field_DA++;
+ }
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ gActionForBanks[i] = ACTION_INIT_VALUE;
+ gChosenMovesByBanks[i] = MOVE_NONE;
+ }
+
+ for (i = 0; i < 4; i++)
+ *(gBattleStruct->field_5C + i) = 6;
+
+ *(&gBattleStruct->field_91) = gAbsentBankFlags;
+ sub_814F9EC(gText_EmptyString3, 0);
+ gBattleMainFunc = HandleTurnActionSelectionState;
+ gRandomTurnNumber = Random();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ BattleScriptExecute(gUnknown_082DB881);
+ else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->field_DA == 0)
+ BattleScriptExecute(gUnknown_082DB8BE);
+}
+
+u8 IsRunningFromBattleImpossible(void)
+{
+ u8 holdEffect;
+ u8 side;
+ s32 i;
+
+ if (gBattleMons[gActiveBank].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[gActiveBank].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBank].item);
+
+ gStringBank = gActiveBank;
+
+ if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
+ return 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ return 0;
+ if (gBattleMons[gActiveBank].ability == ABILITY_RUN_AWAY)
+ return 0;
+
+ side = GetBankSide(gActiveBank);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (side != GetBankSide(i)
+ && gBattleMons[i].ability == ABILITY_SHADOW_TAG)
+ {
+ gBattleScripting.bank = i;
+ gLastUsedAbility = gBattleMons[i].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return 2;
+ }
+ if (side != GetBankSide(i)
+ && gBattleMons[gActiveBank].ability != ABILITY_LEVITATE
+ && gBattleMons[gActiveBank].type1 != TYPE_FLYING
+ && gBattleMons[gActiveBank].type2 != TYPE_FLYING
+ && gBattleMons[i].ability == ABILITY_ARENA_TRAP)
+ {
+ gBattleScripting.bank = i;
+ gLastUsedAbility = gBattleMons[i].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return 2;
+ }
+ }
+ i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK, gActiveBank, ABILITY_MAGNET_PULL, 0, 0);
+ if (i != 0 && (gBattleMons[gActiveBank].type1 == TYPE_STEEL || gBattleMons[gActiveBank].type2 == TYPE_STEEL))
+ {
+ gBattleScripting.bank = i - 1;
+ gLastUsedAbility = gBattleMons[i - 1].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return 2;
+ }
+ if ((gBattleMons[gActiveBank].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED))
+ || (gStatuses3[gActiveBank] & STATUS3_ROOTED))
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ return 1;
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ return 1;
+ }
+ return 0;
+}
+
+void sub_803BDA0(u8 bank)
+{
+ s32 i;
+ u8 r4;
+ u8 r1;
+
+ // gBattleStruct->field_60[bank][i]
+
+ for (i = 0; i < 3; i++)
+ gUnknown_0203CF00[i] = *(bank * 3 + i + (u8*)(gBattleStruct->field_60));
+
+ r4 = pokemon_order_func(gBattlePartyID[bank]);
+ r1 = pokemon_order_func(*(gBattleStruct->field_5C + bank));
+ sub_81B8FB0(r4, r1);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ *(bank * 3 + i + (u8*)(gBattleStruct->field_60)) = gUnknown_0203CF00[i];
+ *((bank ^ BIT_MON) * 3 + i + (u8*)(gBattleStruct->field_60)) = gUnknown_0203CF00[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < 3; i++)
+ {
+ *(bank * 3 + i + (u8*)(gBattleStruct->field_60)) = gUnknown_0203CF00[i];
+ }
+ }
+}
+
+enum
+{
+ STATE_TURN_START_RECORD,
+ STATE_BEFORE_ACTION_CHOSEN,
+ STATE_WAIT_ACTION_CHOSEN,
+ STATE_WAIT_ACTION_CASE_CHOSEN,
+ STATE_WAIT_ACTION_CONFIRMED_STANDBY,
+ STATE_WAIT_ACTION_CONFIRMED,
+ STATE_SELECTION_SCRIPT,
+ STATE_WAIT_SET_BEFORE_ACTION,
+ STATE_SELECTION_SCRIPT_MAY_RUN
+};
+
+static void HandleTurnActionSelectionState(void)
+{
+ s32 i;
+
+ gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ u8 identity = GetBankIdentity(gActiveBank);
+ switch (gBattleCommunication[gActiveBank])
+ {
+ case STATE_TURN_START_RECORD: // recorded battle related on start of every turn
+ sub_8185FD0();
+ gBattleCommunication[gActiveBank] = STATE_BEFORE_ACTION_CHOSEN;
+ break;
+ case STATE_BEFORE_ACTION_CHOSEN: // choose an action
+ *(gBattleStruct->field_5C + gActiveBank) = 6;
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI
+ || !(identity & BIT_MON)
+ || gBattleStruct->field_91 & gBitTable[GetBankByIdentity(identity ^ BIT_MON)]
+ || gBattleCommunication[GetBankByIdentity(identity ^ BIT_MON)] == 5)
+ {
+ if (gBattleStruct->field_91 & gBitTable[gActiveBank])
+ {
+ gActionForBanks[gActiveBank] = ACTION_NOTHING_FAINTED;
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED;
+ else
+ gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ }
+ else
+ {
+ if (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS
+ || gBattleMons[gActiveBank].status2 & STATUS2_RECHARGE)
+ {
+ gActionForBanks[gActiveBank] = ACTION_USE_MOVE;
+ gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ }
+ else
+ {
+ EmitChooseAction(0, gActionForBanks[0], gBattleBufferB[0][1] | (gBattleBufferB[0][2] << 8));
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleCommunication[gActiveBank]++;
+ }
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CHOSEN: // try to perform an action
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][1]);
+ gActionForBanks[gActiveBank] = gBattleBufferB[gActiveBank][1];
+
+ switch (gBattleBufferB[gActiveBank][1])
+ {
+ case ACTION_USE_MOVE:
+ if (AreAllMovesUnusable())
+ {
+ gBattleCommunication[gActiveBank] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ *(gBattleStruct->moveTarget + gActiveBank) = gBattleBufferB[gActiveBank][3];
+ return;
+ }
+ else if (gDisableStructs[gActiveBank].encoredMove != 0)
+ {
+ gChosenMovesByBanks[gActiveBank] = gDisableStructs[gActiveBank].encoredMove;
+ *(gBattleStruct->chosenMovePositions + gActiveBank) = gDisableStructs[gActiveBank].encoredMovePos;
+ gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ return;
+ }
+ else
+ {
+ struct ChooseMoveStruct moveInfo;
+
+ moveInfo.species = gBattleMons[gActiveBank].species;
+ moveInfo.monType1 = gBattleMons[gActiveBank].type1;
+ moveInfo.monType2 = gBattleMons[gActiveBank].type2;
+
+ for (i = 0; i < 4; i++)
+ {
+ moveInfo.moves[i] = gBattleMons[gActiveBank].moves[i];
+ moveInfo.ppNumbers[i] = gBattleMons[gActiveBank].pp[i];
+ moveInfo.ppWithBonusNumbers[i] = CalculatePPWithBonus(
+ gBattleMons[gActiveBank].moves[i],
+ gBattleMons[gActiveBank].ppBonuses,
+ i);
+ }
+
+ EmitChooseMove(0, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0, FALSE, &moveInfo);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ break;
+ case ACTION_USE_ITEM:
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_FRONTIER_NO_PYRAMID
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_x2000000))
+ {
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ gBattlescriptPtrsForSelection[gActiveBank] = BattleScript_ActionSelectionItemsCantBeUsed;
+ gBattleCommunication[gActiveBank] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ EmitOpenBag(0, gBattleStruct->field_60[gActiveBank]);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ break;
+ case ACTION_SWITCH:
+ *(gBattleStruct->field_58 + gActiveBank) = gBattlePartyID[gActiveBank];
+ if (gBattleMons[gActiveBank].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)
+ || gBattleTypeFlags & BATTLE_TYPE_ARENA
+ || gStatuses3[gActiveBank] & STATUS3_ROOTED)
+ {
+ EmitChoosePokemon(0, 2, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBank]);
+ }
+ else if ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBank, ABILITY_SHADOW_TAG, 0, 0))
+ || ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBank, ABILITY_ARENA_TRAP, 0, 0))
+ && gBattleMons[gActiveBank].type1 != TYPE_FLYING
+ && gBattleMons[gActiveBank].type2 != TYPE_FLYING
+ && gBattleMons[gActiveBank].ability != ABILITY_LEVITATE)
+ || ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK, gActiveBank, ABILITY_MAGNET_PULL, 0, 0))
+ && (gBattleMons[gActiveBank].type1 == TYPE_STEEL
+ || gBattleMons[gActiveBank].type2 == TYPE_STEEL)))
+ {
+ EmitChoosePokemon(0, ((i - 1) << 4) | 4, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBank]);
+ }
+ else
+ {
+ if (gActiveBank == 2 && gActionForBanks[0] == ACTION_SWITCH)
+ EmitChoosePokemon(0, 0, *(gBattleStruct->field_5C + 0), ABILITY_NONE, gBattleStruct->field_60[gActiveBank]);
+ else if (gActiveBank == 3 && gActionForBanks[1] == ACTION_SWITCH)
+ EmitChoosePokemon(0, 0, *(gBattleStruct->field_5C + 1), ABILITY_NONE, gBattleStruct->field_60[gActiveBank]);
+ else
+ EmitChoosePokemon(0, 0, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBank]);
+ }
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case ACTION_SAFARI_ZONE_BALL:
+ if (IsPlayerPartyAndPokemonStorageFull())
+ {
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DAB11;
+ gBattleCommunication[gActiveBank] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ break;
+ case ACTION_POKEBLOCK_CASE:
+ EmitOpenBag(0, gBattleStruct->field_60[gActiveBank]);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case ACTION_CANCEL_PARTNER:
+ gBattleCommunication[gActiveBank] = 7;
+ gBattleCommunication[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)] = 1;
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ if (gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_MULTIPLETURNS
+ || gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_RECHARGE)
+ {
+ Emit_x32(0);
+ MarkBufferBankForExecution(gActiveBank);
+ return;
+ }
+ else if (gActionForBanks[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)] == ACTION_SWITCH)
+ {
+ RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 2);
+ }
+ else if (gActionForBanks[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)] == ACTION_RUN)
+ {
+ RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 1);
+ }
+ else if (gActionForBanks[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)] == ACTION_USE_MOVE
+ && (gProtectStructs[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].onlyStruggle
+ || gDisableStructs[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].encoredMove))
+ {
+ RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 1);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_PALACE
+ && gActionForBanks[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)] == ACTION_USE_MOVE)
+ {
+ gRngValue = gBattlePalaceMoveSelectionRngValue;
+ RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 1);
+ }
+ else
+ {
+ RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 3);
+ }
+ Emit_x32(0);
+ MarkBufferBankForExecution(gActiveBank);
+ return;
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_x4000000)
+ && gBattleBufferB[gActiveBank][1] == ACTION_RUN)
+ {
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB9BA;
+ gBattleCommunication[gActiveBank] = 8;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ && gBattleBufferB[gActiveBank][1] == ACTION_RUN)
+ {
+ BattleScriptExecute(gUnknown_082DAAFE);
+ gBattleCommunication[gActiveBank] = 1;
+ }
+ else if (IsRunningFromBattleImpossible() != 0
+ && gBattleBufferB[gActiveBank][1] == ACTION_RUN)
+ {
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DAB0B;
+ gBattleCommunication[gActiveBank] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ gBattleCommunication[gActiveBank]++;
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CASE_CHOSEN:
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ switch (gActionForBanks[gActiveBank])
+ {
+ case ACTION_USE_MOVE:
+ switch (gBattleBufferB[gActiveBank][1])
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ gActionForBanks[gActiveBank] = gBattleBufferB[gActiveBank][1];
+ return;
+ case 15:
+ gActionForBanks[gActiveBank] = ACTION_SWITCH;
+ sub_803CDF8();
+ return;
+ default:
+ sub_818603C(2);
+ if ((gBattleBufferB[gActiveBank][2] | (gBattleBufferB[gActiveBank][3] << 8)) == 0xFFFF)
+ {
+ gBattleCommunication[gActiveBank] = 1;
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ }
+ else if (TrySetCantSelectMoveBattleScript())
+ {
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ gBattleCommunication[gActiveBank] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBank) = FALSE;
+ gBattleBufferB[gActiveBank][1] = 0;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBank) = STATE_WAIT_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_PALACE))
+ {
+ RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][2]);
+ RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][3]);
+ }
+ *(gBattleStruct->chosenMovePositions + gActiveBank) = gBattleBufferB[gActiveBank][2];
+ gChosenMovesByBanks[gActiveBank] = gBattleMons[gActiveBank].moves[*(gBattleStruct->chosenMovePositions + gActiveBank)];
+ *(gBattleStruct->moveTarget + gActiveBank) = gBattleBufferB[gActiveBank][3];
+ gBattleCommunication[gActiveBank]++;
+ }
+ break;
+ }
+ break;
+ case ACTION_USE_ITEM:
+ if ((gBattleBufferB[gActiveBank][1] | (gBattleBufferB[gActiveBank][2] << 8)) == 0)
+ {
+ gBattleCommunication[gActiveBank] = 1;
+ }
+ else
+ {
+ gLastUsedItem = (gBattleBufferB[gActiveBank][1] | (gBattleBufferB[gActiveBank][2] << 8));
+ gBattleCommunication[gActiveBank]++;
+ }
+ break;
+ case ACTION_SWITCH:
+ if (gBattleBufferB[gActiveBank][1] == 6)
+ {
+ gBattleCommunication[gActiveBank] = 1;
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ }
+ else
+ {
+ sub_803CDF8();
+ gBattleCommunication[gActiveBank]++;
+ }
+ break;
+ case ACTION_RUN:
+ gHitMarker |= HITMARKER_RUN;
+ gBattleCommunication[gActiveBank]++;
+ break;
+ case ACTION_WATCHES_CAREFULLY:
+ gBattleCommunication[gActiveBank]++;
+ break;
+ case ACTION_SAFARI_ZONE_BALL:
+ gBattleCommunication[gActiveBank]++;
+ break;
+ case ACTION_POKEBLOCK_CASE:
+ if ((gBattleBufferB[gActiveBank][1] | (gBattleBufferB[gActiveBank][2] << 8)) != 0)
+ {
+ gBattleCommunication[gActiveBank]++;
+ }
+ else
+ {
+ gBattleCommunication[gActiveBank] = STATE_BEFORE_ACTION_CHOSEN;
+ }
+ break;
+ case ACTION_GO_NEAR:
+ gBattleCommunication[gActiveBank]++;
+ break;
+ case ACTION_SAFARI_ZONE_RUN:
+ gHitMarker |= HITMARKER_RUN;
+ gBattleCommunication[gActiveBank]++;
+ break;
+ case ACTION_9:
+ gBattleCommunication[gActiveBank]++;
+ break;
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CONFIRMED_STANDBY:
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ i = (sub_803CDB8() != 0);
+
+ if (((gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_DOUBLE)) != BATTLE_TYPE_DOUBLE)
+ || (identity & BIT_MON)
+ || (*(&gBattleStruct->field_91) & gBitTable[GetBankByIdentity(identity ^ BIT_MON)]))
+ {
+ EmitLinkStandbyMsg(0, 0, i);
+ }
+ else
+ {
+ EmitLinkStandbyMsg(0, 1, i);
+ }
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleCommunication[gActiveBank]++;
+ }
+ break;
+ case STATE_WAIT_ACTION_CONFIRMED:
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ gBattleCommunication[ACTIONS_CONFIRMED_COUNT]++;
+ }
+ break;
+ case STATE_SELECTION_SCRIPT:
+ if (*(gBattleStruct->selectionScriptFinished + gActiveBank))
+ {
+ gBattleCommunication[gActiveBank] = *(gBattleStruct->stateIdAfterSelScript + gActiveBank);
+ }
+ else
+ {
+ gBankAttacker = gActiveBank;
+ gBattlescriptCurrInstr = gBattlescriptPtrsForSelection[gActiveBank];
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+ gBattlescriptPtrsForSelection[gActiveBank] = gBattlescriptCurrInstr;
+ }
+ break;
+ case STATE_WAIT_SET_BEFORE_ACTION:
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ gBattleCommunication[gActiveBank] = 1;
+ }
+ break;
+ case STATE_SELECTION_SCRIPT_MAY_RUN:
+ if (*(gBattleStruct->selectionScriptFinished + gActiveBank))
+ {
+ if (gBattleBufferB[gActiveBank][1] == 13)
+ {
+ gHitMarker |= HITMARKER_RUN;
+ gActionForBanks[gActiveBank] = ACTION_RUN;
+ gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ }
+ else
+ {
+ RecordedBattle_ClearBankAction(gActiveBank, 1);
+ gBattleCommunication[gActiveBank] = *(gBattleStruct->stateIdAfterSelScript + gActiveBank);
+ }
+ }
+ else
+ {
+ gBankAttacker = gActiveBank;
+ gBattlescriptCurrInstr = gBattlescriptPtrsForSelection[gActiveBank];
+ if (!(gBattleExecBuffer & ((gBitTable[gActiveBank]) | (0xF0000000) | (gBitTable[gActiveBank] << 4) | (gBitTable[gActiveBank] << 8) | (gBitTable[gActiveBank] << 0xC))))
+ {
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+ gBattlescriptPtrsForSelection[gActiveBank] = gBattlescriptCurrInstr;
+ }
+ break;
+ }
+ }
+
+ // check if everyone chose actions
+ if (gBattleCommunication[ACTIONS_CONFIRMED_COUNT] == gNoOfAllBanks)
+ {
+ sub_818603C(1);
+ gBattleMainFunc = SetActionsAndBanksTurnOrder;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gActionForBanks[i] == ACTION_SWITCH)
+ sub_80571DC(i, *(gBattleStruct->field_5C + i));
+ }
+ }
+ }
+}
+
+static bool8 sub_803CDB8(void)
+{
+ s32 i, var;
+
+ for (var = 0, i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleCommunication[i] == 5)
+ var++;
+ }
+
+ if (var + 1 == gNoOfAllBanks)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void sub_803CDF8(void)
+{
+ *(gBattleStruct->field_5C + gActiveBank) = gBattleBufferB[gActiveBank][1];
+ RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][1]);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) &= 0xF;
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0);
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 1) = gBattleBufferB[gActiveBank][3];
+
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) &= (0xF0);
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4;
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBank][3];
+ }
+}
+
+void SwapTurnOrder(u8 id1, u8 id2)
+{
+ u32 temp = gActionsByTurnOrder[id1];
+ gActionsByTurnOrder[id1] = gActionsByTurnOrder[id2];
+ gActionsByTurnOrder[id2] = temp;
+
+ temp = gBanksByTurnOrder[id1];
+ gBanksByTurnOrder[id1] = gBanksByTurnOrder[id2];
+ gBanksByTurnOrder[id2] = temp;
+}
+
+u8 GetWhoStrikesFirst(u8 bank1, u8 bank2, bool8 ignoreChosenMoves)
+{
+ u8 strikesFirst = 0;
+ u8 speedMultiplierBank1 = 0, speedMultiplierBank2 = 0;
+ u32 speedBank1 = 0, speedBank2 = 0;
+ u8 holdEffect = 0;
+ u8 holdEffectParam = 0;
+ u16 moveBank1 = 0, moveBank2 = 0;
+
+ if (WEATHER_HAS_EFFECT)
+ {
+ if ((gBattleMons[bank1].ability == ABILITY_SWIFT_SWIM && gBattleWeather & WEATHER_RAIN_ANY)
+ || (gBattleMons[bank1].ability == ABILITY_CHLOROPHYLL && gBattleWeather & WEATHER_SUN_ANY))
+ speedMultiplierBank1 = 2;
+ else
+ speedMultiplierBank1 = 1;
+
+ if ((gBattleMons[bank2].ability == ABILITY_SWIFT_SWIM && gBattleWeather & WEATHER_RAIN_ANY)
+ || (gBattleMons[bank2].ability == ABILITY_CHLOROPHYLL && gBattleWeather & WEATHER_SUN_ANY))
+ speedMultiplierBank2 = 2;
+ else
+ speedMultiplierBank2 = 1;
+ }
+ else
+ {
+ speedMultiplierBank1 = 1;
+ speedMultiplierBank2 = 1;
+ }
+
+ speedBank1 = (gBattleMons[bank1].speed * speedMultiplierBank1)
+ * (gStatStageRatios[gBattleMons[bank1].statStages[STAT_STAGE_SPEED]][0])
+ / (gStatStageRatios[gBattleMons[bank1].statStages[STAT_STAGE_SPEED]][1]);
+
+ if (gBattleMons[bank1].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[bank1].holdEffect;
+ holdEffectParam = gEnigmaBerries[bank1].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[bank1].item);
+ holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[bank1].item);
+ }
+
+ // badge boost
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER))
+ && FlagGet(BADGE03_GET)
+ && GetBankSide(bank1) == SIDE_PLAYER)
+ {
+ speedBank1 = (speedBank1 * 110) / 100;
+ }
+
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ speedBank1 /= 2;
+
+ if (gBattleMons[bank1].status1 & STATUS_PARALYSIS)
+ speedBank1 /= 4;
+
+ if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
+ speedBank1 = UINT_MAX;
+
+ // check second bank's speed
+
+ speedBank2 = (gBattleMons[bank2].speed * speedMultiplierBank2)
+ * (gStatStageRatios[gBattleMons[bank2].statStages[STAT_STAGE_SPEED]][0])
+ / (gStatStageRatios[gBattleMons[bank2].statStages[STAT_STAGE_SPEED]][1]);
+
+ if (gBattleMons[bank2].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[bank2].holdEffect;
+ holdEffectParam = gEnigmaBerries[bank2].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[bank2].item);
+ holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[bank2].item);
+ }
+
+ // badge boost
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER))
+ && FlagGet(BADGE03_GET)
+ && GetBankSide(bank2) == SIDE_PLAYER)
+ {
+ speedBank2 = (speedBank2 * 110) / 100;
+ }
+
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ speedBank2 /= 2;
+
+ if (gBattleMons[bank2].status1 & STATUS_PARALYSIS)
+ speedBank2 /= 4;
+
+ if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
+ speedBank2 = UINT_MAX;
+
+ if (ignoreChosenMoves)
+ {
+ moveBank1 = MOVE_NONE;
+ moveBank2 = MOVE_NONE;
+ }
+ else
+ {
+ if (gActionForBanks[bank1] == ACTION_USE_MOVE)
+ {
+ if (gProtectStructs[bank1].onlyStruggle)
+ moveBank1 = MOVE_STRUGGLE;
+ else
+ moveBank1 = gBattleMons[bank1].moves[*(gBattleStruct->chosenMovePositions + bank1)];
+ }
+ else
+ moveBank1 = MOVE_NONE;
+
+ if (gActionForBanks[bank2] == ACTION_USE_MOVE)
+ {
+ if (gProtectStructs[bank2].onlyStruggle)
+ moveBank2 = MOVE_STRUGGLE;
+ else
+ moveBank2 = gBattleMons[bank2].moves[*(gBattleStruct->chosenMovePositions + bank2)];
+ }
+ else
+ moveBank2 = MOVE_NONE;
+ }
+
+ // both move priorities are different than 0
+ if (gBattleMoves[moveBank1].priority != 0 || gBattleMoves[moveBank2].priority != 0)
+ {
+ // both priorities are the same
+ if (gBattleMoves[moveBank1].priority == gBattleMoves[moveBank2].priority)
+ {
+ if (speedBank1 == speedBank2 && Random() & 1)
+ strikesFirst = 2; // same speeds, same priorities
+ else if (speedBank1 < speedBank2)
+ strikesFirst = 1; // bank2 has more speed
+
+ // else bank1 has more speed
+ }
+ else if (gBattleMoves[moveBank1].priority < gBattleMoves[moveBank2].priority)
+ strikesFirst = 1; // bank2's move has greater priority
+
+ // else bank1's move has greater priority
+ }
+ // both priorities are equal to 0
+ else
+ {
+ if (speedBank1 == speedBank2 && Random() & 1)
+ strikesFirst = 2; // same speeds, same priorities
+ else if (speedBank1 < speedBank2)
+ strikesFirst = 1; // bank2 has more speed
+
+ // else bank1 has more speed
+ }
+
+ return strikesFirst;
+}
+
+static void SetActionsAndBanksTurnOrder(void)
+{
+ s32 var = 0;
+ s32 i, j;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ gActionsByTurnOrder[var] = gActionForBanks[gActiveBank];
+ gBanksByTurnOrder[var] = gActiveBank;
+ var++;
+ }
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (gActionForBanks[gActiveBank] == ACTION_RUN)
+ {
+ var = 5;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (gActionForBanks[0] == ACTION_RUN)
+ {
+ gActiveBank = 0;
+ var = 5;
+ }
+ if (gActionForBanks[2] == ACTION_RUN)
+ {
+ gActiveBank = 2;
+ var = 5;
+ }
+ }
+
+ if (var == 5)
+ {
+ gActionsByTurnOrder[0] = gActionForBanks[gActiveBank];
+ gBanksByTurnOrder[0] = gActiveBank;
+ var = 1;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (i != gActiveBank)
+ {
+ gActionsByTurnOrder[var] = gActionForBanks[i];
+ gBanksByTurnOrder[var] = i;
+ var++;
+ }
+ }
+ gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
+ gBattleStruct->focusPunchBank = 0;
+ return;
+ }
+ else
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (gActionForBanks[gActiveBank] == ACTION_USE_ITEM || gActionForBanks[gActiveBank] == ACTION_SWITCH)
+ {
+ gActionsByTurnOrder[var] = gActionForBanks[gActiveBank];
+ gBanksByTurnOrder[var] = gActiveBank;
+ var++;
+ }
+ }
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (gActionForBanks[gActiveBank] != ACTION_USE_ITEM && gActionForBanks[gActiveBank] != ACTION_SWITCH)
+ {
+ gActionsByTurnOrder[var] = gActionForBanks[gActiveBank];
+ gBanksByTurnOrder[var] = gActiveBank;
+ var++;
+ }
+ }
+ for (i = 0; i < gNoOfAllBanks - 1; i++)
+ {
+ for (j = i + 1; j < gNoOfAllBanks; j++)
+ {
+ u8 bank1 = gBanksByTurnOrder[i];
+ u8 bank2 = gBanksByTurnOrder[j];
+ if (gActionsByTurnOrder[i] != ACTION_USE_ITEM
+ && gActionsByTurnOrder[j] != ACTION_USE_ITEM
+ && gActionsByTurnOrder[i] != ACTION_SWITCH
+ && gActionsByTurnOrder[j] != ACTION_SWITCH)
+ {
+ if (GetWhoStrikesFirst(bank1, bank2, FALSE))
+ SwapTurnOrder(i, j);
+ }
+ }
+ }
+ }
+ }
+ gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
+ gBattleStruct->focusPunchBank = 0;
+}
+
+static void TurnValuesCleanUp(bool8 var0)
+{
+ s32 i;
+ u8 *dataPtr;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (var0)
+ {
+ gProtectStructs[gActiveBank].protected = 0;
+ gProtectStructs[gActiveBank].endured = 0;
+ }
+ else
+ {
+ dataPtr = (u8*)(&gProtectStructs[gActiveBank]);
+ for (i = 0; i < sizeof(struct ProtectStruct); i++)
+ dataPtr[i] = 0;
+
+ if (gDisableStructs[gActiveBank].isFirstTurn)
+ gDisableStructs[gActiveBank].isFirstTurn--;
+
+ if (gDisableStructs[gActiveBank].rechargeCounter)
+ {
+ gDisableStructs[gActiveBank].rechargeCounter--;
+ if (gDisableStructs[gActiveBank].rechargeCounter == 0)
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_RECHARGE);
+ }
+ }
+
+ if (gDisableStructs[gActiveBank].substituteHP == 0)
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_SUBSTITUTE);
+ }
+
+ gSideTimers[0].followmeTimer = 0;
+ gSideTimers[1].followmeTimer = 0;
+}
+
+static void SpecialStatusesClear(void)
+{
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ s32 i;
+ u8 *dataPtr = (u8*)(&gSpecialStatuses[gActiveBank]);
+
+ for (i = 0; i < sizeof(struct SpecialStatus); i++)
+ dataPtr[i] = 0;
+ }
+}
+
+static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
+{
+ if (!(gHitMarker & HITMARKER_RUN))
+ {
+ while (gBattleStruct->focusPunchBank < gNoOfAllBanks)
+ {
+ gActiveBank = gBankAttacker = gBattleStruct->focusPunchBank;
+ gBattleStruct->focusPunchBank++;
+ if (gChosenMovesByBanks[gActiveBank] == MOVE_FOCUS_PUNCH
+ && !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP)
+ && !(gDisableStructs[gBankAttacker].truantCounter)
+ && !(gProtectStructs[gActiveBank].onlyStruggle))
+ {
+ BattleScriptExecute(BattleScript_FocusPunchSetUp);
+ return;
+ }
+ }
+ }
+
+ TryClearRageStatuses();
+ gCurrentTurnActionNumber = 0;
+{
+ // something stupid needed to match
+ u8 zero;
+ gCurrentActionFuncId = gActionsByTurnOrder[(zero = 0)];
+}
+ gDynamicBasePower = 0;
+ gBattleStruct->dynamicMoveType = 0;
+ gBattleMainFunc = RunTurnActionsFunctions;
+ gBattleCommunication[3] = 0;
+ gBattleCommunication[4] = 0;
+ gBattleScripting.field_16 = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+}
+
+static void RunTurnActionsFunctions(void)
+{
+ if (gBattleOutcome != 0)
+ gCurrentActionFuncId = 12;
+
+ *(&gBattleStruct->field_4B) = gCurrentTurnActionNumber;
+ sTurnActionsFuncsTable[gCurrentActionFuncId]();
+
+ if (gCurrentTurnActionNumber >= gNoOfAllBanks) // everyone did their actions, turn finished
+ {
+ gHitMarker &= ~(HITMARKER_x100000);
+ gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F];
+ }
+ else
+ {
+ if (gBattleStruct->field_4B != gCurrentTurnActionNumber) // action turn has been done, clear hitmarker bits for another bank
+ {
+ gHitMarker &= ~(HITMARKER_NO_ATTACKSTRING);
+ gHitMarker &= ~(HITMARKER_UNABLE_TO_USE_MOVE);
+ }
+ }
+}
+
+static void HandleEndTurn_BattleWon(void)
+{
+ gCurrentActionFuncId = 0;
+
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ {
+ gScriptResult = gBattleOutcome;
+ gBattleTextBuff1[0] = gBattleOutcome;
+ gBankAttacker = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost;
+ gBattleOutcome &= ~(BATTLE_OUTCOME_BIT_x80);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_x4000000 | BATTLE_TYPE_EREADER_TRAINER))
+ {
+ BattleMusicStop();
+ gBattlescriptCurrInstr = BattleScript_FrontierTrainerBattleWon;
+
+ if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_3FE)
+ PlayBGM(BGM_KACHI3);
+ else
+ PlayBGM(BGM_KACHI1);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ BattleMusicStop();
+ gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon;
+
+ switch (gTrainers[gTrainerBattleOpponent_A].trainerClass)
+ {
+ case CLASS_ELITE_FOUR:
+ case CLASS_CHAMPION:
+ PlayBGM(BGM_KACHI5);
+ break;
+ case CLASS_TEAM_AQUA:
+ case CLASS_TEAM_MAGMA:
+ case CLASS_AQUA_ADMIN:
+ case CLASS_AQUA_LEADER:
+ case CLASS_MAGMA_ADMIN:
+ case CLASS_MAGMA_LEADER:
+ PlayBGM(BGM_KACHI4);
+ break;
+ case CLASS_LEADER:
+ PlayBGM(BGM_KACHI3);
+ break;
+ default:
+ PlayBGM(BGM_KACHI1);
+ break;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BattleScript_PayDayMoneyAndPickUpItems;
+ }
+
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_BattleLost(void)
+{
+ gCurrentActionFuncId = 0;
+
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ {
+ if (gBattleOutcome & BATTLE_OUTCOME_BIT_x80)
+ {
+ gBattlescriptCurrInstr = gUnknown_082DB9C8;
+ gBattleOutcome &= ~(BATTLE_OUTCOME_BIT_x80);
+ gSaveBlock2Ptr->field_CA9_b = 1;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = gUnknown_082DAA0B;
+ gBattleOutcome &= ~(BATTLE_OUTCOME_BIT_x80);
+ }
+ }
+ else
+ {
+ gBattleTextBuff1[0] = gBattleOutcome;
+ gBankAttacker = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost;
+ gBattleOutcome &= ~(BATTLE_OUTCOME_BIT_x80);
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BattleScript_LocalBattleLost;
+ }
+
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_RanFromBattle(void)
+{
+ gCurrentActionFuncId = 0;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER && gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ gBattlescriptCurrInstr = gUnknown_082DB9C1;
+ gBattleOutcome = BATTLE_FORFEITED;
+ gSaveBlock2Ptr->field_CA9_b = 1;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
+ {
+ gBattlescriptCurrInstr = gUnknown_082DB9C1;
+ gBattleOutcome = BATTLE_FORFEITED;
+ }
+ else
+ {
+ switch (gProtectStructs[gBankAttacker].fleeFlag)
+ {
+ default:
+ gBattlescriptCurrInstr = BattleScript_GotAwaySafely;
+ break;
+ case 1:
+ gBattlescriptCurrInstr = BattleScript_SmokeBallEscape;
+ break;
+ case 2:
+ gBattlescriptCurrInstr = BattleScript_RanAwayUsingMonAbility;
+ break;
+ }
+ }
+
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_MonFled(void)
+{
+ gCurrentActionFuncId = 0;
+
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, gBattlePartyID[gBankAttacker]);
+ gBattlescriptCurrInstr = BattleScript_WildMonFled;
+
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_FinishBattle(void)
+{
+ if (gCurrentActionFuncId == 0xB || gCurrentActionFuncId == 0xC)
+ {
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_FIRST_BATTLE
+ | BATTLE_TYPE_SAFARI
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_WALLY_TUTORIAL
+ | BATTLE_TYPE_FRONTIER)))
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ if (gBattleResults.playerMon1Species == SPECIES_NONE)
+ {
+ gBattleResults.playerMon1Species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES, NULL);
+ GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_NICKNAME, gBattleResults.playerMon1Name);
+ }
+ else
+ {
+ gBattleResults.playerMon2Species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES, NULL);
+ GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_NICKNAME, gBattleResults.playerMon2Name);
+ }
+ }
+ }
+ sub_80EC728();
+ }
+
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_TRAINER
+ | BATTLE_TYPE_FIRST_BATTLE
+ | BATTLE_TYPE_SAFARI
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_WALLY_TUTORIAL))
+ && gBattleResults.unk5_6)
+ {
+ sub_80EE184();
+ }
+
+ sub_8186444();
+ BeginFastPaletteFade(3);
+ FadeOutMapMusic(5);
+ gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions;
+ gUnknown_030061E8 = BattleMainCB2;
+ }
+ else
+ {
+ if (gBattleExecBuffer == 0)
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+}
+
+static void FreeResetData_ReturnToOvOrDoEvolutions(void)
+{
+ if (!gPaletteFade.active)
+ {
+ ResetSpriteData();
+ if (gLeveledUpInBattle == 0 || gBattleOutcome != BATTLE_WON)
+ {
+ gBattleMainFunc = ReturnFromBattleToOverworld;
+ return;
+ }
+ else
+ {
+ gBattleMainFunc = TryEvolvePokemon;
+ }
+ }
+
+ FreeAllWindowBuffers();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ FreeMonSpritesGfx();
+ FreeBattleResources();
+ FreeBattleSpritesData();
+ }
+}
+
+static void TryEvolvePokemon(void)
+{
+ s32 i;
+
+ while (gLeveledUpInBattle != 0)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (gLeveledUpInBattle & gBitTable[i])
+ {
+ u16 species;
+ u8 levelUpBits = gLeveledUpInBattle;
+
+ levelUpBits &= ~(gBitTable[i]);
+ gLeveledUpInBattle = levelUpBits;
+
+ species = GetEvolutionTargetSpecies(&gPlayerParty[i], 0, levelUpBits);
+ if (species != SPECIES_NONE)
+ {
+ FreeAllWindowBuffers();
+ gBattleMainFunc = WaitForEvoSceneToFinish;
+ EvolutionScene(&gPlayerParty[i], species, TRUE, i);
+ return;
+ }
+ }
+ }
+ }
+
+ gBattleMainFunc = ReturnFromBattleToOverworld;
+}
+
+static void WaitForEvoSceneToFinish(void)
+{
+ if (gMain.callback2 == BattleMainCB2)
+ gBattleMainFunc = TryEvolvePokemon;
+}
+
+static void ReturnFromBattleToOverworld(void)
+{
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ RandomlyGivePartyPokerus(gPlayerParty);
+ PartySpreadPokerus(gPlayerParty);
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK && gReceivedRemoteLinkPlayers != 0)
+ return;
+
+ gScriptResult = gBattleOutcome;
+ gMain.inBattle = 0;
+ gMain.callback1 = gPreBattleCallback1;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_ROAMER)
+ {
+ UpdateRoamerHPStatus(&gEnemyParty[0]);
+ if ((gBattleOutcome & BATTLE_WON) || gBattleOutcome == BATTLE_CAUGHT)
+ SetRoamerInactive();
+ }
+
+ m4aSongNumStop(0x5A);
+ SetMainCallback2(gMain.savedCallback);
+}
+
+void RunBattleScriptCommands_PopCallbacksStack(void)
+{
+ if (gCurrentActionFuncId == 0xB || gCurrentActionFuncId == 0xC)
+ {
+ if (BATTLE_CALLBACKS_STACK->size != 0)
+ BATTLE_CALLBACKS_STACK->size--;
+ gBattleMainFunc = BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size];
+ }
+ else
+ {
+ if (gBattleExecBuffer == 0)
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+}
+
+void RunBattleScriptCommands(void)
+{
+ if (gBattleExecBuffer == 0)
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+}
+
+static void HandleAction_UseMove(void)
+{
+ u8 side;
+ u8 var = 4;
+
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+
+ if (*(&gBattleStruct->field_91) & gBitTable[gBankAttacker])
+ {
+ gCurrentActionFuncId = ACTION_FINISHED;
+ return;
+ }
+
+ gCritMultiplier = 1;
+ gBattleScripting.dmgMultiplier = 1;
+ gBattleStruct->atkCancellerTracker = 0;
+ gBattleMoveFlags = 0;
+ gMultiHitCounter = 0;
+ gBattleCommunication[6] = 0;
+ gCurrMovePos = gUnknown_020241E9 = *(gBattleStruct->chosenMovePositions + gBankAttacker);
+
+ // choose move
+ if (gProtectStructs[gBankAttacker].onlyStruggle)
+ {
+ gProtectStructs[gBankAttacker].onlyStruggle = 0;
+ gCurrentMove = gLastUsedMove = MOVE_STRUGGLE;
+ gHitMarker |= HITMARKER_NO_PPDEDUCT;
+ *(gBattleStruct->moveTarget + gBankAttacker) = GetMoveTarget(MOVE_STRUGGLE, 0);
+ }
+ else if (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS || gBattleMons[gBankAttacker].status2 & STATUS2_RECHARGE)
+ {
+ gCurrentMove = gLastUsedMove = gLockedMoves[gBankAttacker];
+ }
+ // encore forces you to use the same move
+ else if (gDisableStructs[gBankAttacker].encoredMove != MOVE_NONE
+ && gDisableStructs[gBankAttacker].encoredMove == gBattleMons[gBankAttacker].moves[gDisableStructs[gBankAttacker].encoredMovePos])
+ {
+ gCurrentMove = gLastUsedMove = gDisableStructs[gBankAttacker].encoredMove;
+ gCurrMovePos = gUnknown_020241E9 = gDisableStructs[gBankAttacker].encoredMovePos;
+ *(gBattleStruct->moveTarget + gBankAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ // check if the encored move wasn't overwritten
+ else if (gDisableStructs[gBankAttacker].encoredMove != MOVE_NONE
+ && gDisableStructs[gBankAttacker].encoredMove != gBattleMons[gBankAttacker].moves[gDisableStructs[gBankAttacker].encoredMovePos])
+ {
+ gCurrMovePos = gUnknown_020241E9 = gDisableStructs[gBankAttacker].encoredMovePos;
+ gCurrentMove = gLastUsedMove = gBattleMons[gBankAttacker].moves[gCurrMovePos];
+ gDisableStructs[gBankAttacker].encoredMove = MOVE_NONE;
+ gDisableStructs[gBankAttacker].encoredMovePos = 0;
+ gDisableStructs[gBankAttacker].encoreTimer1 = 0;
+ *(gBattleStruct->moveTarget + gBankAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ else if (gBattleMons[gBankAttacker].moves[gCurrMovePos] != gChosenMovesByBanks[gBankAttacker])
+ {
+ gCurrentMove = gLastUsedMove = gBattleMons[gBankAttacker].moves[gCurrMovePos];
+ *(gBattleStruct->moveTarget + gBankAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ else
+ {
+ gCurrentMove = gLastUsedMove = gBattleMons[gBankAttacker].moves[gCurrMovePos];
+ }
+
+ if (gBattleMons[gBankAttacker].hp != 0)
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ gBattleResults.lastUsedMovePlayer = gCurrentMove;
+ else
+ gBattleResults.lastUsedMoveOpponent = gCurrentMove;
+ }
+
+ // choose target
+ side = GetBankSide(gBankAttacker) ^ BIT_SIDE;
+ if (gSideTimers[side].followmeTimer != 0
+ && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
+ && GetBankSide(gBankAttacker) != GetBankSide(gSideTimers[side].followmeTarget)
+ && gBattleMons[gSideTimers[side].followmeTarget].hp != 0)
+ {
+ gBankTarget = gSideTimers[side].followmeTarget;
+ }
+ else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ && gSideTimers[side].followmeTimer == 0
+ && (gBattleMoves[gCurrentMove].power != 0
+ || gBattleMoves[gCurrentMove].target != MOVE_TARGET_x10)
+ && gBattleMons[*(gBattleStruct->moveTarget + gBankAttacker)].ability != ABILITY_LIGHTNING_ROD
+ && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ {
+ side = GetBankSide(gBankAttacker);
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (side != GetBankSide(gActiveBank)
+ && *(gBattleStruct->moveTarget + gBankAttacker) != gActiveBank
+ && gBattleMons[gActiveBank].ability == ABILITY_LIGHTNING_ROD
+ && BankGetTurnOrder(gActiveBank) < var)
+ {
+ var = BankGetTurnOrder(gActiveBank);
+ }
+ }
+ if (var == 4)
+ {
+ if (gBattleMoves[gLastUsedMove].target & MOVE_TARGET_RANDOM)
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ {
+ if (Random() & 1)
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
+ }
+ else
+ {
+ if (Random() & 1)
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON2);
+ }
+ }
+ else
+ {
+ gBankTarget = *(gBattleStruct->moveTarget + gBankAttacker);
+ }
+
+ if (gAbsentBankFlags & gBitTable[gBankTarget])
+ {
+ if (GetBankSide(gBankAttacker) != GetBankSide(gBankTarget))
+ {
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ }
+ else
+ {
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_SIDE);
+ if (gAbsentBankFlags & gBitTable[gBankTarget])
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ }
+ }
+ }
+ else
+ {
+ gActiveBank = gBanksByTurnOrder[var];
+ RecordAbilityBattle(gActiveBank, gBattleMons[gActiveBank].ability);
+ gSpecialStatuses[gActiveBank].lightningRodRedirected = 1;
+ gBankTarget = gActiveBank;
+ }
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && gBattleMoves[gLastUsedMove].target & MOVE_TARGET_RANDOM)
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ {
+ if (Random() & 1)
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
+ }
+ else
+ {
+ if (Random() & 1)
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON2);
+ }
+
+ if (gAbsentBankFlags & gBitTable[gBankTarget]
+ && GetBankSide(gBankAttacker) != GetBankSide(gBankTarget))
+ {
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ }
+ }
+ else
+ {
+ gBankTarget = *(gBattleStruct->moveTarget + gBankAttacker);
+ if (gAbsentBankFlags & gBitTable[gBankTarget])
+ {
+ if (GetBankSide(gBankAttacker) != GetBankSide(gBankTarget))
+ {
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ }
+ else
+ {
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_SIDE);
+ if (gAbsentBankFlags & gBitTable[gBankTarget])
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ }
+ }
+ }
+
+ // choose battlescript
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE
+ && gProtectStructs[gBankAttacker].flag_x10)
+ {
+ if (gBattleMons[gBankAttacker].hp == 0)
+ {
+ gCurrentActionFuncId = 12;
+ return;
+ }
+ else if (gUnknown_02024230[gBankAttacker] != NULL)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ gBattlescriptCurrInstr = gUnknown_02024230[gBankAttacker];
+ gUnknown_02024230[gBankAttacker] = NULL;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ sub_81A56E8(gBankAttacker);
+
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+static void HandleAction_Switch(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gActionSelectionCursor[gBankAttacker] = 0;
+ gMoveSelectionCursor[gBankAttacker] = 0;
+
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, *(gBattleStruct->field_58 + gBankAttacker))
+
+ gBattleScripting.bank = gBankAttacker;
+ gBattlescriptCurrInstr = BattleScript_ActionSwitch;
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+
+ if (gBattleResults.playerSwitchesCounter < 255)
+ gBattleResults.playerSwitchesCounter++;
+}
+
+static void HandleAction_UseItem(void)
+{
+ gBankAttacker = gBankTarget = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ ClearFuryCutterDestinyBondGrudge(gBankAttacker);
+ gLastUsedItem = gBattleBufferB[gBankAttacker][1] | (gBattleBufferB[gBankAttacker][2] << 8);
+
+ if (gLastUsedItem <= ITEM_PREMIER_BALL) // is ball
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForBallThrow[gLastUsedItem];
+ }
+ else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0];
+ }
+ else if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ {
+ gBattlescriptCurrInstr = gUnknown_082DBD3C[0];
+ }
+ else
+ {
+ gBattleScripting.bank = gBankAttacker;
+
+ switch (*(gBattleStruct->field_C4 + (gBankAttacker >> 1)))
+ {
+ case 1:
+ case 2:
+ break;
+ case 3:
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ if (*(gBattleStruct->field_C6 + gBankAttacker / 2) & 1)
+ {
+ if (*(gBattleStruct->field_C6 + gBankAttacker / 2) & 0x3E)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ }
+ else
+ {
+ while (!(*(gBattleStruct->field_C6 + gBankAttacker / 2) & 1))
+ {
+ *(gBattleStruct->field_C6 + gBankAttacker / 2) >>= 1;
+ gBattleCommunication[MULTISTRING_CHOOSER]++;
+ }
+ }
+ break;
+ case 4:
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ if (*(gBattleStruct->field_C6 + (gBankAttacker >> 1)) & 0x80)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ }
+ else
+ {
+ PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK)
+ PREPARE_STRING_BUFFER(gBattleTextBuff2, 0xD2)
+
+ while (!((*(gBattleStruct->field_C6 + (gBankAttacker >> 1))) & 1))
+ {
+ *(gBattleStruct->field_C6 + gBankAttacker / 2) >>= 1;
+ gBattleTextBuff1[2]++;
+ }
+
+ gBattleScripting.animArg1 = gBattleTextBuff1[2] + 14;
+ gBattleScripting.animArg2 = 0;
+ }
+ break;
+ case 5:
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ break;
+ }
+
+ gBattlescriptCurrInstr = gUnknown_082DBD3C[*(gBattleStruct->field_C4 + gBankAttacker / 2)];
+ }
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+bool8 TryRunFromBattle(u8 bank)
+{
+ bool8 effect = FALSE;
+ u8 holdEffect;
+ u8 pyramidMultiplier;
+ u8 speedVar;
+
+ if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[bank].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[bank].item);
+
+ gStringBank = bank;
+
+ if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
+ {
+ gLastUsedItem = gBattleMons[bank].item ;
+ gProtectStructs[bank].fleeFlag = 1;
+ effect++;
+ }
+ else if (gBattleMons[bank].ability == ABILITY_RUN_AWAY)
+ {
+ if (InBattlePyramid())
+ {
+ gBattleStruct->runTries++;
+ pyramidMultiplier = sub_81A9E28();
+ speedVar = (gBattleMons[bank].speed * pyramidMultiplier) / (gBattleMons[bank ^ BIT_SIDE].speed) + (gBattleStruct->runTries * 30);
+ if (speedVar > (Random() & 0xFF))
+ {
+ gLastUsedAbility = ABILITY_RUN_AWAY;
+ gProtectStructs[bank].fleeFlag = 2;
+ effect++;
+ }
+ }
+ else
+ {
+ gLastUsedAbility = ABILITY_RUN_AWAY;
+ gProtectStructs[bank].fleeFlag = 2;
+ effect++;
+ }
+ }
+ else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_x4000000) && gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ effect++;
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ if (InBattlePyramid())
+ {
+ pyramidMultiplier = sub_81A9E28();
+ speedVar = (gBattleMons[bank].speed * pyramidMultiplier) / (gBattleMons[bank ^ BIT_SIDE].speed) + (gBattleStruct->runTries * 30);
+ if (speedVar > (Random() & 0xFF))
+ effect++;
+ }
+ else if (gBattleMons[bank].speed < gBattleMons[bank ^ BIT_SIDE].speed)
+ {
+ speedVar = (gBattleMons[bank].speed * 128) / (gBattleMons[bank ^ BIT_SIDE].speed) + (gBattleStruct->runTries * 30);
+ if (speedVar > (Random() & 0xFF))
+ effect++;
+ }
+ else // same speed or faster
+ {
+ effect++;
+ }
+ }
+
+ gBattleStruct->runTries++;
+ }
+
+ if (effect)
+ {
+ gCurrentTurnActionNumber = gNoOfAllBanks;
+ gBattleOutcome = BATTLE_RAN;
+ }
+
+ return effect;
+}
+
+static void HandleAction_Run(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ {
+ gCurrentTurnActionNumber = gNoOfAllBanks;
+
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ if (gActionForBanks[gActiveBank] == ACTION_RUN)
+ gBattleOutcome |= BATTLE_LOST;
+ }
+ else
+ {
+ if (gActionForBanks[gActiveBank] == ACTION_RUN)
+ gBattleOutcome |= BATTLE_WON;
+ }
+ }
+
+ gBattleOutcome |= BATTLE_OUTCOME_BIT_x80;
+ gSaveBlock2Ptr->field_CA9_b = 1;
+ }
+ else
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ {
+ if (!TryRunFromBattle(gBankAttacker)) // failed to run away
+ {
+ ClearFuryCutterDestinyBondGrudge(gBankAttacker);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 3;
+ gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+ }
+ }
+ else
+ {
+ if (gBattleMons[gBankAttacker].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+ }
+ else
+ {
+ gCurrentTurnActionNumber = gNoOfAllBanks;
+ gBattleOutcome = BATTLE_POKE_FLED;
+ }
+ }
+ }
+}
+
+static void HandleAction_WatchesCarefully(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[0];
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+static void HandleAction_SafariZoneBallThrow(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gNumSafariBalls--;
+ gLastUsedItem = ITEM_SAFARI_BALL;
+ gBattlescriptCurrInstr = gBattlescriptsForBallThrow[ITEM_SAFARI_BALL];
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+static void HandleAction_ThrowPokeblock(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattleCommunication[MULTISTRING_CHOOSER] = gBattleBufferB[gBankAttacker][1] - 1;
+ gLastUsedItem = gBattleBufferB[gBankAttacker][2];
+
+ if (gBattleResults.field_1F < 0xFF)
+ gBattleResults.field_1F++;
+ if (gBattleStruct->field_7A < 3)
+ gBattleStruct->field_7A++;
+ if (gBattleStruct->field_7B > 1)
+ {
+ if (gBattleStruct->field_7B < sUnknown_0831BCE0[gBattleStruct->field_7A][gBattleCommunication[MULTISTRING_CHOOSER]])
+ gBattleStruct->field_7B = 1;
+ else
+ gBattleStruct->field_7B -= sUnknown_0831BCE0[gBattleStruct->field_7A][gBattleCommunication[MULTISTRING_CHOOSER]];
+ }
+
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[2];
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+static void HandleAction_GoNear(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+
+ gBattleStruct->field_7C += sUnknown_0831BCEF[gBattleStruct->field_79];
+ if (gBattleStruct->field_7C > 20)
+ gBattleStruct->field_7C = 20;
+
+ gBattleStruct->field_7B +=sUnknown_0831BCF3[gBattleStruct->field_79];
+ if (gBattleStruct->field_7B > 20)
+ gBattleStruct->field_7B = 20;
+
+ if (gBattleStruct->field_79 < 3)
+ {
+ gBattleStruct->field_79++;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[1];
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+}
+
+static void HandleAction_SafriZoneRun(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ PlaySE(SE_NIGERU);
+ gCurrentTurnActionNumber = gNoOfAllBanks;
+ gBattleOutcome = BATTLE_RAN;
+}
+
+static void HandleAction_Action9(void)
+{
+ gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, gBattlePartyID[gBankAttacker])
+
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[3];
+ gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
+ gActionsByTurnOrder[1] = ACTION_FINISHED;
+}
+
+static void HandleAction_Action11(void)
+{
+ if (!sub_8041728())
+ {
+ gBattleStruct->field_4D = 0;
+ gCurrentActionFuncId = ACTION_FINISHED;
+ }
+}
+
+static void HandleAction_NothingIsFainted(void)
+{
+ gCurrentTurnActionNumber++;
+ gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
+ gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
+ | HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
+ | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
+ | HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
+ | HITMARKER_x8000000 | HITMARKER_x4000000);
+}
+
+static void HandleAction_ActionFinished(void)
+{
+ *(gBattleStruct->field_5C + gBanksByTurnOrder[gCurrentTurnActionNumber]) = 6;
+ gCurrentTurnActionNumber++;
+ gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
+ SpecialStatusesClear();
+ gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
+ | HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
+ | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
+ | HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
+ | HITMARKER_x8000000 | HITMARKER_x4000000);
+
+ gCurrentMove = 0;
+ gBattleMoveDamage = 0;
+ gBattleMoveFlags = 0;
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gUnknown_02024250[gBankAttacker] = 0;
+ gUnknown_02024258[gBankAttacker] = 0;
+ gBattleStruct->dynamicMoveType = 0;
+ gDynamicBasePower = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleCommunication[3] = 0;
+ gBattleCommunication[4] = 0;
+ gBattleScripting.field_16 = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+}
diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c
index dae43f13c..92126e40c 100644
--- a/src/battle_ai_script_commands.c
+++ b/src/battle_ai_script_commands.c
@@ -73,7 +73,7 @@ extern const struct BaseStats gBaseStats[];
extern const u32 gBitTable[];
extern u8 * const gBattleAI_ScriptsTable[];
-extern u8 b_first_side(u8, u8, u8);
+extern u8 GetWhoStrikesFirst(u8, u8, u8);
extern void AI_CalcDmg(u8, u8);
extern u8 CheckMoveLimitations();
@@ -1756,7 +1756,7 @@ static void BattleAICmd_if_arg_not_equal(void)
static void BattleAICmd_if_would_go_first(void)
{
- if (b_first_side(sBank_AI, gBankTarget, 1) == gAIScriptPtr[1])
+ if (GetWhoStrikesFirst(sBank_AI, gBankTarget, 1) == gAIScriptPtr[1])
gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2);
else
gAIScriptPtr += 6;
@@ -1764,7 +1764,7 @@ static void BattleAICmd_if_would_go_first(void)
static void BattleAICmd_if_would_not_go_first(void)
{
- if (b_first_side(sBank_AI, gBankTarget, 1) != gAIScriptPtr[1])
+ if (GetWhoStrikesFirst(sBank_AI, gBankTarget, 1) != gAIScriptPtr[1])
gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2);
else
gAIScriptPtr += 6;
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index e0cb3e941..e53292442 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -47,8 +47,8 @@ extern u8 gActiveBank;
extern u32 gBattleExecBuffer;
extern u8 gNoOfAllBanks;
extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
-extern u8 gTurnOrder[BATTLE_BANKS_COUNT];
-extern u8 gUnknown_0202407A[BATTLE_BANKS_COUNT];
+extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT];
+extern u8 gActionsByTurnOrder[BATTLE_BANKS_COUNT];
extern u16 gCurrentMove;
extern u8 gLastUsedAbility;
extern u16 gBattleWeather;
@@ -67,7 +67,7 @@ extern u8 gBankAttacker;
extern u8 gBankTarget;
extern const u8* gBattlescriptCurrInstr;
extern u8 gCurrMovePos;
-extern u8 gFightStateTracker;
+extern u8 gCurrentActionFuncId;
extern u32 gHitMarker;
extern u8 gBattleMoveFlags;
extern u8 gBattleCommunication[];
@@ -92,7 +92,7 @@ extern u16 gMoveToLearn;
extern u16 gRandomMove;
extern u8 gBankInMenu;
extern u8 gActionForBanks[BATTLE_BANKS_COUNT];
-extern u8 gCurrentMoveTurn;
+extern u8 gCurrentTurnActionNumber;
extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
extern u16 gLockedMoves[BATTLE_BANKS_COUNT];
extern u16 gPartnerTrainerId;
@@ -145,8 +145,7 @@ extern u16 GetBattlePyramidPickupItemId(void);
extern u8 sav1_map_get_light_level(void);
extern u8 sub_813B21C(void);
extern u16 get_unknown_box_id(void);
-extern void c2_berry_program_update_menu(void);
-extern void sub_8035AA4(void);
+extern void sub_80356D0(void);
// BattleScripts
extern const u8 BattleScript_MoveEnd[];
@@ -332,7 +331,7 @@ static void atk40_jump_if_move_affected_by_protect(void);
static void atk41_call(void);
static void atk42_jumpiftype2(void);
static void atk43_jumpifabilitypresent(void);
-static void atk44(void);
+static void atk44_end_selection_script(void);
static void atk45_playanimation(void);
static void atk46_playanimation2(void);
static void atk47_setgraphicalstatchangevalues(void);
@@ -361,7 +360,7 @@ static void atk5D_getmoneyreward(void);
static void atk5E_8025A70(void);
static void atk5F_8025B24(void);
static void atk60_increment_gamestat(void);
-static void atk61_8025BA4(void);
+static void atk61_draw_party_status_summary(void);
static void atk62_08025C6C(void);
static void atk63_jumptorandomattack(void);
static void atk64_statusanimation(void);
@@ -378,7 +377,7 @@ static void atk6E_set_atk_to_player0(void);
static void atk6F_set_visible(void);
static void atk70_record_last_used_ability(void);
static void atk71_buffer_move_to_learn(void);
-static void atk72_jump_if_can_run_frombattle(void);
+static void atk72_jump_if_run_attempt_success(void);
static void atk73_hp_thresholds(void);
static void atk74_hp_thresholds2(void);
static void atk75_item_effect_on_opponent(void);
@@ -510,8 +509,8 @@ static void atkF2_display_dex_info(void);
static void atkF3_nickname_caught_poke(void);
static void atkF4_subattackerhpbydmg(void);
static void atkF5_removeattackerstatus1(void);
-static void atkF6_802BF48(void);
-static void atkF7_802BF54(void);
+static void atkF6_action_finished(void);
+static void atkF7_turn_finished(void);
static void atkF8_trainer_slide_back(void);
void (* const gBattleScriptingCommandsTable[])(void) =
@@ -584,7 +583,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk41_call,
atk42_jumpiftype2,
atk43_jumpifabilitypresent,
- atk44,
+ atk44_end_selection_script,
atk45_playanimation,
atk46_playanimation2,
atk47_setgraphicalstatchangevalues,
@@ -613,7 +612,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk5E_8025A70,
atk5F_8025B24,
atk60_increment_gamestat,
- atk61_8025BA4,
+ atk61_draw_party_status_summary,
atk62_08025C6C,
atk63_jumptorandomattack,
atk64_statusanimation,
@@ -630,7 +629,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk6F_set_visible,
atk70_record_last_used_ability,
atk71_buffer_move_to_learn,
- atk72_jump_if_can_run_frombattle,
+ atk72_jump_if_run_attempt_success,
atk73_hp_thresholds,
atk74_hp_thresholds2,
atk75_item_effect_on_opponent,
@@ -762,8 +761,8 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atkF3_nickname_caught_poke,
atkF4_subattackerhpbydmg,
atkF5_removeattackerstatus1,
- atkF6_802BF48,
- atkF7_802BF54,
+ atkF6_action_finished,
+ atkF7_turn_finished,
atkF8_trainer_slide_back
};
@@ -1098,9 +1097,9 @@ static void atk00_attackcanceler(void)
{
s32 i;
- if (gBattleOutcome)
+ if (gBattleOutcome != 0)
{
- gFightStateTracker = 0xC;
+ gCurrentActionFuncId = ACTION_FINISHED;
return;
}
if (gBattleMons[gBankAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
@@ -1152,11 +1151,11 @@ static void atk00_attackcanceler(void)
for (i = 0; i < gNoOfAllBanks; i++)
{
- if ((gProtectStructs[gTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
+ if ((gProtectStructs[gBanksByTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
{
- PressurePPLose(gBankAttacker, gTurnOrder[i], MOVE_SNATCH);
- gProtectStructs[gTurnOrder[i]].stealMove = 0;
- gBattleScripting.bank = gTurnOrder[i];
+ PressurePPLose(gBankAttacker, gBanksByTurnOrder[i], MOVE_SNATCH);
+ gProtectStructs[gBanksByTurnOrder[i]].stealMove = 0;
+ gBattleScripting.bank = gBanksByTurnOrder[i];
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SnatchedMove;
return;
@@ -1601,7 +1600,7 @@ static void atk06_typecalc(void)
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
- gProtectStructs[gBankAttacker].notEffective = 1;
+ gProtectStructs[gBankAttacker].targetNotAffected = 1;
gBattlescriptCurrInstr++;
}
@@ -1640,14 +1639,14 @@ static void CheckWonderGuardAndLevitate(void)
if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 0)
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
- gProtectStructs[gBankAttacker].notEffective = 1;
+ gProtectStructs[gBankAttacker].targetNotAffected = 1;
}
if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 &&
gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 &&
gTypeEffectiveness[i + 2] == TYPE_MUL_NO_EFFECT)
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
- gProtectStructs[gBankAttacker].notEffective = 1;
+ gProtectStructs[gBankAttacker].targetNotAffected = 1;
}
// check super effective
@@ -2379,7 +2378,7 @@ u8 BankGetTurnOrder(u8 bank)
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
{
- if (gTurnOrder[i] == bank)
+ if (gBanksByTurnOrder[i] == bank)
break;
}
return i;
@@ -2737,7 +2736,7 @@ void SetMoveEffect(bool8 primary, u8 certain)
}
else
{
- if (BankGetTurnOrder(gEffectBank) > gCurrentMoveTurn)
+ if (BankGetTurnOrder(gEffectBank) > gCurrentTurnActionNumber)
gBattleMons[gEffectBank].status2 |= sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]];
gBattlescriptCurrInstr++;
}
@@ -3209,7 +3208,7 @@ static void atk19_faint_pokemon(void)
&& gBattleMons[gBankAttacker].hp != 0
&& gCurrentMove != MOVE_STRUGGLE)
{
- u8 moveIndex = *(gBattleStruct->chosenMovesIds + gBankAttacker);
+ u8 moveIndex = *(gBattleStruct->chosenMovePositions + gBankAttacker);
gBattleMons[gBankAttacker].pp[moveIndex] = 0;
BattleScriptPush(gBattlescriptCurrInstr);
@@ -3252,7 +3251,7 @@ static void atk1B_faint_effects_clear(void)
MarkBufferBankForExecution(gActiveBank);
}
- UndoEffectsAfterFainting(); // Effects like attractions, trapping, etc.
+ FaintClearSetData(); // Effects like attractions, trapping, etc.
gBattlescriptCurrInstr += 2;
}
}
@@ -4422,13 +4421,13 @@ static void atk3D_end(void)
gBattleMoveFlags = 0;
gActiveBank = 0;
- gFightStateTracker = 0xB;
+ gCurrentActionFuncId = 0xB;
}
static void atk3E_end2(void)
{
gActiveBank = 0;
- gFightStateTracker = 0xB;
+ gCurrentActionFuncId = 0xB;
}
static void atk3F_end3(void) // pops the main function stack
@@ -4463,9 +4462,9 @@ static void atk43_jumpifabilitypresent(void)
gBattlescriptCurrInstr += 6;
}
-static void atk44(void)
+static void atk44_end_selection_script(void)
{
- *(gBankAttacker + gBattleStruct->field_54) = 1;
+ *(gBankAttacker + gBattleStruct->selectionScriptFinished) = TRUE;
}
static void atk45_playanimation(void)
@@ -5067,7 +5066,7 @@ static void atk49_moveend(void)
case 9: // make attacker sprite visible
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT
|| !(gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE))
- || HasMoveFailed(gBankAttacker))
+ || WasUnableToUseMove(gBankAttacker))
{
gActiveBank = gBankAttacker;
EmitSpriteInvisibility(0, FALSE);
@@ -5298,7 +5297,7 @@ static void atk4A_typecalc2(void)
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
- gProtectStructs[gBankAttacker].notEffective = 1;
+ gProtectStructs[gBankAttacker].targetNotAffected = 1;
gBattlescriptCurrInstr++;
}
@@ -5367,7 +5366,7 @@ static void atk4D_switch_data_update(void)
gBattleMons[gActiveBank].status2 = oldData.status2;
}
- SwitchInClearStructs();
+ SwitchInClearSetData();
if (gBattleTypeFlags & BATTLE_TYPE_PALACE && gBattleMons[gActiveBank].maxHP / 2 >= gBattleMons[gActiveBank].hp
&& gBattleMons[gActiveBank].hp != 0 && !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP))
@@ -5904,15 +5903,15 @@ static void atk51_switch_handle_order(void)
gBattleCommunication[0] = gBattleBufferB[gActiveBank][1];
*(gBattleStruct->field_5C + gActiveBank) = gBattleBufferB[gActiveBank][1];
- if ((gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_LINK)) == (BATTLE_TYPE_MULTI | BATTLE_TYPE_LINK))
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) &= 0xF;
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0);
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 1) = gBattleBufferB[gActiveBank][3];
- *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 0) &= (0xF0);
- *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4;
- *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBank][3];
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) &= (0xF0);
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4;
+ *((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBank][3];
}
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
@@ -5984,8 +5983,8 @@ static void atk52_switch_in_effects(void)
for (i = 0; i < gNoOfAllBanks; i++)
{
- if (gTurnOrder[i] == gActiveBank)
- gUnknown_0202407A[i] = 0xC;
+ if (gBanksByTurnOrder[i] == gActiveBank)
+ gActionsByTurnOrder[i] = ACTION_CANCEL_PARTNER;
}
for (i = 0; i < gNoOfAllBanks; i++)
@@ -6412,7 +6411,7 @@ static void atk60_increment_gamestat(void)
gBattlescriptCurrInstr += 2;
}
-static void atk61_8025BA4(void)
+static void atk61_draw_party_status_summary(void)
{
s32 i;
struct Pokemon* party;
@@ -6443,7 +6442,7 @@ static void atk61_8025BA4(void)
}
}
- EmitCmd48(0, hpStatuses, 1);
+ EmitDrawPartyStatusSummary(0, hpStatuses, 1);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
@@ -6570,7 +6569,7 @@ static void atk68_80246A0(void)
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
- gUnknown_0202407A[i] = 0xC;
+ gActionsByTurnOrder[i] = ACTION_CANCEL_PARTNER;
gBattlescriptCurrInstr++;
}
@@ -6957,9 +6956,9 @@ static void atk71_buffer_move_to_learn(void)
gBattlescriptCurrInstr++;
}
-static void atk72_jump_if_can_run_frombattle(void)
+static void atk72_jump_if_run_attempt_success(void)
{
- if (CanRunFromBattle(gBank1))
+ if (TryRunFromBattle(gBank1))
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
@@ -7046,7 +7045,7 @@ static void atk76_various(void)
else
gBankTarget = gActiveBank;
break;
- case 2:
+ case VARIOUS_CAN_RUN_FROM_BATTLE:
gBattleCommunication[0] = IsRunningFromBattleImpossible();
break;
case VARIOUS_GET_MOVE_TARGET:
@@ -7197,7 +7196,7 @@ static void atk76_various(void)
gBattleOutcome = BATTLE_OPPONENT_TELEPORTED;
break;
case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC:
- EmitPlaySound(0, 0x19C, 1);
+ EmitPlaySound(0, BGM_KACHI1, 1);
MarkBufferBankForExecution(gActiveBank);
break;
}
@@ -7213,7 +7212,7 @@ static void atk77_set_protect_like(void) // protect and endure
if (lastMove != MOVE_PROTECT && lastMove != MOVE_DETECT && lastMove != MOVE_ENDURE)
gDisableStructs[gBankAttacker].protectUses = 0;
- if (gCurrentMoveTurn == (gNoOfAllBanks - 1))
+ if (gCurrentTurnActionNumber == (gNoOfAllBanks - 1))
notLastTurn = FALSE;
if (sProtectSuccessRates[gDisableStructs[gBankAttacker].protectUses] >= Random() && notLastTurn)
@@ -9519,19 +9518,19 @@ static void atkB3_rolloutdamagecalculation(void)
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) // first hit
{
- gDisableStructs[gBankAttacker].rolloutTimer1 = 5;
- gDisableStructs[gBankAttacker].rolloutTimer2 = 5;
+ gDisableStructs[gBankAttacker].rolloutCounter1 = 5;
+ gDisableStructs[gBankAttacker].rolloutCounter2 = 5;
gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gBankAttacker] = gCurrentMove;
}
- if (--gDisableStructs[gBankAttacker].rolloutTimer1 == 0) // last hit
+ if (--gDisableStructs[gBankAttacker].rolloutCounter1 == 0) // last hit
{
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
}
gDynamicBasePower = gBattleMoves[gCurrentMove].power;
- for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutTimer1); i++)
+ for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutCounter1); i++)
gDynamicBasePower *= 2;
if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL)
@@ -9711,12 +9710,12 @@ static void atkBA_jumpifnopursuitswitchdmg(void)
for (i = 0; i < gNoOfAllBanks; i++)
{
- if (gTurnOrder[i] == gBankTarget)
- gUnknown_0202407A[i] = 11;
+ if (gBanksByTurnOrder[i] == gBankTarget)
+ gActionsByTurnOrder[i] = 11;
}
gCurrentMove = MOVE_PURSUIT;
- gCurrMovePos = gUnknown_020241E9 = *(gBattleStruct->chosenMovesIds + gBankTarget);
+ gCurrMovePos = gUnknown_020241E9 = *(gBattleStruct->chosenMovePositions + gBankTarget);
gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1;
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
@@ -10632,7 +10631,7 @@ static void atkDF_setmagiccoat(void)
{
gBankTarget = gBankAttacker;
gSpecialStatuses[gBankAttacker].flag20 = 1;
- if (gCurrentMoveTurn == gNoOfAllBanks - 1) // moves last turn
+ if (gCurrentTurnActionNumber == gNoOfAllBanks - 1) // moves last turn
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
@@ -10646,7 +10645,7 @@ static void atkDF_setmagiccoat(void)
static void atkE0_setstealstatchange(void) // snatch
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
- if (gCurrentMoveTurn == gNoOfAllBanks - 1) // moves last turn
+ if (gCurrentTurnActionNumber == gNoOfAllBanks - 1) // moves last turn
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
@@ -10943,7 +10942,7 @@ static void atkEC_pursuit_sth(void)
&& gActionForBanks[gActiveBank] == 0
&& gChosenMovesByBanks[gActiveBank] == MOVE_PURSUIT)
{
- gUnknown_0202407A[gActiveBank] = 11;
+ gActionsByTurnOrder[gActiveBank] = 11;
gCurrentMove = MOVE_PURSUIT;
gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1;
@@ -11217,8 +11216,8 @@ static void atkF2_display_dex_info(void)
}
break;
case 3:
- c2_berry_program_update_menu();
- sub_8035AA4();
+ sub_80356D0();
+ LoadBattleTextboxAndBackground();
gBattle_BG3_X = 0x100;
gBattleCommunication[0]++;
break;
@@ -11394,15 +11393,15 @@ static void atkF5_removeattackerstatus1(void)
gBattlescriptCurrInstr++;
}
-static void atkF6_802BF48(void)
+static void atkF6_action_finished(void)
{
- gFightStateTracker = 0xC;
+ gCurrentActionFuncId = ACTION_FINISHED;
}
-static void atkF7_802BF54(void)
+static void atkF7_turn_finished(void)
{
- gFightStateTracker = 0xC;
- gCurrentMoveTurn = gNoOfAllBanks;
+ gCurrentActionFuncId = ACTION_FINISHED;
+ gCurrentTurnActionNumber = gNoOfAllBanks;
}
static void atkF8_trainer_slide_back(void)
diff --git a/src/battle_3.c b/src/battle_util.c
index e42d9317d..c6762dd99 100644
--- a/src/battle_3.c
+++ b/src/battle_util.c
@@ -17,9 +17,10 @@
#include "battle_controllers.h"
#include "event_data.h"
#include "calculate_base_damage.h"
+#include "link.h"
extern const u8* gBattlescriptCurrInstr;
-extern const u8* gUnknown_02024220[BATTLE_BANKS_COUNT];
+extern const u8* gBattlescriptPtrsForSelection[BATTLE_BANKS_COUNT];
extern const u8* gUnknown_02024230[BATTLE_BANKS_COUNT];
extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
extern u8 gActiveBank;
@@ -32,8 +33,8 @@ extern u8 gBankAttacker;
extern u8 gBankTarget;
extern u8 gAbsentBankFlags;
extern u16 gBattleWeather;
-extern u8 gTurnOrder[BATTLE_BANKS_COUNT];
-extern u16 gSideAffecting[];
+extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT];
+extern u16 gSideAffecting[2];
extern u8 gBattleCommunication[];
extern void (*gBattleMainFunc)(void);
extern s32 gBattleMoveDamage;
@@ -45,16 +46,17 @@ extern u32 gHitMarker;
extern u8 gEffectBank;
extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
extern u8 gBank1;
-extern u16 gChosenMovesByBanks[];
+extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
extern u8 gBattleMoveFlags;
extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
extern u8 gLastUsedAbility;
-extern u8 gFightStateTracker;
+extern u8 gCurrentActionFuncId;
extern u32 gBattleExecBuffer;
extern u16 gRandomMove;
extern u8 gCurrMovePos;
extern u8 gUnknown_020241E9;
+extern u8 gSentPokesToOpponent[2];
extern const struct BattleMove gBattleMoves[];
@@ -169,24 +171,278 @@ extern const u8 gUnknown_082DB6A5[]; //disobedient, uses a random move
extern const u8 gUnknown_082DB6D9[]; //disobedient, went to sleep
extern const u8 gUnknown_082DB6F0[]; //disobedient, hits itself
-extern const u8 gStatusConditionString_PoisonJpn[];
-extern const u8 gStatusConditionString_SleepJpn[];
-extern const u8 gStatusConditionString_ParalysisJpn[];
-extern const u8 gStatusConditionString_BurnJpn[];
-extern const u8 gStatusConditionString_IceJpn[];
-extern const u8 gStatusConditionString_ConfusionJpn[];
-extern const u8 gStatusConditionString_LoveJpn[];
-extern const u16 gSoundMovesTable[];
-
-extern u8 b_first_side(u8, u8, u8);
-extern void sub_803CEDC(u8, u8);
-extern void BattleTurnPassed(void);
-extern void sub_803F9EC();
-extern bool8 sub_80423F4(u8 bank, u8, u8);
extern u8 weather_get_current(void);
-extern void sub_803E08C(void);
-extern void bc_move_exec_returning(void);
-extern s8 GetFlavourRelationByPersonality(u32 personality, u8 flavor);
+
+// rom const data
+static const u16 sSoundMovesTable[] =
+{
+ MOVE_GROWL, MOVE_ROAR, MOVE_SING, MOVE_SUPERSONIC, MOVE_SCREECH, MOVE_SNORE,
+ MOVE_UPROAR, MOVE_METAL_SOUND, MOVE_GRASS_WHISTLE, MOVE_HYPER_VOICE, 0xFFFF
+};
+
+u8 GetBattleBank(u8 caseId)
+{
+ u8 ret = 0;
+ switch (caseId)
+ {
+ case BS_GET_TARGET:
+ ret = gBankTarget;
+ break;
+ case BS_GET_ATTACKER:
+ ret = gBankAttacker;
+ break;
+ case BS_GET_EFFECT_BANK:
+ ret = gEffectBank;
+ break;
+ case 7:
+ ret = 0;
+ break;
+ case BS_GET_SCRIPTING_BANK:
+ ret = gBattleScripting.bank;
+ break;
+ case 3:
+ ret = gBank1;
+ break;
+ case 5:
+ ret = gBank1;
+ break;
+ case 4:
+ case 6:
+ case 8:
+ case 9:
+ case BS_GET_PLAYER1:
+ ret = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ break;
+ case BS_GET_OPPONENT1:
+ ret = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ break;
+ case BS_GET_PLAYER2:
+ ret = GetBankByIdentity(IDENTITY_PLAYER_MON2);
+ break;
+ case BS_GET_OPPONENT2:
+ ret = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
+ break;
+ }
+ return ret;
+}
+
+void PressurePPLose(u8 bankDef, u8 bankAtk, u16 move)
+{
+ s32 i;
+
+ if (gBattleMons[bankDef].ability != ABILITY_PRESSURE)
+ return;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[bankAtk].moves[i] == move)
+ break;
+ }
+
+ if (i == 4) // mons don't share any moves
+ return;
+
+ if (gBattleMons[bankAtk].pp[i] != 0)
+ gBattleMons[bankAtk].pp[i]--;
+
+ if (!(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[bankAtk].unk18_b & gBitTable[i]))
+ {
+ gActiveBank = bankAtk;
+ EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBank].pp[i]);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+}
+
+void PressurePPLoseOnUsingImprision(u8 bankAtk)
+{
+ s32 i, j;
+ s32 imprisionPos = 4;
+ u8 atkSide = GetBankSide(bankAtk);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (atkSide != GetBankSide(i) && gBattleMons[i].ability == ABILITY_PRESSURE)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (gBattleMons[bankAtk].moves[j] == MOVE_IMPRISON)
+ break;
+ }
+ if (j != 4)
+ {
+ imprisionPos = j;
+ if (gBattleMons[bankAtk].pp[j] != 0)
+ gBattleMons[bankAtk].pp[j]--;
+ }
+ }
+ }
+
+ if (imprisionPos != 4
+ && !(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[bankAtk].unk18_b & gBitTable[imprisionPos]))
+ {
+ gActiveBank = bankAtk;
+ EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + imprisionPos, 0, 1, &gBattleMons[gActiveBank].pp[imprisionPos]);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+}
+
+void PressurePPLoseOnUsingPerishSong(u8 bankAtk)
+{
+ s32 i, j;
+ s32 perishSongPos = 4;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ABILITY_PRESSURE && i != bankAtk)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (gBattleMons[bankAtk].moves[j] == MOVE_PERISH_SONG)
+ break;
+ }
+ if (j != 4)
+ {
+ perishSongPos = j;
+ if (gBattleMons[bankAtk].pp[j] != 0)
+ gBattleMons[bankAtk].pp[j]--;
+ }
+ }
+ }
+
+ if (perishSongPos != 4
+ && !(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[bankAtk].unk18_b & gBitTable[perishSongPos]))
+ {
+ gActiveBank = bankAtk;
+ EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + perishSongPos, 0, 1, &gBattleMons[gActiveBank].pp[perishSongPos]);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+}
+
+void MarkAllBufferBanksForExecution(void) // unused
+{
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ gBattleExecBuffer |= gBitTable[i] << 0x1C;
+ }
+ else
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ gBattleExecBuffer |= gBitTable[i];
+ }
+}
+
+void MarkBufferBankForExecution(u8 bank)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleExecBuffer |= gBitTable[bank] << 0x1C;
+ }
+ else
+ {
+ gBattleExecBuffer |= gBitTable[bank];
+ }
+}
+
+void sub_803F850(u8 arg0)
+{
+ s32 i;
+
+ for (i = 0; i < sub_8009FCC(); i++)
+ gBattleExecBuffer |= gBitTable[arg0] << (i << 2);
+
+ gBattleExecBuffer &= ~(0x10000000 << arg0);
+}
+
+void CancelMultiTurnMoves(u8 bank)
+{
+ gBattleMons[bank].status2 &= ~(STATUS2_MULTIPLETURNS);
+ gBattleMons[bank].status2 &= ~(STATUS2_LOCK_CONFUSE);
+ gBattleMons[bank].status2 &= ~(STATUS2_UPROAR);
+ gBattleMons[bank].status2 &= ~(STATUS2_BIDE);
+
+ gStatuses3[bank] &= ~(STATUS3_SEMI_INVULNERABLE);
+
+ gDisableStructs[bank].rolloutCounter1 = 0;
+ gDisableStructs[bank].furyCutterCounter = 0;
+}
+
+bool8 WasUnableToUseMove(u8 bank)
+{
+ if (gProtectStructs[bank].prlzImmobility
+ || gProtectStructs[bank].targetNotAffected
+ || gProtectStructs[bank].usedImprisionedMove
+ || gProtectStructs[bank].loveImmobility
+ || gProtectStructs[bank].usedDisabledMove
+ || gProtectStructs[bank].usedTauntedMove
+ || gProtectStructs[bank].flag2Unknown
+ || gProtectStructs[bank].flinchImmobility
+ || gProtectStructs[bank].confusionSelfDmg)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void PrepareStringBattle(u16 stringId, u8 bank)
+{
+ gActiveBank = bank;
+ EmitPrintString(0, stringId);
+ MarkBufferBankForExecution(gActiveBank);
+}
+
+void ResetSentPokesToOpponentValue(void)
+{
+ s32 i;
+ u32 bits = 0;
+
+ gSentPokesToOpponent[0] = 0;
+ gSentPokesToOpponent[1] = 0;
+
+ for (i = 0; i < gNoOfAllBanks; i += 2)
+ bits |= gBitTable[gBattlePartyID[i]];
+
+ for (i = 1; i < gNoOfAllBanks; i += 2)
+ gSentPokesToOpponent[(i & BIT_MON) >> 1] = bits;
+}
+
+void sub_803F9EC(u8 bank)
+{
+ s32 i = 0;
+ u32 bits = 0;
+
+ if (GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ u8 id = ((bank & BIT_MON) >> 1);
+ gSentPokesToOpponent[id] = 0;
+
+ for (i = 0; i < gNoOfAllBanks; i += 2)
+ {
+ if (!(gAbsentBankFlags & gBitTable[i]))
+ bits |= gBitTable[gBattlePartyID[i]];
+ }
+
+ gSentPokesToOpponent[id] = bits;
+ }
+}
+
+void sub_803FA70(u8 bank)
+{
+ if (GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ sub_803F9EC(bank);
+ }
+ else
+ {
+ s32 i;
+ for (i = 1; i < gNoOfAllBanks; i++)
+ gSentPokesToOpponent[(i & BIT_MON) >> 1] |= gBitTable[gBattlePartyID[bank]];
+ }
+}
void BattleScriptPush(const u8* bsPtr)
{
@@ -203,7 +459,7 @@ void BattleScriptPop(void)
gBattlescriptCurrInstr = BATTLESCRIPTS_STACK->ptr[--BATTLESCRIPTS_STACK->size];
}
-u8 sub_803FB4C(void) // msg, can't select a move
+u8 TrySetCantSelectMoveBattleScript(void)
{
u8 limitations = 0;
u16 move = gBattleMons[gActiveBank].moves[gBattleBufferB[gActiveBank][2]];
@@ -221,7 +477,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DAE1F;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DAE1F;
limitations = 1;
}
}
@@ -236,7 +492,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DB089;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB089;
limitations++;
}
}
@@ -251,7 +507,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DB0A0;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB0A0;
limitations++;
}
}
@@ -266,7 +522,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DB181;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB181;
limitations++;
}
}
@@ -288,7 +544,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DB812;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB812;
limitations++;
}
}
@@ -301,7 +557,7 @@ u8 sub_803FB4C(void) // msg, can't select a move
}
else
{
- gUnknown_02024220[gActiveBank] = gUnknown_082DB076;
+ gBattlescriptPtrsForSelection[gActiveBank] = gUnknown_082DB076;
limitations++;
}
}
@@ -352,7 +608,7 @@ bool8 AreAllMovesUnusable(void)
if (unusable == 0xF) // all moves are unusable
{
gProtectStructs[gActiveBank].onlyStruggle = 1;
- gUnknown_02024220[gActiveBank] = BattleScript_NoMovesLeft;
+ gBattlescriptPtrsForSelection[gActiveBank] = BattleScript_NoMovesLeft;
}
else
{
@@ -407,15 +663,15 @@ u8 UpdateTurnCounters(void)
case 0:
for (i = 0; i < gNoOfAllBanks; i++)
{
- gTurnOrder[i] = i;
+ gBanksByTurnOrder[i] = i;
}
for (i = 0; i < gNoOfAllBanks - 1; i++)
{
s32 j;
for (j = i + 1; j < gNoOfAllBanks; j++)
{
- if (b_first_side(gTurnOrder[i], gTurnOrder[j], 0))
- sub_803CEDC(i, j);
+ if (GetWhoStrikesFirst(gBanksByTurnOrder[i], gBanksByTurnOrder[j], 0))
+ SwapTurnOrder(i, j);
}
}
@@ -540,7 +796,7 @@ u8 UpdateTurnCounters(void)
case 5:
while (gBattleStruct->turnSideTracker < gNoOfAllBanks)
{
- gActiveBank = gTurnOrder[gBattleStruct->turnSideTracker];
+ gActiveBank = gBanksByTurnOrder[gBattleStruct->turnSideTracker];
if (gWishFutureKnock.wishCounter[gActiveBank] != 0
&& --gWishFutureKnock.wishCounter[gActiveBank] == 0
&& gBattleMons[gActiveBank].hp != 0)
@@ -652,7 +908,7 @@ u8 TurnBasedEffects(void)
gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20);
while (gBattleStruct->turnEffectsBank < gNoOfAllBanks && gBattleStruct->turnEffectsTracker <= TURNBASED_MAX_CASE)
{
- gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->turnEffectsBank];
+ gActiveBank = gBankAttacker = gBanksByTurnOrder[gBattleStruct->turnEffectsBank];
if (gAbsentBankFlags & gBitTable[gActiveBank])
{
gBattleStruct->turnEffectsBank++;
@@ -833,7 +1089,7 @@ u8 TurnBasedEffects(void)
{
gBankAttacker = gActiveBank;
gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down
- if (HasMoveFailed(gActiveBank))
+ if (WasUnableToUseMove(gActiveBank))
{
CancelMultiTurnMoves(gActiveBank);
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
@@ -859,7 +1115,7 @@ u8 TurnBasedEffects(void)
if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
{
gBattleMons[gActiveBank].status2 -= 0x400;
- if (HasMoveFailed(gActiveBank))
+ if (WasUnableToUseMove(gActiveBank))
CancelMultiTurnMoves(gActiveBank);
else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
&& (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS))
@@ -1021,7 +1277,7 @@ bool8 sub_8041364(void)
case 1:
while (gBattleStruct->field_1A1 < gNoOfAllBanks)
{
- gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->field_1A1];
+ gActiveBank = gBankAttacker = gBanksByTurnOrder[gBattleStruct->field_1A1];
if (gAbsentBankFlags & gBitTable[gActiveBank])
{
gBattleStruct->field_1A1++;
@@ -1130,7 +1386,7 @@ bool8 sub_8041728(void)
case 4:
do
{
- gBank1 = gBankTarget = gBattleStruct->field_4E; //or should banks be switched?
+ gBank1 = gBankTarget = gBattleStruct->field_4E;
if (gBattleMons[gBattleStruct->field_4E].hp == 0
&& !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E]))
{
@@ -1159,7 +1415,7 @@ bool8 sub_8041728(void)
return FALSE;
}
-void b_clear_atk_up_if_hit_flag_unless_enraged(void)
+void TryClearRageStatuses(void)
{
int i;
for (i = 0; i < gNoOfAllBanks; i++)
@@ -1667,7 +1923,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg)
gBankAttacker = bank;
switch (gLastUsedAbility)
{
- case 0xFF: //weather from overworld
+ case ABILITYEFFECT_SWITCH_IN_WEATHER:
//_08042A86
switch (weather_get_current())
{
@@ -1850,12 +2106,12 @@ u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg)
//_08042EF8
if (gLastUsedAbility == ABILITY_SOUNDPROOF)
{
- for (i = 0; gSoundMovesTable[i] != 0xFFFF; i++)
+ for (i = 0; sSoundMovesTable[i] != 0xFFFF; i++)
{
- if (gSoundMovesTable[i] == move)
+ if (sSoundMovesTable[i] == move)
break;
}
- if (gSoundMovesTable[i] != 0xFFFF)
+ if (sSoundMovesTable[i] != 0xFFFF)
{
if (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
@@ -3156,7 +3412,7 @@ _08042EF8:\n\
bl _0804441E\n\
_08042F02:\n\
movs r4, 0\n\
- ldr r0, =gSoundMovesTable\n\
+ ldr r0, =sSoundMovesTable\n\
ldrh r2, [r0]\n\
ldr r3, =0x0000ffff\n\
adds r1, r0, 0\n\
@@ -5444,8 +5700,8 @@ void BattleScriptExecute(const u8* BS_ptr)
{
gBattlescriptCurrInstr = BS_ptr;
BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size++] = gBattleMainFunc;
- gBattleMainFunc = bc_move_exec_returning;
- gFightStateTracker = 0;
+ gBattleMainFunc = RunBattleScriptCommands_PopCallbacksStack;
+ gCurrentActionFuncId = 0;
}
void BattleScriptPushCursorAndCallback(const u8* BS_ptr)
@@ -5453,7 +5709,7 @@ void BattleScriptPushCursorAndCallback(const u8* BS_ptr)
BattleScriptPushCursor();
gBattlescriptCurrInstr = BS_ptr;
BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size++] = gBattleMainFunc;
- gBattleMainFunc = sub_803E08C;
+ gBattleMainFunc = RunBattleScriptCommands;
}
enum
@@ -5523,7 +5779,7 @@ u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn)
switch (caseID)
{
- case 0:
+ case ITEMEFFECT_ON_SWITCH_IN:
switch (bankHoldEffect)
{
case HOLD_EFFECT_DOUBLE_PRIZE:
@@ -6188,14 +6444,14 @@ u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn)
return effect;
}
-void sub_8045868(u8 bank)
+void ClearFuryCutterDestinyBondGrudge(u8 bank)
{
gDisableStructs[bank].furyCutterCounter = 0;
gBattleMons[bank].status2 &= ~(STATUS2_DESTINY_BOND);
gStatuses3[bank] &= ~(STATUS3_GRUDGE);
}
-void sub_80458B4(void)
+void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands
{
if (gBattleExecBuffer == 0)
gBattleScriptingCommandsTable[*gBattlescriptCurrInstr]();
diff --git a/src/berry_blender.c b/src/berry_blender.c
new file mode 100644
index 000000000..db50fe4c4
--- /dev/null
+++ b/src/berry_blender.c
@@ -0,0 +1,18 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA void *berry_blender_c_unused_03000de4;
+IWRAM_DATA s16 gUnknown_03000DE8[8];
+IWRAM_DATA s16 gUnknown_03000DF8[6];
+IWRAM_DATA s16 gUnknown_03000E04;
+IWRAM_DATA s16 gUnknown_03000E06;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c
new file mode 100755
index 000000000..83d32b56c
--- /dev/null
+++ b/src/braille_puzzles.c
@@ -0,0 +1,583 @@
+#include "global.h"
+#include "event_data.h"
+#include "songs.h"
+#include "sound.h"
+#include "script.h"
+#include "species.h"
+#include "task.h"
+#include "field_effect.h"
+#include "flags.h"
+
+extern void MapGridSetMetatileIdAt(s32 x, s32 y, u16 metatileId); // fieldmap
+extern void DrawWholeMapView(); // field_camera
+extern void SetCameraPanningCallback(void ( *callback)()); // field_camera
+extern void InstallCameraPanAheadCallback(void);
+extern void SetCameraPanning(s16 x, s16 y);
+extern u8 brm_get_pokemon_selection(void);
+extern void FieldEffectActiveListRemove(u8 id); // field_effect
+extern u8 oei_task_add(void);
+
+// why do this, GF?
+enum
+{
+ STRENGTH_PUZZLE,
+ FLY_PUZZLE
+};
+
+extern u8 gBraillePuzzleCallbackFlag;
+extern u8 gUnknown_085EFE74[][2];
+
+void SealedChamberShakingEffect(u8);
+void sub_8179860(void);
+void sub_8179944(void);
+
+bool8 ShouldDoBrailleDigEffect(void)
+{
+ if (!FlagGet(SYS_BRAILLE_DIG)
+ && (gSaveBlock1Ptr->location.mapGroup == 0x18
+ && gSaveBlock1Ptr->location.mapNum == 0x47))
+ {
+ if (gSaveBlock1Ptr->pos.x == 10 && gSaveBlock1Ptr->pos.y == 3)
+ return TRUE;
+ if (gSaveBlock1Ptr->pos.x == 9 && gSaveBlock1Ptr->pos.y == 3)
+ return TRUE;
+ if (gSaveBlock1Ptr->pos.x == 11 && gSaveBlock1Ptr->pos.y == 3)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void DoBrailleDigEffect(void)
+{
+ MapGridSetMetatileIdAt(16, 8, 554);
+ MapGridSetMetatileIdAt(17, 8, 555);
+ MapGridSetMetatileIdAt(18, 8, 556);
+ MapGridSetMetatileIdAt(16, 9, 3634);
+ MapGridSetMetatileIdAt(17, 9, 563);
+ MapGridSetMetatileIdAt(18, 9, 3636);
+ DrawWholeMapView();
+ PlaySE(SE_BAN);
+ FlagSet(SYS_BRAILLE_DIG);
+ ScriptContext2_Disable();
+}
+
+bool8 CheckRelicanthWailord(void)
+{
+ // Emerald change: why did they flip it?
+ // First comes Wailord
+ if (GetMonData(&gPlayerParty[0], MON_DATA_SPECIES2, 0) == SPECIES_WAILORD)
+ {
+ CalculatePlayerPartyCount();
+ // Last comes Relicanth
+ if (GetMonData(&gPlayerParty[gPlayerPartyCount - 1], MON_DATA_SPECIES2, 0) == SPECIES_RELICANTH)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// THEORY: this was caused by block commenting out all of the older R/S braille functions but leaving the call to it itself, which creates the nullsub.
+// the code is shown below to show what this might look like.
+void ShouldDoBrailleStrengthEffectOld(void)
+{
+ /*
+ if (!FlagGet(SYS_BRAILLE_STRENGTH) && (gSaveBlock1.location.mapGroup == MAP_GROUP_DESERT_RUINS && gSaveBlock1.location.mapNum == MAP_ID_DESERT_RUINS))
+ {
+ if (gSaveBlock1.pos.x == 10 && gSaveBlock1.pos.y == 23)
+ return TRUE;
+ else if (gSaveBlock1.pos.x == 9 && gSaveBlock1.pos.y == 23)
+ return TRUE;
+ else if (gSaveBlock1.pos.x == 11 && gSaveBlock1.pos.y == 23)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void DoBrailleStrengthEffect(void)
+{
+ FieldEffectActiveListRemove(FLDEFF_USE_STRENGTH);
+ MapGridSetMetatileIdAt(14, 26, 554);
+ MapGridSetMetatileIdAt(15, 26, 555);
+ MapGridSetMetatileIdAt(16, 26, 556);
+ MapGridSetMetatileIdAt(14, 27, 3634);
+ MapGridSetMetatileIdAt(15, 27, 563);
+ MapGridSetMetatileIdAt(16, 27, 3636);
+ DrawWholeMapView();
+ PlaySE(SE_BAN);
+ FlagSet(SYS_BRAILLE_STRENGTH);
+ ScriptContext2_Disable();
+}
+
+bool8 ShouldDoBrailleFlyEffect(void)
+{
+ if (!FlagGet(SYS_BRAILLE_FLY) && (gSaveBlock1.location.mapGroup == MAP_GROUP_ANCIENT_TOMB && gSaveBlock1.location.mapNum == MAP_ID_ANCIENT_TOMB))
+ {
+ if (gSaveBlock1.pos.x == 8 && gSaveBlock1.pos.y == 25)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void DoBrailleFlyEffect(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB);
+}
+
+bool8 FldEff_UseFlyAncientTomb(void)
+{
+ u8 taskId = oei_task_add();
+
+ gTasks[taskId].data[8] = (u32)UseFlyAncientTomb_Callback >> 16;
+ gTasks[taskId].data[9] = (u32)UseFlyAncientTomb_Callback;
+ return FALSE;
+}
+
+void UseFlyAncientTomb_Callback(void)
+{
+ FieldEffectActiveListRemove(FLDEFF_USE_FLY_ANCIENT_TOMB);
+ UseFlyAncientTomb_Finish();
+}
+
+void UseFlyAncientTomb_Finish(void)
+{
+ MapGridSetMetatileIdAt(14, 26, 554);
+ MapGridSetMetatileIdAt(15, 26, 555);
+ MapGridSetMetatileIdAt(16, 26, 556);
+ MapGridSetMetatileIdAt(14, 27, 3634);
+ MapGridSetMetatileIdAt(15, 27, 563);
+ MapGridSetMetatileIdAt(16, 27, 3636);
+ DrawWholeMapView();
+ PlaySE(SE_BAN);
+ FlagSet(SYS_BRAILLE_FLY);
+ ScriptContext2_Disable();
+}
+ */
+}
+
+void DoSealedChamberShakingEffect1(void)
+{
+ u8 taskId = CreateTask(SealedChamberShakingEffect, 9);
+
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[4] = 2;
+ gTasks[taskId].data[5] = 5;
+ gTasks[taskId].data[6] = 50;
+ SetCameraPanningCallback(0);
+}
+
+void DoSealedChamberShakingEffect2(void)
+{
+ u8 taskId = CreateTask(SealedChamberShakingEffect, 9);
+
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[4] = 3;
+ gTasks[taskId].data[5] = 5;
+ gTasks[taskId].data[6] = 2;
+ SetCameraPanningCallback(0);
+}
+
+void SealedChamberShakingEffect(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ task->data[1]++;
+
+ if (!(task->data[1] % task->data[5]))
+ {
+ task->data[1] = 0;
+ task->data[2]++;
+ task->data[4] = -task->data[4];
+ SetCameraPanning(0, task->data[4]);
+ if (task->data[2] == task->data[6])
+ {
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ InstallCameraPanAheadCallback();
+ }
+ }
+}
+
+// moved later in the function because it was rewritten.
+bool8 ShouldDoBrailleStrengthEffect(void)
+{
+ if (!FlagGet(SYS_BRAILLE_STRENGTH) && (gSaveBlock1Ptr->location.mapGroup == 0x18 && gSaveBlock1Ptr->location.mapNum == 0x06))
+ {
+ if (gSaveBlock1Ptr->pos.x == 6 && gSaveBlock1Ptr->pos.y == 23)
+ { gBraillePuzzleCallbackFlag = STRENGTH_PUZZLE; return TRUE; }
+ else if (gSaveBlock1Ptr->pos.x == 5 && gSaveBlock1Ptr->pos.y == 23)
+ { gBraillePuzzleCallbackFlag = STRENGTH_PUZZLE; return TRUE; }
+ else if (gSaveBlock1Ptr->pos.x == 7 && gSaveBlock1Ptr->pos.y == 23)
+ { gBraillePuzzleCallbackFlag = STRENGTH_PUZZLE; return TRUE; }
+ }
+
+ return FALSE;
+}
+
+void sub_8179834(void)
+{
+ gFieldEffectSpawnParams[0] = brm_get_pokemon_selection();
+ FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB);
+}
+
+void UseStrengthDesertRuins_Callback(void)
+{
+ FieldEffectActiveListRemove(FLDEFF_USE_FLY_ANCIENT_TOMB);
+ sub_8179860();
+}
+
+void sub_8179860(void)
+{
+ MapGridSetMetatileIdAt(14, 26, 554);
+ MapGridSetMetatileIdAt(15, 26, 555);
+ MapGridSetMetatileIdAt(16, 26, 556);
+ MapGridSetMetatileIdAt(14, 27, 3634);
+ MapGridSetMetatileIdAt(15, 27, 563);
+ MapGridSetMetatileIdAt(16, 27, 3636);
+ DrawWholeMapView();
+ PlaySE(SE_BAN);
+ FlagSet(SYS_BRAILLE_STRENGTH);
+ ScriptContext2_Disable();
+}
+
+bool8 ShouldDoBrailleFlyEffect(void)
+{
+ if (!FlagGet(SYS_BRAILLE_FLY) && (gSaveBlock1Ptr->location.mapGroup == 0x18 && gSaveBlock1Ptr->location.mapNum == 0x44))
+ {
+ if (gSaveBlock1Ptr->pos.x == 8 && gSaveBlock1Ptr->pos.y == 25)
+ { gBraillePuzzleCallbackFlag = FLY_PUZZLE; return TRUE; }
+ }
+ return FALSE;
+}
+
+void sub_8179918(void)
+{
+ gFieldEffectSpawnParams[0] = brm_get_pokemon_selection();
+ FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB);
+}
+
+void UseFlyAncientTomb_Callback(void)
+{
+ FieldEffectActiveListRemove(FLDEFF_USE_FLY_ANCIENT_TOMB);
+ sub_8179944();
+}
+
+void sub_8179944(void)
+{
+ MapGridSetMetatileIdAt(14, 26, 554);
+ MapGridSetMetatileIdAt(15, 26, 555);
+ MapGridSetMetatileIdAt(16, 26, 556);
+ MapGridSetMetatileIdAt(14, 27, 3634);
+ MapGridSetMetatileIdAt(15, 27, 563);
+ MapGridSetMetatileIdAt(16, 27, 3636);
+ DrawWholeMapView();
+ PlaySE(SE_BAN);
+ FlagSet(SYS_BRAILLE_FLY);
+ ScriptContext2_Disable();
+}
+
+// theory: another commented out DoBrailleWait and Task_BrailleWait.
+void DoBrailleWait(void)
+{
+ /*
+ if (!FlagGet(SYS_BRAILLE_WAIT))
+ CreateTask(Task_BrailleWait, 0x50);
+}
+
+void Task_BrailleWait(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ data[1] = 7200;
+ data[0] = 1;
+ break;
+ case 1:
+ if (BrailleWait_CheckButtonPress() != FALSE)
+ {
+ MenuZeroFillScreen();
+ PlaySE(SE_SELECT);
+ data[0] = 2;
+ }
+ else
+ {
+ data[1] = data[1] - 1;
+ if (data[1] == 0)
+ {
+ MenuZeroFillScreen();
+ data[0] = 3;
+ data[1] = 30;
+ }
+ }
+ break;
+ case 2:
+ if (BrailleWait_CheckButtonPress() == FALSE)
+ {
+ data[1] = data[1] - 1;
+ if (data[1] == 0)
+ data[0] = 4;
+ break;
+ }
+ sub_8064E2C();
+ DestroyTask(taskId);
+ ScriptContext2_Disable();
+ break;
+ case 3:
+ data[1] = data[1] - 1;
+ if (data[1] == 0)
+ data[0] = 4;
+ break;
+ case 4:
+ sub_8064E2C();
+ ScriptContext1_SetupScript(S_OpenRegiceChamber);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+bool32 BrailleWait_CheckButtonPress(void)
+{
+ u16 keyMask = A_BUTTON | B_BUTTON | START_BUTTON | SELECT_BUTTON | DPAD_ANY;
+
+ if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR)
+ keyMask |= L_BUTTON | R_BUTTON;
+ if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A)
+ keyMask |= L_BUTTON;
+
+ if (gMain.newKeys & keyMask)
+ return TRUE;
+ else
+ return FALSE;
+ */
+}
+
+// this used to be FldEff_UseFlyAncientTomb . why did GF merge the 2 functions?
+bool8 FldEff_UsePuzzleEffect(void)
+{
+ u8 taskId = oei_task_add();
+
+ if (gBraillePuzzleCallbackFlag == FLY_PUZZLE)
+ {
+ gTasks[taskId].data[8] = (u32)UseFlyAncientTomb_Callback >> 16;
+ gTasks[taskId].data[9] = (u32)UseFlyAncientTomb_Callback;
+ }
+ else
+ {
+ gTasks[taskId].data[8] = (u32)UseStrengthDesertRuins_Callback >> 16;
+ gTasks[taskId].data[9] = (u32)UseStrengthDesertRuins_Callback;
+ }
+ return FALSE;
+}
+
+// can't get this one to match due to the weird macro-like varsets with strange bitshifting.
+// to note: 0x10000 is loaded in, and its obviously supposed to be 1, but i cant get 0x80 << 9 to be loaded in without using it directly.
+// maybe there's some way of writing it that works?
+#ifdef NONMATCHING
+// ShouldDoBrailleRegicePuzzle
+bool8 ShouldDoBrailleRegicePuzzle(void)
+{
+ u8 i;
+
+ if (gSaveBlock1Ptr->location.mapGroup == 0x18 && gSaveBlock1Ptr->location.mapNum == 0x43)
+ {
+ // _08179A1A
+ if (FlagGet(SYS_BRAILLE_WAIT) != FALSE)
+ return FALSE;
+ if (FlagGet(2) == FALSE)
+ return FALSE;
+ if (FlagGet(3) == TRUE)
+ return FALSE;
+
+ for (i = 0; i < 36; i++)
+ {
+ if (gSaveBlock1Ptr->pos.x == gUnknown_085EFE74[i][0] && gSaveBlock1Ptr->pos.y == gUnknown_085EFE74[i][1])
+ {
+ if (i < 16)
+ VarSet(0x403B, (0x10000 << i | VarGet(0x403B) << 16) >> 16); // correct
+ else if (i < 32)
+ VarSet(0x403C, (0x10000 << (i - 16) | VarGet(0x403C) << 16) >> 16); // hmm?
+ else
+ VarSet(0x403D, (0x10000 << (i - 32) | VarGet(0x403D) << 16) >> 16); // hmm?
+
+ if (VarGet(0x403B) != 0xFFFF || VarGet(0x403C) != 0xFF || VarGet(0x403D) != 0xF)
+ return FALSE;
+
+ if (gSaveBlock1Ptr->pos.x == 8 && gSaveBlock1Ptr->pos.y == 21)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ }
+ }
+ // TODO: Find what flags 2 and 3 are.
+ FlagSet(3);
+ FlagReset(2);
+ return FALSE;
+}
+#else
+__attribute__((naked))
+bool8 ShouldDoBrailleRegicePuzzle(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r9\n\
+ mov r6, r8\n\
+ push {r6,r7}\n\
+ ldr r4, =gSaveBlock1Ptr\n\
+ ldr r0, [r4]\n\
+ ldrh r1, [r0, 0x4]\n\
+ ldr r0, =0x00004318\n\
+ cmp r1, r0\n\
+ beq _08179A1A\n\
+ b _08179B5A\n\
+_08179A1A:\n\
+ ldr r0, =0x000008b1\n\
+ bl FlagGet\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ beq _08179A28\n\
+ b _08179B5A\n\
+_08179A28:\n\
+ movs r0, 0x2\n\
+ bl FlagGet\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ bne _08179A36\n\
+ b _08179B5A\n\
+_08179A36:\n\
+ movs r0, 0x3\n\
+ bl FlagGet\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0x1\n\
+ bne _08179A58\n\
+ b _08179B5A\n\
+ .pool\n\
+_08179A54:\n\
+ movs r0, 0x1\n\
+ b _08179B5C\n\
+_08179A58:\n\
+ movs r5, 0\n\
+ mov r8, r4\n\
+ ldr r4, =gUnknown_085EFE74\n\
+ adds r0, r4, 0x1\n\
+ mov r12, r0\n\
+ ldr r6, =0x0000403b\n\
+ ldr r1, =0x0000403c\n\
+ mov r9, r1\n\
+_08179A68:\n\
+ lsls r0, r5, 1\n\
+ adds r1, r0, r4\n\
+ add r0, r12\n\
+ ldrb r3, [r0]\n\
+ mov r7, r8\n\
+ ldr r2, [r7]\n\
+ movs r7, 0\n\
+ ldrsh r0, [r2, r7]\n\
+ ldrb r1, [r1]\n\
+ cmp r0, r1\n\
+ bne _08179B44\n\
+ movs r1, 0x2\n\
+ ldrsh r0, [r2, r1]\n\
+ cmp r0, r3\n\
+ bne _08179B44\n\
+ cmp r5, 0xF\n\
+ bhi _08179AB0\n\
+ adds r0, r6, 0\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ movs r1, 0x80\n\
+ lsls r1, 9\n\
+ lsls r1, r5\n\
+ orrs r1, r0\n\
+ lsrs r1, 16\n\
+ adds r0, r6, 0\n\
+ bl VarSet\n\
+ b _08179AF0\n\
+ .pool\n\
+_08179AB0:\n\
+ cmp r5, 0x1F\n\
+ bhi _08179AD2\n\
+ mov r0, r9\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ adds r2, r5, 0\n\
+ subs r2, 0x10\n\
+ movs r1, 0x80\n\
+ lsls r1, 9\n\
+ lsls r1, r2\n\
+ orrs r1, r0\n\
+ lsrs r1, 16\n\
+ mov r0, r9\n\
+ bl VarSet\n\
+ b _08179AF0\n\
+_08179AD2:\n\
+ ldr r4, =0x0000403d\n\
+ adds r0, r4, 0\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ adds r2, r5, 0\n\
+ subs r2, 0x20\n\
+ movs r1, 0x80\n\
+ lsls r1, 9\n\
+ lsls r1, r2\n\
+ orrs r1, r0\n\
+ lsrs r1, 16\n\
+ adds r0, r4, 0\n\
+ bl VarSet\n\
+_08179AF0:\n\
+ ldr r0, =0x0000403b\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ lsrs r4, r0, 16\n\
+ ldr r0, =0x0000ffff\n\
+ cmp r4, r0\n\
+ bne _08179B5A\n\
+ ldr r0, =0x0000403c\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ cmp r0, r4\n\
+ bne _08179B5A\n\
+ ldr r0, =0x0000403d\n\
+ bl VarGet\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ cmp r0, 0xF\n\
+ bne _08179B5A\n\
+ ldr r0, =gSaveBlock1Ptr\n\
+ ldr r0, [r0]\n\
+ ldr r1, [r0]\n\
+ ldr r0, =0x00150008\n\
+ cmp r1, r0\n\
+ beq _08179A54\n\
+ b _08179B5A\n\
+ .pool\n\
+_08179B44:\n\
+ adds r0, r5, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ cmp r5, 0x23\n\
+ bls _08179A68\n\
+ movs r0, 0x3\n\
+ bl FlagSet\n\
+ movs r0, 0x2\n\
+ bl FlagReset\n\
+_08179B5A:\n\
+ movs r0, 0\n\
+_08179B5C:\n\
+ pop {r3,r4}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .syntax divided");
+}
+#endif
diff --git a/src/diploma.c b/src/diploma.c
new file mode 100755
index 000000000..f2cbcabb7
--- /dev/null
+++ b/src/diploma.c
@@ -0,0 +1,218 @@
+#include "global.h"
+#include "palette.h"
+#include "main.h"
+#include "gpu_regs.h"
+#include "unknown_task.h"
+#include "task.h"
+#include "malloc.h"
+#include "decompress.h"
+#include "bg.h"
+#include "window.h"
+#include "string_util.h"
+#include "text.h"
+
+extern void reset_temp_tile_data_buffers(void);
+extern int decompress_and_copy_tile_data_to_vram(u8 bg_id, void *src, int size, u16 offset, u8 mode);
+extern bool8 free_temp_tile_data_buffers_if_possible(void);
+extern void sub_80861E8(void); // rom4
+extern bool16 sub_80C0944(void);
+extern void AddTextPrinterParametrized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, struct TextColor *color, s8 speed, u8 *str);
+
+extern u16 gUnknown_0860F074[];
+
+extern u8 gText_DexNational[];
+extern u8 gText_DexHoenn[];
+extern u8 gText_PokedexDiploma[];
+
+static void MainCB2(void);
+static void Task_DiplomaFadeIn(u8);
+static void Task_DiplomaWaitForKeyPress(u8);
+static void Task_DiplomaFadeOut(u8);
+static void DisplayDiplomaText(void);
+static void InitDiplomaBg(void);
+static void InitDiplomaWindow(void);
+static void PrintDiplomaText(u8 *, u8, u8);
+
+EWRAM_DATA void **gDiplomaTilemapPtr = {NULL};
+
+static void VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static const u16 gDiplomaPalettes[][16] =
+{
+ INCBIN_U16("graphics/misc/diploma_national.gbapal"),
+ INCBIN_U16("graphics/misc/diploma_hoenn.gbapal"),
+};
+
+static const u8 gDiplomaTilemap[] = INCBIN_U8("graphics/misc/diploma_map.bin.lz");
+static const u8 gDiplomaTiles[] = INCBIN_U8("graphics/misc/diploma.4bpp.lz");
+
+void CB2_ShowDiploma(void)
+{
+ SetVBlankCallback(NULL);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG3CNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG2CNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG1CNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG0CNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, DISPCNT_MODE_0);
+ // why doesn't this one use the dma manager either?
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, 0, PLTT, PLTT_SIZE);
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ LoadPalette(gDiplomaPalettes, 0, 64);
+ gDiplomaTilemapPtr = malloc(0x1000);
+ InitDiplomaBg();
+ InitDiplomaWindow();
+ reset_temp_tile_data_buffers();
+ decompress_and_copy_tile_data_to_vram(1, &gDiplomaTiles, 0, 0, 0);
+ while (free_temp_tile_data_buffers_if_possible())
+ ;
+ LZDecompressWram(&gDiplomaTilemap, gDiplomaTilemapPtr);
+ CopyBgTilemapBufferToVram(1);
+ DisplayDiplomaText();
+ BlendPalettes(-1, 16, 0);
+ BeginNormalPaletteFade(-1, 0, 16, 0, 0);
+ EnableInterrupts(1);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(MainCB2);
+ CreateTask(Task_DiplomaFadeIn, 0);
+}
+
+static void MainCB2(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void Task_DiplomaFadeIn(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = Task_DiplomaWaitForKeyPress;
+}
+
+static void Task_DiplomaWaitForKeyPress(u8 taskId)
+{
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = Task_DiplomaFadeOut;
+ }
+}
+
+static void Task_DiplomaFadeOut(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ Free(gDiplomaTilemapPtr);
+ FreeAllWindowBuffers();
+ DestroyTask(taskId);
+ SetMainCallback2(sub_80861E8);
+ }
+}
+
+static void DisplayDiplomaText(void)
+{
+ if (sub_80C0944())
+ {
+ SetGpuReg(REG_OFFSET_BG1HOFS, DISPCNT_BG0_ON);
+ StringCopy(gStringVar1, gText_DexNational);
+ }
+ else
+ {
+ SetGpuReg(REG_OFFSET_BG1HOFS, DISPCNT_MODE_0);
+ StringCopy(gStringVar1, gText_DexHoenn);
+ }
+ StringExpandPlaceholders(gStringVar4, gText_PokedexDiploma);
+ PrintDiplomaText(gStringVar4, 0, 1);
+ PutWindowTilemap(0);
+ CopyWindowToVram(0, 3);
+}
+
+static const struct BgTemplate gDiplomaBgTemplates[2] =
+{
+ {
+ .bg = 0,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0,
+ },
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 6,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0,
+ },
+};
+
+static void InitDiplomaBg(void)
+{
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gDiplomaBgTemplates, 2);
+ SetBgTilemapBuffer(1, gDiplomaTilemapPtr);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ ShowBg(0);
+ ShowBg(1);
+ SetGpuReg(REG_OFFSET_BLDCNT, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, DISPCNT_MODE_0);
+ SetGpuReg(REG_OFFSET_BLDY, DISPCNT_MODE_0);
+}
+
+static const struct WindowTemplate gDiplomaWinTemplates[2] =
+{
+ {
+ .priority = 0,
+ .tilemapLeft = 5,
+ .tilemapTop = 2,
+ .width = 20,
+ .height = 16,
+ .paletteNum = 15,
+ .baseBlock = 1,
+ },
+ DUMMY_WIN_TEMPLATE,
+};
+
+static void InitDiplomaWindow(void)
+{
+ InitWindows(gDiplomaWinTemplates);
+ DeactivateAllTextPrinters();
+ LoadPalette(gUnknown_0860F074, 0xF0, 0x20);
+ FillWindowPixelBuffer(0, 0);
+ PutWindowTilemap(0);
+}
+
+static void PrintDiplomaText(u8 *text, u8 var1, u8 var2)
+{
+ struct TextColor color =
+ {
+ .fgColor = 0,
+ .bgColor = 2,
+ .shadowColor = 3,
+ };
+
+ AddTextPrinterParametrized2(0, 1, var1, var2, 0, 0, &color, -1, text);
+}
diff --git a/src/dma3_manager.c b/src/dma3_manager.c
index 7cce06c15..bb015c5cf 100644
--- a/src/dma3_manager.c
+++ b/src/dma3_manager.c
@@ -1,12 +1,23 @@
#include "global.h"
#include "dma3.h"
+IWRAM_DATA struct {
+ /* 0x00 */ const u8 *src;
+ /* 0x04 */ u8 *dest;
+ /* 0x08 */ u16 size;
+ /* 0x0A */ u16 mode;
+ /* 0x0C */ u32 value;
+} gDma3Requests[128];
+
+static bool8 gDma3ManagerLocked;
+static u8 gDma3RequestCursor;
+
void ClearDma3Requests(void)
{
int i;
gDma3ManagerLocked = TRUE;
- gDma3RequestCursor = FALSE;
+ gDma3RequestCursor = 0;
for(i = 0; i < (u8)ARRAY_COUNT(gDma3Requests); i++)
{
@@ -22,7 +33,6 @@ void ClearDma3Requests(void)
void ProcessDma3Requests(void)
{
// NOTE: the fillerA member of the DMA struct is actually u32 value;
- // NOTE: gUnknown_0300001C is just a pointer inside the gDma3Requests structure, not a true symbol; feel free to remove
u16 total_size;
if (gDma3ManagerLocked)
@@ -331,7 +341,7 @@ _08000DB2:\n\
mov r5, r12\n\
ldrb r0, [r5]\n\
lsls r0, 4\n\
- ldr r3, =gUnknown_0300001C\n\
+ ldr r3, =gDma3Requests + 0x0C\n\
adds r0, r3\n\
ldr r0, [r0]\n\
strh r0, [r1]\n\
@@ -347,7 +357,7 @@ _08000DB2:\n\
bhi _08000DB2\n\
ldrb r0, [r5]\n\
lsls r0, 4\n\
- ldr r5, =gUnknown_0300001C\n\
+ ldr r5, =gDma3Requests + 0x0C\n\
adds r0, r5\n\
ldr r0, [r0]\n\
strh r0, [r1]\n\
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
index 6d14e92f0..4e4c10090 100644
--- a/src/egg_hatch.c
+++ b/src/egg_hatch.c
@@ -64,8 +64,8 @@ extern void sub_806A068(u16, u8);
extern void fade_screen(u8, u8);
extern void overworld_free_bg_tilemaps(void);
extern void sub_80AF168(void);
-extern void init_uns_table_pokemon_copy(void);
-extern void sub_805F094(void);
+extern void AllocateMonSpritesGfx(void);
+extern void FreeMonSpritesGfx(void);
extern void remove_some_task(void);
extern void reset_temp_tile_data_buffers(void);
extern void c2_exit_to_overworld_2_switch(void);
@@ -439,7 +439,7 @@ static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc
u16 species = GetMonData(mon, MON_DATA_SPECIES);
u32 pid = GetMonData(mon, MON_DATA_PERSONALITY);
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
- gBattleSpritesGfx->sprites[(a0 * 2) + 1],
+ gMonSpritesGfxPtr->sprites[(a0 * 2) + 1],
species, pid);
LoadCompressedObjectPalette(sub_806E794(mon));
*speciesLoc = species;
@@ -488,7 +488,7 @@ static void CB2_EggHatch_0(void)
SetGpuReg(REG_OFFSET_DISPCNT, 0);
sEggHatchData = Alloc(sizeof(struct EggHatchData));
- init_uns_table_pokemon_copy();
+ AllocateMonSpritesGfx();
sEggHatchData->eggPartyID = gSpecialVar_0x8004;
sEggHatchData->eggShardVelocityID = 0;
@@ -570,7 +570,7 @@ static void CB2_EggHatch_0(void)
static void EggHatchSetMonNickname(void)
{
SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
- sub_805F094();
+ FreeMonSpritesGfx();
Free(sEggHatchData);
SetMainCallback2(c2_exit_to_overworld_2_switch);
}
@@ -691,7 +691,7 @@ static void CB2_EggHatch_1(void)
case 12:
if (!gPaletteFade.active)
{
- sub_805F094();
+ FreeMonSpritesGfx();
RemoveWindow(sEggHatchData->windowId);
UnsetBgTilemapBuffer(0);
UnsetBgTilemapBuffer(1);
diff --git a/src/field_camera.c b/src/field_camera.c
new file mode 100644
index 000000000..17ced6aa5
--- /dev/null
+++ b/src/field_camera.c
@@ -0,0 +1,28 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+struct FieldCameraUnknownStruct
+{
+ u8 unk0;
+ u8 unk1;
+ u8 unk2;
+ u8 unk3;
+ bool8 unk4;
+};
+
+// Static RAM declarations
+
+IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20;
+IWRAM_DATA s16 gUnknown_03000E28;
+IWRAM_DATA s16 gUnknown_03000E2A;
+IWRAM_DATA u8 gUnknown_03000E2C;
+IWRAM_DATA void (*gUnknown_03000E30)(void);
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/field_effect.c b/src/field_effect.c
new file mode 100644
index 000000000..628dc776a
--- /dev/null
+++ b/src/field_effect.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F58[32];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/field_screen.c b/src/field_screen.c
new file mode 100644
index 000000000..2d33d237f
--- /dev/null
+++ b/src/field_screen.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA u8 *gUnknown_03000F50;
+IWRAM_DATA u32 filler_03000f54;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/fldeff_cut.c b/src/fldeff_cut.c
new file mode 100644
index 000000000..9929dd6f9
--- /dev/null
+++ b/src/fldeff_cut.c
@@ -0,0 +1,19 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03001100;
+IWRAM_DATA u8 gUnknown_03001101;
+IWRAM_DATA u8 gUnknown_03001102;
+IWRAM_DATA u32 fldeff_cut_unused_03001104;
+IWRAM_DATA u8 gUnknown_03001108[25];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/link.c b/src/link.c
new file mode 100644
index 000000000..ae2cd1992
--- /dev/null
+++ b/src/link.c
@@ -0,0 +1,56 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+struct BlockTransfer
+{
+ u16 pos;
+ u16 size;
+ void *src;
+ bool8 active;
+ u8 multiplayerId;
+};
+
+struct LinkTestBGInfo
+{
+ u32 screenBaseBlock;
+ u32 paletteNum;
+ u32 dummy_8;
+ u32 dummy_C;
+};
+
+// Static RAM declarations
+
+IWRAM_DATA struct BlockTransfer gUnknown_03000D10;
+IWRAM_DATA u32 link_c_unused_03000d1c;
+IWRAM_DATA struct BlockTransfer gUnknown_03000D20[4];
+IWRAM_DATA u32 gUnknown_03000D50;
+IWRAM_DATA u32 gUnknown_03000D54;
+IWRAM_DATA u8 gUnknown_03000D58;
+IWRAM_DATA u32 gUnknown_03000D5C;
+IWRAM_DATA u32 gUnknown_03000D60;
+IWRAM_DATA u8 gUnknown_03000D64[4]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D68[4];
+IWRAM_DATA u8 gUnknown_03000D6C;
+IWRAM_DATA bool8 gUnknown_03000D6D;
+IWRAM_DATA u16 gUnknown_03000D6E;
+IWRAM_DATA u16 gUnknown_03000D70;
+IWRAM_DATA u8 gUnknown_03000D72;
+IWRAM_DATA u8 gUnknown_03000D73;
+IWRAM_DATA u8 gUnknown_03000D74[4]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D78[8]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D80[16];
+IWRAM_DATA u16 gUnknown_03000D90[8];
+IWRAM_DATA u32 gUnknown_03000DA0;
+IWRAM_DATA u32 gUnknown_03000DA4;
+IWRAM_DATA void *gUnknown_03000DA8;
+IWRAM_DATA void *gUnknown_03000DAC;
+IWRAM_DATA bool32 gUnknown_03000DB0;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/main.c b/src/main.c
index 5707e18af..665a4dd84 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,7 +77,7 @@ const IntrFunc gIntrTableTemplate[] =
#define INTR_COUNT ((int)(sizeof(gIntrTableTemplate)/sizeof(IntrFunc)))
-extern u16 gUnknown_03000000;
+static u16 gUnknown_03000000;
extern u16 gKeyRepeatStartDelay;
extern u8 gUnknown_030022B4;
diff --git a/src/main_menu.c b/src/main_menu.c
new file mode 100644
index 000000000..8608159c2
--- /dev/null
+++ b/src/main_menu.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000DD0;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/malloc.c b/src/malloc.c
index ccb2f7d20..1d64351c3 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -2,6 +2,7 @@
static void *sHeapStart;
static u32 sHeapSize;
+static u32 malloc_c_unused_0300000c; // needed to align dma3_manager.o(.bss)
#define MALLOC_SYSTEM_ID 0xA3A3
diff --git a/src/palette.c b/src/palette.c
index aa9a84e4c..d60efdbc5 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -1,5 +1,8 @@
#include "global.h"
+#include "blend_palette.h"
#include "palette.h"
+#include "decompress.h"
+#include "gpu_regs.h"
#include "task.h"
enum
@@ -28,7 +31,7 @@ struct PaletteStructTemplate
struct PaletteStruct
{
- struct PaletteStructTemplate *base;
+ const struct PaletteStructTemplate *base;
u32 ps_field_4_0:1;
u16 ps_field_4_1:1;
u32 baseDestOffset:9;
@@ -38,31 +41,6 @@ struct PaletteStruct
u8 ps_field_9;
};
-extern void LZDecompressWram(const void *src, void *dest);
-extern void SetGpuReg(u8 regOffset, u16 value);
-extern void sub_8149DFC(u8 a1);
-extern void sub_80A1670(u16 a1);
-extern void sub_80A2D54(u8 a1);
-extern void SetWordTaskArg(u8 taskId, u8 dataElem, u32 value);
-extern void _call_via_r1(u32 a1, void *a2);
-
-extern void BlendPalette(u16, u16, u8, u16);
-
-EWRAM_DATA u16 gPlttBufferUnfaded[0x200] = {0};
-EWRAM_DATA u16 gPlttBufferFaded[0x200] = {0};
-EWRAM_DATA struct PaletteStruct sPaletteStructs[0x10] = {0};
-EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
-EWRAM_DATA u32 gFiller_2037FE0 = 0;
-EWRAM_DATA u32 sPlttBufferTransferPending = 0;
-EWRAM_DATA u8 gPaletteDecompressionBuffer[0x400] = {0};
-
-extern struct PaletteStructTemplate gDummyPaletteStructTemplate;
-extern void *gUnknown_0852487C;
-extern u8 gUnknown_0852489C[];
-
-extern u16 gUnknown_03000F3C;
-extern void *gUnknown_03000F44;
-
static void unused_sub_80A1CDC(struct PaletteStruct *, u32 *);
static void unused_sub_80A1E40(struct PaletteStruct *, u32 *);
static void unused_sub_80A1F00(struct PaletteStruct *);
@@ -73,32 +51,29 @@ static u8 UpdateFastPaletteFade(void);
static u8 UpdateHardwarePaletteFade(void);
static void UpdateBlendRegisters(void);
static bool8 IsSoftwarePaletteFadeFinishing(void);
+static void sub_80A2D54(u8 taskId);
-void sub_80A1818(u16 a1)
-{
- void **v1 = &gUnknown_0852487C;
- CpuSet(v1[a1 & 0x3], gPlttBufferUnfaded + 0x80, 0x10);
- BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
- if ((u8)FindTaskIdByFunc(sub_8149DFC) != 0xFF )
- {
- gUnknown_03000F44 = sub_80A1670;
- gUnknown_03000F3C = 0x20;
- }
- return;
-}
+EWRAM_DATA u16 gPlttBufferUnfaded[0x200] = {0};
+EWRAM_DATA u16 gPlttBufferFaded[0x200] = {0};
+EWRAM_DATA struct PaletteStruct sPaletteStructs[0x10] = {0};
+EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
+static EWRAM_DATA u32 gFiller_2037FE0 = 0;
+static EWRAM_DATA u32 sPlttBufferTransferPending = 0;
+EWRAM_DATA u8 gPaletteDecompressionBuffer[0x400] = {0};
-void sub_80A1884(u16 a1)
-{
- void **v1 = &gUnknown_0852487C;
- CpuSet(v1[a1 & 0x3], gPlttBufferUnfaded + 0x80, 0x10);
- if ((u8)FindTaskIdByFunc(sub_8149DFC) == 0xFF )
- {
- BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
- if (!--gUnknown_03000F3C)
- gUnknown_03000F44 = 0;
- }
- return;
-}
+static const struct PaletteStructTemplate gDummyPaletteStructTemplate = {
+ .uid = 0xFFFF,
+ .pst_field_B_5 = 1
+};
+static const u8 gUnknown_0852489C[] = {
+ 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5,
+ 11, 11, 11, 11, 11,
+ 16, 16, 16, 16, 16,
+ 21, 21, 21, 21, 21,
+ 27, 27, 27, 27, 27,
+ 31, 31
+};
void LoadCompressedPalette(const void *src, u16 offset, u16 size)
{
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
index c3d3bf8cf..ee54f0e4d 100644
--- a/src/pokemon_2.c
+++ b/src/pokemon_2.c
@@ -152,8 +152,8 @@ u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
void sub_806A068(u16 species, u8 bankIdentity)
{
- if (gBattleSpritesGfx != NULL)
- gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
else if (gUnknown_020249B4[0])
gUnknown_0202499C = gUnknown_020249B4[0]->templates[bankIdentity];
else if (gUnknown_020249B4[1])
@@ -180,8 +180,8 @@ void sub_806A12C(u16 trainerSpriteId, u8 bankIdentity)
}
else
{
- if (gBattleSpritesGfx != NULL)
- gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
else
gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId];
@@ -190,8 +190,8 @@ void sub_806A12C(u16 trainerSpriteId, u8 bankIdentity)
void sub_806A1C0(u16 arg0, u8 bankIdentity)
{
- if (gBattleSpritesGfx != NULL)
- gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
else
gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
gUnknown_0202499C.paletteTag = arg0;
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
index d44c0cb2f..5ff99aee2 100644
--- a/src/pokemon_3.c
+++ b/src/pokemon_3.c
@@ -486,8 +486,8 @@ u16 SpeciesToCryId(u16 species)
void sub_806D544(u16 species, u32 personality, u8 *dest)
{
if (species == SPECIES_SPINDA
- && dest != gBattleSpritesGfx->sprites[0]
- && dest != gBattleSpritesGfx->sprites[2])
+ && dest != gMonSpritesGfxPtr->sprites[0]
+ && dest != gMonSpritesGfxPtr->sprites[2])
{
int i;
for (i = 0; i < 4; i++)
@@ -1519,8 +1519,6 @@ void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u
DoMonFrontSpriteAnimation(sprite, species, noCry, arg3);
}
-bool8 HasTwoFramesAnimation(u16 species);
-
extern void SpriteCallbackDummy_2(struct Sprite*);
extern void sub_817F60C(struct Sprite*);
diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c
new file mode 100644
index 000000000..3e409244c
--- /dev/null
+++ b/src/pokemon_storage_system.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F78[0x188];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/record_mixing.c b/src/record_mixing.c
new file mode 100644
index 000000000..151835e5e
--- /dev/null
+++ b/src/record_mixing.c
@@ -0,0 +1,28 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA bool8 gUnknown_03001130;
+IWRAM_DATA struct SecretBaseRecord *gUnknown_03001134;
+IWRAM_DATA TVShow *gUnknown_03001138;
+IWRAM_DATA struct UnknownSaveStruct2ABC *gUnknown_0300113C;
+IWRAM_DATA OldMan *gUnknown_03001140;
+IWRAM_DATA struct EasyChatPair *gUnknown_03001144;
+IWRAM_DATA struct DaycareData *gUnknown_03001148;
+IWRAM_DATA void *gUnknown_0300114C; // gSaveBlock2Ptr->field_64C
+IWRAM_DATA LilycoveLady *gUnknown_03001150;
+IWRAM_DATA void *gUnknown_03001154; // gSaveBlock2Ptr->field_0DC;
+IWRAM_DATA void *gUnknown_03001158; // gSaveBlock2Ptr->field_64C
+IWRAM_DATA u32 gUnknown_0300115C;
+IWRAM_DATA u8 gUnknown_03001160[8];
+IWRAM_DATA u32 gUnknown_03001168[3];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/rom4.c b/src/rom4.c
new file mode 100644
index 000000000..c538595f2
--- /dev/null
+++ b/src/rom4.c
@@ -0,0 +1,19 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA void *gUnknown_03000E0C;
+IWRAM_DATA u8 gUnknown_03000E10[4];
+IWRAM_DATA u8 (*gUnknown_03000E14)(u32);
+IWRAM_DATA u8 gUnknown_03000E18;
+IWRAM_DATA u8 gUnknown_03000E19;
+IWRAM_DATA void *rom4_c_unused_03000e1c;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/save.c b/src/save.c
index aee20d451..2c1b26ca9 100644
--- a/src/save.c
+++ b/src/save.c
@@ -15,7 +15,6 @@ extern const struct SaveSectionOffsets gSaveSectionOffsets[0xE];
extern void DoSaveFailedScreen(u8); // save_failed_screen
extern void LoadSerializedGame(void); // load_save
extern bool32 ProgramFlashSectorAndVerify(u8 sector, u8 *data);
-extern void ReadFlash(u8 sector, u32 arg1, void* data, u32 size);
// iwram common
u16 gLastWrittenSector;
@@ -806,7 +805,7 @@ u32 sub_81535DC(u8 sector, u8* dst)
if (sector != 30 && sector != 31)
return 0xFF;
- ReadFlash(sector, 0, &gSaveDataBuffer, sizeof(struct SaveSection));
+ ReadFlash(sector, 0, (u8 *)&gSaveDataBuffer, sizeof(struct SaveSection));
if (*(u32*)(&gSaveDataBuffer.data[0]) != 0xB39D)
return 0xFF;
// copies whole save section except u32 counter
diff --git a/src/save_failed_screen.c b/src/save_failed_screen.c
new file mode 100755
index 000000000..3f49b89e6
--- /dev/null
+++ b/src/save_failed_screen.c
@@ -0,0 +1,426 @@
+#include "global.h"
+#include "text.h"
+#include "main.h"
+#include "palette.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "task.h"
+#include "window.h"
+#include "menu.h"
+#include "save.h"
+#include "gba/flash_internal.h"
+
+#define MSG_WIN_TOP 12
+#define CLOCK_WIN_TOP (MSG_WIN_TOP - 4)
+
+extern void AddTextPrinterParametrized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, struct TextColor *color, s8 speed, u8 *str);
+
+extern void (*gGameContinueCallback)(void);
+
+extern u32 gDamagedSaveSectors;
+
+extern const u8 gBirchHelpGfx[];
+extern const u8 gBirchBagTilemap[];
+extern const u8 gBirchGrassTilemap[];
+extern const u16 gBirchBagGrassPal[];
+extern const u16 gUnknown_0850FEFC[];
+extern const u16 gUnknown_0860F074[];
+extern const u32 gUnknown_0850E87C[];
+extern struct SaveSection gSaveDataBuffer;
+
+extern u8 gText_SaveFailedCheckingBackup[];
+extern u8 gText_BackupMemoryDamaged[];
+extern u8 gText_CheckCompleted[];
+extern u8 gText_SaveCompleteGameCannotContinue[];
+extern u8 gText_SaveCompletePressA[];
+extern u8 gText_GamePlayCannotBeContinued[];
+
+extern u8 gDecompressionBuffer[];
+
+// gSaveFailedClockInfo enum
+enum
+{
+ CLOCK_RUNNING,
+ DEBUG_TIMER
+};
+
+// gSaveFailedWindowIds enum
+enum
+{
+ TEXT_WIN_ID,
+ CLOCK_WIN_ID
+};
+
+EWRAM_DATA u16 gSaveFailedType = {0};
+EWRAM_DATA u16 gSaveFailedClockInfo[2] = {0};
+EWRAM_DATA u8 gSaveFailedUnused1[12] = {0};
+EWRAM_DATA u8 gSaveFailedWindowIds[2] = {0};
+EWRAM_DATA u8 gSaveFailedUnused2[4] = {0};
+
+static const struct OamData sClockOamData =
+{
+ 160, // Y
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+static const struct BgTemplate gUnknown_085EFD88[3] =
+{
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0,
+ },
+ {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 14,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0,
+ },
+ {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0,
+ },
+};
+
+static const struct WindowTemplate gUnknown_085EFD94[] =
+{
+ {
+ .priority = 255,
+ .tilemapLeft = 0,
+ .tilemapTop = 0,
+ .width = 0,
+ .height = 0,
+ .paletteNum = 0,
+ .baseBlock = 0,
+ }
+};
+
+static const struct WindowTemplate gUnknown_085EFD9C[] =
+{
+ {
+ .priority = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 13,
+ .width = 28,
+ .height = 6,
+ .paletteNum = 15,
+ .baseBlock = 1,
+ }
+};
+
+static const struct WindowTemplate gUnknown_085EFDA4[] =
+{
+ {
+ .priority = 0,
+ .tilemapLeft = 14,
+ .tilemapTop = 9,
+ .width = 2,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 169,
+ }
+};
+
+static const u8 sClockFrames[8][3] =
+{
+ { 1, 0, 0 },
+ { 5, 0, 0 },
+ { 9, 0, 0 },
+ { 5, 0, 1 },
+ { 1, 0, 1 },
+ { 5, 1, 1 },
+ { 9, 1, 0 },
+ { 5, 1, 0 },
+};
+
+static const u8 gSaveFailedClockPal[] = INCBIN_U8("graphics/misc/clock_small.gbapal");
+static const u8 gSaveFailedClockGfx[] = INCBIN_U8("graphics/misc/clock_small.4bpp.lz");
+
+static void CB2_SaveFailedScreen(void);
+static void CB2_WipeSave(void);
+static void CB2_GameplayCannotBeContinued(void);
+static void CB2_FadeAndReturnToTitleScreen(void);
+static void CB2_ReturnToTitleScreen(void);
+static void VBlankCB_UpdateClockGraphics(void);
+static bool8 VerifySectorWipe(u16 sector);
+static bool8 WipeSectors(u32);
+
+// although this is a general text printer, it's only used in this file.
+static void SaveFailedScreenTextPrint(u8 *text, u8 var1, u8 var2)
+{
+ struct TextColor color;
+
+ color.fgColor = 0;
+ color.bgColor = 15;
+ color.shadowColor = 3;
+ AddTextPrinterParametrized2(gSaveFailedWindowIds[TEXT_WIN_ID], 1, var1 * 8, var2 * 8 + 1, 0, 0, &color, 0, text);
+}
+
+void DoSaveFailedScreen(u8 saveType)
+{
+ SetMainCallback2(CB2_SaveFailedScreen);
+ gSaveFailedType = saveType;
+ gSaveFailedClockInfo[CLOCK_RUNNING] = FALSE;
+ gSaveFailedClockInfo[DEBUG_TIMER] = 0;
+ gSaveFailedWindowIds[TEXT_WIN_ID] = 0;
+ gSaveFailedWindowIds[CLOCK_WIN_ID] = 0;
+}
+
+static void VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void CB2_SaveFailedScreen(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ SetVBlankCallback(NULL);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ SetGpuReg(REG_OFFSET_BG3CNT, 0);
+ SetGpuReg(REG_OFFSET_BG2CNT, 0);
+ SetGpuReg(REG_OFFSET_BG1CNT, 0);
+ SetGpuReg(REG_OFFSET_BG0CNT, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ // how come this doesnt use the Dma manager?
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, 0, PLTT, PLTT_SIZE);
+ LZ77UnCompVram(gBirchHelpGfx, (void *)VRAM);
+ LZ77UnCompVram(gBirchBagTilemap, (void *)(VRAM + 0x7000));
+ LZ77UnCompVram(gBirchGrassTilemap, (void *)(VRAM + 0x7800));
+ LZ77UnCompVram(gSaveFailedClockGfx, (void *)(VRAM + 0x10020));
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_085EFD88, 3);
+ SetBgTilemapBuffer(0, (void *)&gDecompressionBuffer[0x2000]);
+ CpuFill32(0, &gDecompressionBuffer[0x2000], 0x800);
+ LoadBgTiles(0, gUnknown_0850E87C, 0x120, 0x214);
+ InitWindows(gUnknown_085EFD94);
+ // AddWindowWithoutTileMap returns a u16/integer, but the info is clobbered into a u8 here resulting in lost info. Bug?
+ gSaveFailedWindowIds[TEXT_WIN_ID] = AddWindowWithoutTileMap(gUnknown_085EFD9C);
+ SetWindowAttribute(gSaveFailedWindowIds[TEXT_WIN_ID], 7, (u32)&gDecompressionBuffer[0x2800]);
+ gSaveFailedWindowIds[CLOCK_WIN_ID] = AddWindowWithoutTileMap(gUnknown_085EFDA4);
+ SetWindowAttribute(gSaveFailedWindowIds[CLOCK_WIN_ID], 7, (u32)&gDecompressionBuffer[0x3D00]);
+ DeactivateAllTextPrinters();
+ ResetSpriteData();
+ ResetTasks();
+ ResetPaletteFade();
+ LoadPalette(gBirchBagGrassPal, 0, 0x40);
+ LoadPalette(gSaveFailedClockPal, 0x100, 0x20);
+ LoadPalette(gUnknown_0850FEFC, 0xE0, 0x20);
+ LoadPalette(gUnknown_0860F074, 0xF0, 0x20);
+ SetWindowBorderStyle(gSaveFailedWindowIds[TEXT_WIN_ID], FALSE, 0x214, 0xE);
+ SetWindowBorderStyle(gSaveFailedWindowIds[CLOCK_WIN_ID], FALSE, 0x214, 0xE);
+ FillWindowPixelBuffer(gSaveFailedWindowIds[CLOCK_WIN_ID], 0x11); // backwards?
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ CopyWindowToVram(gSaveFailedWindowIds[CLOCK_WIN_ID], 2); // again?
+ CopyWindowToVram(gSaveFailedWindowIds[TEXT_WIN_ID], 1);
+ SaveFailedScreenTextPrint(gText_SaveFailedCheckingBackup, 1, 0);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ EnableInterrupts(1);
+ SetVBlankCallback(VBlankCB);
+ SetGpuReg(0, 0x1040);
+ ShowBg(0);
+ ShowBg(2);
+ ShowBg(3);
+ gMain.state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ SetMainCallback2(CB2_WipeSave);
+ SetVBlankCallback(VBlankCB_UpdateClockGraphics);
+ }
+ break;
+ }
+}
+
+static void CB2_WipeSave(void)
+{
+ u8 wipeTries = 0;
+
+ gSaveFailedClockInfo[CLOCK_RUNNING] = TRUE;
+
+ while (gDamagedSaveSectors != 0 && wipeTries < 3)
+ {
+ if (WipeSectors(gDamagedSaveSectors) != FALSE)
+ {
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ SaveFailedScreenTextPrint(gText_BackupMemoryDamaged, 1, 0);
+ SetMainCallback2(CB2_GameplayCannotBeContinued);
+ return;
+ }
+
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ SaveFailedScreenTextPrint(gText_CheckCompleted, 1, 0);
+ HandleSavingData(gSaveFailedType);
+
+ if (gDamagedSaveSectors != 0)
+ {
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ SaveFailedScreenTextPrint(gText_SaveFailedCheckingBackup, 1, 0);
+ }
+
+ wipeTries++;
+ }
+
+ if (wipeTries == 3)
+ {
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ SaveFailedScreenTextPrint(gText_BackupMemoryDamaged, 1, 0);
+ }
+ else
+ {
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+
+ if (gGameContinueCallback == NULL)
+ SaveFailedScreenTextPrint(gText_SaveCompleteGameCannotContinue, 1, 0);
+ else
+ SaveFailedScreenTextPrint(gText_SaveCompletePressA, 1, 0);
+ }
+
+ SetMainCallback2(CB2_FadeAndReturnToTitleScreen);
+}
+
+static void CB2_GameplayCannotBeContinued(void)
+{
+ gSaveFailedClockInfo[CLOCK_RUNNING] = FALSE;
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ FillWindowPixelBuffer(gSaveFailedWindowIds[TEXT_WIN_ID], 0x11);
+ SaveFailedScreenTextPrint(gText_GamePlayCannotBeContinued, 1, 0);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_FadeAndReturnToTitleScreen);
+ }
+}
+
+static void CB2_FadeAndReturnToTitleScreen(void)
+{
+ gSaveFailedClockInfo[CLOCK_RUNNING] = FALSE;
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_ReturnToTitleScreen);
+ }
+}
+
+static void CB2_ReturnToTitleScreen(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ if (gGameContinueCallback == NULL) // no callback exists, so do a soft reset.
+ {
+ DoSoftReset();
+ }
+ else
+ {
+ SetMainCallback2((MainCallback)gGameContinueCallback);
+ gGameContinueCallback = NULL;
+ }
+ }
+}
+
+static void VBlankCB_UpdateClockGraphics(void)
+{
+ unsigned int n = (gMain.vblankCounter2 >> 3) & 7;
+
+ gMain.oamBuffer[0] = sClockOamData;
+ gMain.oamBuffer[0].x = 112;
+ gMain.oamBuffer[0].y = (CLOCK_WIN_TOP + 1) * 8;;
+
+ if (gSaveFailedClockInfo[CLOCK_RUNNING] != FALSE)
+ {
+ gMain.oamBuffer[0].tileNum = sClockFrames[n][0];
+ gMain.oamBuffer[0].matrixNum = (sClockFrames[n][2] << 4) | (sClockFrames[n][1] << 3);
+ }
+ else
+ {
+ gMain.oamBuffer[0].tileNum = 1;
+ }
+
+ CpuFastCopy(gMain.oamBuffer, (void *)OAM, 4);
+
+ if (gSaveFailedClockInfo[DEBUG_TIMER])
+ gSaveFailedClockInfo[DEBUG_TIMER]--;
+}
+
+static bool8 VerifySectorWipe(u16 sector)
+{
+ u32 *ptr = (u32 *)&gSaveDataBuffer;
+ u16 i;
+
+ ReadFlash(sector, 0, (u8 *)ptr, 4096);
+
+ for (i = 0; i < 0x400; i++, ptr++)
+ if (*ptr)
+ return TRUE;
+
+ return FALSE;
+}
+
+static bool8 WipeSector(u16 sector)
+{
+ u16 i, j;
+ bool8 failed = TRUE;
+
+ for (i = 0; failed && i < 130; i++)
+ {
+ for (j = 0; j < 0x1000; j++)
+ ProgramFlashByte(sector, j, 0);
+
+ failed = VerifySectorWipe(sector);
+ }
+
+ return failed;
+}
+
+static bool8 WipeSectors(u32 sectorBits)
+{
+ u16 i;
+
+ for (i = 0; i < 0x20; i++)
+ if ((sectorBits & (1 << i)) && !WipeSector(i))
+ sectorBits &= ~(1 << i);
+
+ if (sectorBits == 0)
+ return FALSE;
+ else
+ return TRUE;
+}
diff --git a/src/save_location.c b/src/save_location.c
new file mode 100755
index 000000000..87067e14d
--- /dev/null
+++ b/src/save_location.c
@@ -0,0 +1,145 @@
+#include "global.h"
+#include "map_constants.h"
+
+// used to make the list defines a little less ugly.
+#define MAP(name) ((MAP_GROUP_##name << 8) + (MAP_ID_##name))
+
+// specialSaveWarp flags
+#define POKECENTER_SAVEWARP (1 << 1)
+#define LOBBY_SAVEWARP (1 << 2)
+#define UNK_SPECIAL_SAVE_WARP_FLAG_3 (1 << 3)
+
+static bool32 IsCurMapInLocationList(const u16 *list)
+{
+ u16 locSum = (gSaveBlock1Ptr->location.mapGroup << 8) + (gSaveBlock1Ptr->location.mapNum);
+
+ // im sure it was written a different way, but for the love of christ I cant figure out how to write it different where it still matches.
+ if (*list != 0xFFFF)
+ {
+ u16 termValue = 0xFFFF;
+ const u16 *localList;
+ for (localList = list; *localList != termValue; localList++)
+ if (*localList == locSum)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// TODO: Not require a packed u16 array for these lists
+static const u16 gSaveLocationPokeCenterList[] =
+{
+ MAP(OLDALE_TOWN_POKEMON_CENTER_1F),
+ MAP(OLDALE_TOWN_POKEMON_CENTER_2F),
+ MAP(DEWFORD_TOWN_POKEMON_CENTER_1F),
+ MAP(DEWFORD_TOWN_POKEMON_CENTER_2F),
+ MAP(LAVARIDGE_TOWN_POKEMON_CENTER_1F),
+ MAP(LAVARIDGE_TOWN_POKEMON_CENTER_2F),
+ MAP(FALLARBOR_TOWN_POKEMON_CENTER_1F),
+ MAP(FALLARBOR_TOWN_POKEMON_CENTER_2F),
+ MAP(VERDANTURF_TOWN_POKEMON_CENTER_1F),
+ MAP(VERDANTURF_TOWN_POKEMON_CENTER_2F),
+ MAP(PACIFIDLOG_TOWN_POKEMON_CENTER_1F),
+ MAP(PACIFIDLOG_TOWN_POKEMON_CENTER_2F),
+ MAP(PETALBURG_CITY_POKEMON_CENTER_1F),
+ MAP(PETALBURG_CITY_POKEMON_CENTER_2F),
+ MAP(SLATEPORT_CITY_POKEMON_CENTER_1F),
+ MAP(SLATEPORT_CITY_POKEMON_CENTER_2F),
+ MAP(MAUVILLE_CITY_POKEMON_CENTER_1F),
+ MAP(MAUVILLE_CITY_POKEMON_CENTER_2F),
+ MAP(RUSTBORO_CITY_POKEMON_CENTER_1F),
+ MAP(RUSTBORO_CITY_POKEMON_CENTER_2F),
+ MAP(FORTREE_CITY_POKEMON_CENTER_1F),
+ MAP(FORTREE_CITY_POKEMON_CENTER_2F),
+ MAP(LILYCOVE_CITY_POKEMON_CENTER_1F),
+ MAP(LILYCOVE_CITY_POKEMON_CENTER_2F),
+ MAP(MOSSDEEP_CITY_POKEMON_CENTER_1F),
+ MAP(MOSSDEEP_CITY_POKEMON_CENTER_2F),
+ MAP(SOOTOPOLIS_CITY_POKEMON_CENTER_1F),
+ MAP(SOOTOPOLIS_CITY_POKEMON_CENTER_2F),
+ MAP(EVER_GRANDE_CITY_POKEMON_CENTER_1F),
+ MAP(EVER_GRANDE_CITY_POKEMON_CENTER_2F),
+ MAP(EVER_GRANDE_CITY_POKEMON_LEAGUE_1F),
+ MAP(EVER_GRANDE_CITY_POKEMON_LEAGUE_2F),
+ MAP(BATTLE_FRONTIER_POKEMON_CENTER_1F),
+ MAP(BATTLE_FRONTIER_POKEMON_CENTER_2F),
+ MAP(SINGLE_BATTLE_COLOSSEUM),
+ MAP(TRADE_CENTER),
+ MAP(RECORD_CORNER),
+ MAP(DOUBLE_BATTLE_COLOSSEUM),
+ 0xFFFF,
+};
+
+static bool32 IsCurMapPokeCenter(void)
+{
+ return IsCurMapInLocationList(gSaveLocationPokeCenterList);
+}
+
+static const u16 gSaveLocationReloadLocList[] = // there's only 1 location, and it's presumed its for the save reload feature for battle tower
+{
+ MAP(BATTLE_TOWER_LOBBY),
+ 0xFFFF,
+};
+
+static bool32 IsCurMapReloadLocation(void)
+{
+ return IsCurMapInLocationList(gSaveLocationReloadLocList);
+}
+
+// nulled out list. unknown what this would have been
+static const u16 gUnknown_0861440E[] =
+{
+ 0xFFFF,
+};
+
+bool32 sub_81AFCEC(void)
+{
+ return IsCurMapInLocationList(gUnknown_0861440E);
+}
+
+static void TrySetPokeCenterWarpStatus(void)
+{
+ if (IsCurMapPokeCenter() == FALSE)
+ gSaveBlock2Ptr->specialSaveWarp &= ~(POKECENTER_SAVEWARP);
+ else
+ gSaveBlock2Ptr->specialSaveWarp |= POKECENTER_SAVEWARP;
+}
+
+static void TrySetReloadWarpStatus(void)
+{
+ if (!IsCurMapReloadLocation())
+ gSaveBlock2Ptr->specialSaveWarp &= ~(LOBBY_SAVEWARP);
+ else
+ gSaveBlock2Ptr->specialSaveWarp |= LOBBY_SAVEWARP;
+}
+
+// this function definitely sets a warp status, but because the list is empty, it's unknown what this does yet.
+static void sub_81AFD5C(void)
+{
+ if (!sub_81AFCEC())
+ gSaveBlock2Ptr->specialSaveWarp &= ~(UNK_SPECIAL_SAVE_WARP_FLAG_3);
+ else
+ gSaveBlock2Ptr->specialSaveWarp |= UNK_SPECIAL_SAVE_WARP_FLAG_3;
+}
+
+void TrySetMapSaveWarpStatus(void)
+{
+ TrySetPokeCenterWarpStatus();
+ TrySetReloadWarpStatus();
+ sub_81AFD5C();
+}
+
+void sub_81AFDA0(void)
+{
+ gSaveBlock2Ptr->field_A8 |= 0x8000;
+ gSaveBlock2Ptr->field_A8 |= 0x1;
+ gSaveBlock2Ptr->field_A8 |= 0x2;
+ gSaveBlock2Ptr->field_A8 |= 0x4;
+ gSaveBlock2Ptr->field_A8 |= 0x10;
+ gSaveBlock2Ptr->field_A8 |= 0x20;
+ gSaveBlock2Ptr->field_A8 |= 0x8;
+}
+
+void sub_81AFDD0(void)
+{
+ gSaveBlock2Ptr->specialSaveWarp |= 0x80;
+}
diff --git a/src/scrcmd.c b/src/scrcmd.c
new file mode 100644
index 000000000..b56a53caf
--- /dev/null
+++ b/src/scrcmd.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F30;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/script_menu.c b/src/script_menu.c
new file mode 100644
index 000000000..04f1e82b7
--- /dev/null
+++ b/src/script_menu.c
@@ -0,0 +1,16 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03001124[6];
+IWRAM_DATA u32 filler_0300112c;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/text.c b/src/text.c
index 0081a8244..7cc46cd92 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1,9 +1,9 @@
#include "global.h"
-#include "text.h"
#include "main.h"
#include "palette.h"
#include "string_util.h"
#include "window.h"
+#include "text.h"
extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
extern void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
@@ -32,11 +32,7 @@ u8 gUnknown_03002FB0[0x20];
u8 gUnknown_03002FD0[0x20];
u8 gUnknown_03002FF0[0x20];
u8 gGlyphDimensions[0x2];
-struct {
- u8 flag_0:1;
- u8 flag_1:1;
- u8 flag_2:1;
-} gTextFlags;
+TextFlags gTextFlags;
const u8 gFontHalfRowOffsets[] = {
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
@@ -1972,7 +1968,7 @@ bool8 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter)
}
}
-bool8 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
+bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
{
bool8 result = FALSE;
if (gTextFlags.flag_2 != 0)
@@ -1991,9 +1987,9 @@ bool8 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
return result;
}
-bool8 TextPrinterWait(struct TextPrinter *textPrinter)
+bool16 TextPrinterWait(struct TextPrinter *textPrinter)
{
- bool8 result = FALSE;
+ bool16 result = FALSE;
if (gTextFlags.flag_2 != 0)
{
result = TextPrinterWaitAutoMode(textPrinter);
diff --git a/src/tileset_anims.c b/src/tileset_anims.c
new file mode 100644
index 000000000..4ad787e1c
--- /dev/null
+++ b/src/tileset_anims.c
@@ -0,0 +1,1411 @@
+
+// Includes
+#include "global.h"
+#include "palette.h"
+#include "blend_palette.h"
+#include "battle_transition.h"
+#include "task.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+static EWRAM_DATA struct {
+ const u16 *src;
+ u16 *dest;
+ u16 size;
+} sTilesetDMA3TransferBuffer[20] = {0};
+
+static u8 sTilesetDMA3TransferBufferSize;
+static u16 sPrimaryTilesetCBCounter;
+static u16 sPrimaryTilesetCBBufferSize;
+static u16 sSecondaryTilesetCBCounter;
+static u16 sSecondaryTilesetCBBufferSize;
+static void (*sPrimaryTilesetCB)(u16);
+static void (*sSecondaryTilesetCB)(u16);
+
+// Static ROM declarations
+
+static void cur_mapheader_run_tileset1_func(void);
+static void cur_mapheader_run_tileset2_func(void);
+
+// .rodata
+
+
+const u16 gUnknown_085105C4[] = INCBIN_U16("data/tilesets/primary/general/anim/0/1.4bpp");
+
+const u16 gUnknown_08510644[] = INCBIN_U16("data/tilesets/primary/general/anim/0/0.4bpp");
+
+const u16 gUnknown_085106C4[] = INCBIN_U16("data/tilesets/primary/general/anim/0/2.4bpp");
+
+const u16 tileset_anims_space_0[16] = {};
+
+const u16 *const gTilesetAnims_General0[] = {
+ gUnknown_08510644,
+ gUnknown_085105C4,
+ gUnknown_08510644,
+ gUnknown_085106C4
+};
+
+const u16 gUnknown_08510774[] = INCBIN_U16("data/tilesets/primary/general/anim/1/0.4bpp");
+
+const u16 gUnknown_08510B34[] = INCBIN_U16("data/tilesets/primary/general/anim/1/1.4bpp");
+
+const u16 gUnknown_08510EF4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/2.4bpp");
+
+const u16 gUnknown_085112B4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/3.4bpp");
+
+const u16 gUnknown_08511674[] = INCBIN_U16("data/tilesets/primary/general/anim/1/4.4bpp");
+
+const u16 gUnknown_08511A34[] = INCBIN_U16("data/tilesets/primary/general/anim/1/5.4bpp");
+
+const u16 gUnknown_08511DF4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/6.4bpp");
+
+const u16 gUnknown_085121B4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/7.4bpp");
+
+const u16 *const gTilesetAnims_General1[] = {
+ gUnknown_08510774,
+ gUnknown_08510B34,
+ gUnknown_08510EF4,
+ gUnknown_085112B4,
+ gUnknown_08511674,
+ gUnknown_08511A34,
+ gUnknown_08511DF4,
+ gUnknown_085121B4
+};
+
+const u16 gUnknown_08512594[] = INCBIN_U16("data/tilesets/primary/general/anim/2/0.4bpp");
+
+const u16 gUnknown_085126D4[] = INCBIN_U16("data/tilesets/primary/general/anim/2/1.4bpp");
+
+const u16 gUnknown_08512814[] = INCBIN_U16("data/tilesets/primary/general/anim/2/2.4bpp");
+
+const u16 gUnknown_08512954[] = INCBIN_U16("data/tilesets/primary/general/anim/2/3.4bpp");
+
+const u16 gUnknown_08512A94[] = INCBIN_U16("data/tilesets/primary/general/anim/2/4.4bpp");
+
+const u16 gUnknown_08512BD4[] = INCBIN_U16("data/tilesets/primary/general/anim/2/5.4bpp");
+
+const u16 gUnknown_08512D14[] = INCBIN_U16("data/tilesets/primary/general/anim/2/6.4bpp");
+
+const u16 *const gTilesetAnims_General2[] = {
+ gUnknown_08512594,
+ gUnknown_085126D4,
+ gUnknown_08512814,
+ gUnknown_08512954,
+ gUnknown_08512A94,
+ gUnknown_08512BD4,
+ gUnknown_08512D14,
+ gUnknown_08512594
+};
+
+const u16 gUnknown_08512E74[] = INCBIN_U16("data/tilesets/primary/general/anim/3/0.4bpp");
+
+const u16 gUnknown_08512F34[] = INCBIN_U16("data/tilesets/primary/general/anim/3/1.4bpp");
+
+const u16 gUnknown_08512FF4[] = INCBIN_U16("data/tilesets/primary/general/anim/3/2.4bpp");
+
+const u16 gUnknown_085130B4[] = INCBIN_U16("data/tilesets/primary/general/anim/3/3.4bpp");
+
+const u16 *const gTilesetAnims_General3[] = {
+ gUnknown_08512E74,
+ gUnknown_08512F34,
+ gUnknown_08512FF4,
+ gUnknown_085130B4
+};
+
+const u16 gUnknown_08513184[] = INCBIN_U16("data/tilesets/primary/general/anim/4/0.4bpp");
+
+const u16 gUnknown_085132C4[] = INCBIN_U16("data/tilesets/primary/general/anim/4/1.4bpp");
+
+const u16 gUnknown_08513404[] = INCBIN_U16("data/tilesets/primary/general/anim/4/2.4bpp");
+
+const u16 gUnknown_08513544[] = INCBIN_U16("data/tilesets/primary/general/anim/4/3.4bpp");
+
+const u16 *const gTilesetAnims_General4[] = {
+ gUnknown_08513184,
+ gUnknown_085132C4,
+ gUnknown_08513404,
+ gUnknown_08513544
+};
+
+const u16 gUnknown_08513694[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/0.4bpp");
+
+const u16 gUnknown_08513714[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/1.4bpp");
+
+const u16 gUnknown_08513794[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/2.4bpp");
+
+const u16 gUnknown_08513814[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Lavaridge0[] = {
+ gUnknown_08513694,
+ gUnknown_08513714,
+ gUnknown_08513794,
+ gUnknown_08513814
+};
+
+const u16 gUnknown_085138A4[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/0.4bpp");
+
+const u16 gUnknown_08513C64[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/1.4bpp");
+
+const u16 gUnknown_08514024[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/2.4bpp");
+
+const u16 *const gTilesetAnims_Pacifidlog0[] = {
+ gUnknown_085138A4,
+ gUnknown_08513C64,
+ gUnknown_08514024,
+ gUnknown_08513C64
+};
+
+const u16 gUnknown_085143F4[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/0.4bpp");
+
+const u16 gUnknown_08514474[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/1.4bpp");
+
+const u16 gUnknown_085144F4[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/2.4bpp");
+
+const u16 gUnknown_08514574[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Underwater0[] = {
+ gUnknown_085143F4,
+ gUnknown_08514474,
+ gUnknown_085144F4,
+ gUnknown_08514574
+};
+
+const u16 gUnknown_08514604[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/0.4bpp");
+
+const u16 gUnknown_08514704[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/1.4bpp");
+
+const u16 gUnknown_08514804[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/2.4bpp");
+
+const u16 gUnknown_08514904[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/3.4bpp");
+
+const u16 gUnknown_08514A04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/4.4bpp");
+
+const u16 gUnknown_08514B04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/5.4bpp");
+
+const u16 gUnknown_08514C04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/6.4bpp");
+
+const u16 gUnknown_08514D04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/7.4bpp");
+
+const u16 *const gTilesetAnims_Pacifidlog1[] = {
+ gUnknown_08514604,
+ gUnknown_08514704,
+ gUnknown_08514804,
+ gUnknown_08514904,
+ gUnknown_08514A04,
+ gUnknown_08514B04,
+ gUnknown_08514C04,
+ gUnknown_08514D04
+};
+
+const u16 gUnknown_08514E24[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/0.4bpp");
+
+const u16 gUnknown_08514EA4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/1.4bpp");
+
+const u16 gUnknown_08514F24[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/2.4bpp");
+
+const u16 gUnknown_08514FA4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/3.4bpp");
+
+const u16 gUnknown_08515024[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/1/a/1.4bpp");
+
+const u16 gUnknown_085150A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/0.4bpp");
+
+const u16 gUnknown_08515124[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/1.4bpp");
+
+const u16 gUnknown_085151A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/2.4bpp");
+
+const u16 gUnknown_08515224[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/3.4bpp");
+
+const u16 gUnknown_085152A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/1/b/1.4bpp");
+
+const u16 tileset_anims_space_1[16] = {};
+
+u16 *const gTilesetAnims_MauvilleVDests0[] = {
+ (u16 *)(BG_VRAM + 0x4c00),
+ (u16 *)(BG_VRAM + 0x4c80),
+ (u16 *)(BG_VRAM + 0x4d00),
+ (u16 *)(BG_VRAM + 0x4d80),
+ (u16 *)(BG_VRAM + 0x4e00),
+ (u16 *)(BG_VRAM + 0x4e80),
+ (u16 *)(BG_VRAM + 0x4f00),
+ (u16 *)(BG_VRAM + 0x4f80)
+};
+
+u16 *const gTilesetAnims_MauvilleVDests1[] = {
+ (u16 *)(BG_VRAM + 0x5000),
+ (u16 *)(BG_VRAM + 0x5080),
+ (u16 *)(BG_VRAM + 0x5100),
+ (u16 *)(BG_VRAM + 0x5180),
+ (u16 *)(BG_VRAM + 0x5200),
+ (u16 *)(BG_VRAM + 0x5280),
+ (u16 *)(BG_VRAM + 0x5300),
+ (u16 *)(BG_VRAM + 0x5380)
+};
+
+const u16 *const gTilesetAnims_Mauville0a[] = {
+ gUnknown_08514E24,
+ gUnknown_08514E24,
+ gUnknown_08514EA4,
+ gUnknown_08514F24,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514F24,
+ gUnknown_08514EA4
+};
+
+const u16 *const gTilesetAnims_Mauville0b[] = {
+ gUnknown_085150A4,
+ gUnknown_085150A4,
+ gUnknown_08515124,
+ gUnknown_085151A4,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_085151A4,
+ gUnknown_08515124
+};
+
+const u16 *const gTilesetAnims_Mauville1a[] = {
+ gUnknown_08514E24,
+ gUnknown_08514E24,
+ gUnknown_08515024,
+ gUnknown_08515024
+};
+
+const u16 *const gTilesetAnims_Mauville1b[] = {
+ gUnknown_085150A4,
+ gUnknown_085150A4,
+ gUnknown_085152A4,
+ gUnknown_085152A4
+};
+
+const u16 gUnknown_08515404[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/0.4bpp");
+
+const u16 gUnknown_08515484[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/1.4bpp");
+
+const u16 gUnknown_08515504[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/2.4bpp");
+
+const u16 gUnknown_08515584[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/3.4bpp");
+
+const u16 gUnknown_08515604[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/4.4bpp");
+
+const u16 gUnknown_08515684[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/5.4bpp");
+
+const u16 gUnknown_08515704[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/6.4bpp");
+
+const u16 gUnknown_08515784[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/7.4bpp");
+
+u16 *const gTilesetAnims_RustboroVDests0[] = {
+ (u16 *)(BG_VRAM + 0x5000),
+ (u16 *)(BG_VRAM + 0x5080),
+ (u16 *)(BG_VRAM + 0x5100),
+ (u16 *)(BG_VRAM + 0x5180),
+ (u16 *)(BG_VRAM + 0x5200),
+ (u16 *)(BG_VRAM + 0x5280),
+ (u16 *)(BG_VRAM + 0x5300),
+ (u16 *)(BG_VRAM + 0x5380)
+};
+
+const u16 *const gTilesetAnims_Rustboro0[] = {
+ gUnknown_08515404,
+ gUnknown_08515484,
+ gUnknown_08515504,
+ gUnknown_08515584,
+ gUnknown_08515604,
+ gUnknown_08515684,
+ gUnknown_08515704,
+ gUnknown_08515784
+};
+
+const u16 gUnknown_08515844[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/1/0.4bpp");
+
+const u16 gUnknown_085158C4[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/1/1.4bpp");
+
+const u16 tileset_anims_space_2[16] = {};
+
+const u16 *const gTilesetAnims_Rustboro1[] = {
+ gUnknown_08515844,
+ gUnknown_085158C4
+};
+
+const u16 gUnknown_0851596C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/0.4bpp");
+
+const u16 gUnknown_085159EC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/1.4bpp");
+
+const u16 gUnknown_08515A6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/2.4bpp");
+
+const u16 gUnknown_08515AEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/3.4bpp");
+
+const u16 gUnknown_08515B6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/0.4bpp");
+
+const u16 gUnknown_08515BEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/1.4bpp");
+
+const u16 gUnknown_08515C6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/2.4bpp");
+
+const u16 gUnknown_08515CEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/3.4bpp");
+
+const u16 tileset_anims_space_3[16] = {};
+
+const u16 *const gTilesetAnims_Lavaridge1_Cave0[] = {
+ gUnknown_0851596C,
+ gUnknown_085159EC,
+ gUnknown_08515A6C,
+ gUnknown_08515AEC
+};
+
+const u16 gUnknown_08515D9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/0.4bpp");
+
+const u16 gUnknown_08515E1C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/1.4bpp");
+
+const u16 gUnknown_08515E9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/2.4bpp");
+
+const u16 gUnknown_08515F1C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/3.4bpp");
+
+const u16 gUnknown_08515F9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/4.4bpp");
+
+const u16 gUnknown_0851601C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/5.4bpp");
+
+const u16 gUnknown_0851609C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/6.4bpp");
+
+const u16 gUnknown_0851611C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/7.4bpp");
+
+const u16 tileset_anims_space_4[16] = {};
+
+u16 *const gTilesetAnims_EverGrandeVDests0[] = {
+ (u16 *)(BG_VRAM + 0x5c00),
+ (u16 *)(BG_VRAM + 0x5c80),
+ (u16 *)(BG_VRAM + 0x5d00),
+ (u16 *)(BG_VRAM + 0x5d80),
+ (u16 *)(BG_VRAM + 0x5e00),
+ (u16 *)(BG_VRAM + 0x5e80),
+ (u16 *)(BG_VRAM + 0x5f00),
+ (u16 *)(BG_VRAM + 0x5f80)
+};
+
+const u16 *const gTilesetAnims_EverGrande0[] = {
+ gUnknown_08515D9C,
+ gUnknown_08515E1C,
+ gUnknown_08515E9C,
+ gUnknown_08515F1C,
+ gUnknown_08515F9C,
+ gUnknown_0851601C,
+ gUnknown_0851609C,
+ gUnknown_0851611C
+};
+
+const u16 gUnknown_085161FC[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/0.4bpp");
+
+const u16 gUnknown_085162BC[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/1.4bpp");
+
+const u16 gUnknown_0851637C[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/2.4bpp");
+
+const u16 gUnknown_0851643C[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Dewford0[] = {
+ gUnknown_085161FC,
+ gUnknown_085162BC,
+ gUnknown_0851637C,
+ gUnknown_0851643C
+};
+
+const u16 gUnknown_0851650C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/0.4bpp");
+
+const u16 gUnknown_085165CC[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/1.4bpp");
+
+const u16 gUnknown_0851668C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/2.4bpp");
+
+const u16 gUnknown_0851674C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_BattleFrontierOutsideWest0[] = {
+ gUnknown_0851650C,
+ gUnknown_085165CC,
+ gUnknown_0851668C,
+ gUnknown_0851674C
+};
+
+const u16 gUnknown_0851681C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/0.4bpp");
+
+const u16 gUnknown_085168DC[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/1.4bpp");
+
+const u16 gUnknown_0851699C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/2.4bpp");
+
+const u16 gUnknown_08516A5C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_BattleFrontierOutsideEast0[] = {
+ gUnknown_0851681C,
+ gUnknown_085168DC,
+ gUnknown_0851699C,
+ gUnknown_08516A5C
+};
+
+const u16 gUnknown_08516B2C[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/0.4bpp");
+
+const u16 gUnknown_08516BAC[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/1.4bpp");
+
+const u16 gUnknown_08516C2C[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/2.4bpp");
+
+const u16 gUnknown_08516CAC[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Slateport0[] = {
+ gUnknown_08516B2C,
+ gUnknown_08516BAC,
+ gUnknown_08516C2C,
+ gUnknown_08516CAC
+};
+
+const u16 gUnknown_08516D3C[] = INCBIN_U16("data/tilesets/primary/building/anim/0.4bpp");
+
+const u16 gUnknown_08516DBC[] = INCBIN_U16("data/tilesets/primary/building/anim/1.4bpp");
+
+const u16 *const gTilesetAnims_InsideBuilding0[] = {
+ gUnknown_08516D3C,
+ gUnknown_08516DBC
+};
+
+const u16 gUnknown_08516E44[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/0.4bpp");
+
+const u16 gUnknown_08516FC4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/1.4bpp");
+
+const u16 gUnknown_08517144[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/2.4bpp");
+
+const u16 gUnknown_085172C4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/0.4bpp");
+
+const u16 gUnknown_08517544[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/1.4bpp");
+
+const u16 gUnknown_085177C4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/2.4bpp");
+
+const u16 *const gTilesetAnims_SootopolisGym0[] = {
+ gUnknown_08516E44,
+ gUnknown_08516FC4,
+ gUnknown_08517144
+};
+
+const u16 *const gTilesetAnims_SootopolisGym1[] = {
+ gUnknown_085172C4,
+ gUnknown_08517544,
+ gUnknown_085177C4
+};
+
+const u16 gUnknown_08517A5C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/1/0.4bpp");
+
+const u16 gUnknown_08517ADC[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/1/1.4bpp");
+
+const u16 gUnknown_08517B5C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/0.4bpp");
+
+const u16 gUnknown_08517B7C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/1.4bpp");
+
+const u16 gUnknown_08517B9C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/2.4bpp");
+
+const u16 gUnknown_08517BBC[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/3.4bpp");
+
+const u16 tileset_anims_space_5[16] = {};
+
+const u16 *const gTilesetAnims_EliteFour1[] = {
+ gUnknown_08517B5C,
+ gUnknown_08517B7C,
+ gUnknown_08517B9C,
+ gUnknown_08517BBC
+};
+
+const u16 *const gTilesetAnims_EliteFour0[] = {
+ gUnknown_08517A5C,
+ gUnknown_08517ADC
+};
+
+const u16 gUnknown_08517C14[] = INCBIN_U16("data/tilesets/secondary/mauville_gym/anim/0.4bpp");
+
+const u16 gUnknown_08517E14[] = INCBIN_U16("data/tilesets/secondary/mauville_gym/anim/1.4bpp");
+
+const u16 tileset_anims_space_6[16] = {};
+
+const u16 *const gTilesetAnims_MauvilleGym0[] = {
+ gUnknown_08517C14,
+ gUnknown_08517E14
+};
+
+const u16 gUnknown_0851803C[] = INCBIN_U16("data/tilesets/secondary/bike_shop/anim/0.4bpp");
+
+const u16 gUnknown_0851815C[] = INCBIN_U16("data/tilesets/secondary/bike_shop/anim/1.4bpp");
+
+const u16 tileset_anims_space_7[16] = {};
+
+const u16 *const gTilesetAnims_BikeShop0[] = {
+ gUnknown_0851803C,
+ gUnknown_0851815C
+};
+
+const u16 gUnknown_085182A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/0.4bpp");
+
+const u16 gUnknown_08518EA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/1.4bpp");
+
+const u16 gUnknown_08519AA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/2.4bpp");
+
+const u16 gUnknown_0851A6A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/3.4bpp");
+
+const u16 gUnknown_0851B2A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/4.4bpp");
+
+const u16 gUnknown_0851BEA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/5.4bpp");
+
+const u16 gUnknown_0851CAA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/6.4bpp");
+
+const u16 gUnknown_0851D6A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/7.4bpp");
+
+const u16 tileset_anims_space_8[16] = {};
+
+const u16 gUnknown_0851E2C4[] = INCBIN_U16("data/tilesets/secondary/unused_1/0.4bpp");
+
+const u16 gUnknown_0851EAC4[] = INCBIN_U16("data/tilesets/secondary/unused_1/1.4bpp");
+
+const u16 gUnknown_0851F2C4[] = INCBIN_U16("data/tilesets/secondary/unused_1/2.4bpp");
+
+const u16 gUnknown_0851FAC4[] = INCBIN_U16("data/tilesets/secondary/unused_1/3.4bpp");
+
+const u16 *const gTilesetAnims_Sootopolis0[] = {
+ gUnknown_085182A4,
+ gUnknown_08518EA4,
+ gUnknown_08519AA4,
+ gUnknown_0851A6A4,
+ gUnknown_0851B2A4,
+ gUnknown_0851BEA4,
+ gUnknown_0851CAA4,
+ gUnknown_0851D6A4
+};
+
+const u16 gUnknown_085202E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/0.4bpp");
+
+const u16 gUnknown_085203E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/1.4bpp");
+
+const u16 gUnknown_085204E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/2.4bpp");
+
+const u16 tileset_anims_space_9[16] = {};
+
+const u16 gUnknown_08520604[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/0.4bpp");
+
+const u16 gUnknown_08520704[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/1.4bpp");
+
+const u16 gUnknown_08520804[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/2.4bpp");
+
+const u16 tileset_anims_space_10[7808] = {};
+
+const u16 gUnknown_08524604[] = INCBIN_U16("data/tilesets/secondary/unused_2/0.4bpp");
+
+const u16 tileset_anims_space_11[224] = {};
+
+const u16 gUnknown_08524804[] = INCBIN_U16("data/tilesets/secondary/unused_2/1.4bpp");
+
+const u16 *const gTilesetAnims_BattlePyramid0[] = {
+ gUnknown_085202E4,
+ gUnknown_085203E4,
+ gUnknown_085204E4
+};
+
+const u16 *const gTilesetAnims_BattlePyramid1[] = {
+ gUnknown_08520604,
+ gUnknown_08520704,
+ gUnknown_08520804
+};
+
+extern const u16 gUnknown_08D85640[];
+extern const u16 gUnknown_08D85660[];
+extern const u16 gUnknown_08D85680[];
+extern const u16 gUnknown_08D856A0[];
+
+static const u16 *const gTilesetAnims_BattleDomePals0[] = {
+ gUnknown_08D85640,
+ gUnknown_08D85660,
+ gUnknown_08D85680,
+ gUnknown_08D856A0,
+};
+
+// .text
+
+static void ResetTilesetAnimBuffer(void)
+{
+ sTilesetDMA3TransferBufferSize = 0;
+ CpuFill32(0, sTilesetDMA3TransferBuffer, sizeof sTilesetDMA3TransferBuffer);
+}
+
+static void AppendTilesetAnimToBuffer(const u16 *src, u16 *dest, u16 size)
+{
+ if (sTilesetDMA3TransferBufferSize < 20)
+ {
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].src = src;
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].dest = dest;
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].size = size;
+ sTilesetDMA3TransferBufferSize ++;
+ }
+}
+
+void TransferTilesetAnimsBuffer(void)
+{
+ int i;
+
+ for (i = 0; i < sTilesetDMA3TransferBufferSize; i ++)
+ {
+ DmaCopy16(3, sTilesetDMA3TransferBuffer[i].src, sTilesetDMA3TransferBuffer[i].dest, sTilesetDMA3TransferBuffer[i].size);
+ }
+ sTilesetDMA3TransferBufferSize = 0;
+}
+
+void cur_mapheader_run_tileset_funcs_after_some_cpuset(void)
+{
+ ResetTilesetAnimBuffer();
+ cur_mapheader_run_tileset1_func();
+ cur_mapheader_run_tileset2_func();
+}
+
+void sub_80A0A2C(void)
+{
+ cur_mapheader_run_tileset2_func();
+}
+
+void sub_80A0A38(void)
+{
+ ResetTilesetAnimBuffer();
+ if (++sPrimaryTilesetCBCounter >= sPrimaryTilesetCBBufferSize)
+ sPrimaryTilesetCBCounter = 0;
+ if (++sSecondaryTilesetCBCounter >= sSecondaryTilesetCBBufferSize)
+ sSecondaryTilesetCBCounter = 0;
+ if (sPrimaryTilesetCB)
+ sPrimaryTilesetCB(sPrimaryTilesetCBCounter);
+ if (sSecondaryTilesetCB)
+ sSecondaryTilesetCB(sSecondaryTilesetCBCounter);
+}
+
+static void cur_mapheader_run_tileset1_func(void)
+{
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0;
+ sPrimaryTilesetCB = NULL;
+ if (gMapHeader.mapData->primaryTileset && gMapHeader.mapData->primaryTileset->callback)
+ gMapHeader.mapData->primaryTileset->callback();
+}
+
+static void cur_mapheader_run_tileset2_func(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 0;
+ sSecondaryTilesetCB = NULL;
+ if (gMapHeader.mapData->secondaryTileset && gMapHeader.mapData->secondaryTileset->callback)
+ gMapHeader.mapData->secondaryTileset->callback();
+}
+
+void TilesetCb_General(void)
+{
+ static void sub_80A0B70(u16);
+
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0x100;
+ sPrimaryTilesetCB = sub_80A0B70;
+}
+
+void TilesetCb_InsideBuilding(void)
+{
+ static void sub_80A0BB4(u16);
+
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0x100;
+ sPrimaryTilesetCB = sub_80A0BB4;
+}
+
+static void sub_80A0B70(u16 timer)
+{
+ static void sub_80A0BCC(u16);
+ static void sub_80A0BF4(u16);
+ static void sub_80A0C1C(u16);
+ static void sub_80A0C44(u16);
+ static void sub_80A12AC(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A0BCC(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A0BF4(timer >> 4);
+ if ((timer & 0x0F) == 2)
+ sub_80A0C1C(timer >> 4);
+ if ((timer & 0x0F) == 3)
+ sub_80A0C44(timer >> 4);
+ if ((timer & 0x0F) == 4)
+ sub_80A12AC(timer >> 4);
+}
+
+static void sub_80A0BB4(u16 timer)
+{
+ static void sub_80A1688(u16);
+
+ if ((timer & 0x7) == 0)
+ sub_80A1688(timer >> 3);
+}
+
+static void sub_80A0BCC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General0[idx], (u16 *)(BG_VRAM + 0x3F80), 0x80);
+}
+
+static void sub_80A0BF4(u16 timer)
+{
+ u8 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General1[idx], (u16 *)(BG_VRAM + 0x3600), 0x3C0);
+}
+
+static void sub_80A0C1C(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General2[idx], (u16 *)(BG_VRAM + 0x3a00), 0x140);
+}
+
+static void sub_80A0C44(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General3[idx], (u16 *)(BG_VRAM + 0x3e00), 0xc0);
+}
+
+void TilesetCb_Petalburg(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Rustboro(void)
+{
+ static void sub_80A103C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A103C;
+}
+
+void TilesetCb_Dewford(void)
+{
+ static void sub_80A10B8(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10B8;
+}
+
+void TilesetCb_Slateport(void)
+{
+ static void sub_80A10D0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10D0;
+}
+
+void TilesetCb_Mauville(void)
+{
+ static void sub_80A10E8(u16);
+
+ sSecondaryTilesetCBCounter = sPrimaryTilesetCBCounter;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10E8;
+}
+
+void TilesetCb_Lavaridge(void)
+{
+ static void sub_80A115C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A115C;
+}
+
+void TilesetCb_Fallarbor(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Fortree(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Lilycove(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Mossdeep(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_EverGrande(void)
+{
+ static void sub_80A1188(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1188;
+}
+
+void TilesetCb_Pacifidlog(void)
+{
+ static void sub_80A11FC(u16);
+
+ sSecondaryTilesetCBCounter = sPrimaryTilesetCBCounter;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A11FC;
+}
+
+void TilesetCb_Sootopolis(void)
+{
+ static void sub_80A122C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A122C;
+}
+
+void TilesetCb_BattleFrontierOutsideWest(void)
+{
+ static void sub_80A127C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A127C;
+}
+
+void TilesetCb_BattleFrontierOutsideEast(void)
+{
+ static void sub_80A1294(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1294;
+}
+
+void TilesetCb_Underwater(void)
+{
+ static void sub_80A1244(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 128;
+ sSecondaryTilesetCB = sub_80A1244;
+}
+
+void TilesetCb_SootopolisGym(void)
+{
+ static void sub_80A15D8(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 240;
+ sSecondaryTilesetCB = sub_80A15D8;
+}
+
+void TilesetCb_Cave(void)
+{
+ static void sub_80A1260(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1260;
+}
+
+void TilesetCb_EliteFour(void)
+{
+ static void sub_80A15F0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 128;
+ sSecondaryTilesetCB = sub_80A15F0;
+}
+
+void TilesetCb_MauvilleGym(void)
+{
+ static void sub_80A15C0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A15C0;
+}
+
+void TilesetCb_BikeShop(void)
+{
+ static void sub_80A161C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A161C;
+}
+
+void TilesetCb_BattlePyramid(void)
+{
+ static void sub_80A1634(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1634;
+}
+
+void TilesetCb_BattleDome(void)
+{
+ static void sub_80A1658(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1658;
+}
+
+static void sub_80A103C(u16 timer)
+{
+ static void sub_80A1434(u16, u8);
+ static void sub_80A1470(u16);
+
+ if ((timer & 0x07) == 0)
+ {
+ sub_80A1434(timer >> 3, 0);
+ sub_80A1470(timer >> 3);
+ }
+ if ((timer & 0x07) == 1)
+ sub_80A1434(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A1434(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A1434(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A1434(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A1434(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A1434(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A1434(timer >> 3, 7);
+}
+
+static void sub_80A10B8(u16 timer)
+{
+ static void sub_80A1520(u16);
+
+ if ((timer & 7) == 0)
+ sub_80A1520(timer >> 3);
+}
+
+static void sub_80A10D0(u16 timer)
+{
+ static void sub_80A1598(u16);
+
+ if ((timer & 15) == 0)
+ sub_80A1598(timer >> 4);
+}
+
+static void sub_80A10E8(u16 timer)
+{
+ static void sub_80A1394(u16, u8);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1394(timer >> 3, 0);
+ if ((timer & 0x07) == 1)
+ sub_80A1394(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A1394(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A1394(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A1394(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A1394(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A1394(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A1394(timer >> 3, 7);
+}
+
+static void sub_80A115C(u16 timer)
+{
+ static void sub_80A12D4(u8);
+ static void sub_80A1498(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A12D4(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A1498(timer >> 4);
+}
+
+static void sub_80A1188(u16 timer)
+{
+ static void sub_80A14C0(u16, u8);
+
+ if ((timer & 0x07) == 0)
+ sub_80A14C0(timer >> 3, 0);
+ if ((timer & 0x07) == 1)
+ sub_80A14C0(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A14C0(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A14C0(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A14C0(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A14C0(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A14C0(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A14C0(timer >> 3, 7);
+}
+
+static void sub_80A11FC(u16 timer)
+{
+ static void sub_80A131C(u8);
+ static void sub_80A136C(u8);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A131C(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A136C(timer >> 4);
+}
+
+static void sub_80A122C(u16 timer)
+{
+ static void sub_80A1798(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A1798(timer >> 4);
+}
+
+static void sub_80A1244(u16 timer)
+{
+ static void sub_80A1344(u8);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A1344(timer >> 4);
+}
+
+static void sub_80A1260(u16 timer)
+{
+ static void sub_80A14F8(u16);
+
+ if ((timer & 0x0F) == 1)
+ sub_80A14F8(timer >> 4);
+}
+
+static void sub_80A127C(u16 timer)
+{
+ static void sub_80A1548(u16);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1548(timer >> 3);
+}
+
+static void sub_80A1294(u16 timer)
+{
+ static void sub_80A1570(u16);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1570(timer >> 3);
+}
+
+static void sub_80A12AC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General4[idx], (u16 *)(BG_VRAM + 0x3c00), 0x140);
+}
+
+static void sub_80A12D4(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge0[idx], (u16 *)(BG_VRAM + 0x6400), 0x80);
+
+ idx = (timer + 2) % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge0[idx], (u16 *)(BG_VRAM + 0x6480), 0x80);
+}
+
+static void sub_80A131C(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Pacifidlog0[idx], (u16 *)(BG_VRAM + 0x7a00), 0x3C0);
+}
+
+static void sub_80A1344(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Underwater0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x80);
+}
+
+static void sub_80A136C(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Pacifidlog1[idx], (u16 *)(BG_VRAM + 0x7e00), 0x100);
+}
+
+static void sub_80A1394(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ if (timer_div < 12) // almost certainly a typo
+ {
+ timer_div %= 12;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville0a[timer_div], gTilesetAnims_MauvilleVDests0[timer_mod], 0x80);
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville0b[timer_div], gTilesetAnims_MauvilleVDests1[timer_mod], 0x80);
+ }
+ else
+ {
+ timer_div %= 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville1a[timer_div], gTilesetAnims_MauvilleVDests0[timer_mod], 0x80);
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville1b[timer_div], gTilesetAnims_MauvilleVDests1[timer_mod], 0x80);
+ }
+}
+
+static void sub_80A1434(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ timer_div %= 8;
+ if (gTilesetAnims_Rustboro0[timer_div])
+ AppendTilesetAnimToBuffer(gTilesetAnims_Rustboro0[timer_div], gTilesetAnims_RustboroVDests0[timer_mod], 0x80);
+}
+
+static void sub_80A1470(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Rustboro1[idx], (u16 *)(BG_VRAM + 0x7800), 0x80);
+}
+
+static void sub_80A1498(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge1_Cave0[idx], (u16 *)(BG_VRAM + 0x5400), 0x80);
+}
+
+static void sub_80A14C0(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ timer_div %= 8;
+
+ AppendTilesetAnimToBuffer(gTilesetAnims_EverGrande0[timer_div], gTilesetAnims_EverGrandeVDests0[timer_mod], 0x80);
+}
+
+static void sub_80A14F8(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge1_Cave0[idx], (u16 *)(BG_VRAM + 0x7400), 0x80);
+}
+
+static void sub_80A1520(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Dewford0[idx], (u16 *)(BG_VRAM + 0x5540), 0xC0);
+}
+
+static void sub_80A1548(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattleFrontierOutsideWest0[idx], (u16 *)(BG_VRAM + 0x5b40), 0xC0);
+}
+
+static void sub_80A1570(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattleFrontierOutsideEast0[idx], (u16 *)(BG_VRAM + 0x5b40), 0xC0);
+}
+
+static void sub_80A1598(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Slateport0[idx], (u16 *)(BG_VRAM + 0x5c00), 0x80);
+}
+
+static void sub_80A15C0(u16 timer)
+{
+ static void sub_80A1748(u16);
+
+ if ((timer & 1) == 0)
+ sub_80A1748(timer >> 1);
+}
+
+static void sub_80A15D8(u16 timer)
+{
+ static void sub_80A16B0(u16);
+
+ if ((timer & 7) == 0)
+ sub_80A16B0(timer >> 3);
+}
+
+static void sub_80A15F0(u16 timer)
+{
+ static void sub_80A1720(u16);
+ static void sub_80A16F8(u16);
+
+ if ((timer & 0x3f) == 1)
+ sub_80A1720(timer >> 6);
+ if ((timer & 0x07) == 1)
+ sub_80A16F8(timer >> 3);
+}
+static void sub_80A161C(u16 timer)
+{
+ static void sub_80A1770(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1770(timer >> 2);
+}
+
+static void sub_80A1634(u16 timer)
+{
+ static void sub_80A17C0(u16);
+ static void sub_80A17EC(u16);
+
+ if ((timer & 7) == 0)
+ {
+ sub_80A17C0(timer >> 3);
+ sub_80A17EC(timer >> 3);
+ }
+}
+
+static void sub_80A1658(u16 timer)
+{
+ static void sub_80A1818(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1818(timer >> 2);
+}
+
+static void sub_80A1670(u16 timer)
+{
+ static void sub_80A1884(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1884(timer >> 2);
+}
+
+static void sub_80A1688(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_InsideBuilding0[idx], (u16 *)(BG_VRAM + 0x3e00), 0x80);
+}
+
+static void sub_80A16B0(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_SootopolisGym0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x180);
+ AppendTilesetAnimToBuffer(gTilesetAnims_SootopolisGym1[idx], (u16 *)(BG_VRAM + 0x7a00), 0x280);
+}
+
+static void sub_80A16F8(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_EliteFour1[idx], (u16 *)(BG_VRAM + 0x7f00), 0x20);
+}
+
+static void sub_80A1720(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_EliteFour0[idx], (u16 *)(BG_VRAM + 0x7c00), 0x80);
+}
+
+static void sub_80A1748(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_MauvilleGym0[idx], (u16 *)(BG_VRAM + 0x5200), 0x200);
+}
+
+static void sub_80A1770(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BikeShop0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x120);
+}
+
+static void sub_80A1798(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Sootopolis0[idx], (u16 *)(BG_VRAM + 0x5e00), 0xc00);
+}
+
+static void sub_80A17C0(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattlePyramid0[idx], (u16 *)(BG_VRAM + 0x52e0), 0x100);
+}
+
+static void sub_80A17EC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattlePyramid1[idx], (u16 *)(BG_VRAM + 0x50e0), 0x100);
+}
+
+static void sub_80A1818(u16 a1)
+{
+ CpuCopy16(gTilesetAnims_BattleDomePals0[a1 & 0x3], gPlttBufferUnfaded + 0x80, 32);
+ BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
+ if ((u8)FindTaskIdByFunc(sub_8149DFC) != 0xFF )
+ {
+ sSecondaryTilesetCB = sub_80A1670;
+ sSecondaryTilesetCBBufferSize = 0x20;
+ }
+}
+
+static void sub_80A1884(u16 a1)
+{
+ CpuCopy16(gTilesetAnims_BattleDomePals0[a1 & 0x3], gPlttBufferUnfaded + 0x80, 32);
+ if ((u8)FindTaskIdByFunc(sub_8149DFC) == 0xFF )
+ {
+ BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
+ if (!--sSecondaryTilesetCBBufferSize)
+ sSecondaryTilesetCB = NULL;
+ }
+}
diff --git a/src/unk_text_util_2.c b/src/unk_text_util_2.c
new file mode 100644
index 000000000..d88af611f
--- /dev/null
+++ b/src/unk_text_util_2.c
@@ -0,0 +1,219 @@
+#include "global.h"
+#include "main.h"
+#include "window.h"
+#include "text.h"
+#include "sound.h"
+
+static const u8 gUnknown_08616124[] = {1, 2, 4};
+static const u16 gFont6BrailleGlyphs[] = INCBIN_U16("data/graphics/fonts/font6.fwjpnfont");
+
+static void DecompressGlyphFont6(u16);
+
+u16 Font6Func(struct TextPrinter *textPrinter)
+{
+ u16 char_;
+ struct TextPrinterSubStruct *sub;
+
+ sub = &textPrinter->sub_union.sub;
+ switch (textPrinter->state)
+ {
+ case 0:
+ if (gMain.heldKeys & (A_BUTTON | B_BUTTON) && sub->font_type_upper)
+ {
+ textPrinter->delayCounter = 0;
+ }
+ if (textPrinter->delayCounter && textPrinter->text_speed)
+ {
+ textPrinter->delayCounter --;
+ if (gTextFlags.flag_0 && gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ sub->font_type_upper = TRUE;
+ textPrinter->delayCounter = 0;
+ }
+ return 3;
+ }
+ if (gTextFlags.flag_2)
+ {
+ textPrinter->delayCounter = 3;
+ }
+ else
+ {
+ textPrinter->delayCounter = textPrinter->text_speed;
+ }
+ char_ = *textPrinter->subPrinter.current_text_offset ++;
+ switch (char_)
+ {
+ case EOS:
+ return 1;
+ case CHAR_NEWLINE:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY += gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ return 2;
+ case PLACEHOLDER_BEGIN:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case EXT_CTRL_CODE_BEGIN:
+ char_ = *textPrinter->subPrinter.current_text_offset ++;
+ switch (char_)
+ {
+ case 1:
+ textPrinter->subPrinter.fontColor_h = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 2:
+ textPrinter->subPrinter.bgColor = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 3:
+ textPrinter->subPrinter.shadowColor = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 4:
+ textPrinter->subPrinter.fontColor_h = *textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.bgColor = *++ textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.shadowColor = *++ textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.current_text_offset ++;
+
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 5:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 6:
+ sub->font_type = *textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 7:
+ return 2;
+ case 8:
+ textPrinter->delayCounter = *textPrinter->subPrinter.current_text_offset ++;
+ textPrinter->state = 6;
+ return 2;
+ case 9:
+ textPrinter->state = 1;
+ if (gTextFlags.flag_2)
+ {
+ sub->frames_visible_counter = 0;
+ }
+ return 3;
+ case 10:
+ textPrinter->state = 5;
+ return 3;
+ case 11:
+ case 16:
+ textPrinter->subPrinter.current_text_offset += 2;
+ return 2;
+ case 12:
+ char_ = *++textPrinter->subPrinter.current_text_offset;
+ break;
+ case 13:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x + *textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 14:
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y + *textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 15:
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ return 2;
+ }
+ break;
+ case CHAR_PROMPT_CLEAR:
+ textPrinter->state = 2;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case CHAR_PROMPT_SCROLL:
+ textPrinter->state = 3;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case 0xF9:
+ char_ = *textPrinter->subPrinter.current_text_offset ++ | 0x100;
+ break;
+ case 0xF8:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 0;
+ }
+ DecompressGlyphFont6(char_);
+ CopyGlyphToWindow(textPrinter);
+ textPrinter->subPrinter.currentX += gUnknown_03002F90[0x80] + textPrinter->subPrinter.letterSpacing;
+ return 0;
+ case 1:
+ if (TextPrinterWait(textPrinter))
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 2:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y;
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 3:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ TextPrinterClearDownArrow(textPrinter);
+ textPrinter->scrollDistance = gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->state = 4;
+ }
+ return 3;
+ case 4:
+ if (textPrinter->scrollDistance)
+ {
+ if (textPrinter->scrollDistance < gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed])
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, textPrinter->scrollDistance, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->scrollDistance = 0;
+ }
+ else
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed], textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->scrollDistance -= gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed];
+ }
+ CopyWindowToVram(textPrinter->subPrinter.windowId, 2);
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 5:
+ if (!IsSEPlaying())
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 6:
+ if (textPrinter->delayCounter)
+ {
+ textPrinter->delayCounter --;
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ }
+ return 1;
+}
+
+static void DecompressGlyphFont6(u16 glyph)
+{
+ const u16 *glyphs;
+
+ glyphs = gFont6BrailleGlyphs + 0x100 * (glyph / 8) + 0x10 * (glyph % 8);
+ DecompressGlyphTile(glyphs, (u16 *)gUnknown_03002F90);
+ DecompressGlyphTile(glyphs + 0x8, (u16 *)(gUnknown_03002F90 + 0x20));
+ DecompressGlyphTile(glyphs + 0x80, (u16 *)(gUnknown_03002F90 + 0x40));
+ DecompressGlyphTile(glyphs + 0x88, (u16 *)(gUnknown_03002F90 + 0x60));
+ gUnknown_03002F90[0x80] = 0x10;
+ gUnknown_03002F90[0x81] = 0x10;
+}
+
+u8 GetGlyphWidthFont6(void)
+{
+ return 0x10;
+}
diff --git a/src/window.c b/src/window.c
index 704060b9d..f4cb48ec0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -190,7 +190,7 @@ u16 AddWindow(const struct WindowTemplate *template)
return win;
}
-int AddWindowWithoutTileMap(struct WindowTemplate *template)
+int AddWindowWithoutTileMap(const struct WindowTemplate *template)
{
u16 win;
u8 bgLayer;