summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_2.c7
-rw-r--r--src/battle_ai_switch_items.c18
-rw-r--r--src/battle_anim.c1850
-rw-r--r--src/battle_controllers.c1551
-rw-r--r--src/battle_interface.c2632
-rw-r--r--src/battle_script_commands.c34
-rwxr-xr-xsrc/braille_puzzles.c8
-rw-r--r--src/coins.c4
-rw-r--r--src/decompress.c2
-rw-r--r--src/egg_hatch.c2
-rw-r--r--src/event_data.c52
-rwxr-xr-xsrc/field_map_obj.c28
-rwxr-xr-xsrc/field_special_scene.c18
-rw-r--r--src/international_string_util.c57
-rw-r--r--src/lilycove_lady.c2
-rw-r--r--src/mail.c577
-rw-r--r--src/money.c4
-rw-r--r--src/new_game.c4
-rw-r--r--src/palette.c6
-rw-r--r--src/pokemon_2.c2
-rw-r--r--src/reset_save_heap.c2
-rw-r--r--src/reshow_battle_screen.c4
-rw-r--r--src/safari_zone.c4
-rw-r--r--src/scrcmd.c2451
-rw-r--r--src/script.c4
-rw-r--r--src/sprite.c2
-rw-r--r--src/text.c2
-rw-r--r--src/tv.c30
-rw-r--r--src/walda_phrase.c257
29 files changed, 9486 insertions, 128 deletions
diff --git a/src/battle_2.c b/src/battle_2.c
index aeba69213..16c07114a 100644
--- a/src/battle_2.c
+++ b/src/battle_2.c
@@ -204,9 +204,6 @@ extern const u8 BattleScript_ActionSwitch[];
extern const u8 BattleScript_PrintFailedToRunString[];
// functions
-extern void HandleLinkBattleSetup(void); // rom_3
-extern void SetUpBattleVarsAndBirchZigzagoon(void); // rom_3
-extern void sub_8032768(void); // rom_3
extern void dp12_8087EA4(void);
extern void sub_80356D0(void);
extern void GetFrontierTrainerName(u8* dst, u16 trainerId); // battle tower
@@ -4083,7 +4080,7 @@ static void HandleTurnActionSelectionState(void)
if (gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_MULTIPLETURNS
|| gBattleMons[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)].status2 & STATUS2_RECHARGE)
{
- Emit_x32(0);
+ EmitCmd50(0);
MarkBufferBankForExecution(gActiveBank);
return;
}
@@ -4111,7 +4108,7 @@ static void HandleTurnActionSelectionState(void)
{
RecordedBattle_ClearBankAction(GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON), 3);
}
- Emit_x32(0);
+ EmitCmd50(0);
MarkBufferBankForExecution(gActiveBank);
return;
}
diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c
index 661759a98..d86be6fad 100644
--- a/src/battle_ai_switch_items.c
+++ b/src/battle_ai_switch_items.c
@@ -39,7 +39,7 @@ static bool8 ShouldSwitchIfPerishSong(void)
&& gDisableStructs[gActiveBank].perishSong1 == 0)
{
*(gBattleStruct->field_294 + gActiveBank) = 6;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
@@ -121,7 +121,7 @@ static bool8 ShouldSwitchIfWonderGuard(void)
{
// we found a mon
*(gBattleStruct->field_294 + gActiveBank) = i;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
}
@@ -221,7 +221,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
{
// we found a mon
*(gBattleStruct->field_294 + gActiveBank) = i;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
}
@@ -241,13 +241,13 @@ static bool8 ShouldSwitchIfNaturalCure(void)
if ((gUnknown_02024250[gActiveBank] == 0 || gUnknown_02024250[gActiveBank] == 0xFFFF) && Random() & 1)
{
*(gBattleStruct->field_294 + gActiveBank) = 6;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
else if (gBattleMoves[gUnknown_02024250[gActiveBank]].power == 0 && Random() & 1)
{
*(gBattleStruct->field_294 + gActiveBank) = 6;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
@@ -258,7 +258,7 @@ static bool8 ShouldSwitchIfNaturalCure(void)
if (Random() & 1)
{
*(gBattleStruct->field_294 + gActiveBank) = 6;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
@@ -426,7 +426,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent)
if (moveFlags & MOVESTATUS_SUPEREFFECTIVE && Random() % moduloPercent == 0)
{
*(gBattleStruct->field_294 + gActiveBank) = i;
- EmitCmd_x21(1, 2, 0);
+ EmitCmd33(1, 2, 0);
return TRUE;
}
}
@@ -611,7 +611,7 @@ void AI_TrySwitchOrUseItem(void)
}
}
- EmitCmd_x21(1, 0, (gActiveBank ^ BIT_SIDE) << 8);
+ EmitCmd33(1, 0, (gActiveBank ^ BIT_SIDE) << 8);
}
#define TYPE_FORESIGHT 0xFE
@@ -940,7 +940,7 @@ static bool8 ShouldUseItem(void)
if (shouldUse)
{
- EmitCmd_x21(1, 1, 0);
+ EmitCmd33(1, 1, 0);
*(gBattleStruct->field_C0 + (gActiveBank / 2) * 2) = item;
gBattleResources->battleHistory->trainerItems[i] = 0;
return shouldUse;
diff --git a/src/battle_anim.c b/src/battle_anim.c
new file mode 100644
index 000000000..023272017
--- /dev/null
+++ b/src/battle_anim.c
@@ -0,0 +1,1850 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "sprite.h"
+#include "contest.h"
+#include "m4a.h"
+#include "pokemon.h"
+#include "battle_interface.h"
+#include "task.h"
+#include "decompress.h"
+#include "sound.h"
+#include "dma3.h"
+#include "bg.h"
+#include "gpu_regs.h"
+#include "palette.h"
+#include "main.h"
+
+// sprites start at 10000 and thus must be subtracted of 10000 to account for the true index.
+#define GET_TRUE_SPRITE_INDEX(i) ((i - 10000))
+
+#define SCRIPT_READ_16(ptr) ((ptr)[0] | ((ptr)[1] << 8))
+#define SCRIPT_READ_32(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
+#define SCRIPT_READ_PTR(ptr) ((const u8*)(SCRIPT_READ_32(ptr)))
+
+#define ANIM_SPRITE_INDEX_COUNT 8
+
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u16 gBattle_WIN0H;
+extern u16 gBattle_WIN0V;
+extern u16 gBattle_WIN1H;
+extern u16 gBattle_WIN1V;
+extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gBankSpriteIds[BATTLE_BANKS_COUNT];
+extern struct MusicPlayerInfo gMPlay_BGM;
+extern struct MusicPlayerInfo gMPlay_SE1;
+extern struct MusicPlayerInfo gMPlay_SE2;
+extern u8 gDecompressionBuffer[];
+
+extern const u16 gUnknown_082C8D64[];
+extern const u8 * const gBattleAnims_Moves[];
+extern const struct CompressedSpriteSheet gBattleAnimPicTable[];
+extern const struct CompressedSpritePalette gBattleAnimPaletteTable[];
+extern const struct BattleAnimBackground gBattleAnimBackgroundTable[];
+
+extern void sub_80A8278(void); // rom_80A5C6C.s
+extern void sub_80A6B30(struct UnknownAnimStruct2*); // rom_80A5C6C.s
+extern void sub_80A6B90(struct UnknownAnimStruct2*, u32 arg1); // rom_80A5C6C.s
+extern u8 sub_80A82E4(u8 bank); // rom_80A5C6C.s
+extern u8 sub_80A5C6C(u8 bank, u8 attributeId); // rom_80A5C6C.s
+extern bool8 AnimBankSpriteExists(u8 bank); // rom_80A5C6C.s
+extern void sub_80A6C68(u8 arg0); // rom_80A5C6C.s
+extern u8 GetAnimBankSpriteId(u8 wantedBank); // rom_80A5C6C.s
+extern u8 sub_80A6D94(void);
+extern u8 sub_80A8364(u8);
+extern bool8 IsDoubleBattle(void);
+
+// this file's functions
+static void ScriptCmd_loadspritegfx(void);
+static void ScriptCmd_unloadspritegfx(void);
+static void ScriptCmd_createsprite(void);
+static void ScriptCmd_createvisualtask(void);
+static void ScriptCmd_delay(void);
+static void ScriptCmd_waitforvisualfinish(void);
+static void ScriptCmd_hang1(void);
+static void ScriptCmd_hang2(void);
+static void ScriptCmd_end(void);
+static void ScriptCmd_playse(void);
+static void ScriptCmd_monbg(void);
+static void ScriptCmd_clearmonbg(void);
+static void ScriptCmd_setalpha(void);
+static void ScriptCmd_blendoff(void);
+static void ScriptCmd_call(void);
+static void ScriptCmd_return(void);
+static void ScriptCmd_setarg(void);
+static void ScriptCmd_choosetwoturnanim(void);
+static void ScriptCmd_jumpifmoveturn(void);
+static void ScriptCmd_jump(void);
+static void ScriptCmd_fadetobg(void);
+static void ScriptCmd_restorebg(void);
+static void ScriptCmd_waitbgfadeout(void);
+static void ScriptCmd_waitbgfadein(void);
+static void ScriptCmd_changebg(void);
+static void ScriptCmd_playsewithpan(void);
+static void ScriptCmd_setpan(void);
+static void ScriptCmd_panse_1B(void);
+static void ScriptCmd_loopsewithpan(void);
+static void ScriptCmd_waitplaysewithpan(void);
+static void ScriptCmd_setbldcnt(void);
+static void ScriptCmd_createsoundtask(void);
+static void ScriptCmd_waitsound(void);
+static void ScriptCmd_jumpargeq(void);
+static void ScriptCmd_monbg_22(void);
+static void ScriptCmd_clearmonbg_23(void);
+static void ScriptCmd_jumpifcontest(void);
+static void ScriptCmd_fadetobgfromset(void);
+static void ScriptCmd_panse_26(void);
+static void ScriptCmd_panse_27(void);
+static void ScriptCmd_monbgprio_28(void);
+static void ScriptCmd_monbgprio_29(void);
+static void ScriptCmd_monbgprio_2A(void);
+static void ScriptCmd_invisible(void);
+static void ScriptCmd_visible(void);
+static void ScriptCmd_doublebattle_2D(void);
+static void ScriptCmd_doublebattle_2E(void);
+static void ScriptCmd_stopsound(void);
+
+static void RunAnimScriptCommand(void);
+static void task_pA_ma0A_obj_to_bg_pal(u8 taskId);
+static void sub_80A46A0(void);
+static void sub_80A4980(u8 taskId);
+static void sub_80A4BB0(u8 taskId);
+static void Task_FadeToBg(u8 taskId);
+static void Task_PanFromInitialToTarget(u8 taskId);
+static void Task_LoopAndPlaySE(u8 taskId);
+static void Task_WaitAndPlaySE(u8 taskId);
+static void LoadDefaultBg(void);
+static void LoadMoveBg(u16 bgId);
+
+// ewram
+EWRAM_DATA static const u8 *sBattleAnimScriptPtr = NULL;
+EWRAM_DATA static const u8 *sBattleAnimScriptRetAddr = NULL;
+EWRAM_DATA void (*gAnimScriptCallback)(void) = NULL;
+EWRAM_DATA static s8 gAnimFramesToWait = 0;
+EWRAM_DATA bool8 gAnimScriptActive = FALSE;
+EWRAM_DATA u8 gAnimVisualTaskCount = 0;
+EWRAM_DATA u8 gAnimSoundTaskCount = 0;
+EWRAM_DATA struct DisableStruct *gAnimDisableStructPtr = NULL;
+EWRAM_DATA u32 gAnimMoveDmg = 0;
+EWRAM_DATA u16 gAnimMovePower = 0;
+EWRAM_DATA static u16 sAnimSpriteIndexArray[ANIM_SPRITE_INDEX_COUNT] = {0};
+EWRAM_DATA u8 gAnimFriendship = 0;
+EWRAM_DATA u16 gWeatherMoveAnim = 0;
+EWRAM_DATA s16 gBattleAnimArgs[ANIM_ARGS_COUNT] = {0};
+EWRAM_DATA static u16 sSoundAnimFramesToWait = 0;
+EWRAM_DATA static u8 sMonAnimTaskIdArray[2] = {0};
+EWRAM_DATA u8 gAnimMoveTurn = 0;
+EWRAM_DATA static u8 sAnimBackgroundFadeState = 0;
+EWRAM_DATA static u16 sAnimMoveIndex = 0; // set but unused.
+EWRAM_DATA u8 gAnimBankAttacker = 0;
+EWRAM_DATA u8 gAnimBankTarget = 0;
+EWRAM_DATA u16 gAnimSpeciesByBanks[BATTLE_BANKS_COUNT] = {0};
+EWRAM_DATA u8 gUnknown_02038440 = 0;
+
+// const rom data
+static void (* const sScriptCmdTable[])(void) =
+{
+ ScriptCmd_loadspritegfx,
+ ScriptCmd_unloadspritegfx,
+ ScriptCmd_createsprite,
+ ScriptCmd_createvisualtask,
+ ScriptCmd_delay,
+ ScriptCmd_waitforvisualfinish,
+ ScriptCmd_hang1,
+ ScriptCmd_hang2,
+ ScriptCmd_end,
+ ScriptCmd_playse,
+ ScriptCmd_monbg,
+ ScriptCmd_clearmonbg,
+ ScriptCmd_setalpha,
+ ScriptCmd_blendoff,
+ ScriptCmd_call,
+ ScriptCmd_return,
+ ScriptCmd_setarg,
+ ScriptCmd_choosetwoturnanim,
+ ScriptCmd_jumpifmoveturn,
+ ScriptCmd_jump,
+ ScriptCmd_fadetobg,
+ ScriptCmd_restorebg,
+ ScriptCmd_waitbgfadeout,
+ ScriptCmd_waitbgfadein,
+ ScriptCmd_changebg,
+ ScriptCmd_playsewithpan,
+ ScriptCmd_setpan,
+ ScriptCmd_panse_1B,
+ ScriptCmd_loopsewithpan,
+ ScriptCmd_waitplaysewithpan,
+ ScriptCmd_setbldcnt,
+ ScriptCmd_createsoundtask,
+ ScriptCmd_waitsound,
+ ScriptCmd_jumpargeq,
+ ScriptCmd_monbg_22,
+ ScriptCmd_clearmonbg_23,
+ ScriptCmd_jumpifcontest,
+ ScriptCmd_fadetobgfromset,
+ ScriptCmd_panse_26,
+ ScriptCmd_panse_27,
+ ScriptCmd_monbgprio_28,
+ ScriptCmd_monbgprio_29,
+ ScriptCmd_monbgprio_2A,
+ ScriptCmd_invisible,
+ ScriptCmd_visible,
+ ScriptCmd_doublebattle_2D,
+ ScriptCmd_doublebattle_2E,
+ ScriptCmd_stopsound
+};
+
+void ClearBattleAnimationVars(void)
+{
+ s32 i;
+
+ gAnimFramesToWait = 0;
+ gAnimScriptActive = FALSE;
+ gAnimVisualTaskCount = 0;
+ gAnimSoundTaskCount = 0;
+ gAnimDisableStructPtr = NULL;
+ gAnimMoveDmg = 0;
+ gAnimMovePower = 0;
+ gAnimFriendship = 0;
+
+ // clear index array.
+ for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++)
+ sAnimSpriteIndexArray[i] |= 0xFFFF;
+
+ // clear anim args.
+ for (i = 0; i < ANIM_ARGS_COUNT; i++)
+ gBattleAnimArgs[i] = 0;
+
+ sMonAnimTaskIdArray[0] = 0xFF;
+ sMonAnimTaskIdArray[1] = 0xFF;
+ gAnimMoveTurn = 0;
+ sAnimBackgroundFadeState = 0;
+ sAnimMoveIndex = 0;
+ gAnimBankAttacker = 0;
+ gAnimBankTarget = 0;
+ gUnknown_02038440 = 0;
+}
+
+void DoMoveAnim(u16 move)
+{
+ gAnimBankAttacker = gBankAttacker;
+ gAnimBankTarget = gBankTarget;
+ DoBattleAnim(gBattleAnims_Moves, move, TRUE);
+}
+
+void DoBattleAnim(const u8 *const animsTable[], u16 tableId, bool8 isMoveAnim)
+{
+ s32 i;
+
+ if (!IsContest())
+ {
+ sub_80A8278();
+ UpdateOamPriorityInAllHealthboxes(0);
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ if (GetBankSide(i) != 0)
+ gAnimSpeciesByBanks[i] = GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_SPECIES);
+ else
+ gAnimSpeciesByBanks[i] = GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_SPECIES);
+ }
+ }
+ else
+ {
+ for (i = 0; i < 4; i++)
+ gAnimSpeciesByBanks[i] = gContestResources->field_18->field_0;
+ }
+
+ if (!isMoveAnim)
+ sAnimMoveIndex = 0;
+ else
+ sAnimMoveIndex = tableId;
+
+ for (i = 0; i < ANIM_ARGS_COUNT; i++)
+ gBattleAnimArgs[i] = 0;
+
+ sMonAnimTaskIdArray[0] = 0xFF;
+ sMonAnimTaskIdArray[1] = 0xFF;
+ sBattleAnimScriptPtr = animsTable[tableId];
+ gAnimScriptActive = TRUE;
+ gAnimFramesToWait = 0;
+ gAnimScriptCallback = RunAnimScriptCommand;
+
+ for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++)
+ sAnimSpriteIndexArray[i] |= 0xFFFF;
+
+ if (isMoveAnim)
+ {
+ for (i = 0; gUnknown_082C8D64[i] != 0xFFFF; i++)
+ {
+ if (tableId == gUnknown_082C8D64[i])
+ {
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 128);
+ break;
+ }
+ }
+ }
+
+ gBattle_WIN0H = 0;
+ gBattle_WIN0V = 0;
+ gBattle_WIN1H = 0;
+ gBattle_WIN1V = 0;
+}
+
+void DestroyAnimSprite(struct Sprite *sprite)
+{
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+ gAnimVisualTaskCount--;
+}
+
+void DestroyAnimVisualTask(u8 taskId)
+{
+ DestroyTask(taskId);
+ gAnimVisualTaskCount--;
+}
+
+void DestroyAnimSoundTask(u8 taskId)
+{
+ DestroyTask(taskId);
+ gAnimSoundTaskCount--;
+}
+
+static void AddSpriteIndex(u16 index)
+{
+ s32 i;
+
+ for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++)
+ {
+ if (sAnimSpriteIndexArray[i] == 0xFFFF)
+ {
+ sAnimSpriteIndexArray[i] = index;
+ return;
+ }
+ }
+}
+
+static void ClearSpriteIndex(u16 index)
+{
+ s32 i;
+
+ for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++)
+ {
+ if (sAnimSpriteIndexArray[i] == index)
+ {
+ sAnimSpriteIndexArray[i] |= 0xFFFF;
+ return;
+ }
+ }
+}
+
+static void WaitAnimFrameCount(void)
+{
+ if (gAnimFramesToWait <= 0)
+ {
+ gAnimScriptCallback = RunAnimScriptCommand;
+ gAnimFramesToWait = 0;
+ }
+ else
+ {
+ gAnimFramesToWait--;
+ }
+}
+
+static void RunAnimScriptCommand(void)
+{
+ do
+ {
+ sScriptCmdTable[sBattleAnimScriptPtr[0]]();
+ } while (gAnimFramesToWait == 0 && gAnimScriptActive);
+}
+
+static void ScriptCmd_loadspritegfx(void)
+{
+ u16 index;
+
+ sBattleAnimScriptPtr++;
+ index = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)]);
+ LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(index)]);
+ sBattleAnimScriptPtr += 2;
+ AddSpriteIndex(GET_TRUE_SPRITE_INDEX(index));
+ gAnimFramesToWait = 1;
+ gAnimScriptCallback = WaitAnimFrameCount;
+}
+
+static void ScriptCmd_unloadspritegfx(void)
+{
+ u16 index;
+
+ sBattleAnimScriptPtr++;
+ index = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ FreeSpriteTilesByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag);
+ FreeSpritePaletteByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag);
+ sBattleAnimScriptPtr += 2;
+ ClearSpriteIndex(GET_TRUE_SPRITE_INDEX(index));
+}
+
+static void ScriptCmd_createsprite(void)
+{
+ s32 i;
+ const struct SpriteTemplate *template;
+ u8 argVar;
+ u8 argsCount;
+ s16 subpriority;
+
+ sBattleAnimScriptPtr++;
+ template = (const struct SpriteTemplate *)(SCRIPT_READ_32(sBattleAnimScriptPtr));
+ sBattleAnimScriptPtr += 4;
+
+ argVar = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+
+ argsCount = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+ for (i = 0; i < argsCount; i++)
+ {
+ gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr += 2;
+ }
+
+ if (argVar & 0x80)
+ {
+ argVar ^= 0x80;
+ if (argVar >= 0x40)
+ argVar -= 0x40;
+ else
+ argVar *= -1;
+
+ subpriority = sub_80A82E4(gAnimBankTarget) + (s8)(argVar);
+ }
+ else
+ {
+ if (argVar >= 0x40)
+ argVar -= 0x40;
+ else
+ argVar *= -1;
+
+ subpriority = sub_80A82E4(gAnimBankAttacker) + (s8)(argVar);
+ }
+
+ if (subpriority < 3)
+ subpriority = 3;
+
+ CreateSpriteAndAnimate(template, sub_80A5C6C(gAnimBankTarget, 2), sub_80A5C6C(gAnimBankTarget, 3), subpriority);
+ gAnimVisualTaskCount++;
+}
+
+static void ScriptCmd_createvisualtask(void)
+{
+ TaskFunc taskFunc;
+ u8 taskPriority;
+ u8 taskId;
+ u8 numArgs;
+ s32 i;
+
+ sBattleAnimScriptPtr++;
+
+ taskFunc = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr += 4;
+
+ taskPriority = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+
+ numArgs = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+
+ for (i = 0; i < numArgs; i++)
+ {
+ gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr += 2;
+ }
+
+ taskId = CreateTask(taskFunc, taskPriority);
+ taskFunc(taskId);
+ gAnimVisualTaskCount++;
+}
+
+static void ScriptCmd_delay(void)
+{
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = sBattleAnimScriptPtr[0];
+ if (gAnimFramesToWait == 0)
+ gAnimFramesToWait = -1;
+ sBattleAnimScriptPtr++;
+ gAnimScriptCallback = WaitAnimFrameCount;
+}
+
+// wait for visual tasks to finish.
+static void ScriptCmd_waitforvisualfinish(void)
+{
+ if (gAnimVisualTaskCount == 0)
+ {
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = 0;
+ }
+ else
+ {
+ gAnimFramesToWait = 1;
+ }
+}
+
+static void ScriptCmd_hang1(void)
+{
+}
+
+static void ScriptCmd_hang2(void)
+{
+}
+
+static void ScriptCmd_end(void)
+{
+ s32 i;
+ bool32 continuousAnim = FALSE;
+
+ // keep waiting as long as there is animations to be done.
+ if (gAnimVisualTaskCount != 0 || gAnimSoundTaskCount != 0
+ || sMonAnimTaskIdArray[0] != 0xFF || sMonAnimTaskIdArray[1] != 0xFF)
+ {
+ sSoundAnimFramesToWait = 0;
+ gAnimFramesToWait = 1;
+ return;
+ }
+
+ // finish the sound effects.
+ if (IsSEPlaying())
+ {
+ if (++sSoundAnimFramesToWait <= 90) // wait 90 frames, then halt the sound effect.
+ {
+ gAnimFramesToWait = 1;
+ return;
+ }
+ else
+ {
+ m4aMPlayStop(&gMPlay_SE1);
+ m4aMPlayStop(&gMPlay_SE2);
+ }
+ }
+
+ // the SE has halted, so set the SE Frame Counter to 0 and continue.
+ sSoundAnimFramesToWait = 0;
+
+ for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++)
+ {
+ if (sAnimSpriteIndexArray[i] != 0xFFFF)
+ {
+ FreeSpriteTilesByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag);
+ FreeSpritePaletteByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag);
+ sAnimSpriteIndexArray[i] |= 0xFFFF; // set terminator.
+ }
+ }
+
+ if (!continuousAnim) // may have been used for debug?
+ {
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256);
+ if (!IsContest())
+ {
+ sub_80A8278();
+ UpdateOamPriorityInAllHealthboxes(1);
+ }
+ gAnimScriptActive = FALSE;
+ }
+}
+
+static void ScriptCmd_playse(void)
+{
+ sBattleAnimScriptPtr++;
+ PlaySE(SCRIPT_READ_16(sBattleAnimScriptPtr));
+ sBattleAnimScriptPtr += 2;
+}
+
+#define t1_MONBG_BANK 0
+#define t1_MON_IN_BG2 1
+#define t1_CREATE_ANOTHER_TASK 2
+#define t1_IS_SECONDMON_BG 3
+
+#define t2_BANK_SPRITE_ID 0
+#define t2_MON_IN_BG2 5
+#define t2_MONBG_BANK 6
+
+static void sub_80A40F4(u8 taskId)
+{
+ u8 newTaskId;
+
+ s16 *selfData = gTasks[taskId].data;
+ u8 bankSpriteId = gBankSpriteIds[selfData[t1_MONBG_BANK]];
+ gSprites[bankSpriteId].invisible = 1;
+
+ if (!selfData[t1_CREATE_ANOTHER_TASK])
+ {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+
+ newTaskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10);
+ gTasks[newTaskId].data[t2_BANK_SPRITE_ID] = bankSpriteId;
+ gTasks[newTaskId].data[1] = gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x;
+ gTasks[newTaskId].data[2] = gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y;
+
+ if (!selfData[t1_MON_IN_BG2])
+ {
+ gTasks[newTaskId].data[3] = gBattle_BG1_X;
+ gTasks[newTaskId].data[4] = gBattle_BG1_Y;
+ }
+ else
+ {
+ gTasks[newTaskId].data[3] = gBattle_BG2_X;
+ gTasks[newTaskId].data[4] = gBattle_BG2_Y;
+ }
+
+ gTasks[newTaskId].data[t2_MON_IN_BG2] = selfData[t1_MON_IN_BG2];
+ gTasks[newTaskId].data[t2_MONBG_BANK] = selfData[t1_MONBG_BANK];
+ sMonAnimTaskIdArray[selfData[t1_IS_SECONDMON_BG]] = newTaskId;
+ DestroyAnimVisualTask(taskId);
+}
+
+static void ScriptCmd_monbg(void)
+{
+ bool8 toBG_2;
+ u8 taskId;
+ u8 bank;
+ u8 animBank;
+
+ sBattleAnimScriptPtr++;
+
+ animBank = sBattleAnimScriptPtr[0];
+ if (animBank & ANIM_BANK_TARGET)
+ bank = gAnimBankTarget;
+ else
+ bank = gAnimBankAttacker;
+
+ if (IsAnimBankSpriteVisible(bank))
+ {
+ u8 identity = GetBankIdentity(bank);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ toBG_2 = FALSE;
+ else
+ toBG_2 = TRUE;
+
+ sub_80A438C(bank, toBG_2, FALSE);
+ taskId = CreateTask(sub_80A40F4, 10);
+ gAnimVisualTaskCount++;
+ gTasks[taskId].data[t1_MONBG_BANK] = bank;
+ gTasks[taskId].data[t1_MON_IN_BG2] = toBG_2;
+ gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE;
+ gTasks[taskId].data[t1_IS_SECONDMON_BG] = 0;
+
+ }
+
+ bank ^= BIT_MON;
+ if (IsAnimBankSpriteVisible(bank))
+ {
+ u8 identity = GetBankIdentity(bank);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ toBG_2 = FALSE;
+ else
+ toBG_2 = TRUE;
+
+ sub_80A438C(bank, toBG_2, FALSE);
+ taskId = CreateTask(sub_80A40F4, 10);
+ gAnimVisualTaskCount++;
+ gTasks[taskId].data[0] = bank;
+ gTasks[taskId].data[1] = toBG_2;
+ gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE;
+ gTasks[taskId].data[t1_IS_SECONDMON_BG] = 1;
+ }
+
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = 1;
+ gAnimScriptCallback = WaitAnimFrameCount;
+}
+
+bool8 IsAnimBankSpriteVisible(u8 bank)
+{
+ if (IsContest())
+ {
+ if (bank == gAnimBankAttacker)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ if (!AnimBankSpriteExists(bank))
+ return FALSE;
+ if (IsContest())
+ return TRUE; // this line wont ever be reached.
+ if (!gBattleSpritesDataPtr->bankData[bank].invisible || !gSprites[gBankSpriteIds[bank]].invisible)
+ return TRUE;
+
+ return FALSE;
+}
+
+void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible)
+{
+ struct UnknownAnimStruct2 unknownStruct;
+ u8 bankSpriteId;
+
+ if (!toBG_2)
+ {
+ u8 bankIdentity;
+
+ if (IsContest() == TRUE)
+ {
+ RequestDma3Fill(0, (void*)(VRAM + 0x8000), 0x2000, 1);
+ RequestDma3Fill(0xFF, (void*)(VRAM + 0xF000), 0x1000, 0);
+ }
+ else
+ {
+ RequestDma3Fill(0, (void*)(VRAM + 0x4000), 0x2000, 1);
+ RequestDma3Fill(0xFF, (void*)(VRAM + 0xe000), 0x1000, 0);
+ }
+
+ sub_80A6B30(&unknownStruct);
+ CpuFill16(0, unknownStruct.unk0, 0x1000);
+ CpuFill16(0xFF, unknownStruct.unk4, 0x800);
+
+ SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2);
+ SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 1);
+ SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 0);
+
+ bankSpriteId = gBankSpriteIds[bank];
+
+ gBattle_BG1_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20;
+ if (IsContest() && IsSpeciesNotUnown(gContestResources->field_18->field_0))
+ gBattle_BG1_X--;
+
+ gBattle_BG1_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20;
+ if (setSpriteInvisible)
+ gSprites[gBankSpriteIds[bank]].invisible = 1;
+
+ SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X);
+ SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
+
+ LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], unknownStruct.unk8 * 16, 0x20);
+ CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + unknownStruct.unk8 * 32), 0x20);
+
+ if (IsContest())
+ bankIdentity = 0;
+ else
+ bankIdentity = GetBankIdentity(bank);
+
+ sub_8118FBC(1, 0, 0, bankIdentity, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA);
+
+ if (IsContest())
+ sub_80A46A0();
+ }
+ else
+ {
+ RequestDma3Fill(0, (void*)(VRAM + 0x6000), 0x2000, 1);
+ RequestDma3Fill(0, (void*)(VRAM + 0xF000), 0x1000, 1);
+ sub_80A6B90(&unknownStruct, 2);
+ CpuFill16(0, unknownStruct.unk0 + 0x1000, 0x1000);
+ CpuFill16(0, unknownStruct.unk4 + 0x400, 0x800);
+ SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2);
+ SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 1);
+ SetAnimBgAttribute(2, BG_ANIM_AREA_OVERFLOW_MODE, 0);
+
+ bankSpriteId = gBankSpriteIds[bank];
+
+ gBattle_BG2_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20;
+ gBattle_BG2_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20;
+
+ if (setSpriteInvisible)
+ gSprites[gBankSpriteIds[bank]].invisible = 1;
+
+ SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X);
+ SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y);
+
+ LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], 0x90, 0x20);
+ CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + 0x120), 0x20);
+
+ sub_8118FBC(2, 0, 0, GetBankIdentity(bank), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA);
+ }
+}
+
+static void sub_80A46A0(void)
+{
+ s32 i, j;
+ struct UnknownAnimStruct2 unknownStruct;
+ u16 *ptr;
+
+ if (IsSpeciesNotUnown(gContestResources->field_18->field_0))
+ {
+ sub_80A6B30(&unknownStruct);
+ ptr = unknownStruct.unk4;
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ u16 temp = ptr[j + i * 32];
+
+ ptr[j + i * 32] = ptr[7 - j + i * 32];
+ ptr[7 - j + i * 32] = temp;
+ }
+ }
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ ptr[j + i * 32] ^= 0x400;
+ }
+ }
+}
+
+void sub_80A4720(u16 a, u16 *b, u32 c, u8 d)
+{
+ s32 i, j;
+ s32 var;
+
+ if (d == 0)
+ var = 32;
+ else
+ var = 64;
+ a <<= 12;
+ for (i = 0; i < var; i++)
+ {
+ for (j = 0; j < 32; j++)
+ b[j + i * 32] = ((b[j + i * 32] & 0xFFF) | a) + c;
+ }
+}
+
+void sub_80A477C(bool8 to_BG2)
+{
+ struct UnknownAnimStruct2 unknownStruct;
+ sub_80A6B30(&unknownStruct);
+
+ if (!to_BG2 || IsContest())
+ {
+ sub_80A6C68(1);
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ }
+ else
+ {
+ sub_80A6C68(2);
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ }
+}
+
+static void task_pA_ma0A_obj_to_bg_pal(u8 taskId)
+{
+ u8 spriteId, palIndex;
+ s16 x, y;
+ struct UnknownAnimStruct2 unknownStruct;
+
+ spriteId = gTasks[taskId].data[0];
+ palIndex = gTasks[taskId].data[6];
+ sub_80A6B30(&unknownStruct);
+ x = gTasks[taskId].data[1] - (gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x);
+ y = gTasks[taskId].data[2] - (gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y);
+
+ if (gTasks[taskId].data[5] == 0)
+ {
+ u16 *src;
+ u16 *dst;
+
+ gBattle_BG1_X = x + gTasks[taskId].data[3];
+ gBattle_BG1_Y = y + gTasks[taskId].data[4];
+ src = gPlttBufferFaded + 0x100 + palIndex * 16;
+ dst = gPlttBufferFaded + 0x100 + unknownStruct.unk8 * 16 - 256;
+ CpuCopy32(src, dst, 0x20);
+ }
+ else
+ {
+ u16 *src;
+ u16 *dst;
+
+ gBattle_BG2_X = x + gTasks[taskId].data[3];
+ gBattle_BG2_Y = y + gTasks[taskId].data[4];
+ src = gPlttBufferFaded + 0x100 + palIndex * 16;
+ dst = gPlttBufferFaded + 0x100 - 112;
+ CpuCopy32(src, dst, 0x20);
+ }
+}
+
+static void ScriptCmd_clearmonbg(void)
+{
+ u8 animBankId;
+ u8 bank;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ animBankId = sBattleAnimScriptPtr[0];
+
+ if (animBankId == ANIM_BANK_ATTACKER)
+ animBankId = ANIM_BANK_ATK_PARTNER;
+ else if (animBankId == ANIM_BANK_TARGET)
+ animBankId = ANIM_BANK_DEF_PARTNER;
+
+ if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER)
+ bank = gAnimBankAttacker;
+ else
+ bank = gAnimBankTarget;
+
+ if (sMonAnimTaskIdArray[0] != 0xFF)
+ gSprites[gBankSpriteIds[bank]].invisible = 0;
+ if (animBankId > 1 && sMonAnimTaskIdArray[1] != 0xFF)
+ gSprites[gBankSpriteIds[bank ^ BIT_MON]].invisible = 0;
+ else
+ animBankId = 0;
+
+ taskId = CreateTask(sub_80A4980, 5);
+ gTasks[taskId].data[0] = animBankId;
+ gTasks[taskId].data[2] = bank;
+
+ sBattleAnimScriptPtr++;
+}
+
+static void sub_80A4980(u8 taskId)
+{
+ gTasks[taskId].data[1]++;
+ if (gTasks[taskId].data[1] != 1)
+ {
+ u8 to_BG2;
+ u8 identity = GetBankIdentity(gTasks[taskId].data[2]);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ to_BG2 = FALSE;
+ else
+ to_BG2 = TRUE;
+
+ if (sMonAnimTaskIdArray[0] != 0xFF)
+ {
+ sub_80A477C(to_BG2);
+ DestroyTask(sMonAnimTaskIdArray[0]);
+ sMonAnimTaskIdArray[0] = 0xFF;
+ }
+ if (gTasks[taskId].data[0] > 1)
+ {
+ sub_80A477C(to_BG2 ^ 1);
+ DestroyTask(sMonAnimTaskIdArray[1]);
+ sMonAnimTaskIdArray[1] = 0xFF;
+ }
+ DestroyTask(taskId);
+ }
+}
+
+static void ScriptCmd_monbg_22(void)
+{
+ bool8 toBG_2;
+ u8 bank;
+ u8 animBankId;
+
+ sBattleAnimScriptPtr++;
+
+ animBankId = sBattleAnimScriptPtr[0];
+
+ if (animBankId == ANIM_BANK_ATTACKER)
+ animBankId = ANIM_BANK_ATK_PARTNER;
+ else if (animBankId == ANIM_BANK_TARGET)
+ animBankId = ANIM_BANK_DEF_PARTNER;
+
+ if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER)
+ bank = gAnimBankAttacker;
+ else
+ bank = gAnimBankTarget;
+
+ if (IsAnimBankSpriteVisible(bank))
+ {
+ u8 identity = GetBankIdentity(bank);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ toBG_2 = FALSE;
+ else
+ toBG_2 = TRUE;
+
+ sub_80A438C(bank, toBG_2, FALSE);
+ }
+
+ bank ^= BIT_MON;
+ if (animBankId > 1 && IsAnimBankSpriteVisible(bank))
+ {
+ u8 identity = GetBankIdentity(bank);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ toBG_2 = FALSE;
+ else
+ toBG_2 = TRUE;
+
+ sub_80A438C(bank, toBG_2, FALSE);
+ }
+
+ sBattleAnimScriptPtr++;
+}
+
+static void ScriptCmd_clearmonbg_23(void)
+{
+ u8 animBankId;
+ u8 bank;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ animBankId = sBattleAnimScriptPtr[0];
+
+ if (animBankId == ANIM_BANK_ATTACKER)
+ animBankId = ANIM_BANK_ATK_PARTNER;
+ else if (animBankId == ANIM_BANK_TARGET)
+ animBankId = ANIM_BANK_DEF_PARTNER;
+
+ if (animBankId == ANIM_BANK_ATTACKER || animBankId == ANIM_BANK_ATK_PARTNER)
+ bank = gAnimBankAttacker;
+ else
+ bank = gAnimBankTarget;
+
+ if (IsAnimBankSpriteVisible(bank))
+ gSprites[gBankSpriteIds[bank]].invisible = 0;
+ if (animBankId > 1 && IsAnimBankSpriteVisible(bank ^ BIT_MON))
+ gSprites[gBankSpriteIds[bank ^ BIT_MON]].invisible = 0;
+ else
+ animBankId = 0;
+
+ taskId = CreateTask(sub_80A4BB0, 5);
+ gTasks[taskId].data[0] = animBankId;
+ gTasks[taskId].data[2] = bank;
+
+ sBattleAnimScriptPtr++;
+}
+
+static void sub_80A4BB0(u8 taskId)
+{
+ gTasks[taskId].data[1]++;
+ if (gTasks[taskId].data[1] != 1)
+ {
+ bool8 toBG_2;
+ u8 bank = gTasks[taskId].data[2];
+ u8 identity = GetBankIdentity(bank);
+ if (identity == IDENTITY_OPPONENT_MON1 || identity == IDENTITY_PLAYER_MON2 || IsContest())
+ toBG_2 = FALSE;
+ else
+ toBG_2 = TRUE;
+
+ if (IsAnimBankSpriteVisible(bank))
+ sub_80A477C(toBG_2);
+ if (gTasks[taskId].data[0] > 1 && IsAnimBankSpriteVisible(bank ^ BIT_MON))
+ sub_80A477C(toBG_2 ^ 1);
+
+ DestroyTask(taskId);
+ }
+}
+
+#undef t1_MONBG_BANK
+#undef t1_MON_IN_BG2
+#undef t1_CREATE_ANOTHER_TASK
+#undef t1_IS_SECONDMON_BG
+
+#undef t2_BANK_SPRITE_ID
+#undef t2_MON_IN_BG2
+#undef t2_MONBG_BANK
+
+static void ScriptCmd_setalpha(void)
+{
+ u16 half1, half2;
+
+ sBattleAnimScriptPtr++;
+ half1 = *(sBattleAnimScriptPtr++);
+ half2 = *(sBattleAnimScriptPtr++) << 8;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x3F40);
+ SetGpuReg(REG_OFFSET_BLDALPHA, half1 | half2);
+}
+
+static void ScriptCmd_setbldcnt(void)
+{
+ u16 half1, half2;
+
+ sBattleAnimScriptPtr++;
+ half1 = *(sBattleAnimScriptPtr++);
+ half2 = *(sBattleAnimScriptPtr++) << 8;
+ SetGpuReg(REG_OFFSET_BLDCNT, half1 | half2);
+}
+
+static void ScriptCmd_blendoff(void)
+{
+ sBattleAnimScriptPtr++;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+}
+
+static void ScriptCmd_call(void)
+{
+ sBattleAnimScriptPtr++;
+ sBattleAnimScriptRetAddr = sBattleAnimScriptPtr + 4;
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr);
+}
+
+static void ScriptCmd_return(void)
+{
+ sBattleAnimScriptPtr = sBattleAnimScriptRetAddr;
+}
+
+static void ScriptCmd_setarg(void)
+{
+ const u8 *addr = sBattleAnimScriptPtr;
+ u16 value;
+ u8 argId;
+
+ sBattleAnimScriptPtr++;
+ argId = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+ value = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr = addr + 4;
+ gBattleAnimArgs[argId] = value;
+}
+
+static void ScriptCmd_choosetwoturnanim(void)
+{
+ sBattleAnimScriptPtr++;
+ if (gAnimMoveTurn & 1)
+ sBattleAnimScriptPtr += 4;
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr);
+}
+
+static void ScriptCmd_jumpifmoveturn(void)
+{
+ u8 toCheck;
+ sBattleAnimScriptPtr++;
+ toCheck = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+
+ if (toCheck == gAnimMoveTurn)
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr);
+ else
+ sBattleAnimScriptPtr += 4;
+}
+
+static void ScriptCmd_jump(void)
+{
+ sBattleAnimScriptPtr++;
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr);
+}
+
+// Uses of this function that rely on a TRUE return are expecting inBattle to not be ticked as defined in contest behavior. As a result, if misused, this function cannot reliably discern between field and contest status and could result in undefined behavior.
+bool8 IsContest(void)
+{
+ if (!gMain.inBattle)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+#define tBackgroundId data[0]
+#define tState data[10]
+
+static void ScriptCmd_fadetobg(void)
+{
+ u8 backgroundId;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ backgroundId = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+ taskId = CreateTask(Task_FadeToBg, 5);
+ gTasks[taskId].tBackgroundId = backgroundId;
+ sAnimBackgroundFadeState = 1;
+}
+
+static void ScriptCmd_fadetobgfromset(void)
+{
+ u8 bg1, bg2, bg3;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ bg1 = sBattleAnimScriptPtr[0];
+ bg2 = sBattleAnimScriptPtr[1];
+ bg3 = sBattleAnimScriptPtr[2];
+ sBattleAnimScriptPtr += 3;
+ taskId = CreateTask(Task_FadeToBg, 5);
+
+ if (IsContest())
+ gTasks[taskId].tBackgroundId = bg3;
+ else if (GetBankSide(gAnimBankTarget) == SIDE_PLAYER)
+ gTasks[taskId].tBackgroundId = bg2;
+ else
+ gTasks[taskId].tBackgroundId = bg1;
+
+ sAnimBackgroundFadeState = 1;
+}
+
+static void Task_FadeToBg(u8 taskId)
+{
+ if (gTasks[taskId].tState == 0)
+ {
+ BeginHardwarePaletteFade(0xE8, 0, 0, 16, 0);
+ gTasks[taskId].tState++;
+ return;
+ }
+ if (gPaletteFade.active)
+ return;
+ if (gTasks[taskId].tState == 1)
+ {
+ gTasks[taskId].tState++;
+ sAnimBackgroundFadeState = 2;
+ }
+ else if (gTasks[taskId].tState == 2)
+ {
+ s16 bgId = gTasks[taskId].tBackgroundId;
+
+ if (bgId == -1)
+ LoadDefaultBg();
+ else
+ LoadMoveBg(bgId);
+
+ BeginHardwarePaletteFade(0xE8, 0, 16, 0, 1);
+ gTasks[taskId].tState++;
+ return;
+ }
+ if (gPaletteFade.active)
+ return;
+ if (gTasks[taskId].tState == 3)
+ {
+ DestroyTask(taskId);
+ sAnimBackgroundFadeState = 0;
+ }
+}
+
+static void LoadMoveBg(u16 bgId)
+{
+ if (IsContest())
+ {
+ const void *tilemap = gBattleAnimBackgroundTable[bgId].tilemap;
+ void *dmaSrc;
+ void *dmaDest;
+
+ LZDecompressWram(tilemap, gDecompressionBuffer);
+ sub_80A4720(sub_80A6D94(), (void*)(gDecompressionBuffer), 0x100, 0);
+ dmaSrc = gDecompressionBuffer;
+ dmaDest = (void *)(VRAM + 0xD000);
+ DmaCopy32(3, dmaSrc, dmaDest, 0x800);
+ LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x2000));
+ LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, sub_80A6D94() * 16, 32);
+ }
+ else
+ {
+ LZDecompressVram(gBattleAnimBackgroundTable[bgId].tilemap, (void *)(VRAM + 0xD000));
+ LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x8000));
+ LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, 32, 32);
+ }
+}
+
+static void LoadDefaultBg(void)
+{
+ if (IsContest())
+ LoadContestBgAfterMoveAnim();
+ else
+ DrawMainBattleBackground();
+}
+
+static void ScriptCmd_restorebg(void)
+{
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ taskId = CreateTask(Task_FadeToBg, 5);
+ gTasks[taskId].tBackgroundId = -1;
+ sAnimBackgroundFadeState = 1;
+}
+
+#undef tBackgroundId
+#undef tState
+
+static void ScriptCmd_waitbgfadeout(void)
+{
+ if (sAnimBackgroundFadeState == 2)
+ {
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = 0;
+ }
+ else
+ {
+ gAnimFramesToWait = 1;
+ }
+}
+
+static void ScriptCmd_waitbgfadein(void)
+{
+ if (sAnimBackgroundFadeState == 0)
+ {
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = 0;
+ }
+ else
+ {
+ gAnimFramesToWait = 1;
+ }
+}
+
+static void ScriptCmd_changebg(void)
+{
+ sBattleAnimScriptPtr++;
+ LoadMoveBg(sBattleAnimScriptPtr[0]);
+ sBattleAnimScriptPtr++;
+}
+
+s8 BattleAnimAdjustPanning(s8 pan)
+{
+ if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10)
+ {
+ if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER)
+ pan = PAN_SIDE_OPPONENT;
+ else
+ pan = PAN_SIDE_PLAYER;
+ }
+ else if (IsContest())
+ {
+ if (gAnimBankAttacker != gAnimBankTarget || gAnimBankAttacker != 2 || pan != PAN_SIDE_OPPONENT)
+ pan *= -1;
+ }
+ else if (GetBankSide(gAnimBankAttacker) == SIDE_PLAYER)
+ {
+ if (GetBankSide(gAnimBankTarget) == SIDE_PLAYER)
+ {
+ if (pan == PAN_SIDE_OPPONENT)
+ pan = PAN_SIDE_PLAYER;
+ else if (pan != PAN_SIDE_PLAYER)
+ pan *= -1;
+ }
+ }
+ else if (GetBankSide(gAnimBankTarget) == SIDE_OPPONENT)
+ {
+ if (pan == PAN_SIDE_PLAYER)
+ pan = PAN_SIDE_OPPONENT;
+ }
+ else
+ {
+ pan *= -1;
+ }
+
+ if (pan > PAN_SIDE_OPPONENT)
+ pan = PAN_SIDE_OPPONENT;
+ else if (pan < PAN_SIDE_PLAYER)
+ pan = PAN_SIDE_PLAYER;
+
+ return pan;
+}
+
+s8 BattleAnimAdjustPanning2(s8 pan)
+{
+ if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].flag_x10)
+ {
+ if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER)
+ pan = PAN_SIDE_OPPONENT;
+ else
+ pan = PAN_SIDE_PLAYER;
+ }
+ else
+ {
+ if (GetBankSide(gAnimBankAttacker) != SIDE_PLAYER || IsContest())
+ pan = -pan;
+ }
+ return pan;
+}
+
+s16 sub_80A52EC(s16 a)
+{
+ s16 var = a;
+
+ if (var > 63)
+ var = 63;
+ else if (var < -64)
+ var = -64;
+
+ return var;
+}
+
+s16 CalculatePanIncrement(s16 sourcePan, s16 targetPan, s16 incrementPan)
+{
+ s16 ret;
+
+ if (sourcePan < targetPan)
+ ret = ((incrementPan < 0) ? -incrementPan : incrementPan);
+ else if (sourcePan > targetPan)
+ ret = -((incrementPan < 0) ? -incrementPan : incrementPan);
+ else
+ ret = 0;
+
+ return ret;
+}
+
+static void ScriptCmd_playsewithpan(void)
+{
+ u16 songId;
+ s8 pan;
+
+ sBattleAnimScriptPtr++;
+ songId = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ pan = sBattleAnimScriptPtr[2];
+ PlaySE12WithPanning(songId, BattleAnimAdjustPanning(pan));
+ sBattleAnimScriptPtr += 3;
+}
+
+static void ScriptCmd_setpan(void)
+{
+ s8 pan;
+
+ sBattleAnimScriptPtr++;
+ pan = sBattleAnimScriptPtr[0];
+ SE12PanpotControl(BattleAnimAdjustPanning(pan));
+ sBattleAnimScriptPtr++;
+}
+
+#define tInitialPan data[0]
+#define tTargetPan data[1]
+#define tIncrementPan data[2]
+#define tFramesToWait data[3]
+#define tCurrentPan data[4]
+#define tFrameCounter data[8]
+
+static void ScriptCmd_panse_1B(void)
+{
+ u16 songNum;
+ s8 currentPanArg, incrementPan, incrementPanArg, currentPan, targetPan;
+ u8 framesToWait;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ songNum = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ currentPanArg = sBattleAnimScriptPtr[2];
+ incrementPan = sBattleAnimScriptPtr[3];
+ incrementPanArg = sBattleAnimScriptPtr[4];
+ framesToWait = sBattleAnimScriptPtr[5];
+
+ currentPan = BattleAnimAdjustPanning(currentPanArg);
+ targetPan = BattleAnimAdjustPanning(incrementPan);
+ incrementPan = CalculatePanIncrement(currentPan, targetPan, incrementPanArg);
+ taskId = CreateTask(Task_PanFromInitialToTarget, 1);
+ gTasks[taskId].tInitialPan = currentPan;
+ gTasks[taskId].tTargetPan = targetPan;
+ gTasks[taskId].tIncrementPan = incrementPan;
+ gTasks[taskId].tFramesToWait = framesToWait;
+ gTasks[taskId].tCurrentPan = currentPan;
+
+ PlaySE12WithPanning(songNum, currentPan);
+
+ gAnimSoundTaskCount++;
+ sBattleAnimScriptPtr += 6;
+}
+
+void Task_PanFromInitialToTarget(u8 taskId)
+{
+ bool32 destroyTask = FALSE;
+ if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait)
+ {
+ s16 pan;
+ s16 initialPanning, targetPanning, currentPan, incrementPan;
+
+ gTasks[taskId].tFrameCounter = 0;
+ initialPanning = gTasks[taskId].tInitialPan;
+ targetPanning = gTasks[taskId].tTargetPan;
+ currentPan = gTasks[taskId].tCurrentPan;
+ incrementPan = gTasks[taskId].tIncrementPan;
+ pan = currentPan + incrementPan;
+ gTasks[taskId].tCurrentPan = pan;
+
+ if (incrementPan == 0) // If we're not incrementing, just cancel the task immediately
+ {
+ destroyTask = TRUE;
+ }
+ else if (initialPanning < targetPanning) // Panning increasing
+ {
+ if (pan >= targetPanning) // Target reached
+ destroyTask = TRUE;
+ }
+ else // Panning decreasing
+ {
+ if (pan <= targetPanning) // Target reached
+ destroyTask = TRUE;
+ }
+
+ if (destroyTask)
+ {
+ pan = targetPanning;
+ DestroyTask(taskId);
+ gAnimSoundTaskCount--;
+ }
+
+ SE12PanpotControl(pan);
+ }
+}
+
+static void ScriptCmd_panse_26(void)
+{
+ u16 songId;
+ s8 currentPan, targetPan, incrementPan;
+ u8 framesToWait;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ songId = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ currentPan = sBattleAnimScriptPtr[2];
+ targetPan = sBattleAnimScriptPtr[3];
+ incrementPan = sBattleAnimScriptPtr[4];
+ framesToWait = sBattleAnimScriptPtr[5];
+
+ taskId = CreateTask(Task_PanFromInitialToTarget, 1);
+ gTasks[taskId].tInitialPan = currentPan;
+ gTasks[taskId].tTargetPan = targetPan;
+ gTasks[taskId].tIncrementPan = incrementPan;
+ gTasks[taskId].tFramesToWait = framesToWait;
+ gTasks[taskId].tCurrentPan = currentPan;
+
+ PlaySE12WithPanning(songId, currentPan);
+
+ gAnimSoundTaskCount++;
+ sBattleAnimScriptPtr += 6;
+}
+
+static void ScriptCmd_panse_27(void)
+{
+ u16 songId;
+ s8 targetPanArg, incrementPanArg, currentPanArg, currentPan, targetPan, incrementPan;
+ u8 framesToWait;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ songId = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ currentPanArg = sBattleAnimScriptPtr[2];
+ targetPanArg = sBattleAnimScriptPtr[3];
+ incrementPanArg = sBattleAnimScriptPtr[4];
+ framesToWait = sBattleAnimScriptPtr[5];
+
+ currentPan = BattleAnimAdjustPanning2(currentPanArg);
+ targetPan = BattleAnimAdjustPanning2(targetPanArg);
+ incrementPan = BattleAnimAdjustPanning2(incrementPanArg);
+
+ taskId = CreateTask(Task_PanFromInitialToTarget, 1);
+ gTasks[taskId].tInitialPan = currentPan;
+ gTasks[taskId].tTargetPan = targetPan;
+ gTasks[taskId].tIncrementPan = incrementPan;
+ gTasks[taskId].tFramesToWait = framesToWait;
+ gTasks[taskId].tCurrentPan = currentPan;
+
+ PlaySE12WithPanning(songId, currentPan);
+
+ gAnimSoundTaskCount++;
+ sBattleAnimScriptPtr += 6;
+}
+
+#undef tInitialPan
+#undef tTargetPan
+#undef tIncrementPan
+#undef tFramesToWait
+#undef tCurrentPan
+#undef tFrameCounter
+
+#define tSongId data[0]
+#define tPanning data[1]
+#define tFramesToWait data[2]
+#define tNumberOfPlays data[3]
+#define tFrameCounter data[8]
+
+static void ScriptCmd_loopsewithpan(void)
+{
+ u16 songId;
+ s8 panningArg, panning;
+ u8 framesToWait, numberOfPlays;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ songId = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ panningArg = sBattleAnimScriptPtr[2];
+ framesToWait = sBattleAnimScriptPtr[3];
+ numberOfPlays = sBattleAnimScriptPtr[4];
+ panning = BattleAnimAdjustPanning(panningArg);
+
+ taskId = CreateTask(Task_LoopAndPlaySE, 1);
+ gTasks[taskId].tSongId = songId;
+ gTasks[taskId].tPanning = panning;
+ gTasks[taskId].tFramesToWait = framesToWait;
+ gTasks[taskId].tNumberOfPlays = numberOfPlays;
+ gTasks[taskId].tFrameCounter = framesToWait;
+ gTasks[taskId].func(taskId);
+
+ gAnimSoundTaskCount++;
+ sBattleAnimScriptPtr += 5;
+}
+
+static void Task_LoopAndPlaySE(u8 taskId)
+{
+ if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait)
+ {
+ u16 songId;
+ s8 panning;
+ u8 numberOfPlays;
+
+ gTasks[taskId].tFrameCounter = 0;
+ songId = gTasks[taskId].tSongId;
+ panning = gTasks[taskId].tPanning;
+ numberOfPlays = --gTasks[taskId].tNumberOfPlays;
+ PlaySE12WithPanning(songId, panning);
+ if (numberOfPlays == 0)
+ {
+ DestroyTask(taskId);
+ gAnimSoundTaskCount--;
+ }
+ }
+}
+
+#undef tSongId
+#undef tPanning
+#undef tFramesToWait
+#undef tNumberOfPlays
+#undef tFrameCounter
+
+#define tSongId data[0]
+#define tPanning data[1]
+#define tFramesToWait data[2]
+
+static void ScriptCmd_waitplaysewithpan(void)
+{
+ u16 songId;
+ s8 panningArg, panning;
+ u8 framesToWait;
+ u8 taskId;
+
+ sBattleAnimScriptPtr++;
+ songId = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ panningArg = sBattleAnimScriptPtr[2];
+ framesToWait = sBattleAnimScriptPtr[3];
+ panning = BattleAnimAdjustPanning(panningArg);
+
+ taskId = CreateTask(Task_WaitAndPlaySE, 1);
+ gTasks[taskId].tSongId = songId;
+ gTasks[taskId].tPanning = panning;
+ gTasks[taskId].tFramesToWait = framesToWait;
+
+ gAnimSoundTaskCount++;
+ sBattleAnimScriptPtr += 4;
+}
+
+static void Task_WaitAndPlaySE(u8 taskId)
+{
+ if (gTasks[taskId].tFramesToWait-- <= 0)
+ {
+ PlaySE12WithPanning(gTasks[taskId].tSongId, gTasks[taskId].tPanning);
+ DestroyTask(taskId);
+ gAnimSoundTaskCount--;
+ }
+}
+
+#undef tSongId
+#undef tPanning
+#undef tFramesToWait
+
+static void ScriptCmd_createsoundtask(void)
+{
+ TaskFunc func;
+ u8 numArgs, taskId;
+ s32 i;
+
+ sBattleAnimScriptPtr++;
+ func = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr += 4;
+ numArgs = sBattleAnimScriptPtr[0];
+ sBattleAnimScriptPtr++;
+ for (i = 0; i < numArgs; i++)
+ {
+ gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr);
+ sBattleAnimScriptPtr += 2;
+ }
+ taskId = CreateTask(func, 1);
+ func(taskId);
+ gAnimSoundTaskCount++;
+}
+
+static void ScriptCmd_waitsound(void)
+{
+ if (gAnimSoundTaskCount != 0)
+ {
+ sSoundAnimFramesToWait = 0;
+ gAnimFramesToWait = 1;
+ }
+ else if (IsSEPlaying())
+ {
+ if (++sSoundAnimFramesToWait > 90)
+ {
+ m4aMPlayStop(&gMPlay_SE1);
+ m4aMPlayStop(&gMPlay_SE2);
+ sSoundAnimFramesToWait = 0;
+ }
+ else
+ {
+ gAnimFramesToWait = 1;
+ }
+ }
+ else
+ {
+ sSoundAnimFramesToWait = 0;
+ sBattleAnimScriptPtr++;
+ gAnimFramesToWait = 0;
+ }
+}
+
+static void ScriptCmd_jumpargeq(void)
+{
+ u8 argId;
+ s16 valueToCheck;
+
+ sBattleAnimScriptPtr++;
+ argId = sBattleAnimScriptPtr[0];
+ valueToCheck = SCRIPT_READ_16(sBattleAnimScriptPtr + 1);
+
+ if (valueToCheck == gBattleAnimArgs[argId])
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr + 3);
+ else
+ sBattleAnimScriptPtr += 7;
+}
+
+static void ScriptCmd_jumpifcontest(void)
+{
+ sBattleAnimScriptPtr++;
+ if (IsContest())
+ sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr);
+ else
+ sBattleAnimScriptPtr += 4;
+}
+
+static void ScriptCmd_monbgprio_28(void)
+{
+ u8 wantedBank;
+ u8 bank;
+ u8 bankIdentity;
+
+ wantedBank = sBattleAnimScriptPtr[1];
+ sBattleAnimScriptPtr += 2;
+
+ if (wantedBank != ANIM_BANK_ATTACKER)
+ bank = gAnimBankTarget;
+ else
+ bank = gAnimBankAttacker;
+
+ bankIdentity = GetBankIdentity(bank);
+ if (!IsContest() && (bankIdentity == IDENTITY_PLAYER_MON1 || bankIdentity == IDENTITY_OPPONENT_MON2))
+ {
+ SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
+ SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2);
+ }
+}
+
+static void ScriptCmd_monbgprio_29(void)
+{
+ sBattleAnimScriptPtr++;
+ if (!IsContest())
+ {
+ SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
+ SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2);
+ }
+}
+
+static void ScriptCmd_monbgprio_2A(void)
+{
+ u8 wantedBank;
+ u8 bankIdentity;
+ u8 bank;
+
+ wantedBank = sBattleAnimScriptPtr[1];
+ sBattleAnimScriptPtr += 2;
+ if (GetBankSide(gAnimBankAttacker) != GetBankSide(gAnimBankTarget))
+ {
+ if (wantedBank != ANIM_BANK_ATTACKER)
+ bank = gAnimBankTarget;
+ else
+ bank = gAnimBankAttacker;
+
+ bankIdentity = GetBankIdentity(bank);
+ if (!IsContest() && (bankIdentity == IDENTITY_PLAYER_MON1 || bankIdentity == IDENTITY_OPPONENT_MON2))
+ {
+ SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
+ SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2);
+ }
+ }
+}
+
+static void ScriptCmd_invisible(void)
+{
+ u8 spriteId;
+
+ spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]);
+ if (spriteId != 0xFF)
+ gSprites[spriteId].invisible = 1;
+
+ sBattleAnimScriptPtr += 2;
+}
+
+static void ScriptCmd_visible(void)
+{
+ u8 spriteId;
+
+ spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]);
+ if (spriteId != 0xFF)
+ gSprites[spriteId].invisible = 0;
+
+ sBattleAnimScriptPtr += 2;
+}
+
+static void ScriptCmd_doublebattle_2D(void)
+{
+ u8 wantedBank;
+ u8 r4;
+ u8 spriteId;
+
+ wantedBank = sBattleAnimScriptPtr[1];
+ sBattleAnimScriptPtr += 2;
+ if (!IsContest() && IsDoubleBattle()
+ && GetBankSide(gAnimBankAttacker) == GetBankSide(gAnimBankTarget))
+ {
+ if (wantedBank == ANIM_BANK_ATTACKER)
+ {
+ r4 = sub_80A8364(gAnimBankAttacker);
+ spriteId = GetAnimBankSpriteId(0);
+ }
+ else
+ {
+ r4 = sub_80A8364(gAnimBankTarget);
+ spriteId = GetAnimBankSpriteId(1);
+ }
+ if (spriteId != 0xFF)
+ {
+ gSprites[spriteId].invisible = FALSE;
+ if (r4 == 2)
+ gSprites[spriteId].oam.priority = 3;
+
+ if (r4 == 1)
+ sub_80A477C(FALSE);
+ else
+ sub_80A477C(TRUE);
+ }
+ }
+}
+
+static void ScriptCmd_doublebattle_2E(void)
+{
+ u8 wantedBank;
+ u8 r4;
+ u8 spriteId;
+
+ wantedBank = sBattleAnimScriptPtr[1];
+ sBattleAnimScriptPtr += 2;
+ if (!IsContest() && IsDoubleBattle()
+ && GetBankSide(gAnimBankAttacker) == GetBankSide(gAnimBankTarget))
+ {
+ if (wantedBank == ANIM_BANK_ATTACKER)
+ {
+ r4 = sub_80A8364(gAnimBankAttacker);
+ spriteId = GetAnimBankSpriteId(0);
+ }
+ else
+ {
+ r4 = sub_80A8364(gAnimBankTarget);
+ spriteId = GetAnimBankSpriteId(1);
+ }
+
+ if (spriteId != 0xFF && r4 == 2)
+ gSprites[spriteId].oam.priority = 2;
+ }
+}
+
+static void ScriptCmd_stopsound(void)
+{
+ m4aMPlayStop(&gMPlay_SE1);
+ m4aMPlayStop(&gMPlay_SE2);
+ sBattleAnimScriptPtr++;
+}
diff --git a/src/battle_controllers.c b/src/battle_controllers.c
new file mode 100644
index 000000000..9ac18c72f
--- /dev/null
+++ b/src/battle_controllers.c
@@ -0,0 +1,1551 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_controllers.h"
+#include "link.h"
+#include "task.h"
+#include "battle_ai_script_commands.h"
+#include "battle_anim.h"
+#include "pokemon.h"
+#include "species.h"
+#include "recorded_battle.h"
+#include "util.h"
+#include "abilities.h"
+#include "battle_message.h"
+
+extern u32 gBattleTypeFlags;
+extern u32 gBattleExecBuffer;
+extern void (*gBattleMainFunc)(void);
+extern void (*gBattleBankFunc[BATTLE_BANKS_COUNT])(void);
+extern u8 gBanksByIdentity[BATTLE_BANKS_COUNT];
+extern u8 gActionSelectionCursor[BATTLE_BANKS_COUNT];
+extern u8 gMoveSelectionCursor[BATTLE_BANKS_COUNT];
+extern u8 gNoOfAllBanks;
+extern u8 gActiveBank;
+extern u8 gUnknown_0202428C;
+extern u32 gUnknown_02022FF4;
+extern u8 gUnknown_0203C7B4;
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gBattleBufferA[BATTLE_BANKS_COUNT][0x200];
+extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
+extern u8 gBattleBuffersTransferData[0x100];
+extern u8 gUnknown_02022D08;
+extern u8 gUnknown_02022D09;
+extern u8 gUnknown_02022D0A;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gAbsentBankFlags;
+extern u8 gEffectBank;
+extern u16 gBattleWeather;
+extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
+extern u16 gCurrentMove;
+extern u16 gLastUsedMove;
+extern u16 gLastUsedItem;
+extern u8 gBattleOutcome;
+extern u8 gLastUsedAbility;
+extern u8 gStringBank;
+
+extern const struct BattleMove gBattleMoves[];
+
+extern void task00_08081A90(u8 taskId); // cable_club
+extern void sub_81B8D64(u8 bank, u8 arg1); // party_menu
+
+// this file's funcionts
+static void CreateTasksForSendRecvLinkBuffers(void);
+static void SetControllersVariablesInLinkBattle(void);
+static void SetControllersVariables(void);
+static void SetBattlePartyIds(void);
+static void Task_HandleSendLinkBuffersData(u8 taskId);
+static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId);
+
+void HandleLinkBattleSetup(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (gLinkVSyncDisabled)
+ sub_800B488();
+ if (!gReceivedRemoteLinkPlayers)
+ sub_8009734();
+ CreateTask(task00_08081A90, 0);
+ CreateTasksForSendRecvLinkBuffers();
+ }
+}
+
+void SetUpBattleVarsAndBirchZigzagoon(void)
+{
+ s32 i;
+
+ gBattleMainFunc = nullsub_20;
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ gBattleBankFunc[i] = nullsub_21;
+ gBanksByIdentity[i] = 0xFF;
+ gActionSelectionCursor[i] = 0;
+ gMoveSelectionCursor[i] = 0;
+ }
+
+ HandleLinkBattleSetup();
+ gBattleExecBuffer = 0;
+ ClearBattleAnimationVars();
+ ClearBattleMonForms();
+ BattleAI_HandleItemUseBeforeAISetup(0xF);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ ZeroEnemyPartyMons();
+ CreateMon(&gEnemyParty[0], SPECIES_ZIGZAGOON, 2, 32, 0, 0, 0, 0);
+ i = 0;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &i);
+ }
+
+ gUnknown_02022FF4 = 0;
+ gUnknown_0202428C = 0;
+}
+
+void sub_8032768(void)
+{
+ s32 i;
+ u8 *data;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ sub_8184DA4(1);
+ else
+ sub_8184DA4(2);
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
+ sub_8185EB8();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ SetControllersVariablesInLinkBattle();
+ else
+ SetControllersVariables();
+
+ SetBattlePartyIds();
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ sub_81B8D64(i, 0);
+ }
+
+ for (i = 0; i < sizeof(gBattleStruct->field_1A4); i++)
+ *(gBattleStruct->field_1A4 + i) = 0;
+
+ for (i = 0; i < sizeof(gBattleStruct->field_204); i++)
+ *(gBattleStruct->field_204 + i) = 0;
+}
+
+static void SetControllersVariables(void)
+{
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToPlayerPartnerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+ }
+ else
+ {
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToPlayerPartnerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+ }
+
+ gNoOfAllBanks = 4;
+
+ sub_81B8D64(0, 0);
+ sub_81B8D64(1, 0);
+ sub_81B8D64(2, 1);
+ sub_81B8D64(3, 1);
+
+ gBattlePartyID[0] = 0;
+ gBattlePartyID[1] = 0;
+ gBattlePartyID[2] = 3;
+ gBattlePartyID[3] = 3;
+ }
+ else if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ gBattleBankFunc[0] = SetBankFuncToSafariBufferRunCommand;
+ else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
+ gBattleBankFunc[0] = SetBankFuncToWallyBufferRunCommand;
+ else
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gNoOfAllBanks = 2;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gNoOfAllBanks = 2;
+ }
+ else // see how the banks are switched
+ {
+ gBattleBankFunc[1] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[0] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1;
+
+ gNoOfAllBanks = 2;
+ }
+ }
+ else
+ {
+ gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+ }
+ }
+ }
+ else
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+
+ gNoOfAllBanks = 4;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[0] = 0;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = 1;
+
+ gBattleBankFunc[2] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[2] = 2;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = 3;
+
+ gNoOfAllBanks = 4;
+
+ sub_81B8D64(0, 0);
+ sub_81B8D64(1, 0);
+ sub_81B8D64(2, 1);
+ sub_81B8D64(3, 1);
+
+ gBattlePartyID[0] = 0;
+ gBattlePartyID[1] = 0;
+ gBattlePartyID[2] = 3;
+ gBattlePartyID[3] = 3;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ u8 var; // multiplayer Id in a recorded battle?
+
+ for (var = gUnknown_0203C7B4, i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ sub_81B8D64(gLinkPlayers[i].lp_field_18, 0);
+ break;
+ case 1:
+ case 2:
+ sub_81B8D64(gLinkPlayers[i].lp_field_18, 1);
+ break;
+ }
+
+ if (i == var)
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON1;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[var].lp_field_18 & 1))
+ || ((gLinkPlayers[i].lp_field_18 & 1) && (gLinkPlayers[var].lp_field_18 & 1)))
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON1;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_PLAYER_MON2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_OPPONENT_MON1;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = IDENTITY_OPPONENT_MON2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ }
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleBankFunc[0] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ gBattleBankFunc[1] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[3] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+ }
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[3] = SetBankFuncToRecordedPlayerBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_PLAYER_MON2;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ {
+ gBattleBankFunc[0] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToRecordedOpponentBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2;
+ }
+ else
+ {
+ gBattleBankFunc[0] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2;
+ }
+ }
+ }
+ }
+}
+
+static void SetControllersVariablesInLinkBattle(void)
+{
+ s32 i;
+ u8 multiplayerId;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gNoOfAllBanks = 2;
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1;
+
+ gNoOfAllBanks = 2;
+ }
+ }
+ else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+
+ gNoOfAllBanks = 4;
+ }
+ else
+ {
+ gBattleBankFunc[1] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[0] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[3] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[2] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_OPPONENT_MON2;
+
+ gNoOfAllBanks = 4;
+ }
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ {
+ gBattleMainFunc = BeginBattleIntro;
+
+ gBattleBankFunc[0] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToLinkPartnerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+
+ gNoOfAllBanks = 4;
+ }
+ else
+ {
+ gBattleBankFunc[0] = SetBankFuncToLinkPartnerBufferRunCommand;
+ gBanksByIdentity[0] = IDENTITY_PLAYER_MON1;
+
+ gBattleBankFunc[1] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[1] = IDENTITY_OPPONENT_MON1;
+
+ gBattleBankFunc[2] = SetBankFuncToPlayerBufferRunCommand;
+ gBanksByIdentity[2] = IDENTITY_PLAYER_MON2;
+
+ gBattleBankFunc[3] = SetBankFuncToLinkOpponentBufferRunCommand;
+ gBanksByIdentity[3] = IDENTITY_OPPONENT_MON2;
+
+ gNoOfAllBanks = 4;
+ }
+
+ sub_81B8D64(0, 0);
+ sub_81B8D64(1, 0);
+ sub_81B8D64(2, 1);
+ sub_81B8D64(3, 1);
+ gBattlePartyID[0] = 0;
+ gBattlePartyID[1] = 0;
+ gBattlePartyID[2] = 3;
+ gBattlePartyID[3] = 3;
+ }
+ else
+ {
+ multiplayerId = GetMultiplayerId();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_WILD)
+ gBattleMainFunc = BeginBattleIntro;
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ sub_81B8D64(gLinkPlayers[i].lp_field_18, 0);
+ break;
+ case 1:
+ case 2:
+ sub_81B8D64(gLinkPlayers[i].lp_field_18, 1);
+ break;
+ }
+
+ if (i == multiplayerId)
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToPlayerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 0;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[multiplayerId].lp_field_18 & 1))
+ || ((gLinkPlayers[i].lp_field_18 & 1) && (gLinkPlayers[multiplayerId].lp_field_18 & 1)))
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToLinkPartnerBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 0;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 2;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ else
+ {
+ gBattleBankFunc[gLinkPlayers[i].lp_field_18] = SetBankFuncToLinkOpponentBufferRunCommand;
+ switch (gLinkPlayers[i].lp_field_18)
+ {
+ case 0:
+ case 3:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 1;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 0;
+ break;
+ case 1:
+ case 2:
+ gBanksByIdentity[gLinkPlayers[i].lp_field_18] = 3;
+ gBattlePartyID[gLinkPlayers[i].lp_field_18] = 3;
+ break;
+ }
+ }
+ }
+ }
+
+ gNoOfAllBanks = 4;
+ }
+}
+
+static void SetBattlePartyIds(void)
+{
+ s32 i, j;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ for (j = 0; j < 6; j++)
+ {
+ if (i < 2)
+ {
+ if (GET_BANK_SIDE2(i) == SIDE_PLAYER)
+ {
+ if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ else
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (GET_BANK_SIDE2(i) == SIDE_PLAYER)
+ {
+ if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != SPECIES_NONE // Probably a typo by Game Freak. The rest use SPECIES2.
+ && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0
+ && gBattlePartyID[i - 2] != j)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ else
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE
+ && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
+ && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0
+ && gBattlePartyID[i - 2] != j)
+ {
+ gBattlePartyID[i] = j;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ gBattlePartyID[1] = 0, gBattlePartyID[3] = 3;
+ }
+}
+
+static void PrepareBufferDataTransfer(u8 bufferId, u8 *data, u16 size)
+{
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ PrepareBufferDataTransferLink(bufferId, size, data);
+ }
+ else
+ {
+ switch (bufferId)
+ {
+ case 0:
+ for (i = 0; i < size; i++)
+ {
+ gBattleBufferA[gActiveBank][i] = *data;
+ data++;
+ }
+ break;
+ case 1:
+ for (i = 0; i < size; i++)
+ {
+ gBattleBufferB[gActiveBank][i] = *data;
+ data++;
+ }
+ break;
+ }
+ }
+}
+
+static void CreateTasksForSendRecvLinkBuffers(void)
+{
+ gUnknown_02022D08 = CreateTask(Task_HandleSendLinkBuffersData, 0);
+ gTasks[gUnknown_02022D08].data[11] = 0;
+ gTasks[gUnknown_02022D08].data[12] = 0;
+ gTasks[gUnknown_02022D08].data[13] = 0;
+ gTasks[gUnknown_02022D08].data[14] = 0;
+ gTasks[gUnknown_02022D08].data[15] = 0;
+
+ gUnknown_02022D09 = CreateTask(Task_HandleCopyReceivedLinkBuffersData, 0);
+ gTasks[gUnknown_02022D09].data[12] = 0;
+ gTasks[gUnknown_02022D09].data[13] = 0;
+ gTasks[gUnknown_02022D09].data[14] = 0;
+ gTasks[gUnknown_02022D09].data[15] = 0;
+
+ gUnknown_02022D0A = 0;
+}
+
+enum
+{
+ LINK_BUFF_BUFFER_ID,
+ LINK_BUFF_ACTIVE_BANK,
+ LINK_BUFF_ATTACKER,
+ LINK_BUFF_TARGET,
+ LINK_BUFF_SIZE_LO,
+ LINK_BUFF_SIZE_HI,
+ LINK_BUFF_ABSENT_BANK_FLAGS,
+ LINK_BUFF_EFFECT_BANK,
+ LINK_BUFF_DATA
+};
+
+void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data)
+{
+ s32 alignedSize;
+ s32 i;
+
+ alignedSize = size - size % 4 + 4;
+ if (gTasks[gUnknown_02022D08].data[14] + alignedSize + LINK_BUFF_DATA + 1 > BATTLE_BUFFER_LINK_SIZE)
+ {
+ gTasks[gUnknown_02022D08].data[12] = gTasks[gUnknown_02022D08].data[14];
+ gTasks[gUnknown_02022D08].data[14] = 0;
+ }
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_BUFFER_ID] = bufferId;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ACTIVE_BANK] = gActiveBank;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ATTACKER] = gBankAttacker;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_TARGET] = gBankTarget;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_SIZE_LO] = alignedSize;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_SIZE_HI] = (alignedSize & 0x0000FF00) >> 8;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_ABSENT_BANK_FLAGS] = gAbsentBankFlags;
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_EFFECT_BANK] = gEffectBank;
+
+ for (i = 0; i < size; i++)
+ gLinkBattleSendBuffer[gTasks[gUnknown_02022D08].data[14] + LINK_BUFF_DATA + i] = data[i];
+
+ gTasks[gUnknown_02022D08].data[14] = gTasks[gUnknown_02022D08].data[14] + alignedSize + LINK_BUFF_DATA;
+}
+
+static void Task_HandleSendLinkBuffersData(u8 taskId)
+{
+ u16 var;
+ u16 blockSize;
+
+ switch (gTasks[taskId].data[11])
+ {
+ case 0:
+ gTasks[taskId].data[10] = 100;
+ gTasks[taskId].data[11]++;
+ break;
+ case 1:
+ gTasks[taskId].data[10]--;
+ if (gTasks[taskId].data[10] == 0)
+ gTasks[taskId].data[11]++;
+ break;
+ case 2:
+ if (gLinkVSyncDisabled)
+ {
+ gTasks[taskId].data[11]++;
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ var = 2;
+ else
+ var = (gBattleTypeFlags & BATTLE_TYPE_MULTI) ? 4 : 2;
+
+ if (sub_800ABAC() >= var)
+ {
+ if (sub_800ABBC())
+ {
+ sub_800A620();
+ gTasks[taskId].data[11]++;
+ }
+ else
+ {
+ gTasks[taskId].data[11]++;
+ }
+ }
+ }
+ break;
+ case 3:
+ if (gTasks[taskId].data[15] != gTasks[taskId].data[14])
+ {
+ if (gTasks[taskId].data[13] == 0)
+ {
+ if (gTasks[taskId].data[15] > gTasks[taskId].data[14]
+ && gTasks[taskId].data[15] == gTasks[taskId].data[12])
+ {
+ gTasks[taskId].data[12] = 0;
+ gTasks[taskId].data[15] = 0;
+ }
+ blockSize = (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8)) + LINK_BUFF_DATA;
+ SendBlock(bitmask_all_link_players_but_self(), &gLinkBattleSendBuffer[gTasks[taskId].data[15]], blockSize);
+ gTasks[taskId].data[11]++;
+ }
+ else
+ {
+ gTasks[taskId].data[13]--;
+ break;
+ }
+ }
+ break;
+ case 4:
+ if (sub_800A520())
+ {
+ blockSize = gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleSendBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8);
+ gTasks[taskId].data[13] = 1;
+ gTasks[taskId].data[15] = gTasks[taskId].data[15] + blockSize + LINK_BUFF_DATA;
+ gTasks[taskId].data[11] = 3;
+ }
+ break;
+ case 5:
+ gTasks[taskId].data[13]--;
+ if (gTasks[taskId].data[13] == 0)
+ {
+ gTasks[taskId].data[13] = 1;
+ gTasks[taskId].data[11] = 3;
+ }
+ break;
+ }
+}
+
+// fix me
+void sub_8033648(void)
+{
+ u8 i;
+ s32 j;
+ u16 r6;
+ u8 *recvBuffer;
+ u8 *dest;
+ u8 *src;
+
+ if (gReceivedRemoteLinkPlayers != 0 && (gBattleTypeFlags & BATTLE_TYPE_20))
+ {
+ sub_8011BD0();
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ if (GetBlockReceivedStatus() & gBitTable[i])
+ {
+ ResetBlockReceivedFlag(i);
+ recvBuffer = (u8 *)gBlockRecvBuffer[i];
+ #ifndef NONMATCHING
+ asm("");
+ recvBuffer = (u8 *)&gBlockRecvBuffer[i];
+ #endif
+ r6 = gBlockRecvBuffer[i][2];
+
+ if (gTasks[gUnknown_02022D09].data[14] + 9 + r6 > 0x1000)
+ {
+ gTasks[gUnknown_02022D09].data[12] = gTasks[gUnknown_02022D09].data[14];
+ gTasks[gUnknown_02022D09].data[14] = 0;
+ }
+
+ dest = &gLinkBattleRecvBuffer[gTasks[gUnknown_02022D09].data[14]];
+ src = recvBuffer;
+
+ for (j = 0; j < r6 + 8; j++)
+ dest[j] = src[j];
+
+ gTasks[gUnknown_02022D09].data[14] = gTasks[gUnknown_02022D09].data[14] + r6 + 8;
+ }
+ }
+ }
+}
+
+static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId)
+{
+ u16 blockSize;
+ u8 bank;
+ u8 var;
+
+ if (gTasks[taskId].data[15] != gTasks[taskId].data[14])
+ {
+ if (gTasks[taskId].data[15] > gTasks[taskId].data[14]
+ && gTasks[taskId].data[15] == gTasks[taskId].data[12])
+ {
+ gTasks[taskId].data[12] = 0;
+ gTasks[taskId].data[15] = 0;
+ }
+ bank = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BANK];
+ blockSize = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8);
+
+ switch (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 0])
+ {
+ case 0:
+ if (gBattleExecBuffer & gBitTable[bank])
+ return;
+
+ memcpy(gBattleBufferA[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize);
+ sub_803F850(bank);
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_WILD))
+ {
+ gBankAttacker = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 2];
+ gBankTarget = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 3];
+ gAbsentBankFlags = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 6];
+ gEffectBank = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 7];
+ }
+ break;
+ case 1:
+ memcpy(gBattleBufferB[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize);
+ break;
+ case 2:
+ var = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA];
+ gBattleExecBuffer &= ~(gBitTable[bank] << (var * 4));
+ break;
+ }
+
+ gTasks[taskId].data[15] = gTasks[taskId].data[15] + blockSize + LINK_BUFF_DATA;
+ }
+}
+
+void EmitGetMonData(u8 bufferId, u8 arg1, u8 arg2)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA;
+ gBattleBuffersTransferData[1] = arg1;
+ gBattleBuffersTransferData[2] = arg2;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitGetRawMonData(u8 bufferId, u8 monId, u8 bytes)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA;
+ gBattleBuffersTransferData[1] = monId;
+ gBattleBuffersTransferData[2] = bytes;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitSetMonData(u8 bufferId, u8 request, u8 c, u8 bytes, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA;
+ gBattleBuffersTransferData[1] = request;
+ gBattleBuffersTransferData[2] = c;
+ for (i = 0; i < bytes; i++)
+ gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 3 + bytes);
+}
+
+void EmitSetRawMonData(u8 bufferId, u8 monId, u8 bytes, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA;
+ gBattleBuffersTransferData[1] = monId;
+ gBattleBuffersTransferData[2] = bytes;
+ for (i = 0; i < bytes; i++)
+ gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, bytes + 3);
+}
+
+void EmitLoadMonSprite(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE;
+ gBattleBuffersTransferData[1] = 4;
+ gBattleBuffersTransferData[2] = 4;
+ gBattleBuffersTransferData[3] = 4;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitSwitchInAnim(u8 bufferId, u8 partyId, bool8 dontClearSubstituteBit)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM;
+ gBattleBuffersTransferData[1] = partyId;
+ gBattleBuffersTransferData[2] = dontClearSubstituteBit;
+ gBattleBuffersTransferData[3] = 5;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitReturnMonToBall(u8 bufferId, u8 arg1)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL;
+ gBattleBuffersTransferData[1] = arg1;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitDrawTrainerPic(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC;
+ gBattleBuffersTransferData[1] = 7;
+ gBattleBuffersTransferData[2] = 7;
+ gBattleBuffersTransferData[3] = 7;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitTrainerSlide(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE;
+ gBattleBuffersTransferData[1] = 8;
+ gBattleBuffersTransferData[2] = 8;
+ gBattleBuffersTransferData[3] = 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitTrainerSlideBack(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK;
+ gBattleBuffersTransferData[1] = 9;
+ gBattleBuffersTransferData[2] = 9;
+ gBattleBuffersTransferData[3] = 9;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitFaintAnimation(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION;
+ gBattleBuffersTransferData[1] = 10;
+ gBattleBuffersTransferData[2] = 10;
+ gBattleBuffersTransferData[3] = 10;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd11(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_11;
+ gBattleBuffersTransferData[1] = 11;
+ gBattleBuffersTransferData[2] = 11;
+ gBattleBuffersTransferData[3] = 11;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd12(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_12;
+ gBattleBuffersTransferData[1] = 12;
+ gBattleBuffersTransferData[2] = 12;
+ gBattleBuffersTransferData[3] = 12;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitBallThrow(u8 bufferId, u8 caseId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_BALLTHROW;
+ gBattleBuffersTransferData[1] = caseId;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitPause(u8 bufferId, u8 toWait, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_PAUSE;
+ gBattleBuffersTransferData[1] = toWait;
+ for (i = 0; i < toWait * 3; i++)
+ gBattleBuffersTransferData[2 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, toWait * 3 + 2);
+}
+
+void EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION;
+ gBattleBuffersTransferData[1] = move;
+ gBattleBuffersTransferData[2] = (move & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = turnOfMove;
+ gBattleBuffersTransferData[4] = movePower;
+ gBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8;
+ gBattleBuffersTransferData[6] = dmg;
+ gBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[10] = friendship;
+ gBattleBuffersTransferData[11] = multihit;
+ if (WEATHER_HAS_EFFECT2)
+ {
+ gBattleBuffersTransferData[12] = gBattleWeather;
+ gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8;
+ }
+ else
+ {
+ gBattleBuffersTransferData[12] = 0;
+ gBattleBuffersTransferData[13] = 0;
+ }
+ gBattleBuffersTransferData[14] = 0;
+ gBattleBuffersTransferData[15] = 0;
+ memcpy(&gBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct));
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 16 + sizeof(struct DisableStruct));
+}
+
+void EmitPrintString(u8 bufferId, u16 stringID)
+{
+ s32 i;
+ struct StringInfoBattle* stringInfo;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING;
+ gBattleBuffersTransferData[1] = gBattleOutcome;
+ gBattleBuffersTransferData[2] = stringID;
+ gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+
+ stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo->currentMove = gCurrentMove;
+ stringInfo->lastMove = gLastUsedMove;
+ stringInfo->lastItem = gLastUsedItem;
+ stringInfo->lastAbility = gLastUsedAbility;
+ stringInfo->scrActive = gBattleScripting.bank;
+ stringInfo->unk1605E = gBattleStruct->field_52;
+ stringInfo->hpScale = gBattleStruct->hpScale;
+ stringInfo->StringBank = gStringBank;
+ stringInfo->moveType = gBattleMoves[gCurrentMove].type;
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ stringInfo->abilities[i] = gBattleMons[i].ability;
+ for (i = 0; i < TEXT_BUFF_ARRAY_COUNT; i++)
+ {
+ stringInfo->textBuffs[0][i] = gBattleTextBuff1[i];
+ stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
+ stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
+ }
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+}
+
+void EmitPrintStringPlayerOnly(u8 bufferId, u16 stringID)
+{
+ s32 i;
+ struct StringInfoBattle* stringInfo;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY;
+ gBattleBuffersTransferData[1] = 17;
+ gBattleBuffersTransferData[2] = stringID;
+ gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+
+ stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo->currentMove = gCurrentMove;
+ stringInfo->lastMove = gLastUsedMove;
+ stringInfo->lastItem = gLastUsedItem;
+ stringInfo->lastAbility = gLastUsedAbility;
+ stringInfo->scrActive = gBattleScripting.bank;
+ stringInfo->unk1605E = gBattleStruct->field_52;
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ stringInfo->abilities[i] = gBattleMons[i].ability;
+ for (i = 0; i < TEXT_BUFF_ARRAY_COUNT; i++)
+ {
+ stringInfo->textBuffs[0][i] = gBattleTextBuff1[i];
+ stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
+ stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
+ }
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+}
+
+void EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION;
+ gBattleBuffersTransferData[1] = arg1;
+ gBattleBuffersTransferData[2] = arg2;
+ gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd19(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_19;
+ gBattleBuffersTransferData[1] = 19;
+ gBattleBuffersTransferData[2] = 19;
+ gBattleBuffersTransferData[3] = 19;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE;
+ gBattleBuffersTransferData[1] = isDoubleBattle;
+ gBattleBuffersTransferData[2] = NoPpNumber;
+ gBattleBuffersTransferData[3] = 0;
+ for (i = 0; i < sizeof(*movePpData); i++)
+ gBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(*movePpData) + 4);
+}
+
+void EmitOpenBag(u8 bufferId, u8 *arg1)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_OPENBAG;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[1 + i] = arg1[i];
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8* arg4)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON;
+ gBattleBuffersTransferData[1] = caseId;
+ gBattleBuffersTransferData[2] = arg2;
+ gBattleBuffersTransferData[3] = abilityId;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[4 + i] = arg4[i];
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 8); // but only 7 bytes were written
+}
+
+void EmitCmd23(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_23;
+ gBattleBuffersTransferData[1] = 23;
+ gBattleBuffersTransferData[2] = 23;
+ gBattleBuffersTransferData[3] = 23;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+// why is the argument u16 if it's being cast to s16 anyway?
+void EmitHealthBarUpdate(u8 bufferId, u16 hpValue)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE;
+ gBattleBuffersTransferData[1] = 0;
+ gBattleBuffersTransferData[2] = (s16)hpValue;
+ gBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+// why is the argument u16 if it's being cast to s16 anyway?
+void EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE;
+ gBattleBuffersTransferData[1] = partyId;
+ gBattleBuffersTransferData[2] = (s16)expPoints;
+ gBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE;
+ gBattleBuffersTransferData[1] = status1;
+ gBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[5] = status2;
+ gBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 9);
+}
+
+void EmitStatusAnimation(u8 bufferId, bool8 status2, u32 status)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION;
+ gBattleBuffersTransferData[1] = status2;
+ gBattleBuffersTransferData[2] = status;
+ gBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 6);
+}
+
+void EmitStatusXor(u8 bufferId, u8 b)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitDataTransfer(u8 bufferId, u16 size, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER;
+ gBattleBuffersTransferData[1] = 29;
+ gBattleBuffersTransferData[2] = size;
+ gBattleBuffersTransferData[3] = (size & 0xFF00) >> 8;
+ for (i = 0; i < size; i++)
+ gBattleBuffersTransferData[4 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 4);
+}
+
+void EmitDMA3Transfer(u8 bufferId, void *dst, u16 size, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER;
+ gBattleBuffersTransferData[1] = (u32)(dst);
+ gBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8;
+ gBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16;
+ gBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24;
+ gBattleBuffersTransferData[5] = size;
+ gBattleBuffersTransferData[6] = (size & 0xFF00) >> 8;
+ for (i = 0; i < size; i++)
+ gBattleBuffersTransferData[7 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 7);
+}
+
+void EmitPlayBGM(u8 bufferId, u16 songId, void *unusedDumbDataParameter)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_31;
+ gBattleBuffersTransferData[1] = songId;
+ gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ for (i = 0; i < songId; i++) // ????
+ gBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, songId + 3);
+}
+
+void EmitCmd32(u8 bufferId, u16 size, void *data)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_32;
+ gBattleBuffersTransferData[1] = size;
+ gBattleBuffersTransferData[2] = (size & 0xFF00) >> 8;
+ for (i = 0; i < size; i++)
+ gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 3);
+}
+
+void EmitCmd33(u8 bufferId, u8 arg1, u16 arg2)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_33;
+ gBattleBuffersTransferData[1] = arg1;
+ gBattleBuffersTransferData[2] = arg2;
+ gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd34(u8 bufferId, u8 b, u8 *c)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_34;
+ gBattleBuffersTransferData[1] = b;
+ for (i = 0; i < 3; i++)
+ gBattleBuffersTransferData[2 + i] = c[i];
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 5);
+}
+
+void EmitCmd35(u8 bufferId, u16 b)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_35;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd36(u8 bufferId, u16 b)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_36;
+ gBattleBuffersTransferData[1] = b;
+ gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd37(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_37;
+ gBattleBuffersTransferData[1] = 37;
+ gBattleBuffersTransferData[2] = 37;
+ gBattleBuffersTransferData[3] = 37;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd38(u8 bufferId, u8 b)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_38;
+ gBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitCmd39(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_39;
+ gBattleBuffersTransferData[1] = 39;
+ gBattleBuffersTransferData[2] = 39;
+ gBattleBuffersTransferData[3] = 39;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd40(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_40;
+ gBattleBuffersTransferData[1] = 40;
+ gBattleBuffersTransferData[2] = 40;
+ gBattleBuffersTransferData[3] = 40;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitHitAnimation(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION;
+ gBattleBuffersTransferData[1] = 41;
+ gBattleBuffersTransferData[2] = 41;
+ gBattleBuffersTransferData[3] = 41;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd42(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_42;
+ gBattleBuffersTransferData[1] = 42;
+ gBattleBuffersTransferData[2] = 42;
+ gBattleBuffersTransferData[3] = 42;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitEffectivenessSound(u8 bufferId, u16 songId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND;
+ gBattleBuffersTransferData[1] = songId;
+ gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitPlayFanfareOrBGM(u8 bufferId, u16 songId, bool8 playBGM)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM;
+ gBattleBuffersTransferData[1] = songId;
+ gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ gBattleBuffersTransferData[3] = playBGM;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitFaintingCry(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY;
+ gBattleBuffersTransferData[1] = 45;
+ gBattleBuffersTransferData[2] = 45;
+ gBattleBuffersTransferData[3] = 45;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitIntroSlide(u8 bufferId, u8 terrainId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE;
+ gBattleBuffersTransferData[1] = terrainId;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitIntroTrainerBallThrow(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW;
+ gBattleBuffersTransferData[1] = 47;
+ gBattleBuffersTransferData[2] = 47;
+ gBattleBuffersTransferData[3] = 47;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitDrawPartyStatusSummary(u8 bufferId, struct HpAndStatus* hpAndStatus, u8 arg2)
+{
+ s32 i;
+
+ gBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY;
+ gBattleBuffersTransferData[1] = arg2 & 0x7F;
+ gBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7;
+ gBattleBuffersTransferData[3] = 48;
+ for (i = 0; i < (s32)(sizeof(struct HpAndStatus) * 6); i++)
+ gBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus));
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4);
+}
+
+void EmitCmd49(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_49;
+ gBattleBuffersTransferData[1] = 49;
+ gBattleBuffersTransferData[2] = 49;
+ gBattleBuffersTransferData[3] = 49;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitCmd50(u8 bufferId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_50;
+ gBattleBuffersTransferData[1] = 50;
+ gBattleBuffersTransferData[2] = 50;
+ gBattleBuffersTransferData[3] = 50;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitSpriteInvisibility(u8 bufferId, bool8 isInvisible)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY;
+ gBattleBuffersTransferData[1] = isInvisible;
+ gBattleBuffersTransferData[2] = 51;
+ gBattleBuffersTransferData[3] = 51;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitBattleAnimation(u8 bufferId, u8 animationId, u16 argument)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION;
+ gBattleBuffersTransferData[1] = animationId;
+ gBattleBuffersTransferData[2] = argument;
+ gBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+}
+
+void EmitLinkStandbyMsg(u8 bufferId, u8 arg1, bool32 arg2)
+{
+ bool8 arg2_ = arg2;
+ gBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG;
+ gBattleBuffersTransferData[1] = arg1;
+
+ if (arg2_)
+ gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = sub_81850DC(&gBattleBuffersTransferData[4]);
+ else
+ gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = 0;
+
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[2] + 4);
+}
+
+void EmitResetActionMoveSelection(u8 bufferId, u8 caseId)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION;
+ gBattleBuffersTransferData[1] = caseId;
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+}
+
+void EmitCmd55(u8 bufferId, u8 arg1)
+{
+ gBattleBuffersTransferData[0] = CONTROLLER_55;
+ gBattleBuffersTransferData[1] = arg1;
+ gBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b;
+ gBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b;
+ gBattleBuffersTransferData[5] = gBattleBuffersTransferData[4] = sub_81850DC(&gBattleBuffersTransferData[6]);
+ PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[4] + 6);
+}
diff --git a/src/battle_interface.c b/src/battle_interface.c
new file mode 100644
index 000000000..9241db1d9
--- /dev/null
+++ b/src/battle_interface.c
@@ -0,0 +1,2632 @@
+#include "global.h"
+#include "battle.h"
+#include "pokemon.h"
+#include "battle_controllers.h"
+#include "battle_interface.h"
+#include "sprite.h"
+#include "window.h"
+#include "string_util.h"
+#include "text.h"
+#include "sound.h"
+#include "songs.h"
+#include "decompress.h"
+#include "task.h"
+#include "util.h"
+#include "gpu_regs.h"
+#include "battle_message.h"
+#include "species.h"
+#include "pokedex.h"
+#include "palette.h"
+#include "international_string_util.h"
+#include "safari_zone.h"
+#include "battle_anim.h"
+
+enum
+{
+ HEALTH_BAR,
+ EXP_BAR
+};
+
+enum
+{
+ HP_CURRENT,
+ HP_MAX
+};
+
+struct TestingBar
+{
+ s32 maxValue;
+ s32 currValue;
+ s32 field_8;
+ u32 unkC_0:5;
+ u32 unk10;
+};
+
+enum
+{
+ HEALTHBOX_GFX_0,
+ HEALTHBOX_GFX_1,
+ HEALTHBOX_GFX_2,
+ HEALTHBOX_GFX_3,
+ HEALTHBOX_GFX_4,
+ HEALTHBOX_GFX_5,
+ HEALTHBOX_GFX_6,
+ HEALTHBOX_GFX_7,
+ HEALTHBOX_GFX_8,
+ HEALTHBOX_GFX_9,
+ HEALTHBOX_GFX_10,
+ HEALTHBOX_GFX_11,
+ HEALTHBOX_GFX_12,
+ HEALTHBOX_GFX_13,
+ HEALTHBOX_GFX_14,
+ HEALTHBOX_GFX_15,
+ HEALTHBOX_GFX_16,
+ HEALTHBOX_GFX_17,
+ HEALTHBOX_GFX_18,
+ HEALTHBOX_GFX_19,
+ HEALTHBOX_GFX_20,
+ HEALTHBOX_GFX_STATUS_PSN_BANK0,
+ HEALTHBOX_GFX_22,
+ HEALTHBOX_GFX_23,
+ HEALTHBOX_GFX_STATUS_PRZ_BANK0,
+ HEALTHBOX_GFX_25,
+ HEALTHBOX_GFX_26,
+ HEALTHBOX_GFX_STATUS_SLP_BANK0,
+ HEALTHBOX_GFX_28,
+ HEALTHBOX_GFX_29,
+ HEALTHBOX_GFX_STATUS_FRZ_BANK0,
+ HEALTHBOX_GFX_31,
+ HEALTHBOX_GFX_32,
+ HEALTHBOX_GFX_STATUS_BRN_BANK0,
+ HEALTHBOX_GFX_34,
+ HEALTHBOX_GFX_35,
+ HEALTHBOX_GFX_36,
+ HEALTHBOX_GFX_37,
+ HEALTHBOX_GFX_38,
+ HEALTHBOX_GFX_39,
+ HEALTHBOX_GFX_40,
+ HEALTHBOX_GFX_41,
+ HEALTHBOX_GFX_42,
+ HEALTHBOX_GFX_43,
+ HEALTHBOX_GFX_44,
+ HEALTHBOX_GFX_45,
+ HEALTHBOX_GFX_46,
+ HEALTHBOX_GFX_47,
+ HEALTHBOX_GFX_48,
+ HEALTHBOX_GFX_49,
+ HEALTHBOX_GFX_50,
+ HEALTHBOX_GFX_51,
+ HEALTHBOX_GFX_52,
+ HEALTHBOX_GFX_53,
+ HEALTHBOX_GFX_54,
+ HEALTHBOX_GFX_55,
+ HEALTHBOX_GFX_56,
+ HEALTHBOX_GFX_57,
+ HEALTHBOX_GFX_58,
+ HEALTHBOX_GFX_59,
+ HEALTHBOX_GFX_60,
+ HEALTHBOX_GFX_61,
+ HEALTHBOX_GFX_62,
+ HEALTHBOX_GFX_63,
+ HEALTHBOX_GFX_64,
+ HEALTHBOX_GFX_65,
+ HEALTHBOX_GFX_66,
+ HEALTHBOX_GFX_67,
+ HEALTHBOX_GFX_68,
+ HEALTHBOX_GFX_69,
+ HEALTHBOX_GFX_70,
+ HEALTHBOX_GFX_STATUS_PSN_BANK1,
+ HEALTHBOX_GFX_72,
+ HEALTHBOX_GFX_73,
+ HEALTHBOX_GFX_STATUS_PRZ_BANK1,
+ HEALTHBOX_GFX_75,
+ HEALTHBOX_GFX_76,
+ HEALTHBOX_GFX_STATUS_SLP_BANK1,
+ HEALTHBOX_GFX_78,
+ HEALTHBOX_GFX_79,
+ HEALTHBOX_GFX_STATUS_FRZ_BANK1,
+ HEALTHBOX_GFX_81,
+ HEALTHBOX_GFX_82,
+ HEALTHBOX_GFX_STATUS_BRN_BANK1,
+ HEALTHBOX_GFX_84,
+ HEALTHBOX_GFX_85,
+ HEALTHBOX_GFX_STATUS_PSN_BANK2,
+ HEALTHBOX_GFX_87,
+ HEALTHBOX_GFX_88,
+ HEALTHBOX_GFX_STATUS_PRZ_BANK2,
+ HEALTHBOX_GFX_90,
+ HEALTHBOX_GFX_91,
+ HEALTHBOX_GFX_STATUS_SLP_BANK2,
+ HEALTHBOX_GFX_93,
+ HEALTHBOX_GFX_94,
+ HEALTHBOX_GFX_STATUS_FRZ_BANK2,
+ HEALTHBOX_GFX_96,
+ HEALTHBOX_GFX_97,
+ HEALTHBOX_GFX_STATUS_BRN_BANK2,
+ HEALTHBOX_GFX_99,
+ HEALTHBOX_GFX_100,
+ HEALTHBOX_GFX_STATUS_PSN_BANK3,
+ HEALTHBOX_GFX_102,
+ HEALTHBOX_GFX_103,
+ HEALTHBOX_GFX_STATUS_PRZ_BANK3,
+ HEALTHBOX_GFX_105,
+ HEALTHBOX_GFX_106,
+ HEALTHBOX_GFX_STATUS_SLP_BANK3,
+ HEALTHBOX_GFX_108,
+ HEALTHBOX_GFX_109,
+ HEALTHBOX_GFX_STATUS_FRZ_BANK3,
+ HEALTHBOX_GFX_111,
+ HEALTHBOX_GFX_112,
+ HEALTHBOX_GFX_STATUS_BRN_BANK3,
+ HEALTHBOX_GFX_114,
+ HEALTHBOX_GFX_115,
+ HEALTHBOX_GFX_116,
+ HEALTHBOX_GFX_117,
+};
+
+extern u8 gBanksByIdentity[BATTLE_BANKS_COUNT];
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gNoOfAllBanks;
+extern u8 gHealthBoxesIds[BATTLE_BANKS_COUNT];
+
+extern const u8 * const gNatureNamePointers[];
+extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
+
+// strings
+extern const u8 gText_Slash[];
+extern const u8 gText_HighlightDarkGrey[];
+extern const u8 gText_DynColor2[];
+extern const u8 gText_DynColor2Male[];
+extern const u8 gText_DynColor1Female[];
+extern const u8 gText_SafariBalls[];
+extern const u8 gText_SafariBallLeft[];
+
+// graphics
+extern const u8 gBattleInterface_BallStatusBarGfx[];
+extern const u8 gBattleInterface_BallDisplayGfx[];
+extern const u16 gBattleInterface_BallStatusBarPal[];
+extern const u16 gBattleInterface_BallDisplayPal[];
+extern const u8 gHealthboxElementsGfxTable[][32];
+
+// functions
+extern bool8 IsDoubleBattle(void);
+extern void AddTextPrinterParametrized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, struct TextColor *color, s8 speed, const u8 *str); // menu.h
+extern void LoadBattleBarGfx(u8 arg0);
+
+// this file's functions
+
+static const u8 *GetHealthboxElementGfxPtr(u8 elementId);
+static u8* AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 arg3, u32 *windowId);
+
+static void RemoveWindowOnHealthbox(u32 windowId);
+static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent);
+static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId);
+
+static void sub_8075198(void *dest, u8 *windowTileData, s32 arg2);
+static void sub_80751E4(void *dest, u8 *windowTileData, u32 arg2);
+static void sub_8075170(void *dest, u8 *windowTileData, u32 arg2);
+static void sub_807513C(void *dest, u32 arg1, u32 arg2);
+
+static void sub_8073E08(u8 taskId);
+static void sub_8073F98(u8 taskId);
+static void sub_8073E64(u8 taskId);
+
+static void sub_8072924(struct Sprite *sprite);
+static void sub_80728B4(struct Sprite *sprite);
+static void sub_8074158(struct Sprite *sprite);
+static void sub_8074090(struct Sprite *sprite);
+static void SpriteCB_StatusSummaryBar(struct Sprite *sprite);
+static void SpriteCB_StatusSummaryBallsOnBattleStart(struct Sprite *sprite);
+static void SpriteCB_StatusSummaryBallsOnSwitchout(struct Sprite *sprite);
+
+static u8 GetStatusIconForBankId(u8 statusElementId, u8 bank);
+static s32 sub_8074DB8(s32 maxValue, s32 currValue, s32 arg2, s32 *arg3, u8 arg4, u16 arg5);
+static u8 GetScaledExpFraction(s32 currValue, s32 arg1, s32 maxValue, u8 scale);
+static void sub_8074B9C(u8 bank, u8 whichBar);
+static u8 sub_8074E8C(s32 maxValue, s32 currValue, s32 arg2, s32 *arg3, u8 *arg4, u8 arg5);
+static void sub_8074F88(struct TestingBar *barInfo, s32 *arg1, u16 *arg2);
+
+// const rom data
+static const struct OamData sUnknown_0832C138 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteTemplate sHealthboxPlayerSpriteTemplates[2] =
+{
+ {
+ .tileTag = TAG_HEALTHBOX_PLAYER1_TILE,
+ .paletteTag = TAG_HEALTHBOX_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ },
+ {
+ .tileTag = TAG_HEALTHBOX_PLAYER2_TILE,
+ .paletteTag = TAG_HEALTHBOX_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ }
+};
+
+static const struct SpriteTemplate sHealthboxOpponentSpriteTemplates[2] =
+{
+ {
+ .tileTag = TAG_HEALTHBOX_OPPONENT1_TILE,
+ .paletteTag = TAG_HEALTHBOX_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ },
+ {
+ .tileTag = TAG_HEALTHBOX_OPPONENT2_TILE,
+ .paletteTag = TAG_HEALTHBOX_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ }
+};
+
+static const struct SpriteTemplate sHealthboxSafariSpriteTemplate =
+{
+ .tileTag = TAG_HEALTHBOX_SAFARI_TILE,
+ .paletteTag = TAG_HEALTHBOX_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sUnknown_0832C1B8 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 1,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteTemplate sUnknown_0832C1C0[4] =
+{
+ {
+ .tileTag = 0xd704,
+ .paletteTag = 0xd704,
+ .oam = &sUnknown_0832C1B8,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80728B4
+ },
+ {
+ .tileTag = 0xd705,
+ .paletteTag = 0xd704,
+ .oam = &sUnknown_0832C1B8,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80728B4
+ },
+ {
+ .tileTag = 0xd706,
+ .paletteTag = 0xd704,
+ .oam = &sUnknown_0832C1B8,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80728B4
+ },
+ {
+ .tileTag = 0xd707,
+ .paletteTag = 0xd704,
+ .oam = &sUnknown_0832C1B8,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80728B4
+ }
+};
+
+static const struct Subsprite sUnknown_0832C220[] =
+{
+ {240, 0, 1, 3, 0, 1},
+ {48, 0, 0, 2, 32, 1},
+ {240, 32, 1, 1, 48, 1},
+ {16, 32, 1, 1, 52, 1},
+ {48, 32, 1, 1, 56, 1}
+};
+
+static const struct Subsprite sUnknown_0832C234[] =
+{
+ {240, 0, 1, 3, 64, 1},
+ {48, 0, 0, 2, 96, 1},
+ {240, 32, 1, 1, 112, 1},
+ {16, 32, 1, 1, 116, 1},
+ {48, 32, 1, 1, 120, 1}
+};
+
+static const struct Subsprite sUnknown_0832C248[] =
+{
+ {240, 0, 1, 3, 0, 1},
+ {48, 0, 0, 2, 32, 1}
+};
+
+static const struct Subsprite sUnknown_0832C250[] =
+{
+ {240, 0, 1, 3, 0, 1},
+ {48, 0, 0, 2, 32, 1}
+};
+
+static const struct Subsprite sUnknown_0832C258[] =
+{
+ {240, 0, 1, 1, 0, 1},
+ {16, 0, 1, 1, 4, 1}
+};
+
+static const struct Subsprite sUnknown_0832C260[] =
+{
+ {240, 0, 1, 1, 0, 1},
+ {16, 0, 1, 1, 4, 1},
+ {224, 0, 0, 0, 8, 1}
+};
+
+// unused subsprite table
+static const struct SubspriteTable sUnknown_0832C26C[] =
+{
+ {ARRAY_COUNT(sUnknown_0832C220), sUnknown_0832C220},
+ {ARRAY_COUNT(sUnknown_0832C248), sUnknown_0832C248},
+ {ARRAY_COUNT(sUnknown_0832C234), sUnknown_0832C234},
+ {ARRAY_COUNT(sUnknown_0832C250), sUnknown_0832C250}
+};
+
+static const struct SubspriteTable sUnknown_0832C28C[] =
+{
+ {ARRAY_COUNT(sUnknown_0832C258), sUnknown_0832C258},
+ {ARRAY_COUNT(sUnknown_0832C260), sUnknown_0832C260}
+};
+
+static const struct Subsprite sStatusSummaryBar_Subsprites_0[] =
+{
+ {160, 0, 1, 1, 0, 1},
+ {192, 0, 1, 1, 4, 1},
+ {224, 0, 1, 1, 8, 1},
+ {0, 0, 1, 1, 12, 1}
+};
+
+static const struct Subsprite sUnknown_0832C2AC[] =
+{
+ {160, 0, 1, 1, 0, 1},
+ {192, 0, 1, 1, 4, 1},
+ {224, 0, 1, 1, 8, 1},
+ {0, 0, 1, 1, 8, 1},
+ {32, 0, 1, 1, 8, 1},
+ {64, 0, 1, 1, 12, 1}
+};
+
+static const struct SubspriteTable sStatusSummaryBar_SubspriteTable[] =
+{
+ {ARRAY_COUNT(sStatusSummaryBar_Subsprites_0), sStatusSummaryBar_Subsprites_0}
+};
+
+static const struct SubspriteTable sUnknown_0832C2CC[] =
+{
+ {ARRAY_COUNT(sUnknown_0832C2AC), sUnknown_0832C2AC}
+};
+
+// unused unknown image
+static const u8 sUnknown_0832C2D4[] = INCBIN_U8("graphics/battle_interface/unknown_32C2D4.4bpp");
+
+static const struct CompressedSpriteSheet sStatusSummaryBarSpriteSheet =
+{
+ gBattleInterface_BallStatusBarGfx, 0x200, TAG_STATUS_SUMMARY_BAR_TILE
+};
+
+static const struct SpritePalette sStatusSummaryBarSpritePal =
+{
+ gBattleInterface_BallStatusBarPal, TAG_STATUS_SUMMARY_BAR_PAL
+};
+
+static const struct SpritePalette sStatusSummaryBallsSpritePal =
+{
+ gBattleInterface_BallDisplayPal, TAG_STATUS_SUMMARY_BALLS_PAL
+};
+
+static const struct SpriteSheet sStatusSummaryBallsSpriteSheet =
+{
+ gBattleInterface_BallDisplayGfx, 0x80, TAG_STATUS_SUMMARY_BALLS_TILE
+};
+
+// unused oam data
+static const struct OamData sUnknown_0832C354 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct OamData sOamData_StatusSummaryBalls =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteTemplate sStatusSummaryBarSpriteTemplates[2] =
+{
+ {
+ .tileTag = TAG_STATUS_SUMMARY_BAR_TILE,
+ .paletteTag = TAG_STATUS_SUMMARY_BAR_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_StatusSummaryBar
+ },
+ {
+ .tileTag = TAG_STATUS_SUMMARY_BAR_TILE,
+ .paletteTag = TAG_STATUS_SUMMARY_BAR_PAL,
+ .oam = &sUnknown_0832C138,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_StatusSummaryBar
+ }
+};
+
+static const struct SpriteTemplate sStatusSummaryBallsSpriteTemplates[2] =
+{
+ {
+ .tileTag = TAG_STATUS_SUMMARY_BALLS_TILE,
+ .paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL,
+ .oam = &sOamData_StatusSummaryBalls,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_StatusSummaryBallsOnBattleStart
+ },
+ {
+ .tileTag = TAG_STATUS_SUMMARY_BALLS_TILE,
+ .paletteTag = TAG_STATUS_SUMMARY_BALLS_PAL,
+ .oam = &sOamData_StatusSummaryBalls,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_StatusSummaryBallsOnBattleStart
+ }
+};
+
+// possibly text
+static const u8 sUnknown_0832C3C4[] =
+{
+ 0xfc, 0x01, 0x01, 0xfc, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+// possibly text
+static const u8 sUnknown_0832C3D8[] =
+{
+ 0xfc, 0x01, 0x01, 0xfc, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+enum
+{
+ PAL_STATUS_PSN,
+ PAL_STATUS_PAR,
+ PAL_STATUS_SLP,
+ PAL_STATUS_FRZ,
+ PAL_STATUS_BRN
+};
+
+static const u16 sStatusIconPalettes[] =
+{
+ 0x6198, // PAL_STATUS_PSN
+ 0xEF7, // PAL_STATUS_PAR
+ 0x4694, // PAL_STATUS_SLP
+ 0x72D1, // PAL_STATUS_FRZ
+ 0x29DC // PAL_STATUS_BRN
+};
+
+static const struct WindowTemplate sHealthboxWindowTemplate = {0, 0, 0, 8, 2, 0, 0}; // width = 8, height = 2
+
+// code
+
+static s32 DummiedOutFunction(s16 unused1, s16 unused2, s32 unused3)
+{
+ return 9;
+}
+
+#ifdef NONMATCHING
+static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2)
+{
+ s8 i, j;
+ u8 array[4];
+ u8 *arrayPtr;
+ s32 r9, vaaa;
+
+ for (i = 0; i < 4; i++)
+ array[i] = 0;
+
+ i = 3;
+ r9 = -1;
+ arrayPtr = array;
+ while (1)
+ {
+ if (arg0 > 0)
+ {
+ array[i] = arg0 % 10;
+ arg0 = arg0 / 10;
+ i--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for (; i > -1; i--)
+ {
+ array[i] = 0xFF;
+ }
+
+ if (arrayPtr[3] == 0xFF)
+ arrayPtr[3] = 0;
+
+ if (arg2 == 0)
+ {
+ for (i = 0, j = 0; i < 4; i++)
+ {
+ if (array[j] == 0xFF)
+ {
+ arg1[j] &= 0xFC00;
+ arg1[j] |= 0x1E;
+
+ arg1[i + 0x20] &= 0xFC00;
+ arg1[i + 0x20] |= 0x1E;
+ }
+ else
+ {
+ arg1[j] &= 0xFC00;
+ arg1[j] |= array[j] + 0x14;
+
+ arg1[i + 0x20] &= 0xFC00;
+ arg1[i + 0x20] |= array[i] + 0x34;
+ }
+ j++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (array[i] == 0xFF)
+ {
+ arg1[i] &= 0xFC00;
+ arg1[i] |= 0x1E;
+
+ arg1[i + 0x20] &= 0xFC00;
+ arg1[i + 0x20] |= 0x1E;
+ }
+ else
+ {
+ arg1[i] &= 0xFC00;
+ arg1[i] |= array[i] + 0x14;
+
+ arg1[i + 0x20] &= 0xFC00;
+ arg1[i + 0x20] |= array[i] + 0x34;
+ }
+ }
+ }
+}
+
+#else
+__attribute__((naked))
+static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x4\n\
+ adds r7, r1, 0\n\
+ lsls r0, 16\n\
+ lsrs r5, r0, 16\n\
+ lsls r2, 24\n\
+ lsrs r2, 24\n\
+ mov r10, r2\n\
+ movs r3, 0\n\
+ movs r2, 0\n\
+_08072324:\n\
+ lsls r0, r3, 24\n\
+ asrs r0, 24\n\
+ mov r3, sp\n\
+ adds r1, r3, r0\n\
+ strb r2, [r1]\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ asrs r0, 24\n\
+ cmp r0, 0x3\n\
+ ble _08072324\n\
+ movs r3, 0x3\n\
+ movs r0, 0x1\n\
+ negs r0, r0\n\
+ mov r9, r0\n\
+ mov r8, sp\n\
+_08072344:\n\
+ lsls r0, r5, 16\n\
+ asrs r6, r0, 16\n\
+ cmp r6, 0\n\
+ ble _08072372\n\
+ lsls r4, r3, 24\n\
+ asrs r4, 24\n\
+ mov r1, sp\n\
+ adds r5, r1, r4\n\
+ adds r0, r6, 0\n\
+ movs r1, 0xA\n\
+ bl __modsi3\n\
+ strb r0, [r5]\n\
+ adds r0, r6, 0\n\
+ movs r1, 0xA\n\
+ bl __divsi3\n\
+ lsls r0, 16\n\
+ lsrs r5, r0, 16\n\
+ subs r4, 0x1\n\
+ lsls r4, 24\n\
+ lsrs r3, r4, 24\n\
+ b _08072344\n\
+_08072372:\n\
+ lsls r1, r3, 24\n\
+ asrs r0, r1, 24\n\
+ cmp r0, r9\n\
+ ble _08072396\n\
+ movs r4, 0xFF\n\
+ movs r3, 0x1\n\
+ negs r3, r3\n\
+_08072380:\n\
+ asrs r2, r1, 24\n\
+ mov r5, sp\n\
+ adds r1, r5, r2\n\
+ ldrb r0, [r1]\n\
+ orrs r0, r4\n\
+ strb r0, [r1]\n\
+ subs r2, 0x1\n\
+ lsls r1, r2, 24\n\
+ asrs r0, r1, 24\n\
+ cmp r0, r3\n\
+ bgt _08072380\n\
+_08072396:\n\
+ mov r1, r8\n\
+ ldrb r0, [r1, 0x3]\n\
+ cmp r0, 0xFF\n\
+ bne _080723A2\n\
+ movs r0, 0\n\
+ strb r0, [r1, 0x3]\n\
+_080723A2:\n\
+ mov r2, r10\n\
+ cmp r2, 0\n\
+ bne _08072432\n\
+ movs r3, 0\n\
+ movs r1, 0\n\
+ movs r6, 0xFC\n\
+ lsls r6, 8\n\
+ movs r5, 0x1E\n\
+ mov r12, r5\n\
+_080723B4:\n\
+ lsls r1, 24\n\
+ asrs r2, r1, 24\n\
+ mov r0, sp\n\
+ adds r5, r0, r2\n\
+ ldrb r0, [r5]\n\
+ mov r8, r1\n\
+ cmp r0, 0xFF\n\
+ bne _080723EA\n\
+ lsls r1, r2, 1\n\
+ adds r1, r7\n\
+ ldrh r2, [r1]\n\
+ adds r0, r6, 0\n\
+ ands r0, r2\n\
+ mov r2, r12\n\
+ orrs r0, r2\n\
+ strh r0, [r1]\n\
+ lsls r3, 24\n\
+ asrs r1, r3, 23\n\
+ adds r1, r7\n\
+ adds r1, 0x40\n\
+ ldrh r2, [r1]\n\
+ adds r0, r6, 0\n\
+ ands r0, r2\n\
+ mov r5, r12\n\
+ orrs r0, r5\n\
+ strh r0, [r1]\n\
+ b _0807241A\n\
+_080723EA:\n\
+ lsls r2, 1\n\
+ adds r2, r7\n\
+ ldrh r0, [r2]\n\
+ adds r1, r6, 0\n\
+ ands r1, r0\n\
+ ldrb r0, [r5]\n\
+ adds r0, 0x14\n\
+ orrs r1, r0\n\
+ strh r1, [r2]\n\
+ lsls r4, r3, 24\n\
+ asrs r3, r4, 24\n\
+ lsls r2, r3, 1\n\
+ adds r2, r7\n\
+ adds r2, 0x40\n\
+ ldrh r0, [r2]\n\
+ adds r1, r6, 0\n\
+ ands r1, r0\n\
+ mov r5, sp\n\
+ adds r0, r5, r3\n\
+ ldrb r0, [r0]\n\
+ adds r0, 0x34\n\
+ orrs r1, r0\n\
+ strh r1, [r2]\n\
+ adds r3, r4, 0\n\
+_0807241A:\n\
+ movs r0, 0x80\n\
+ lsls r0, 17\n\
+ add r0, r8\n\
+ lsrs r1, r0, 24\n\
+ movs r2, 0x80\n\
+ lsls r2, 17\n\
+ adds r0, r3, r2\n\
+ lsrs r3, r0, 24\n\
+ asrs r0, 24\n\
+ cmp r0, 0x3\n\
+ ble _080723B4\n\
+ b _08072496\n\
+_08072432:\n\
+ movs r3, 0\n\
+ movs r4, 0xFC\n\
+ lsls r4, 8\n\
+ movs r6, 0x1E\n\
+_0807243A:\n\
+ lsls r1, r3, 24\n\
+ asrs r2, r1, 24\n\
+ mov r3, sp\n\
+ adds r5, r3, r2\n\
+ ldrb r0, [r5]\n\
+ adds r3, r1, 0\n\
+ cmp r0, 0xFF\n\
+ bne _08072466\n\
+ lsls r1, r2, 1\n\
+ adds r1, r7\n\
+ ldrh r2, [r1]\n\
+ adds r0, r4, 0\n\
+ ands r0, r2\n\
+ orrs r0, r6\n\
+ strh r0, [r1]\n\
+ adds r1, 0x40\n\
+ ldrh r2, [r1]\n\
+ adds r0, r4, 0\n\
+ ands r0, r2\n\
+ orrs r0, r6\n\
+ strh r0, [r1]\n\
+ b _08072488\n\
+_08072466:\n\
+ lsls r2, 1\n\
+ adds r2, r7\n\
+ ldrh r0, [r2]\n\
+ adds r1, r4, 0\n\
+ ands r1, r0\n\
+ ldrb r0, [r5]\n\
+ adds r0, 0x14\n\
+ orrs r1, r0\n\
+ strh r1, [r2]\n\
+ adds r2, 0x40\n\
+ ldrh r0, [r2]\n\
+ adds r1, r4, 0\n\
+ ands r1, r0\n\
+ ldrb r0, [r5]\n\
+ adds r0, 0x34\n\
+ orrs r1, r0\n\
+ strh r1, [r2]\n\
+_08072488:\n\
+ movs r5, 0x80\n\
+ lsls r5, 17\n\
+ adds r0, r3, r5\n\
+ lsrs r3, r0, 24\n\
+ asrs r0, 24\n\
+ cmp r0, 0x3\n\
+ ble _0807243A\n\
+_08072496:\n\
+ add sp, 0x4\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .syntax divided");
+}
+
+#endif // NONMATCHING
+
+void sub_80724A8(s16 arg0, s16 arg1, u16 *arg2)
+{
+ arg2[4] = 0x1E;
+ sub_8072308(arg1, arg2, 0);
+ sub_8072308(arg0, arg2 + 5, 1);
+}
+
+// because the healthbox is too large to fit into one sprite, it is divided into two sprites
+// healthboxSpriteId_1 or healthboxSpriteId refers to the 'main' healthbox
+// healthboxSpriteId_2 refers to the other part
+// there's also one other sprite that appears to be a black square? dont fully understand its role
+
+u8 CreateBankHealthboxSprites(u8 bank)
+{
+ s16 data6 = 0;
+ u8 healthboxSpriteId_1, healthboxSpriteId_2;
+ u8 unkSpriteId;
+ struct Sprite *unkSpritePtr;
+
+ if (!IsDoubleBattle())
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ healthboxSpriteId_1 = CreateSprite(&sHealthboxPlayerSpriteTemplates[0], 240, 160, 1);
+ healthboxSpriteId_2 = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[0], 240, 160, 1);
+
+ gSprites[healthboxSpriteId_1].oam.shape = 0;
+
+ gSprites[healthboxSpriteId_2].oam.shape = 0;
+ gSprites[healthboxSpriteId_2].oam.tileNum += 64;
+ }
+ else
+ {
+ healthboxSpriteId_1 = CreateSprite(&sHealthboxOpponentSpriteTemplates[0], 240, 160, 1);
+ healthboxSpriteId_2 = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[0], 240, 160, 1);
+
+ gSprites[healthboxSpriteId_2].oam.tileNum += 32;
+
+ data6 = 2;
+ }
+ gSprites[healthboxSpriteId_1].oam.affineParam = healthboxSpriteId_2;
+ gSprites[healthboxSpriteId_2].data5 = healthboxSpriteId_1;
+ gSprites[healthboxSpriteId_2].callback = sub_8072924;
+ }
+ else
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ healthboxSpriteId_1 = CreateSprite(&sHealthboxPlayerSpriteTemplates[GetBankIdentity(bank) / 2], 240, 160, 1);
+ healthboxSpriteId_2 = CreateSpriteAtEnd(&sHealthboxPlayerSpriteTemplates[GetBankIdentity(bank) / 2], 240, 160, 1);
+
+ gSprites[healthboxSpriteId_1].oam.affineParam = healthboxSpriteId_2;
+
+ gSprites[healthboxSpriteId_2].data5 = healthboxSpriteId_1;
+ gSprites[healthboxSpriteId_2].oam.tileNum += 32;
+ gSprites[healthboxSpriteId_2].callback = sub_8072924;
+
+ data6 = 1;
+ }
+ else
+ {
+ healthboxSpriteId_1 = CreateSprite(&sHealthboxOpponentSpriteTemplates[GetBankIdentity(bank) / 2], 240, 160, 1);
+ healthboxSpriteId_2 = CreateSpriteAtEnd(&sHealthboxOpponentSpriteTemplates[GetBankIdentity(bank) / 2], 240, 160, 1);
+
+ gSprites[healthboxSpriteId_1].oam.affineParam = healthboxSpriteId_2;
+
+ gSprites[healthboxSpriteId_2].data5 = healthboxSpriteId_1;
+ gSprites[healthboxSpriteId_2].oam.tileNum += 32;
+ gSprites[healthboxSpriteId_2].callback = sub_8072924;
+
+ data6 = 2;
+ }
+ }
+
+ unkSpriteId = CreateSpriteAtEnd(&sUnknown_0832C1C0[gBanksByIdentity[bank]], 140, 60, 0);
+ unkSpritePtr = &gSprites[unkSpriteId];
+ SetSubspriteTables(unkSpritePtr, &sUnknown_0832C28C[GetBankSide(bank)]);
+ unkSpritePtr->subspriteMode = 2;
+ unkSpritePtr->oam.priority = 1;
+
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void*)(OBJ_VRAM0 + unkSpritePtr->oam.tileNum * 32), 64);
+
+ gSprites[healthboxSpriteId_1].data5 = unkSpriteId;
+ gSprites[healthboxSpriteId_1].data6 = bank;
+ gSprites[healthboxSpriteId_1].invisible = 1;
+
+ gSprites[healthboxSpriteId_2].invisible = 1;
+
+ unkSpritePtr->data5 = healthboxSpriteId_1;
+ unkSpritePtr->data6 = data6;
+ unkSpritePtr->invisible = 1;
+
+ return healthboxSpriteId_1;
+}
+
+u8 CreateSafariPlayerHealthboxSprites(void)
+{
+ u8 healthboxSpriteId_1, healthboxSpriteId_2;
+
+ healthboxSpriteId_1 = CreateSprite(&sHealthboxSafariSpriteTemplate, 240, 160, 1);
+ healthboxSpriteId_2 = CreateSpriteAtEnd(&sHealthboxSafariSpriteTemplate, 240, 160, 1);
+
+ gSprites[healthboxSpriteId_1].oam.shape = 0;
+ gSprites[healthboxSpriteId_2].oam.shape = 0;
+
+ gSprites[healthboxSpriteId_2].oam.tileNum += 64;
+
+ gSprites[healthboxSpriteId_1].oam.affineParam = healthboxSpriteId_2;
+ gSprites[healthboxSpriteId_2].data5 = healthboxSpriteId_1;
+
+ gSprites[healthboxSpriteId_2].callback = sub_8072924;
+
+ return healthboxSpriteId_1;
+}
+
+static const u8 *GetHealthboxElementGfxPtr(u8 elementId)
+{
+ return gHealthboxElementsGfxTable[elementId];
+}
+
+static void sub_80728B4(struct Sprite *sprite)
+{
+ u8 var = sprite->data5;
+
+ switch (sprite->data6)
+ {
+ case 0:
+ sprite->pos1.x = gSprites[var].pos1.x + 16;
+ sprite->pos1.y = gSprites[var].pos1.y;
+ break;
+ case 1:
+ sprite->pos1.x = gSprites[var].pos1.x + 16;
+ sprite->pos1.y = gSprites[var].pos1.y;
+ break;
+ case 2:
+ default:
+ sprite->pos1.x = gSprites[var].pos1.x + 8;
+ sprite->pos1.y = gSprites[var].pos1.y;
+ break;
+ }
+
+ sprite->pos2.x = gSprites[var].pos2.x;
+ sprite->pos2.y = gSprites[var].pos2.y;
+}
+
+static void sub_8072924(struct Sprite *sprite)
+{
+ u8 otherSpriteId = sprite->data5;
+
+ sprite->pos1.x = gSprites[otherSpriteId].pos1.x + 64;
+ sprite->pos1.y = gSprites[otherSpriteId].pos1.y;
+
+ sprite->pos2.x = gSprites[otherSpriteId].pos2.x;
+ sprite->pos2.y = gSprites[otherSpriteId].pos2.y;
+}
+
+void SetBattleBarStruct(u8 bank, u8 healthboxSpriteId, s32 maxVal, s32 currVal, s32 field_C)
+{
+ gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId = healthboxSpriteId;
+ gBattleSpritesDataPtr->battleBars[bank].maxValue = maxVal;
+ gBattleSpritesDataPtr->battleBars[bank].currentValue = currVal;
+ gBattleSpritesDataPtr->battleBars[bank].field_C = field_C;
+ gBattleSpritesDataPtr->battleBars[bank].field_10 = -32768;
+}
+
+void SetHealthboxSpriteInvisible(u8 healthboxSpriteId)
+{
+ gSprites[healthboxSpriteId].invisible = 1;
+ gSprites[gSprites[healthboxSpriteId].data5].invisible = 1;
+ gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = 1;
+}
+
+void SetHealthboxSpriteVisible(u8 healthboxSpriteId)
+{
+ gSprites[healthboxSpriteId].invisible = 0;
+ gSprites[gSprites[healthboxSpriteId].data5].invisible = 0;
+ gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = 0;
+}
+
+static void UpdateSpritePos(u8 spriteId, s16 x, s16 y)
+{
+ gSprites[spriteId].pos1.x = x;
+ gSprites[spriteId].pos1.y = y;
+}
+
+void DestoryHealthboxSprite(u8 healthboxSpriteId)
+{
+ DestroySprite(&gSprites[gSprites[healthboxSpriteId].oam.affineParam]);
+ DestroySprite(&gSprites[gSprites[healthboxSpriteId].data5]);
+ DestroySprite(&gSprites[healthboxSpriteId]);
+}
+
+void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly)
+{
+
+}
+
+void UpdateOamPriorityInAllHealthboxes(u8 priority)
+{
+ s32 i;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ u8 healthboxSpriteId_1 = gHealthBoxesIds[i];
+ u8 healthboxSpriteId_2 = gSprites[gHealthBoxesIds[i]].oam.affineParam;
+ u8 healthboxSpriteId_3 = gSprites[gHealthBoxesIds[i]].data5;
+
+ gSprites[healthboxSpriteId_1].oam.priority = priority;
+ gSprites[healthboxSpriteId_2].oam.priority = priority;
+ gSprites[healthboxSpriteId_3].oam.priority = priority;
+ }
+}
+
+void SetBankHealthboxSpritePos(u8 bank)
+{
+ s16 x = 0, y = 0;
+
+ if (!IsDoubleBattle())
+ {
+ if (GetBankSide(bank) != SIDE_PLAYER)
+ x = 44, y = 30;
+ else
+ x = 158, y = 88;
+ }
+ else
+ {
+ switch (GetBankIdentity(bank))
+ {
+ case IDENTITY_PLAYER_MON1:
+ x = 159, y = 76;
+ break;
+ case IDENTITY_PLAYER_MON2:
+ x = 171, y = 101;
+ break;
+ case IDENTITY_OPPONENT_MON1:
+ x = 44, y = 19;
+ break;
+ case IDENTITY_OPPONENT_MON2:
+ x = 32, y = 44;
+ break;
+ }
+ }
+
+ UpdateSpritePos(gHealthBoxesIds[bank], x, y);
+}
+
+static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
+{
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+ u8 text[16];
+ u32 xPos, var1;
+ void *objVram;
+
+ text[0] = 0xF9;
+ text[1] = 5;
+
+ xPos = (u32) ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
+ // Alright, that part was unmatchable. It's basically doing:
+ // xPos = 5 * (3 - (u32)(&text[2]));
+ xPos--;
+ xPos--;
+ xPos -= ((u32)(text));
+ var1 = (3 - xPos);
+ xPos = 4 * var1;
+ xPos += var1;
+
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, xPos, 3, 2, &windowId);
+ spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * 32;
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER)
+ {
+ objVram = (void*)(OBJ_VRAM0);
+ if (!IsDoubleBattle())
+ objVram += spriteTileNum + 0x820;
+ else
+ objVram += spriteTileNum + 0x420;
+ }
+ else
+ {
+ objVram = (void*)(OBJ_VRAM0);
+ objVram += spriteTileNum + 0x400;
+ }
+ sub_8075198(objVram, windowTileData, 3);
+ RemoveWindowOnHealthbox(windowId);
+}
+
+void UpdateHpTextInHealthbox(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent)
+{
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+ u8 text[32];
+ void *objVram;
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER && !IsDoubleBattle())
+ {
+ spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * 32;
+ if (maxOrCurrent != HP_CURRENT) // singles, max
+ {
+ ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 0, 5, 2, &windowId);
+ objVram = (void*)(OBJ_VRAM0);
+ objVram += spriteTileNum + 0xB40;
+ sub_8075170(objVram, windowTileData, 2);
+ RemoveWindowOnHealthbox(windowId);
+ }
+ else // singles, current
+ {
+ ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ text[3] = CHAR_SLASH;
+ text[4] = EOS;
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 4, 5, 2, &windowId);
+ objVram = (void*)(OBJ_VRAM0);
+ objVram += spriteTileNum + 0x3E0;
+ sub_8075170(objVram, windowTileData, 1);
+ objVram = (void*)(OBJ_VRAM0);
+ objVram += spriteTileNum + 0xB00;
+ sub_8075170(objVram, windowTileData + 0x20, 2);
+ RemoveWindowOnHealthbox(windowId);
+ }
+
+ }
+ else
+ {
+ u8 bank;
+
+ memcpy(text, sUnknown_0832C3C4, sizeof(sUnknown_0832C3C4));
+ bank = gSprites[healthboxSpriteId].data6;
+ if (IsDoubleBattle() == TRUE || GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ UpdateHpTextInHealthboxInDoubles(healthboxSpriteId, value, maxOrCurrent);
+ }
+ else
+ {
+ u32 var;
+ u8 i;
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER)
+ {
+ if (maxOrCurrent == HP_CURRENT)
+ var = 29;
+ else
+ var = 89;
+ }
+ else
+ {
+ if (maxOrCurrent == HP_CURRENT)
+ var = 20;
+ else
+ var = 48;
+ }
+
+ ConvertIntToDecimalStringN(text + 6, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ RenderTextFont9(gMonSpritesGfxPtr->fontPixels, 9, text);
+
+ for (i = 0; i < 3; i++)
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[i * 64 + 32],
+ (void*)((OBJ_VRAM0) + 32 * (gSprites[healthboxSpriteId].oam.tileNum + var + i)),
+ 0x20);
+ }
+ }
+ }
+}
+
+static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent)
+{
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+ u8 text[32];
+ void *objVram;
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER)
+ {
+ if (gBattleSpritesDataPtr->bankData[gSprites[healthboxSpriteId].data6].hpNumbersNoBars) // don't print text if only bars are visible
+ {
+ spriteTileNum = gSprites[gSprites[healthboxSpriteId].data5].oam.tileNum * 32;
+ objVram = (void*)(OBJ_VRAM0) + spriteTileNum;
+
+ if (maxOrCurrent != HP_CURRENT) // doubles, max hp
+ {
+ ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 0, 5, 0, &windowId);
+ sub_8075170((void*)(OBJ_VRAM0) + spriteTileNum + 0xC0, windowTileData, 2);
+ RemoveWindowOnHealthbox(windowId);
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_116),
+ (void*)(OBJ_VRAM0 + 0x680) + (gSprites[healthboxSpriteId].oam.tileNum * 32),
+ 0x20);
+ }
+ else
+ {
+ ConvertIntToDecimalStringN(text, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ text[3] = CHAR_SLASH;
+ text[4] = EOS;
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, 4, 5, 0, &windowId);
+ sub_807513C(objVram, 0, 3);
+ sub_8075170((void*)(OBJ_VRAM0 + 0x60) + spriteTileNum, windowTileData, 3);
+ RemoveWindowOnHealthbox(windowId);
+ }
+ }
+ }
+ else
+ {
+ u8 bank;
+
+ memcpy(text, sUnknown_0832C3D8, sizeof(sUnknown_0832C3D8));
+ bank = gSprites[healthboxSpriteId].data6;
+
+ if (gBattleSpritesDataPtr->bankData[bank].hpNumbersNoBars) // don't print text if only bars are visible
+ {
+ u8 var = 4;
+ u8 r7;
+ u8 *txtPtr;
+ u8 i;
+
+ if (maxOrCurrent == HP_CURRENT)
+ var = 0;
+
+ r7 = gSprites[healthboxSpriteId].data5;
+ txtPtr = ConvertIntToDecimalStringN(text + 6, value, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ if (!maxOrCurrent)
+ StringCopy(txtPtr, gText_Slash);
+ RenderTextFont9(gMonSpritesGfxPtr->fontPixels, 9, text);
+
+ for (i = var; i < var + 3; i++)
+ {
+ if (i < 3)
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[((i - var) * 64) + 32],
+ (void*)((OBJ_VRAM0) + 32 * (1 + gSprites[r7].oam.tileNum + i)),
+ 0x20);
+ }
+ else
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[((i - var) * 64) + 32],
+ (void*)((OBJ_VRAM0 + 0x20) + 32 * (i + gSprites[r7].oam.tileNum)),
+ 0x20);
+ }
+ }
+
+ if (maxOrCurrent == HP_CURRENT)
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[224],
+ (void*)((OBJ_VRAM0) + ((gSprites[r7].oam.tileNum + 4) * 32)),
+ 0x20);
+ CpuFill32(0, (void*)((OBJ_VRAM0) + (gSprites[r7].oam.tileNum * 32)), 0x20);
+ }
+ else
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER) // impossible to reach part, because the bank is from the opponent's side
+ {
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_116),
+ (void*)(OBJ_VRAM0) + ((gSprites[healthboxSpriteId].oam.tileNum + 52) * 32),
+ 0x20);
+ }
+ }
+ }
+ }
+}
+
+static void sub_80730D4(u8 healthboxSpriteId, struct Pokemon *mon)
+{
+ u8 text[20];
+ s32 j, var2;
+ u8 *fontPixels;
+ u8 i, var, nature, healthboxSpriteId_2;
+
+ memcpy(text, sUnknown_0832C3C4, sizeof(sUnknown_0832C3C4));
+ fontPixels = &gMonSpritesGfxPtr->fontPixels[0x520 + (GetBankIdentity(gSprites[healthboxSpriteId].data6) * 384)];
+ var = 5;
+ nature = GetNature(mon);
+ StringCopy(text + 6, gNatureNamePointers[nature]);
+ RenderTextFont9(fontPixels, 9, text);
+
+ for (j = 6, i = 0; i < var; i++, j++)
+ {
+ u8 elementId;
+
+ if ((text[j] >= 55 && text[j] <= 74) || (text[j] >= 135 && text[j] <= 154))
+ elementId = 44;
+ else if ((text[j] >= 75 && text[j] <= 79) || (text[j] >= 155 && text[j] <= 159))
+ elementId = 45;
+ else
+ elementId = 43;
+
+ CpuCopy32(GetHealthboxElementGfxPtr(elementId), fontPixels + (i * 64), 0x20);
+ }
+
+ for (j = 1; j < var + 1; j++)
+ {
+ var2 = (gSprites[healthboxSpriteId].oam.tileNum + (j - (j / 8 * 8)) + (j / 8 * 64)) * 32;
+ CpuCopy32(fontPixels, (void*)(OBJ_VRAM0) + (var2), 0x20);
+ fontPixels += 0x20;
+
+ var2 = (8 + gSprites[healthboxSpriteId].oam.tileNum + (j - (j / 8 * 8)) + (j / 8 * 64)) * 32;
+ CpuCopy32(fontPixels, (void*)(OBJ_VRAM0) + (var2), 0x20);
+ fontPixels += 0x20;
+ }
+
+ healthboxSpriteId_2 = gSprites[healthboxSpriteId].data5;
+ ConvertIntToDecimalStringN(text + 6, gBattleStruct->field_7C, STR_CONV_MODE_RIGHT_ALIGN, 2);
+ ConvertIntToDecimalStringN(text + 9, gBattleStruct->field_7B, STR_CONV_MODE_RIGHT_ALIGN, 2);
+ text[5] = CHAR_SPACE;
+ text[8] = CHAR_SLASH;
+ RenderTextFont9(gMonSpritesGfxPtr->fontPixels, 9, text);
+
+ j = healthboxSpriteId_2; // needed to match for some reason
+ for (j = 0; j < 5; j++)
+ {
+ if (j <= 1)
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[0x40 * j + 0x20],
+ (void*)(OBJ_VRAM0) + (gSprites[healthboxSpriteId_2].oam.tileNum + 2 + j) * 32,
+ 32);
+ }
+ else
+ {
+ CpuCopy32(&gMonSpritesGfxPtr->fontPixels[0x40 * j + 0x20],
+ (void*)(OBJ_VRAM0 + 0xC0) + (j + gSprites[healthboxSpriteId_2].oam.tileNum) * 32,
+ 32);
+ }
+ }
+}
+
+void SwapHpBarsWithHpText(void)
+{
+ s32 i;
+ u8 spriteId;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gSprites[gHealthBoxesIds[i]].callback == SpriteCallbackDummy
+ && GetBankSide(i) != SIDE_OPPONENT
+ && (IsDoubleBattle() || GetBankSide(i) != SIDE_PLAYER))
+ {
+ bool8 noBars;
+
+ gBattleSpritesDataPtr->bankData[i].hpNumbersNoBars ^= 1;
+ noBars = gBattleSpritesDataPtr->bankData[i].hpNumbersNoBars;
+ if (GetBankSide(i) == SIDE_PLAYER)
+ {
+ if (!IsDoubleBattle())
+ continue;
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ continue;
+
+ if (noBars == TRUE) // bars to text
+ {
+ spriteId = gSprites[gHealthBoxesIds[i]].data5;
+
+ CpuFill32(0, (void*)(OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * 32), 0x100);
+ UpdateHpTextInHealthboxInDoubles(gHealthBoxesIds[i], GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_HP), HP_CURRENT);
+ UpdateHpTextInHealthboxInDoubles(gHealthBoxesIds[i], GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_MAX_HP), HP_MAX);
+ }
+ else // text to bars
+ {
+ UpdateStatusIconInHealthbox(gHealthBoxesIds[i]);
+ UpdateHealthboxAttribute(gHealthBoxesIds[i], &gPlayerParty[gBattlePartyID[i]], HEALTHBOX_HEALTH_BAR);
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_117), (void*)(OBJ_VRAM0 + 0x680 + gSprites[gHealthBoxesIds[i]].oam.tileNum * 32), 32);
+ }
+ }
+ else
+ {
+ if (noBars == TRUE) // bars to text
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ {
+ sub_80730D4(gHealthBoxesIds[i], &gEnemyParty[gBattlePartyID[i]]);
+ }
+ else
+ {
+ spriteId = gSprites[gHealthBoxesIds[i]].data5;
+
+ CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * 32), 0x100);
+ UpdateHpTextInHealthboxInDoubles(gHealthBoxesIds[i], GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_HP), HP_CURRENT);
+ UpdateHpTextInHealthboxInDoubles(gHealthBoxesIds[i], GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_MAX_HP), HP_MAX);
+ }
+ }
+ else // text to bars
+ {
+ UpdateStatusIconInHealthbox(gHealthBoxesIds[i]);
+ UpdateHealthboxAttribute(gHealthBoxesIds[i], &gEnemyParty[gBattlePartyID[i]], HEALTHBOX_HEALTH_BAR);
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ UpdateHealthboxAttribute(gHealthBoxesIds[i], &gEnemyParty[gBattlePartyID[i]], HEALTHBOX_NICK);
+ }
+ }
+ gSprites[gHealthBoxesIds[i]].data7 ^= 1;
+ }
+ }
+}
+
+u8 CreatePartyStatusSummarySprites(u8 bank, struct HpAndStatus *partyInfo, u8 arg2, bool8 isBattleStart)
+{
+ bool8 isOpponent;
+ s16 bar_X, bar_Y, bar_pos2_X, bar_data0;
+ s32 i, j, var;
+ u8 barSpriteId;
+ u8 ballIconSpritesIds[6];
+ u8 taskId;
+
+ if (!arg2 || GetBankIdentity(bank) != IDENTITY_OPPONENT_MON2)
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ isOpponent = FALSE;
+ bar_X = 136, bar_Y = 96;
+ bar_pos2_X = 100;
+ bar_data0 = -5;
+ }
+ else
+ {
+ isOpponent = TRUE;
+
+ if (!arg2 || !IsDoubleBattle())
+ bar_X = 104, bar_Y = 40;
+ else
+ bar_X = 104, bar_Y = 16;
+
+ bar_pos2_X = -100;
+ bar_data0 = 5;
+ }
+ }
+ else
+ {
+ isOpponent = TRUE;
+ bar_X = 104, bar_Y = 40;
+ bar_pos2_X = -100;
+ bar_data0 = 5;
+ }
+
+ LoadCompressedObjectPicUsingHeap(&sStatusSummaryBarSpriteSheet);
+ LoadSpriteSheet(&sStatusSummaryBallsSpriteSheet);
+ LoadSpritePalette(&sStatusSummaryBarSpritePal);
+ LoadSpritePalette(&sStatusSummaryBallsSpritePal);
+
+ barSpriteId = CreateSprite(&sStatusSummaryBarSpriteTemplates[isOpponent], bar_X, bar_Y, 10);
+ SetSubspriteTables(&gSprites[barSpriteId], sStatusSummaryBar_SubspriteTable);
+ gSprites[barSpriteId].pos2.x = bar_pos2_X;
+ gSprites[barSpriteId].data0 = bar_data0;
+
+ if (isOpponent)
+ {
+ gSprites[barSpriteId].pos1.x -= 96;
+ gSprites[barSpriteId].oam.matrixNum = 8;
+ }
+ else
+ {
+ gSprites[barSpriteId].pos1.x += 96;
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ ballIconSpritesIds[i] = CreateSpriteAtEnd(&sStatusSummaryBallsSpriteTemplates[isOpponent], bar_X, bar_Y - 4, 9);
+
+ if (!isBattleStart)
+ gSprites[ballIconSpritesIds[i]].callback = SpriteCB_StatusSummaryBallsOnSwitchout;
+
+ if (!isOpponent)
+ {
+ gSprites[ballIconSpritesIds[i]].pos2.x = 0;
+ gSprites[ballIconSpritesIds[i]].pos2.y = 0;
+ }
+
+ gSprites[ballIconSpritesIds[i]].data0 = barSpriteId;
+
+ if (!isOpponent)
+ {
+ gSprites[ballIconSpritesIds[i]].pos1.x += 10 * i + 24;
+ gSprites[ballIconSpritesIds[i]].data1 = i * 7 + 10;
+ gSprites[ballIconSpritesIds[i]].pos2.x = 120;
+ }
+ else
+ {
+ gSprites[ballIconSpritesIds[i]].pos1.x -= 10 * (5 - i) + 24;
+ gSprites[ballIconSpritesIds[i]].data1 = (6 - i) * 7 + 10;
+ gSprites[ballIconSpritesIds[i]].pos2.x = -120;
+ }
+
+ gSprites[ballIconSpritesIds[i]].data2 = isOpponent;
+ }
+
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (partyInfo[i].hp == 0xFFFF) // empty slot or an egg
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 1;
+ gSprites[ballIconSpritesIds[i]].data7 = 1;
+ }
+ else if (partyInfo[i].hp == 0) // fainted mon
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
+ }
+ else if (partyInfo[i].status != 0) // mon with major status
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 2;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0, var = 5, j = 0; j < 6; j++)
+ {
+ if (partyInfo[j].hp == 0xFFFF) // empty slot or an egg
+ {
+ gSprites[ballIconSpritesIds[var]].oam.tileNum += 1;
+ gSprites[ballIconSpritesIds[var]].data7 = 1;
+ var--;
+ continue;
+ }
+ else if (partyInfo[j].hp == 0) // fainted mon
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->field_2A0 & gBitTable[j]) // hmm...?
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 3;
+ }
+ else if (partyInfo[j].status != 0) // mon with major status
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 2;
+ }
+ i++;
+ }
+ }
+ }
+ else
+ {
+ if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS))
+ {
+ for (var = 5, i = 0; i < 6; i++)
+ {
+ if (partyInfo[i].hp == 0xFFFF) // empty slot or an egg
+ {
+ gSprites[ballIconSpritesIds[var]].oam.tileNum += 1;
+ gSprites[ballIconSpritesIds[var]].data7 = 1;
+ }
+ else if (partyInfo[i].hp == 0) // fainted mon
+ {
+ gSprites[ballIconSpritesIds[var]].oam.tileNum += 3;
+ }
+ else if (partyInfo[i].status != 0) // mon with major status
+ {
+ gSprites[ballIconSpritesIds[var]].oam.tileNum += 2;
+ }
+ var--;
+ }
+ }
+ else
+ {
+ for (var = 0, i = 0, j = 0; j < 6; j++)
+ {
+ if (partyInfo[j].hp == 0xFFFF) // empty slot or an egg
+ {
+ gSprites[ballIconSpritesIds[i]].oam.tileNum += 1;
+ gSprites[ballIconSpritesIds[i]].data7 = 1;
+ i++;
+ continue;
+ }
+ else if (partyInfo[j].hp == 0) // fainted mon
+ {
+ gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 3;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->field_2A1 & gBitTable[j]) // hmm...?
+ {
+ gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 3;
+ }
+ else if (partyInfo[j].status != 0) // mon with major status
+ {
+ gSprites[ballIconSpritesIds[5 - var]].oam.tileNum += 2;
+ }
+ var++;
+ }
+ }
+ }
+
+ taskId = CreateTask(TaskDummy, 5);
+ gTasks[taskId].data[0] = bank;
+ gTasks[taskId].data[1] = barSpriteId;
+
+ for (i = 0; i < 6; i++)
+ gTasks[taskId].data[3 + i] = ballIconSpritesIds[i];
+
+ gTasks[taskId].data[10] = isBattleStart;
+
+ if (isBattleStart)
+ {
+ gBattleSpritesDataPtr->animationData->field_9_x1C++;
+ }
+
+ PlaySE12WithPanning(SE_TB_START, 0);
+ return taskId;
+}
+
+void sub_8073C30(u8 taskId)
+{
+ u8 sp[6];
+ u8 r7;
+ u8 r10;
+ u8 bank;
+ s32 i;
+
+ r7 = gTasks[taskId].data[10];
+ r10 = gTasks[taskId].data[1];
+ bank = gTasks[taskId].data[0];
+
+ for (i = 0; i < 6; i++)
+ sp[i] = gTasks[taskId].data[3 + i];
+
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x3F40);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0x10);
+
+ gTasks[taskId].data[15] = 16;
+
+ for (i = 0; i < 6; i++)
+ gSprites[sp[i]].oam.objMode = 1;
+
+ gSprites[r10].oam.objMode = 1;
+
+ if (r7 != 0)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (GetBankSide(bank) != SIDE_PLAYER)
+ {
+ gSprites[sp[5 - i]].data1 = 7 * i;
+ gSprites[sp[5 - i]].data3 = 0;
+ gSprites[sp[5 - i]].data4 = 0;
+ gSprites[sp[5 - i]].callback = sub_8074158;
+ }
+ else
+ {
+ gSprites[sp[i]].data1 = 7 * i;
+ gSprites[sp[i]].data3 = 0;
+ gSprites[sp[i]].data4 = 0;
+ gSprites[sp[i]].callback = sub_8074158;
+ }
+ }
+ gSprites[r10].data0 /= 2;
+ gSprites[r10].data1 = 0;
+ gSprites[r10].callback = sub_8074090;
+ SetSubspriteTables(&gSprites[r10], sUnknown_0832C2CC);
+ gTasks[taskId].func = sub_8073E08;
+ }
+ else
+ {
+ gTasks[taskId].func = sub_8073F98;
+ }
+}
+
+static void sub_8073E08(u8 taskId)
+{
+ u16 temp = gTasks[taskId].data[11]++;
+
+ if (!(temp & 1))
+ {
+ gTasks[taskId].data[15]--;
+ if (gTasks[taskId].data[15] < 0)
+ return;
+
+ SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].data[15]) | ((16 - gTasks[taskId].data[15]) << 8));
+ }
+ if (gTasks[taskId].data[15] == 0)
+ gTasks[taskId].func = sub_8073E64;
+}
+
+static void sub_8073E64(u8 taskId)
+{
+ u8 sp[6];
+ s32 i;
+
+ u8 bank = gTasks[taskId].data[0];
+ gTasks[taskId].data[15]--;
+ if (gTasks[taskId].data[15] == -1)
+ {
+ u8 var = gTasks[taskId].data[1];
+
+ for (i = 0; i < 6; i++)
+ sp[i] = gTasks[taskId].data[3 + i];
+
+ gBattleSpritesDataPtr->animationData->field_9_x1C--;
+ if (!gBattleSpritesDataPtr->animationData->field_9_x1C)
+ {
+ DestroySpriteAndFreeResources(&gSprites[var]);
+ DestroySpriteAndFreeResources(&gSprites[sp[0]]);
+ }
+ else
+ {
+ FreeSpriteOamMatrix(&gSprites[var]);
+ DestroySprite(&gSprites[var]);
+ FreeSpriteOamMatrix(&gSprites[sp[0]]);
+ DestroySprite(&gSprites[sp[0]]);
+ }
+
+ for (i = 1; i < 6; i++)
+ DestroySprite(&gSprites[sp[i]]);
+ }
+ else if (gTasks[taskId].data[15] == -3)
+ {
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x1 = 0;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ DestroyTask(taskId);
+ }
+}
+
+static void sub_8073F98(u8 taskId)
+{
+ u8 sp[6];
+ s32 i;
+
+ u8 bank = gTasks[taskId].data[0];
+ gTasks[taskId].data[15]--;
+ if (gTasks[taskId].data[15] >= 0)
+ {
+ SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].data[15]) | ((16 - gTasks[taskId].data[15]) << 8));
+ }
+ else if (gTasks[taskId].data[15] == -1)
+ {
+ u8 var = gTasks[taskId].data[1];
+
+ for (i = 0; i < 6; i++)
+ sp[i] = gTasks[taskId].data[3 + i];
+
+ DestroySpriteAndFreeResources(&gSprites[var]);
+ DestroySpriteAndFreeResources(&gSprites[sp[0]]);
+
+ for (i = 1; i < 6; i++)
+ DestroySprite(&gSprites[sp[i]]);
+ }
+ else if (gTasks[taskId].data[15] == -3)
+ {
+ gBattleSpritesDataPtr->healthBoxesData[bank].flag_x1 = 0;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ DestroyTask(taskId);
+ }
+}
+
+static void SpriteCB_StatusSummaryBar(struct Sprite *sprite)
+{
+ if (sprite->pos2.x != 0)
+ sprite->pos2.x += sprite->data0;
+}
+
+static void sub_8074090(struct Sprite *sprite)
+{
+ sprite->data1 += 32;
+ if (sprite->data0 > 0)
+ sprite->pos2.x += sprite->data1 >> 4;
+ else
+ sprite->pos2.x -= sprite->data1 >> 4;
+ sprite->data1 &= 0xF;
+}
+
+static void SpriteCB_StatusSummaryBallsOnBattleStart(struct Sprite *sprite)
+{
+ u8 var1;
+ u16 var2;
+ s8 pan;
+
+ if (sprite->data1 > 0)
+ {
+ sprite->data1--;
+ return;
+ }
+
+ var1 = sprite->data2;
+ var2 = sprite->data3;
+ var2 += 56;
+ sprite->data3 = var2 & 0xFFF0;
+
+ if (var1 != 0)
+ {
+ sprite->pos2.x += var2 >> 4;
+ if (sprite->pos2.x > 0)
+ sprite->pos2.x = 0;
+ }
+ else
+ {
+ sprite->pos2.x -= var2 >> 4;
+ if (sprite->pos2.x < 0)
+ sprite->pos2.x = 0;
+ }
+
+ if (sprite->pos2.x == 0)
+ {
+ pan = PAN_SIDE_OPPONENT;
+ if (var1 != 0)
+ pan = PAN_SIDE_PLAYER;
+
+ if (sprite->data7 != 0)
+ PlaySE2WithPanning(SE_TB_KARA, pan);
+ else
+ PlaySE1WithPanning(SE_TB_KON, pan);
+
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void sub_8074158(struct Sprite *sprite)
+{
+ u8 var1;
+ u16 var2;
+
+ if (sprite->data1 > 0)
+ {
+ sprite->data1--;
+ return;
+ }
+ var1 = sprite->data2;
+ var2 = sprite->data3;
+ var2 += 56;
+ sprite->data3 = var2 & 0xFFF0;
+ if (var1 != 0)
+ sprite->pos2.x += var2 >> 4;
+ else
+ sprite->pos2.x -= var2 >> 4;
+ if (sprite->pos2.x + sprite->pos1.x > 248
+ || sprite->pos2.x + sprite->pos1.x < -8)
+ {
+ sprite->invisible = TRUE;
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void SpriteCB_StatusSummaryBallsOnSwitchout(struct Sprite *sprite)
+{
+ u8 barSpriteId = sprite->data0;
+
+ sprite->pos2.x = gSprites[barSpriteId].pos2.x;
+ sprite->pos2.y = gSprites[barSpriteId].pos2.y;
+}
+
+static void UpdateNickInHealthbox(u8 healthboxSpriteId, struct Pokemon *mon)
+{
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+ void *ptr;
+ const u8 *genderTxt;
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+ u16 species;
+ u8 gender;
+
+ StringCopy(gDisplayedStringBattle, gText_HighlightDarkGrey);
+ GetMonData(mon, MON_DATA_NICKNAME, nickname);
+ StringGetEnd10(nickname);
+ ptr = StringAppend(gDisplayedStringBattle, nickname);
+
+ gender = GetMonGender(mon);
+ species = GetMonData(mon, MON_DATA_SPECIES);
+
+ if ((species == SPECIES_NIDORAN_F || species == SPECIES_NIDORAN_M) && StringCompare(nickname, gSpeciesNames[species]) == 0)
+ gender = 100;
+
+ // AddTextPrinterAndCreateWindowOnHealthbox's arguments are the same in all 3 cases.
+ // It's possible they may have been different in early development phases.
+ switch (gender)
+ {
+ default:
+ StringCopy(ptr, gText_DynColor2);
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
+ break;
+ case MON_MALE:
+ StringCopy(ptr, gText_DynColor2Male);
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
+ break;
+ case MON_FEMALE:
+ StringCopy(ptr, gText_DynColor1Female);
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gDisplayedStringBattle, 0, 3, 2, &windowId);
+ break;
+ }
+
+ spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * 32;
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER)
+ {
+ sub_8075198((void*)(0x6010040 + spriteTileNum), windowTileData, 6);
+ ptr = (void*)(OBJ_VRAM0);
+ if (!IsDoubleBattle())
+ ptr += spriteTileNum + 0x800;
+ else
+ ptr += spriteTileNum + 0x400;
+ sub_8075198(ptr, windowTileData + 0xC0, 1);
+ }
+ else
+ {
+ sub_8075198((void*)(0x6010020 + spriteTileNum), windowTileData, 7);
+ }
+
+ RemoveWindowOnHealthbox(windowId);
+}
+
+static void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus)
+{
+ u8 bank, healthboxSpriteId_2;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
+ return;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ return;
+
+ bank = gSprites[healthboxSpriteId].data6;
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ return;
+ if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_SPECIES)), FLAG_GET_CAUGHT))
+ return;
+
+ healthboxSpriteId_2 = gSprites[healthboxSpriteId].data5;
+
+ if (noStatus)
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_70), (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 8) * 32), 32);
+ else
+ CpuFill32(0, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 8) * 32), 32);
+}
+
+static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId)
+{
+ s32 i;
+ u8 bank, healthboxSpriteId_2;
+ u32 status, pltAdder;
+ const u8 *statusGfxPtr;
+ s16 tileNumAdder;
+ u8 statusPalId;
+
+ bank = gSprites[healthboxSpriteId].data6;
+ healthboxSpriteId_2 = gSprites[healthboxSpriteId].data5;
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ status = GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_STATUS);
+ if (!IsDoubleBattle())
+ tileNumAdder = 0x1A;
+ else
+ tileNumAdder = 0x12;
+ }
+ else
+ {
+ status = GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_STATUS);
+ tileNumAdder = 0x11;
+ }
+
+ if (status & STATUS_SLEEP)
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_SLP_BANK0, bank));
+ statusPalId = PAL_STATUS_SLP;
+ }
+ else if (status & STATUS_PSN_ANY)
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PSN_BANK0, bank));
+ statusPalId = PAL_STATUS_PSN;
+ }
+ else if (status & STATUS_BURN)
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_BRN_BANK0, bank));
+ statusPalId = PAL_STATUS_BRN;
+ }
+ else if (status & STATUS_FREEZE)
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_FRZ_BANK0, bank));
+ statusPalId = PAL_STATUS_FRZ;
+ }
+ else if (status & STATUS_PARALYSIS)
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PRZ_BANK0, bank));
+ statusPalId = PAL_STATUS_PAR;
+ }
+ else
+ {
+ statusGfxPtr = GetHealthboxElementGfxPtr(HEALTHBOX_GFX_39);
+
+ for (i = 0; i < 3; i++)
+ CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder + i) * 32), 32);
+
+ if (!gBattleSpritesDataPtr->bankData[bank].hpNumbersNoBars)
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void *)(OBJ_VRAM0 + gSprites[healthboxSpriteId_2].oam.tileNum * 32), 64);
+
+ TryAddPokeballIconToHealthbox(healthboxSpriteId, TRUE);
+ return;
+ }
+
+ pltAdder = gSprites[healthboxSpriteId].oam.paletteNum * 16;
+ pltAdder += bank + 12;
+
+ FillPalette(sStatusIconPalettes[statusPalId], pltAdder + 0x100, 2);
+ CpuCopy16(gPlttBufferUnfaded + 0x100 + pltAdder, (void*)(OBJ_PLTT + pltAdder * 2), 2);
+ CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder) * 32), 96);
+ if (IsDoubleBattle() == TRUE || GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ if (!gBattleSpritesDataPtr->bankData[bank].hpNumbersNoBars)
+ {
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_0), (void*)(OBJ_VRAM0 + gSprites[healthboxSpriteId_2].oam.tileNum * 32), 32);
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_65), (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 1) * 32), 32);
+ }
+ }
+ TryAddPokeballIconToHealthbox(healthboxSpriteId, FALSE);
+}
+
+static u8 GetStatusIconForBankId(u8 statusElementId, u8 bank)
+{
+ u8 ret = statusElementId;
+
+ switch (statusElementId)
+ {
+ case HEALTHBOX_GFX_STATUS_PSN_BANK0:
+ if (bank == 0)
+ ret = HEALTHBOX_GFX_STATUS_PSN_BANK0;
+ else if (bank == 1)
+ ret = HEALTHBOX_GFX_STATUS_PSN_BANK1;
+ else if (bank == 2)
+ ret = HEALTHBOX_GFX_STATUS_PSN_BANK2;
+ else
+ ret = HEALTHBOX_GFX_STATUS_PSN_BANK3;
+ break;
+ case HEALTHBOX_GFX_STATUS_PRZ_BANK0:
+ if (bank == 0)
+ ret = HEALTHBOX_GFX_STATUS_PRZ_BANK0;
+ else if (bank == 1)
+ ret = HEALTHBOX_GFX_STATUS_PRZ_BANK1;
+ else if (bank == 2)
+ ret = HEALTHBOX_GFX_STATUS_PRZ_BANK2;
+ else
+ ret = HEALTHBOX_GFX_STATUS_PRZ_BANK3;
+ break;
+ case HEALTHBOX_GFX_STATUS_SLP_BANK0:
+ if (bank == 0)
+ ret = HEALTHBOX_GFX_STATUS_SLP_BANK0;
+ else if (bank == 1)
+ ret = HEALTHBOX_GFX_STATUS_SLP_BANK1;
+ else if (bank == 2)
+ ret = HEALTHBOX_GFX_STATUS_SLP_BANK2;
+ else
+ ret = HEALTHBOX_GFX_STATUS_SLP_BANK3;
+ break;
+ case HEALTHBOX_GFX_STATUS_FRZ_BANK0:
+ if (bank == 0)
+ ret = HEALTHBOX_GFX_STATUS_FRZ_BANK0;
+ else if (bank == 1)
+ ret = HEALTHBOX_GFX_STATUS_FRZ_BANK1;
+ else if (bank == 2)
+ ret = HEALTHBOX_GFX_STATUS_FRZ_BANK2;
+ else
+ ret = HEALTHBOX_GFX_STATUS_FRZ_BANK3;
+ break;
+ case HEALTHBOX_GFX_STATUS_BRN_BANK0:
+ if (bank == 0)
+ ret = HEALTHBOX_GFX_STATUS_BRN_BANK0;
+ else if (bank == 1)
+ ret = HEALTHBOX_GFX_STATUS_BRN_BANK1;
+ else if (bank == 2)
+ ret = HEALTHBOX_GFX_STATUS_BRN_BANK2;
+ else
+ ret = HEALTHBOX_GFX_STATUS_BRN_BANK3;
+ break;
+ }
+ return ret;
+}
+
+static void UpdateSafariBallsTextOnHealthbox(u8 healthboxSpriteId)
+{
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(gText_SafariBalls, 0, 3, 2, &windowId);
+ spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * 32;
+ sub_8075198((void*)(OBJ_VRAM0 + 0x40) + spriteTileNum, windowTileData, 6);
+ sub_8075198((void*)(OBJ_VRAM0 + 0x800) + spriteTileNum, windowTileData + 0xC0, 2);
+ RemoveWindowOnHealthbox(windowId);
+}
+
+static void UpdateLeftNoOfBallsTextOnHealthbox(u8 healthboxSpriteId)
+{
+ u8 text[16];
+ u8 *txtPtr;
+ u32 windowId, spriteTileNum;
+ u8 *windowTileData;
+
+ txtPtr = StringCopy(text, gText_SafariBallLeft);
+ ConvertIntToDecimalStringN(txtPtr, gNumSafariBalls, STR_CONV_MODE_LEFT_ALIGN, 2);
+
+ windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, GetStringRightAlignXOffset(0, text, 0x2F), 3, 2, &windowId);
+ spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * 32;
+ sub_80751E4((void*)(OBJ_VRAM0 + 0x2C0) + spriteTileNum, windowTileData, 2);
+ sub_80751E4((void*)(OBJ_VRAM0 + 0xA00) + spriteTileNum, windowTileData + 0x40, 4);
+ RemoveWindowOnHealthbox(windowId);
+}
+
+void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elementId)
+{
+ s32 maxHp, currHp;
+ u8 bank = gSprites[healthboxSpriteId].data6;
+
+ if (elementId == HEALTHBOX_ALL && !IsDoubleBattle())
+ GetBankSide(bank); // pointless function call
+
+ if (GetBankSide(gSprites[healthboxSpriteId].data6) == SIDE_PLAYER)
+ {
+ u8 isDoubles;
+
+ if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL)
+ UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL));
+ if (elementId == HEALTHBOX_CURRENT_HP || elementId == HEALTHBOX_ALL)
+ UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_HP), HP_CURRENT);
+ if (elementId == HEALTHBOX_MAX_HP || elementId == HEALTHBOX_ALL)
+ UpdateHpTextInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_MAX_HP), HP_MAX);
+ if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL)
+ {
+ LoadBattleBarGfx(0);
+ maxHp = GetMonData(mon, MON_DATA_MAX_HP);
+ currHp = GetMonData(mon, MON_DATA_HP);
+ SetBattleBarStruct(bank, healthboxSpriteId, maxHp, currHp, 0);
+ sub_8074AA0(bank, healthboxSpriteId, HEALTH_BAR, 0);
+ }
+ isDoubles = IsDoubleBattle();
+ if (!isDoubles && (elementId == HEALTHBOX_EXP_BAR || elementId == HEALTHBOX_ALL))
+ {
+ u16 species;
+ u32 exp, currLevelExp;
+ s32 currExpBarValue, maxExpBarValue;
+ u8 level;
+
+ LoadBattleBarGfx(3);
+ species = GetMonData(mon, MON_DATA_SPECIES);
+ level = GetMonData(mon, MON_DATA_LEVEL);
+ exp = GetMonData(mon, MON_DATA_EXP);
+ currLevelExp = gExperienceTables[gBaseStats[species].growthRate][level];
+ currExpBarValue = exp - currLevelExp;
+ maxExpBarValue = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLevelExp;
+ SetBattleBarStruct(bank, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles);
+ sub_8074AA0(bank, healthboxSpriteId, EXP_BAR, 0);
+ }
+ if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL)
+ UpdateNickInHealthbox(healthboxSpriteId, mon);
+ if (elementId == HEALTHBOX_STATUS_ICON || elementId == HEALTHBOX_ALL)
+ UpdateStatusIconInHealthbox(healthboxSpriteId);
+ if (elementId == HEALTHBOX_SAFARI_ALL_TEXT)
+ UpdateSafariBallsTextOnHealthbox(healthboxSpriteId);
+ if (elementId == HEALTHBOX_SAFARI_ALL_TEXT || elementId == HEALTHBOX_SAFARI_BALLS_TEXT)
+ UpdateLeftNoOfBallsTextOnHealthbox(healthboxSpriteId);
+ }
+ else
+ {
+ if (elementId == HEALTHBOX_LEVEL || elementId == HEALTHBOX_ALL)
+ UpdateLvlInHealthbox(healthboxSpriteId, GetMonData(mon, MON_DATA_LEVEL));
+ if (elementId == HEALTHBOX_HEALTH_BAR || elementId == HEALTHBOX_ALL)
+ {
+ LoadBattleBarGfx(0);
+ maxHp = GetMonData(mon, MON_DATA_MAX_HP);
+ currHp = GetMonData(mon, MON_DATA_HP);
+ SetBattleBarStruct(bank, healthboxSpriteId, maxHp, currHp, 0);
+ sub_8074AA0(bank, healthboxSpriteId, HEALTH_BAR, 0);
+ }
+ if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL)
+ UpdateNickInHealthbox(healthboxSpriteId, mon);
+ if (elementId == HEALTHBOX_STATUS_ICON || elementId == HEALTHBOX_ALL)
+ UpdateStatusIconInHealthbox(healthboxSpriteId);
+ }
+}
+
+s32 sub_8074AA0(u8 bank, u8 healthboxSpriteId, u8 whichBar, u8 arg3)
+{
+ s32 var;
+
+ if (whichBar == HEALTH_BAR) // health bar
+ {
+ var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[bank].maxValue,
+ gBattleSpritesDataPtr->battleBars[bank].currentValue,
+ gBattleSpritesDataPtr->battleBars[bank].field_C,
+ &gBattleSpritesDataPtr->battleBars[bank].field_10,
+ 6, 1);
+ }
+ else // exp bar
+ {
+ u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[bank].currentValue,
+ gBattleSpritesDataPtr->battleBars[bank].field_C,
+ gBattleSpritesDataPtr->battleBars[bank].maxValue, 8);
+ if (expFraction == 0)
+ expFraction = 1;
+ expFraction = abs(gBattleSpritesDataPtr->battleBars[bank].field_C / expFraction);
+
+ var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[bank].maxValue,
+ gBattleSpritesDataPtr->battleBars[bank].currentValue,
+ gBattleSpritesDataPtr->battleBars[bank].field_C,
+ &gBattleSpritesDataPtr->battleBars[bank].field_10,
+ 8, expFraction);
+ }
+
+ if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->bankData[bank].hpNumbersNoBars))
+ sub_8074B9C(bank, whichBar);
+
+ if (var == -1)
+ gBattleSpritesDataPtr->battleBars[bank].field_10 = 0;
+
+ return var;
+}
+
+static void sub_8074B9C(u8 bank, u8 whichBar)
+{
+ u8 array[7];
+ u8 subRet, level;
+ u8 barElementId;
+ u8 i;
+
+ switch (whichBar)
+ {
+ case HEALTH_BAR:
+ subRet = sub_8074E8C(gBattleSpritesDataPtr->battleBars[bank].maxValue,
+ gBattleSpritesDataPtr->battleBars[bank].currentValue,
+ gBattleSpritesDataPtr->battleBars[bank].field_C,
+ &gBattleSpritesDataPtr->battleBars[bank].field_10,
+ array, 6);
+ barElementId = 3;
+ if (subRet <= 0x18)
+ {
+ barElementId = 0x38;
+ if (subRet > 9)
+ barElementId = 0x2F;
+ }
+ for (i = 0; i < 6; i++)
+ {
+ u8 healthboxSpriteId_2 = gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].data5;
+ if (i < 2)
+ CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32,
+ (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 2 + i) * 32), 32);
+ else
+ CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32,
+ (void*)(OBJ_VRAM0 + 64 + (i + gSprites[healthboxSpriteId_2].oam.tileNum) * 32), 32);
+ }
+ break;
+ case EXP_BAR:
+ sub_8074E8C(gBattleSpritesDataPtr->battleBars[bank].maxValue,
+ gBattleSpritesDataPtr->battleBars[bank].currentValue,
+ gBattleSpritesDataPtr->battleBars[bank].field_C,
+ &gBattleSpritesDataPtr->battleBars[bank].field_10,
+ array, 8);
+ level = GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_LEVEL);
+ if (level == MAX_MON_LEVEL)
+ {
+ for (i = 0; i < 8; i++)
+ array[i] = 0;
+ }
+ for (i = 0; i < 8; i++)
+ {
+ if (i < 4)
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32,
+ (void*)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].oam.tileNum + 0x24 + i) * 32), 32);
+ else
+ CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32,
+ (void*)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].oam.tileNum) * 32), 32);
+ }
+ break;
+ }
+}
+
+static s32 sub_8074DB8(s32 maxValue, s32 currValue, s32 arg2, s32 *arg3, u8 arg4, u16 arg5)
+{
+ s32 r6;
+ s32 ret;
+ arg4 <<= 3;
+
+ if (*arg3 == -32768)
+ {
+ if (maxValue < arg4)
+ *arg3 = currValue << 8;
+ else
+ *arg3 = currValue;
+ }
+
+ currValue -= arg2;
+ if (currValue < 0)
+ currValue = 0;
+ else if (currValue > maxValue)
+ currValue = maxValue;
+
+ if (maxValue < arg4)
+ {
+ s32 var = *arg3 >> 8;
+
+ r6 = *arg3;
+ if (currValue == var && (r6 & 0xFF) == 0)
+ return -1;
+ }
+ else
+ {
+ r6 = *arg3;
+ if (currValue == r6)
+ return -1;
+ }
+
+ if (maxValue < arg4)
+ {
+ s32 var = (maxValue << 8) / arg4;
+
+ if (arg2 < 0)
+ {
+ *arg3 = r6 + var;
+ ret = *arg3 >> 8;
+ if (ret >= currValue)
+ {
+ *arg3 = currValue << 8;
+ ret = currValue;
+ }
+ }
+ else
+ {
+ *arg3 = r6 - var;
+ ret = *arg3 >> 8;
+ if ((*arg3 & 0xFF) > 0)
+ ret++;
+ if (ret <= currValue)
+ {
+ *arg3 = currValue << 8;
+ ret = currValue;
+ }
+ }
+ }
+ else
+ {
+ if (arg2 < 0)
+ {
+ *arg3 += arg5;
+ if (*arg3 > currValue)
+ *arg3 = currValue;
+ ret = *arg3;
+ }
+ else
+ {
+ *arg3 -= arg5;
+ if (*arg3 < currValue)
+ *arg3 = currValue;
+ ret = *arg3;
+ }
+ }
+
+ return ret;
+}
+
+static u8 sub_8074E8C(s32 maxValue, s32 currValue, s32 arg2, s32 *arg3, u8 *arg4, u8 arg5)
+{
+ s32 r5 = currValue - arg2;
+ u8 ret;
+ u8 i;
+ u8 r2;
+
+ if (r5 < 0)
+ r5 = 0;
+ else if (r5 > maxValue)
+ r5 = maxValue;
+
+ ret = arg5 << 3;
+
+ for (i = 0; i < arg5; i++)
+ arg4[i] = 0;
+
+ if (maxValue < ret)
+ r2 = (*arg3 * ret / maxValue) >> 8;
+ else
+ r2 = *arg3 * ret / maxValue;
+
+ ret = r2;
+
+ if (ret == 0 && r5 > 0)
+ {
+ arg4[0] = 1;
+ ret = 1;
+ }
+ else
+ {
+ for (i = 0; i < arg5; i++)
+ {
+ if (r2 >= 8)
+ {
+ arg4[i] = 8;
+ }
+ else
+ {
+ arg4[i] = r2;
+ break;
+ }
+ r2 -= 8;
+ }
+ }
+
+ return ret;
+}
+
+static s16 sub_8074F28(struct TestingBar *barInfo, s32 *arg1, u16 *arg2, s32 arg3)
+{
+ s16 ret, var;
+
+ ret = sub_8074DB8(barInfo->maxValue,
+ barInfo->currValue,
+ barInfo->field_8,
+ arg1, 6, 1);
+ sub_8074F88(barInfo, arg1, arg2);
+
+ if (barInfo->maxValue < 0x30)
+ var = *arg1 >> 8;
+ else
+ var = *arg1;
+
+ DummiedOutFunction(barInfo->maxValue, var, arg3);
+
+ return ret;
+}
+
+static void sub_8074F88(struct TestingBar *barInfo, s32 *arg1, u16 *arg2)
+{
+ u8 sp8[6];
+ u16 sp10[6];
+ u8 i;
+
+ sub_8074E8C(barInfo->maxValue, barInfo->currValue,
+ barInfo->field_8, arg1, sp8, 6);
+
+ for (i = 0; i < 6; i++)
+ sp10[i] = (barInfo->unkC_0 << 12) | (barInfo->unk10 + sp8[i]);
+
+ CpuCopy16(sp10, arg2, sizeof(sp10));
+}
+
+static u8 GetScaledExpFraction(s32 currValue, s32 arg1, s32 maxValue, u8 scale)
+{
+ s32 r5, result;
+ s8 r4, r0;
+
+ scale *= 8;
+ r5 = currValue - arg1;
+
+ if (r5 < 0)
+ r5 = 0;
+ else if (r5 > maxValue)
+ r5 = maxValue;
+
+ r4 = currValue * scale / maxValue;
+ r0 = r5 * scale / maxValue;
+ result = r4 - r0;
+
+ return abs(result);
+}
+
+u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale)
+{
+ u8 result = hp * scale / maxhp;
+
+ if (result == 0 && hp > 0)
+ return 1;
+
+ return result;
+}
+
+u8 GetHPBarLevel(s16 hp, s16 maxhp)
+{
+ s32 result;
+
+ if (hp == maxhp)
+ {
+ result = 4;
+ }
+ else
+ {
+ u8 fraction = GetScaledHPFraction(hp, maxhp, 48);
+ if (fraction > 24)
+ result = 3;
+ else if (fraction > 9)
+ result = 2;
+ else if (fraction > 0)
+ result = 1;
+ else
+ result = 0;
+ }
+
+ return result;
+}
+
+static u8* AddTextPrinterAndCreateWindowOnHealthbox(const u8 *str, u32 x, u32 y, u32 arg3, u32 *windowId)
+{
+ u16 winId;
+ struct TextColor color;
+ struct WindowTemplate winTemplate = sHealthboxWindowTemplate;
+
+ winId = AddWindow(&winTemplate);
+ FillWindowPixelBuffer(winId, (arg3 << 4) | (arg3));
+
+ color.fgColor = arg3;
+ color.bgColor = 1;
+ color.shadowColor = 3;
+
+ AddTextPrinterParametrized2(winId, 0, x, y, 0, 0, &color, -1, str);
+
+ *windowId = winId;
+ return (u8*)(GetWindowAttribute(winId, WINDOW_TILE_DATA));
+}
+
+static void RemoveWindowOnHealthbox(u32 windowId)
+{
+ RemoveWindow(windowId);
+}
+
+static void sub_807513C(void *dest, u32 arg1, u32 arg2)
+{
+ CpuFill32(0x11111111 * arg1, dest, arg2 * 32);
+}
+
+static void sub_8075170(void *dest, u8 *windowTileData, u32 arg2)
+{
+ CpuCopy32(windowTileData + 256, dest, arg2 * 32);
+}
+
+static void sub_8075198(void *dest, u8 *windowTileData, s32 arg2)
+{
+ CpuCopy32(windowTileData + 256, dest + 256, arg2 * 32);
+
+ if (arg2 > 0)
+ {
+ do
+ {
+ CpuCopy32(windowTileData + 20, dest + 20, 12);
+ dest += 32, windowTileData+= 32;
+ arg2--;
+ } while (arg2 != 0);
+ }
+}
+
+static void sub_80751E4(void *dest, u8 *windowTileData, u32 arg2)
+{
+ CpuCopy32(windowTileData, dest, arg2 * 32);
+ CpuCopy32(windowTileData + 256, dest + 256, arg2 * 32);
+}
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index fb6a8272b..a1e5767ad 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -349,7 +349,7 @@ static void atk51_switch_handle_order(void);
static void atk52_switch_in_effects(void);
static void atk53_trainer_slide(void);
static void atk54_effectiveness_sound(void);
-static void atk55_play_sound(void);
+static void atk55_play_fanfare(void);
static void atk56_fainting_cry(void);
static void atk57(void);
static void atk58_return_to_ball(void);
@@ -601,7 +601,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk52_switch_in_effects,
atk53_trainer_slide,
atk54_effectiveness_sound,
- atk55_play_sound,
+ atk55_play_fanfare,
atk56_fainting_cry,
atk57,
atk58_return_to_ball,
@@ -5308,7 +5308,7 @@ static void atk4B_return_atk_to_ball(void)
gActiveBank = gBankAttacker;
if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank)))
{
- EmitReturnPokeToBall(0, 0);
+ EmitReturnMonToBall(0, 0);
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr++;
@@ -5627,7 +5627,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -5649,7 +5649,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -5670,7 +5670,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -5692,7 +5692,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -5755,7 +5755,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -5771,7 +5771,7 @@ static void atk50_openpartyscreen(void)
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
- Emit_x2A(0);
+ EmitCmd42(0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
@@ -6031,10 +6031,10 @@ static void atk54_effectiveness_sound(void)
gBattlescriptCurrInstr += 3;
}
-static void atk55_play_sound(void)
+static void atk55_play_fanfare(void)
{
gActiveBank = gBankAttacker;
- EmitPlaySound(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), 0);
+ EmitPlayFanfareOrBGM(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), FALSE);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 3;
@@ -6052,7 +6052,7 @@ static void atk56_fainting_cry(void)
static void atk57(void)
{
gActiveBank = GetBankByIdentity(0);
- Emit_x37(0, gBattleOutcome);
+ EmitCmd55(0, gBattleOutcome);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 1;
@@ -6061,7 +6061,7 @@ static void atk57(void)
static void atk58_return_to_ball(void)
{
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
- EmitReturnPokeToBall(0, 1);
+ EmitReturnMonToBall(0, 1);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
@@ -7137,7 +7137,7 @@ static void atk76_various(void)
gDisableStructs[1].truantUnknownBit = 1;
break;
case 13:
- EmitCmd13(0);
+ EmitCmd19(0);
MarkBufferBankForExecution(gActiveBank);
break;
case 14:
@@ -7162,7 +7162,7 @@ static void atk76_various(void)
gActiveBank = 1;
if (gBattleMons[gActiveBank].hp != 0)
{
- EmitReturnPokeToBall(0, 0);
+ EmitReturnMonToBall(0, 0);
MarkBufferBankForExecution(gActiveBank);
}
break;
@@ -7172,7 +7172,7 @@ static void atk76_various(void)
gActiveBank = 3;
if (gBattleMons[gActiveBank].hp != 0)
{
- EmitReturnPokeToBall(0, 0);
+ EmitReturnMonToBall(0, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
@@ -7197,7 +7197,7 @@ static void atk76_various(void)
gBattleOutcome = BATTLE_OPPONENT_TELEPORTED;
break;
case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC:
- EmitPlaySound(0, BGM_KACHI1, 1);
+ EmitPlayFanfareOrBGM(0, BGM_KACHI1, TRUE);
MarkBufferBankForExecution(gActiveBank);
break;
}
diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c
index 83d32b56c..9a6f0371c 100755
--- a/src/braille_puzzles.c
+++ b/src/braille_puzzles.c
@@ -220,7 +220,7 @@ bool8 ShouldDoBrailleStrengthEffect(void)
void sub_8179834(void)
{
- gFieldEffectSpawnParams[0] = brm_get_pokemon_selection();
+ gFieldEffectArguments[0] = brm_get_pokemon_selection();
FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB);
}
@@ -256,7 +256,7 @@ bool8 ShouldDoBrailleFlyEffect(void)
void sub_8179918(void)
{
- gFieldEffectSpawnParams[0] = brm_get_pokemon_selection();
+ gFieldEffectArguments[0] = brm_get_pokemon_selection();
FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB);
}
@@ -417,7 +417,7 @@ bool8 ShouldDoBrailleRegicePuzzle(void)
}
// TODO: Find what flags 2 and 3 are.
FlagSet(3);
- FlagReset(2);
+ FlagClear(2);
return FALSE;
}
#else
@@ -568,7 +568,7 @@ _08179B44:\n\
movs r0, 0x3\n\
bl FlagSet\n\
movs r0, 0x2\n\
- bl FlagReset\n\
+ bl FlagClear\n\
_08179B5A:\n\
movs r0, 0\n\
_08179B5C:\n\
diff --git a/src/coins.c b/src/coins.c
index 4ee601b22..e1694b29c 100644
--- a/src/coins.c
+++ b/src/coins.c
@@ -5,12 +5,12 @@
#include "text_window.h"
#include "string_util.h"
#include "menu.h"
+#include "international_string_util.h"
#define MAX_COINS 9999
EWRAM_DATA u8 sCoinsWindowId = 0;
-extern s32 GetStringRightAlignXOffset(u8 fontId, u8 *str, s32 totalWidth);
extern void sub_819746C(u8 windowId, bool8 copyToVram);
extern const u8 gText_Coins[];
@@ -54,7 +54,7 @@ void SetCoins(u16 coinAmount)
}
/* Can't match it lol
-bool8 AddCoins(u16 toAdd)
+bool8 GiveCoins(u16 toAdd)
{
u16 newAmount;
u16 ownedCoins = GetCoins();
diff --git a/src/decompress.c b/src/decompress.c
index 2863ff1f5..9210799ec 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -465,7 +465,7 @@ u32 sub_8034974(void* ptr)
return (ptr_[3] << 16) | (ptr_[2] << 8) | (ptr_[1]);
}
-bool8 LoadCompressedObjectPicUsingHeap(struct CompressedSpriteSheet* src)
+bool8 LoadCompressedObjectPicUsingHeap(const struct CompressedSpriteSheet* src)
{
struct SpriteSheet dest;
void* buffer;
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
index a1f187b85..589e8901d 100644
--- a/src/egg_hatch.c
+++ b/src/egg_hatch.c
@@ -462,7 +462,7 @@ static void VBlankCB_EggHatch(void)
TransferPlttBuffer();
}
-static void EggHatch(void)
+void EggHatch(void)
{
ScriptContext2_Enable();
CreateTask(Task_EggHatch, 10);
diff --git a/src/event_data.c b/src/event_data.c
index fb2edb063..19a310db5 100644
--- a/src/event_data.c
+++ b/src/event_data.c
@@ -40,11 +40,11 @@ void ClearTempFieldEventData(void)
{
memset(gSaveBlock1Ptr->flags, 0, TEMP_FLAGS_SIZE);
memset(gSaveBlock1Ptr->vars, 0, TEMP_VARS_SIZE);
- FlagReset(SYS_ENC_UP_ITEM);
- FlagReset(SYS_ENC_DOWN_ITEM);
- FlagReset(SYS_USE_STRENGTH);
- FlagReset(SYS_CTRL_OBJ_DELETE);
- FlagReset(SYS_UNKNOWN_880);
+ FlagClear(SYS_ENC_UP_ITEM);
+ FlagClear(SYS_ENC_DOWN_ITEM);
+ FlagClear(SYS_USE_STRENGTH);
+ FlagClear(SYS_CTRL_OBJ_DELETE);
+ FlagClear(SYS_UNKNOWN_880);
}
// probably had different flag splits at one point.
@@ -58,7 +58,7 @@ void DisableNationalPokedex(void)
u16 *nationalDexVar = GetVarPointer(VAR_NATIONAL_DEX);
gSaveBlock2Ptr->pokedex.nationalMagic = 0;
*nationalDexVar = 0;
- FlagReset(SYS_NATIONAL_DEX);
+ FlagClear(SYS_NATIONAL_DEX);
}
void EnableNationalPokedex(void)
@@ -82,7 +82,7 @@ bool32 IsNationalPokedexEnabled(void)
void DisableMysteryEvent(void)
{
- FlagReset(SYS_MYSTERY_EVENT_ENABLE);
+ FlagClear(SYS_MYSTERY_EVENT_ENABLE);
}
void EnableMysteryEvent(void)
@@ -97,7 +97,7 @@ bool32 IsMysteryEventEnabled(void)
void DisableMysteryGift(void)
{
- FlagReset(SYS_MYSTERY_GIFT_ENABLE);
+ FlagClear(SYS_MYSTERY_GIFT_ENABLE);
}
void EnableMysteryGift(void)
@@ -112,22 +112,22 @@ bool32 IsMysteryGiftEnabled(void)
void sub_809D4D8(void)
{
- FlagReset(0x1E4);
- FlagReset(0x1E5);
- FlagReset(0x1E6);
- FlagReset(0x1E7);
- FlagReset(0x1E8);
- FlagReset(0x1E9);
- FlagReset(0x1EA);
- FlagReset(0x1EB);
- FlagReset(0x1EC);
- FlagReset(0x1ED);
- FlagReset(0x1EE);
- FlagReset(0x1EF);
- FlagReset(0x1F0);
- FlagReset(0x1F1);
- FlagReset(0x1F2);
- FlagReset(0x1F3);
+ FlagClear(0x1E4);
+ FlagClear(0x1E5);
+ FlagClear(0x1E6);
+ FlagClear(0x1E7);
+ FlagClear(0x1E8);
+ FlagClear(0x1E9);
+ FlagClear(0x1EA);
+ FlagClear(0x1EB);
+ FlagClear(0x1EC);
+ FlagClear(0x1ED);
+ FlagClear(0x1EE);
+ FlagClear(0x1EF);
+ FlagClear(0x1F0);
+ FlagClear(0x1F1);
+ FlagClear(0x1F2);
+ FlagClear(0x1F3);
}
void sub_809D570(void)
@@ -145,7 +145,7 @@ void sub_809D570(void)
void DisableResetRTC(void)
{
VarSet(VAR_RESET_RTC_ENABLE, 0);
- FlagReset(SYS_RESET_RTC_ENABLE);
+ FlagClear(SYS_RESET_RTC_ENABLE);
}
void EnableResetRTC(void)
@@ -214,7 +214,7 @@ u8 FlagSet(u16 id)
return 0;
}
-u8 FlagReset(u16 id)
+u8 FlagClear(u16 id)
{
u8 *ptr = GetFlagPointer(id);
if (ptr)
diff --git a/src/field_map_obj.c b/src/field_map_obj.c
index e80e402c8..e822fc1ca 100755
--- a/src/field_map_obj.c
+++ b/src/field_map_obj.c
@@ -3,7 +3,7 @@
#include "global.h"
#include "malloc.h"
#include "sprite.h"
-#include "rom4.h"
+#include "overworld.h"
#include "rng.h"
#include "event_scripts.h"
#include "berry.h"
@@ -2386,10 +2386,10 @@ bool8 do_berry_tree_growth_sparkle_1 (struct MapObject *mapObject, struct Sprite
{
if (!(sprite->data7 & 0x0004) && sprite->animNum == 4)
{
- gFieldEffectSpawnParams[0] = mapObject->coords2.x;
- gFieldEffectSpawnParams[1] = mapObject->coords2.y;
- gFieldEffectSpawnParams[2] = sprite->subpriority - 1;
- gFieldEffectSpawnParams[3] = sprite->oam.priority;
+ gFieldEffectArguments[0] = mapObject->coords2.x;
+ gFieldEffectArguments[1] = mapObject->coords2.y;
+ gFieldEffectArguments[2] = sprite->subpriority - 1;
+ gFieldEffectArguments[3] = sprite->oam.priority;
FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE);
sprite->animNum = berryStage;
}
@@ -2425,10 +2425,10 @@ bool8 do_berry_tree_growth_sparkle_2 (struct MapObject *mapObject, struct Sprite
sprite->data1 = 3;
sprite->data2 = 0;
sprite->data7 |= 0x0002;
- gFieldEffectSpawnParams[0] = mapObject->coords2.x;
- gFieldEffectSpawnParams[1] = mapObject->coords2.y;
- gFieldEffectSpawnParams[2] = sprite->subpriority - 1;
- gFieldEffectSpawnParams[3] = sprite->oam.priority;
+ gFieldEffectArguments[0] = mapObject->coords2.x;
+ gFieldEffectArguments[1] = mapObject->coords2.y;
+ gFieldEffectArguments[2] = sprite->subpriority - 1;
+ gFieldEffectArguments[3] = sprite->oam.priority;
FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE);
return TRUE;
}
@@ -3425,7 +3425,7 @@ void FieldObjectCB_TreeDisguise(struct Sprite *sprite)
mapObject = &gMapObjects[sprite->data0];
if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && !sprite->data7))
{
- FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]);
mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_TREE_DISGUISE);
mapObject->mapobj_unk_21 = 1;
sprite->data7 ++;
@@ -3446,7 +3446,7 @@ void FieldObjectCB_MountainDisguise(struct Sprite *sprite)
mapObject = &gMapObjects[sprite->data0];
if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && !sprite->data7))
{
- FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]);
mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_MOUNTAIN_DISGUISE);
mapObject->mapobj_unk_21 = 1;
sprite->data7 ++;
@@ -4693,7 +4693,7 @@ bool8 sub_80954CC(struct MapObject *mapObject, struct Sprite *sprite)
bool8 do_exclamation_mark_bubble_1(struct MapObject *mapObject, struct Sprite *sprite)
{
- FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]);
FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1);
sprite->data2 = 1;
return TRUE;
@@ -4701,7 +4701,7 @@ bool8 do_exclamation_mark_bubble_1(struct MapObject *mapObject, struct Sprite *s
bool8 do_exclamation_mark_bubble_2(struct MapObject *mapObject, struct Sprite *sprite)
{
- FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]);
FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_2);
sprite->data2 = 1;
return TRUE;
@@ -4709,7 +4709,7 @@ bool8 do_exclamation_mark_bubble_2(struct MapObject *mapObject, struct Sprite *s
bool8 do_heart_bubble(struct MapObject *mapObject, struct Sprite *sprite)
{
- FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]);
FieldEffectStart(FLDEFF_HEART_ICON);
sprite->data2 = 1;
return TRUE;
diff --git a/src/field_special_scene.c b/src/field_special_scene.c
index 9c35a33da..54c1d8144 100755
--- a/src/field_special_scene.c
+++ b/src/field_special_scene.c
@@ -13,10 +13,10 @@
#define SECONDS(value) ((signed) (60.0 * value + 0.5))
extern u8 GetSSTidalLocation(s8 *, s8 *, s16 *, s16 *); // should be in field_specials.h
-extern void warp1_set(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y);
-extern bool8 sub_80D3340(u8, u8, u8);
+extern void Overworld_SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y);
+extern bool8 ScriptMovement_IsObjectMovementFinished(u8, u8, u8);
extern bool32 CountSSTidalStep(u16);
-extern bool8 exec_movement(u8, u8, u8, u8 *);
+extern bool8 ScriptMovement_StartObjectMovementScript(u8, u8, u8, u8 *);
extern void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused);
extern void sp13E_warp_to_last_warp(void);
extern void saved_warp2_set(int unused, s8 mapGroup, s8 mapNum, s8 warpId);
@@ -264,7 +264,7 @@ bool8 sub_80FB59C(void)
}
else
{
- warp1_set(mapGroup, mapNum, -1, x, y);
+ Overworld_SetWarpDestination(mapGroup, mapNum, -1, x, y);
return TRUE;
}
}
@@ -287,7 +287,7 @@ void Task_HandlePorthole(u8 taskId)
case IDLE_CHECK: // idle and move.
if (gMain.newKeys & A_BUTTON)
data[1] = 1;
- if (!sub_80D3340(0xFF, location->mapNum, location->mapGroup))
+ if (!ScriptMovement_IsObjectMovementFinished(0xFF, location->mapNum, location->mapGroup))
return;
if (CountSSTidalStep(1) == TRUE)
{
@@ -308,18 +308,18 @@ void Task_HandlePorthole(u8 taskId)
// run this once.
if (*var == 2) // which direction?
{
- exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AB);
+ ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AB);
data[0] = IDLE_CHECK; // run case 1.
}
else
{
- exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AD);
+ ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AD);
data[0] = IDLE_CHECK; // run case 1.
}
break;
case EXIT_PORTHOLE: // exit porthole.
- FlagReset(0x4001);
- FlagReset(0x4000);
+ FlagClear(0x4001);
+ FlagClear(0x4000);
copy_saved_warp2_bank_and_enter_x_to_warp1(0);
sp13E_warp_to_last_warp();
DestroyTask(taskId);
diff --git a/src/international_string_util.c b/src/international_string_util.c
new file mode 100644
index 000000000..c77b4f8ff
--- /dev/null
+++ b/src/international_string_util.c
@@ -0,0 +1,57 @@
+#include "global.h"
+#include "international_string_util.h"
+#include "text.h"
+
+extern s32 convert_pixel_width_to_tile_width(s32 a0); // script menu
+
+s32 GetStringCenterAlignXOffset(s32 fontId, const u8 *str, s32 totalWidth)
+{
+ return GetStringCenterAlignXOffsetWithLetterSpacing(fontId, str, totalWidth, 0);
+}
+
+s32 GetStringRightAlignXOffset(s32 fontId, const u8 *str, s32 totalWidth)
+{
+ return GetStringWidthDifference(fontId, str, totalWidth, 0);
+}
+
+s32 GetStringCenterAlignXOffsetWithLetterSpacing(s32 fontId, const u8 *str, s32 totalWidth, s32 letterSpacing)
+{
+ return GetStringWidthDifference(fontId, str, totalWidth, letterSpacing) / 2;
+}
+
+s32 GetStringWidthDifference(s32 fontId, const u8 *str, s32 totalWidth, s32 letterSpacing)
+{
+ s32 stringWidth = GetStringWidth(fontId, str, letterSpacing);
+ if (totalWidth > stringWidth)
+ return totalWidth - stringWidth;
+ else
+ return 0;
+}
+
+s32 GetMaxWidthInMenuTable(const u8 **str, s32 arg1)
+{
+ s32 i, var;
+
+ for (var = 0, i = 0; i < arg1; i++)
+ {
+ s32 stringWidth = GetStringWidth(1, str[i * 2], 0);
+ if (stringWidth > var)
+ var = stringWidth;
+ }
+
+ return convert_pixel_width_to_tile_width(var);
+}
+
+s32 sub_81DB3D8(const u8 **str, u8* arg1, s32 arg2)
+{
+ s32 i, var;
+
+ for (var = 0, i = 0; i < arg2; i++)
+ {
+ s32 stringWidth = GetStringWidth(1, str[arg1[i] * 2], 0);
+ if (stringWidth > var)
+ var = stringWidth;
+ }
+
+ return convert_pixel_width_to_tile_width(var);
+}
diff --git a/src/lilycove_lady.c b/src/lilycove_lady.c
index 9f38824f9..3b7ae49f2 100644
--- a/src/lilycove_lady.c
+++ b/src/lilycove_lady.c
@@ -4,7 +4,7 @@
#include "global.h"
#include "main.h"
-#include "rom4.h"
+#include "overworld.h"
#include "rom6.h"
#include "event_data.h"
#include "script.h"
diff --git a/src/mail.c b/src/mail.c
new file mode 100644
index 000000000..1060d73bd
--- /dev/null
+++ b/src/mail.c
@@ -0,0 +1,577 @@
+
+// Includes
+#include "global.h"
+#include "main.h"
+#include "overworld.h"
+#include "task.h"
+#include "unknown_task.h"
+#include "palette.h"
+#include "menu.h"
+#include "menu_helpers.h"
+#include "text.h"
+#include "text_window.h"
+#include "string_util.h"
+#include "international_string_util.h"
+#include "strings.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "pokemon_icon.h"
+#include "species.h"
+#include "malloc.h"
+#include "easy_chat.h"
+#include "mail_data.h"
+#include "mail.h"
+
+// Static type declarations
+
+struct UnkMailStruct
+{
+ u32 numEasyChatWords:2;
+ u32 xOffset:6;
+ u32 lineHeight:8;
+};
+
+struct MailLayout
+{
+ u8 numSubStructs;
+ u8 signatureYPos;
+ u8 signatureWidth;
+ u8 wordsXPos;
+ u8 wordsYPos;
+ const struct UnkMailStruct *var8;
+};
+
+struct MailGraphics
+{
+ const u16 *palette;
+ const u8 *tiles;
+ const u8 *tileMap;
+ u16 var0C;
+ u16 var0E;
+ u16 color10;
+ u16 color12;
+};
+
+// Static RAM declarations
+
+static EWRAM_DATA struct
+{
+ /*0x0000*/ u8 strbuf[8][64];
+ /*0x0200*/ u8 playerName[12];
+ /*0x020C*/ MainCallback callback;
+ /*0x0210*/ MainCallback callback2;
+ /*0x0214*/ struct MailStruct *mail;
+ /*0x0218*/ bool8 flag;
+ /*0x0219*/ u8 signatureWidth;
+ /*0x021a*/ u8 mailType;
+ /*0x021b*/ u8 animsActive;
+ /*0x021c*/ u8 monIconSprite;
+ /*0x021d*/ u8 language;
+ /*0x021e*/ bool8 playerIsSender;
+ /*0x0220*/ void (*parserSingle)(u8 *dest, u16 word);
+ /*0x0224*/ void (*parserMultiple)(u8 *dest, const u16 *src, u16 length1, u16 length2);
+ /*0x0228*/ const struct MailLayout *layout;
+ /*0x022c*/ u8 bg1TilemapBuffer[0x1000];
+ /*0x122c*/ u8 bg2TilemapBuffer[0x1000];
+} *gUnknown_0203A134 = NULL;
+
+// Static ROM declarations
+
+void sub_81219F0(void);
+void sub_8121A1C(void);
+void sub_8121B1C(void);
+void sub_8121C50(void);
+void sub_8121C64(void);
+void sub_8121C98(void);
+void sub_8121CC0(void);
+void sub_8121D00(void);
+
+// .rodata
+
+const struct BgTemplate gUnknown_0859F290[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .priority = 0
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 30,
+ .priority = 1
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 29,
+ .priority = 2
+ }
+};
+
+const struct WindowTemplate gUnknown_0859F29C[] = {
+ {
+ .priority = 0,
+ .tilemapLeft = 2,
+ .tilemapTop = 3,
+ .width = 26,
+ .height = 15,
+ .paletteNum = 15,
+ .baseBlock = 1
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+const u8 gUnknown_0859F2AC[] = {
+ 0,
+ 10,
+ 11
+};
+
+const u16 gUnknown_0859F2B0[][2] = {
+ { 0x6ACD, 0x51A5 },
+ { 0x45FC, 0x38D4 }
+};
+
+extern const u16 gUnknown_08DBE818[];
+extern const u16 gUnknown_08DBE838[];
+extern const u16 gUnknown_08DBE858[];
+extern const u16 gUnknown_08DBE878[];
+extern const u16 gUnknown_08DBE898[];
+extern const u16 gUnknown_08DBE8B8[];
+extern const u16 gUnknown_08DBE8D8[];
+extern const u16 gUnknown_08DBE8F8[];
+extern const u16 gUnknown_08DBE918[];
+extern const u16 gUnknown_08DBE938[];
+extern const u16 gUnknown_08DBE958[];
+extern const u16 gUnknown_08DBE978[];
+extern const u8 gUnknown_08DBE998[];
+extern const u8 gUnknown_08DBFBA4[];
+extern const u8 gUnknown_08DBEB38[];
+extern const u8 gUnknown_08DBFC7C[];
+extern const u8 gUnknown_08DBEC74[];
+extern const u8 gUnknown_08DBFD5C[];
+extern const u8 gUnknown_08DBEE84[];
+extern const u8 gUnknown_08DBFE68[];
+extern const u8 gUnknown_08DBEF5C[];
+extern const u8 gUnknown_08DBFF44[];
+extern const u8 gUnknown_08DBF154[];
+extern const u8 gUnknown_08DC0034[];
+extern const u8 gUnknown_08DBF2D4[];
+extern const u8 gUnknown_08DC0114[];
+extern const u8 gUnknown_08DBF37C[];
+extern const u8 gUnknown_08DC01F4[];
+extern const u8 gUnknown_08DBF50C[];
+extern const u8 gUnknown_08DC0300[];
+extern const u8 gUnknown_08DBF64C[];
+extern const u8 gUnknown_08DC03F0[];
+extern const u8 gUnknown_08DBF7B4[];
+extern const u8 gUnknown_08DC04E8[];
+extern const u8 gUnknown_08DBF904[];
+extern const u8 gUnknown_08DC0600[];
+
+const struct MailGraphics gUnknown_0859F2B8[] = {
+ {
+ gUnknown_08DBE818, gUnknown_08DBE998, gUnknown_08DBFBA4, 0x02c0, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE838, gUnknown_08DBEB38, gUnknown_08DBFC7C, 0x02e0, 0x0000, 0x7fff, 0x4631
+ }, {
+ gUnknown_08DBE858, gUnknown_08DBEC74, gUnknown_08DBFD5C, 0x0400, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE878, gUnknown_08DBEE84, gUnknown_08DBFE68, 0x01e0, 0x0000, 0x7fff, 0x4631
+ }, {
+ gUnknown_08DBE898, gUnknown_08DBEF5C, gUnknown_08DBFF44, 0x02e0, 0x0000, 0x7fff, 0x4631
+ }, {
+ gUnknown_08DBE8B8, gUnknown_08DBF154, gUnknown_08DC0034, 0x0300, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE8D8, gUnknown_08DBF2D4, gUnknown_08DC0114, 0x0140, 0x0000, 0x7fff, 0x4631
+ }, {
+ gUnknown_08DBE8F8, gUnknown_08DBF37C, gUnknown_08DC01F4, 0x0300, 0x0000, 0x7fff, 0x4631
+ }, {
+ gUnknown_08DBE918, gUnknown_08DBF50C, gUnknown_08DC0300, 0x0220, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE938, gUnknown_08DBF64C, gUnknown_08DC03F0, 0x0340, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE958, gUnknown_08DBF7B4, gUnknown_08DC04E8, 0x02a0, 0x0000, 0x294a, 0x6739
+ }, {
+ gUnknown_08DBE978, gUnknown_08DBF904, gUnknown_08DC0600, 0x0520, 0x0000, 0x294a, 0x6739
+ }
+};
+
+const struct UnkMailStruct Unknown_0859F3A8[] = {
+ { .numEasyChatWords = 3, .lineHeight = 16 },
+ { .numEasyChatWords = 3, .lineHeight = 16 },
+ { .numEasyChatWords = 3, .lineHeight = 16 }
+};
+
+const struct MailLayout gUnknown_0859F3B4[] = {
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x08, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
+ { 0x03, 0x00, 0x00, 0x02, 0x00, Unknown_0859F3A8 }
+};
+
+const struct UnkMailStruct Unknown_0859F444[] = {
+ { .numEasyChatWords = 2, .lineHeight = 16 },
+ { .numEasyChatWords = 2, .lineHeight = 16 },
+ { .numEasyChatWords = 2, .lineHeight = 16 },
+ { .numEasyChatWords = 2, .lineHeight = 16 },
+ { .numEasyChatWords = 1, .lineHeight = 16 }
+};
+
+const struct MailLayout gUnknown_0859F458[] = {
+ { 0x05, 0x07, 0x58, 0x0b, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x0a, 0x60, 0x09, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x0c, 0x68, 0x05, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x05, 0x60, 0x08, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x0a, 0x60, 0x09, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x09, 0x70, 0x05, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x0c, 0x68, 0x09, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x0d, 0x68, 0x0d, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x09, 0x60, 0x09, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x09, 0x60, 0x09, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x11, 0x68, 0x0f, 0x1e, Unknown_0859F444 },
+ { 0x05, 0x09, 0x60, 0x05, 0x1e, Unknown_0859F444 }
+};
+
+// What the heck are these meant to be? Call them u16 for now.
+
+const u16 Unknown_0859F4E8[] = {
+ 0x00, 0x4000, 0x00, 0x00
+};
+
+const u16 Unknown_0859F4F0[] = {
+ 0x00, 0x00, -1, 0x00
+};
+
+const u16 Unknown_0859F4F8[] = {
+ 0x04, 0x00, -1, 0x00
+};
+
+const u16 Unknown_0859F500[] = {
+ 0x00, 0x40, -1, 0x00
+};
+
+const u16 *const gUnknown_0859F508[] = {
+ Unknown_0859F4F0,
+ Unknown_0859F4F8,
+ Unknown_0859F500
+};
+
+// .text
+
+void sub_8121478(struct MailStruct *mail, MainCallback callback, bool8 flag) {
+ u16 buffer[2];
+ u16 species;
+
+ gUnknown_0203A134 = calloc(1, sizeof(*gUnknown_0203A134));
+ gUnknown_0203A134->language = LANGUAGE_ENGLISH;
+ gUnknown_0203A134->playerIsSender = TRUE;
+ gUnknown_0203A134->parserSingle = CopyEasyChatWord;
+ gUnknown_0203A134->parserMultiple = ConvertEasyChatWordsToString;
+ if (mail->itemId >= ITEM_ORANGE_MAIL && mail->itemId <= ITEM_RETRO_MAIL) {
+ gUnknown_0203A134->mailType = mail->itemId - ITEM_ORANGE_MAIL;
+ }
+ else
+ {
+ gUnknown_0203A134->mailType = 0;
+ flag = FALSE;
+ }
+ switch (gUnknown_0203A134->playerIsSender)
+ {
+ case FALSE:
+ default:
+ gUnknown_0203A134->layout = &gUnknown_0859F3B4[gUnknown_0203A134->mailType];
+ break;
+ case TRUE:
+ gUnknown_0203A134->layout = &gUnknown_0859F458[gUnknown_0203A134->mailType];
+ break;
+ }
+ species = sub_80D45E8(mail->species, buffer);
+ if (species >= SPECIES_BULBASAUR && species < NUM_SPECIES)
+ {
+ switch (gUnknown_0203A134->mailType)
+ {
+ default:
+ gUnknown_0203A134->animsActive = 0;
+ break;
+ case ITEM_BEAD_MAIL - ITEM_ORANGE_MAIL:
+ gUnknown_0203A134->animsActive = 1;
+ break;
+ case ITEM_DREAM_MAIL - ITEM_ORANGE_MAIL:
+ gUnknown_0203A134->animsActive = 2;
+ break;
+ }
+ }
+ else
+ {
+ gUnknown_0203A134->animsActive = 0;
+ }
+ gUnknown_0203A134->mail = mail;
+ gUnknown_0203A134->callback = callback;
+ gUnknown_0203A134->flag = flag;
+ SetMainCallback2(sub_81219F0);
+}
+
+bool8 sub_81215EC(void)
+{
+ u16 icon;
+
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ remove_some_task();
+ SetGpuReg(REG_OFFSET_DISPCNT, 0x0000);
+ break;
+ case 1:
+ CpuFill16(0, (void *)OAM, OAM_SIZE);
+ break;
+ case 2:
+ ResetPaletteFade();
+ break;
+ case 3:
+ ResetTasks();
+ break;
+ case 4:
+ ResetSpriteData();
+ break;
+ case 5:
+ FreeAllSpritePalettes();
+ reset_temp_tile_data_buffers();
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0x0000);
+ break;
+ case 6:
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_0859F290, 3);
+ SetBgTilemapBuffer(1, gUnknown_0203A134->bg1TilemapBuffer);
+ SetBgTilemapBuffer(2, gUnknown_0203A134->bg2TilemapBuffer);
+ break;
+ case 7:
+ InitWindows(gUnknown_0859F29C);
+ DeactivateAllTextPrinters();
+ break;
+ case 8:
+ decompress_and_copy_tile_data_to_vram(1, gUnknown_0859F2B8[gUnknown_0203A134->mailType].tiles, 0, 0, 0);
+ break;
+ case 9:
+ if (free_temp_tile_data_buffers_if_possible())
+ {
+ return FALSE;
+ }
+ break;
+ case 10:
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(2, 1, 0, 0, 30, 20);
+ CopyToBgTilemapBuffer(1, gUnknown_0859F2B8[gUnknown_0203A134->mailType].tileMap, 0, 0);
+ break;
+ case 11:
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ break;
+ case 12:
+ LoadPalette(sub_8098C64(), 240, 32);
+ gPlttBufferUnfaded[250] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color10;
+ gPlttBufferFaded[250] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color10;
+ gPlttBufferUnfaded[251] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color12;
+ gPlttBufferFaded[251] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color12;
+ LoadPalette(gUnknown_0859F2B8[gUnknown_0203A134->mailType].palette, 0, 32);
+ gPlttBufferUnfaded[10] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
+ gPlttBufferFaded[10] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
+ gPlttBufferUnfaded[11] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
+ gPlttBufferFaded[11] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
+ break;
+ case 13:
+ if (gUnknown_0203A134->flag)
+ {
+ sub_8121A1C();
+ }
+ break;
+ case 14:
+ if (gUnknown_0203A134->flag)
+ {
+ sub_8121B1C();
+ RunTextPrinters();
+ }
+ break;
+ case 15:
+ if (sub_8087598() == TRUE)
+ {
+ return FALSE;
+ }
+ break;
+ case 16:
+ SetVBlankCallback(sub_8121C50);
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ break;
+ case 17:
+ icon = sub_80D2E84(gUnknown_0203A134->mail->species);
+ switch (gUnknown_0203A134->animsActive)
+ {
+ case 1:
+ sub_80D2F68(icon);
+ gUnknown_0203A134->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x60, 0x80, 0, 0);
+ break;
+ case 2:
+ sub_80D2F68(icon);
+ gUnknown_0203A134->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x28, 0x80, 0, 0);
+ break;
+ }
+ break;
+ case 18:
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ BeginNormalPaletteFade(-1, 0, 16, 0, 0);
+ gPaletteFade.bufferTransferDisabled = FALSE;
+ gUnknown_0203A134->callback2 = sub_8121C98;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ gMain.state ++;
+ return FALSE;
+}
+
+void sub_81219F0(void)
+{
+ do
+ {
+ if (sub_81215EC() == TRUE)
+ {
+ SetMainCallback2(sub_8121C64);
+ break;
+ }
+ } while (sub_81221AC() != TRUE);
+}
+
+void sub_8121A1C(void)
+{
+ u16 i;
+ u8 total;
+ u8 *ptr;
+
+ total = 0;
+ for (i = 0; i < gUnknown_0203A134->layout->numSubStructs; i ++)
+ {
+ ConvertEasyChatWordsToString(gUnknown_0203A134->strbuf[i], &gUnknown_0203A134->mail->words[total], gUnknown_0203A134->layout->var8[i].numEasyChatWords, 1);
+ total += gUnknown_0203A134->layout->var8[i].numEasyChatWords;
+ }
+ ptr = StringCopy(gUnknown_0203A134->playerName, gUnknown_0203A134->mail->playerName);
+ if (!gUnknown_0203A134->playerIsSender)
+ {
+ StringCopy(ptr, gText_FromSpace);
+ gUnknown_0203A134->signatureWidth = gUnknown_0203A134->layout->signatureWidth - (StringLength(gUnknown_0203A134->playerName) * 8 - 0x60);
+ }
+ else
+ {
+ sub_81DB52C(gUnknown_0203A134->playerName);
+ gUnknown_0203A134->signatureWidth = gUnknown_0203A134->layout->signatureWidth;
+ }
+}
+
+void sub_8121B1C(void)
+{
+ u16 i;
+ u8 strbuf[0x20];
+ u8 y;
+ u8 *bufptr;
+ s32 box_x;
+ s32 box_y;
+
+ y = 0;
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ FillWindowPixelBuffer(0, 0);
+ FillWindowPixelBuffer(1, 0);
+ for (i = 0; i < gUnknown_0203A134->layout->numSubStructs; i ++)
+ {
+ if (gUnknown_0203A134->strbuf[i][0] == EOS || gUnknown_0203A134->strbuf[i][0] == CHAR_SPACE)
+ {
+ continue;
+ }
+ box_print(0, 1, gUnknown_0203A134->layout->var8[i].xOffset + gUnknown_0203A134->layout->wordsYPos, y + gUnknown_0203A134->layout->wordsXPos, gUnknown_0859F2AC, 0, gUnknown_0203A134->strbuf[i]);
+ y += gUnknown_0203A134->layout->var8[i].lineHeight;
+ }
+ bufptr = StringCopy(strbuf, gText_FromSpace);
+ StringCopy(bufptr, gUnknown_0203A134->playerName);
+ box_x = GetStringCenterAlignXOffset(1, strbuf, gUnknown_0203A134->signatureWidth) + 0x68;
+ box_y = gUnknown_0203A134->layout->signatureYPos + 0x58;
+ box_print(0, 1, box_x, box_y, gUnknown_0859F2AC, 0, strbuf);
+ CopyWindowToVram(0, 3);
+ CopyWindowToVram(1, 3);
+}
+
+void sub_8121C50(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void sub_8121C64(void)
+{
+ if (gUnknown_0203A134->animsActive != 0)
+ {
+ AnimateSprites();
+ BuildOamBuffer();
+ }
+ gUnknown_0203A134->callback2();
+}
+
+void sub_8121C98(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ gUnknown_0203A134->callback2 = sub_8121CC0;
+ }
+}
+
+void sub_8121CC0(void)
+{
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gUnknown_0203A134->callback2 = sub_8121D00;
+ }
+}
+
+void sub_8121D00(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ SetMainCallback2(gUnknown_0203A134->callback);
+ switch (gUnknown_0203A134->animsActive)
+ {
+ case 1:
+ case 2:
+ sub_80D2FF0(sub_80D2E84(gUnknown_0203A134->mail->species));
+ sub_80D2EF8(&gSprites[gUnknown_0203A134->monIconSprite]);
+ }
+ memset(gUnknown_0203A134, 0, sizeof(*gUnknown_0203A134));
+ ResetPaletteFade();
+ UnsetBgTilemapBuffer(0);
+ UnsetBgTilemapBuffer(1);
+ ResetBgsAndClearDma3BusyFlags(0);
+ FreeAllWindowBuffers();
+ free(gUnknown_0203A134);
+ gUnknown_0203A134 = NULL;
+ }
+}
diff --git a/src/money.c b/src/money.c
index 65a45b158..98f25a42a 100644
--- a/src/money.c
+++ b/src/money.c
@@ -110,7 +110,7 @@ void AddMoney(u32* moneyPtr, u32 toAdd)
SetMoney(moneyPtr, toSet);
}
-void SubtractMoney(u32* moneyPtr, u32 toSub)
+void RemoveMoney(u32* moneyPtr, u32 toSub)
{
u32 toSet = GetMoney(moneyPtr);
@@ -130,7 +130,7 @@ bool8 IsEnoughForCostInVar0x8005(void)
void SubtractMoneyFromVar0x8005(void)
{
- SubtractMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
+ RemoveMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
}
void PrintMoneyAmountInMoneyBox(u8 windowId, int amount, u8 speed)
diff --git a/src/new_game.c b/src/new_game.c
index d01aa69d4..d0666dd71 100644
--- a/src/new_game.c
+++ b/src/new_game.c
@@ -29,7 +29,7 @@ extern u8 gUnknown_030060B0;
// TODO: replace those declarations with file headers
extern u16 GetGeneratedTrainerIdLower(void);
extern void ClearContestWinnerPicsInContestHall(void);
-extern void warp1_set(s8 mapBank, s8 mapNo, s8 warpNo, s8 xPos, s8 yPos);
+extern void Overworld_SetWarpDestination(s8 mapBank, s8 mapNo, s8 warpNo, s8 xPos, s8 yPos);
extern void warp_in(void);
extern void sub_80BB358(void);
extern void ResetBagScrollPositions(void);
@@ -131,7 +131,7 @@ void sub_8084400(void)
void WarpToTruck(void)
{
- warp1_set(25, 40, -1, -1, -1); // inside of truck
+ Overworld_SetWarpDestination(25, 40, -1, -1, -1); // inside of truck
warp_in();
}
diff --git a/src/palette.c b/src/palette.c
index d60efdbc5..d4bb593da 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -53,13 +53,13 @@ static void UpdateBlendRegisters(void);
static bool8 IsSoftwarePaletteFadeFinishing(void);
static void sub_80A2D54(u8 taskId);
-EWRAM_DATA u16 gPlttBufferUnfaded[0x200] = {0};
-EWRAM_DATA u16 gPlttBufferFaded[0x200] = {0};
+EWRAM_DATA u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE] = {0};
+EWRAM_DATA u16 gPlttBufferFaded[PLTT_BUFFER_SIZE] = {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};
+EWRAM_DATA u8 gPaletteDecompressionBuffer[PLTT_DECOMP_BUFFER_SIZE] = {0};
static const struct PaletteStructTemplate gDummyPaletteStructTemplate = {
.uid = 0xFFFF,
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
index ee54f0e4d..27441f952 100644
--- a/src/pokemon_2.c
+++ b/src/pokemon_2.c
@@ -1089,7 +1089,7 @@ u8 SendMonToPC(struct Pokemon* mon)
gSpecialVar_0x8012 = boxNo;
gSpecialVar_0x8013 = boxPos;
if (get_unknown_box_id() != boxNo)
- FlagReset(SYS_STORAGE_UNKNOWN_FLAG);
+ FlagClear(SYS_STORAGE_UNKNOWN_FLAG);
VarSet(VAR_STORAGE_UNKNOWN, boxNo);
return MON_GIVEN_TO_PC;
}
diff --git a/src/reset_save_heap.c b/src/reset_save_heap.c
index b786ff9f8..d4dbc5f42 100644
--- a/src/reset_save_heap.c
+++ b/src/reset_save_heap.c
@@ -5,7 +5,7 @@
#include "load_save.h"
#include "save.h"
#include "new_game.h"
-#include "rom4.h"
+#include "overworld.h"
#include "malloc.h"
void sub_81700F8(void)
diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c
index 25c2ca658..343ddb9c0 100644
--- a/src/reshow_battle_screen.c
+++ b/src/reshow_battle_screen.c
@@ -336,9 +336,9 @@ static void CreateHealthboxSprite(u8 bank)
UpdateHealthboxAttribute(gHealthBoxesIds[bank], &gPlayerParty[gBattlePartyID[bank]], HEALTHBOX_ALL);
if (GetBankIdentity(bank) == IDENTITY_OPPONENT_MON2 || GetBankIdentity(bank) == IDENTITY_PLAYER_MON2)
- nullsub_30(gHealthBoxesIds[bank], TRUE);
+ DummyBattleInterfaceFunc(gHealthBoxesIds[bank], TRUE);
else
- nullsub_30(gHealthBoxesIds[bank], FALSE);
+ DummyBattleInterfaceFunc(gHealthBoxesIds[bank], FALSE);
if (GetBankSide(bank) != SIDE_PLAYER)
{
diff --git a/src/safari_zone.c b/src/safari_zone.c
index f7ef28577..77c6bbd61 100644
--- a/src/safari_zone.c
+++ b/src/safari_zone.c
@@ -60,7 +60,7 @@ void SetSafariZoneFlag(void)
void ResetSafariZoneFlag(void)
{
- FlagReset(SYS_SAFARI_MODE);
+ FlagClear(SYS_SAFARI_MODE);
}
void EnterSafariMode(void)
@@ -139,7 +139,7 @@ static void ClearAllPokeblockFeeders(void)
memset(sPokeblockFeeders, 0, sizeof(sPokeblockFeeders));
}
-static void GetPokeblockFeederInFront(void)
+void GetPokeblockFeederInFront(void)
{
s16 x, y;
u16 i;
diff --git a/src/scrcmd.c b/src/scrcmd.c
index b56a53caf..af314609c 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -1,15 +1,2452 @@
-
-// Includes
#include "global.h"
+#include "battle_frontier_2.h"
+#include "battle_setup.h"
+#include "berry.h"
+#include "clock.h"
+#include "coins.h"
+#include "contest_link_80F57C4.h"
+#include "contest_painting.h"
+#include "data2.h"
+#include "decoration.h"
+#include "decoration_inventory.h"
+#include "event_data.h"
+#include "field_door.h"
+#include "field_effect.h"
+#include "field_fadetransition.h"
+#include "field_map_obj.h"
+#include "field_map_obj_helpers.h"
+#include "field_message_box.h"
+#include "field_player_avatar.h"
+#include "field_screen_effect.h"
+#include "field_specials.h"
+#include "field_tasks.h"
+#include "field_weather.h"
+#include "fieldmap.h"
+#include "item.h"
+#include "lilycove_lady.h"
+#include "main.h"
+#include "map_obj_lock.h"
+#include "menu.h"
+#include "money.h"
+#include "mystery_event_script.h"
+#include "new_menu_helpers.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "pokemon_3.h"
+#include "pokemon_storage_system.h"
+#include "rng.h"
+#include "overworld.h"
+#include "rtc.h"
+#include "script.h"
+#include "script_menu.h"
+#include "script_movement.h"
+#include "script_pokemon_80F8.h"
+#include "script_pokemon_81B9.h"
+#include "shop.h"
+#include "slot_machine.h"
+#include "sound.h"
+#include "string_util.h"
+#include "text.h"
+#include "text_window.h"
+#include "trainer_see.h"
+#include "tv.h"
+#include "window.h"
+
+typedef u16 (*SpecialFunc)(void);
+typedef void (*NativeFunc)(void);
+
+extern u32 gUnknown_020375C0;
+
+static EWRAM_DATA u32 gUnknown_020375C4 = 0;
+static EWRAM_DATA u16 sPauseCounter = 0;
+static EWRAM_DATA u16 sMovingNpcId = 0;
+static EWRAM_DATA u16 sMovingNpcMapBank = 0;
+static EWRAM_DATA u16 sMovingNpcMapId = 0;
+static EWRAM_DATA u16 sFieldEffectScriptId = 0;
-// Static type declarations
+extern u16 gSpecialVar_0x8000;
+extern u16 gSpecialVar_0x8001;
+extern u16 gSpecialVar_0x8002;
+extern u16 gSpecialVar_0x8004;
-// Static RAM declarations
+extern u16 gScriptResult;
+
+extern u16 gScriptContestCategory;
IWRAM_DATA u8 gUnknown_03000F30;
-// Static ROM declarations
+extern const SpecialFunc gSpecials[];
+extern const u8 *gStdScripts[];
+extern const u8 *gStdScripts_End[];
+
+void sub_809BDB4(void);
+
+// This is defined in here so the optimizer can't see its value when compiling
+// script.c.
+void * const gNullScriptPtr = NULL;
+
+static const u8 sScriptConditionTable[6][3] =
+{
+// < = >
+ 1, 0, 0, // <
+ 0, 1, 0, // =
+ 0, 0, 1, // >
+ 1, 1, 0, // <=
+ 0, 1, 1, // >=
+ 1, 0, 1, // !=
+};
+
+static u8 * const sScriptStringVars[] =
+{
+ gStringVar1,
+ gStringVar2,
+ gStringVar3,
+};
+
+bool8 ScrCmd_nop(struct ScriptContext *ctx)
+{
+ return FALSE;
+}
+
+bool8 ScrCmd_nop1(struct ScriptContext *ctx)
+{
+ return FALSE;
+}
+
+bool8 ScrCmd_end(struct ScriptContext *ctx)
+{
+ StopScript(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotonative(struct ScriptContext *ctx)
+{
+ bool8 (*addr)(void) = (bool8 (*)(void))ScriptReadWord(ctx);
+
+ SetupNativeScript(ctx, addr);
+ return TRUE;
+}
+
+bool8 ScrCmd_special(struct ScriptContext *ctx)
+{
+ u16 index = ScriptReadHalfword(ctx);
+
+ gSpecials[index]();
+ return FALSE;
+}
+
+bool8 ScrCmd_specialvar(struct ScriptContext *ctx)
+{
+ u16 *var = GetVarPointer(ScriptReadHalfword(ctx));
+
+ *var = gSpecials[ScriptReadHalfword(ctx)]();
+ return FALSE;
+}
+
+bool8 ScrCmd_callnative(struct ScriptContext *ctx)
+{
+ NativeFunc func = (NativeFunc)ScriptReadWord(ctx);
+
+ func();
+ return FALSE;
+}
+
+bool8 ScrCmd_waitstate(struct ScriptContext *ctx)
+{
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_goto(struct ScriptContext *ctx)
+{
+ const u8 *ptr = (const u8 *)ScriptReadWord(ctx);
+
+ ScriptJump(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_return(struct ScriptContext *ctx)
+{
+ ScriptReturn(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_call(struct ScriptContext *ctx)
+{
+ const u8 *ptr = (const u8 *)ScriptReadWord(ctx);
+
+ ScriptCall(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_goto_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 *ptr = (const u8 *)ScriptReadWord(ctx);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptJump(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_call_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 *ptr = (const u8 *)ScriptReadWord(ctx);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptCall(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_setvaddress(struct ScriptContext *ctx)
+{
+ u32 addr1 = (u32)ctx->scriptPtr - 1;
+ u32 addr2 = ScriptReadWord(ctx);
+
+ gUnknown_020375C4 = addr2 - addr1;
+ return FALSE;
+}
+
+bool8 ScrCmd_vgoto(struct ScriptContext *ctx)
+{
+ u32 addr = ScriptReadWord(ctx);
+
+ ScriptJump(ctx, (u8 *)(addr - gUnknown_020375C4));
+ return FALSE;
+}
+
+bool8 ScrCmd_vcall(struct ScriptContext *ctx)
+{
+ u32 addr = ScriptReadWord(ctx);
+
+ ScriptCall(ctx, (u8 *)(addr - gUnknown_020375C4));
+ return FALSE;
+}
+
+bool8 ScrCmd_vgoto_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 *ptr = (const u8 *)(ScriptReadWord(ctx) - gUnknown_020375C4);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptJump(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_vcall_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 *ptr = (const u8 *)(ScriptReadWord(ctx) - gUnknown_020375C4);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptCall(ctx, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotostd(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+ const u8 **ptr = &gStdScripts[index];
+
+ if (ptr < gStdScripts_End)
+ ScriptJump(ctx, *ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_callstd(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+ const u8 **ptr = &gStdScripts[index];
+
+ if (ptr < gStdScripts_End)
+ ScriptCall(ctx, *ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotostd_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ u8 index = ScriptReadByte(ctx);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ {
+ const u8 **ptr = &gStdScripts[index];
+ if (ptr < gStdScripts_End)
+ ScriptJump(ctx, *ptr);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_callstd_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ u8 index = ScriptReadByte(ctx);
+
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ {
+ const u8 **ptr = &gStdScripts[index];
+ if (ptr < gStdScripts_End)
+ ScriptCall(ctx, *ptr);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_gotoram(struct ScriptContext *ctx)
+{
+ ScriptJump(ctx, (const u8 *)gUnknown_020375C0);
+ return FALSE;
+}
+
+bool8 ScrCmd_killscript(struct ScriptContext *ctx)
+{
+ ClearRamScript();
+ StopScript(ctx);
+ return TRUE;
+}
+
+bool8 ScrCmd_setmysteryeventstatus(struct ScriptContext *ctx)
+{
+ u8 value = ScriptReadByte(ctx);
+
+ SetMysteryEventScriptStatus(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_loadword(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+
+ ctx->data[index] = ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_loadbytefromaddr(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+
+ ctx->data[index] = *(const u8 *)ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_writebytetoaddr(struct ScriptContext *ctx)
+{
+ u8 value = ScriptReadByte(ctx);
+
+ *(u8 *)ScriptReadWord(ctx) = value;
+ return FALSE;
+}
+
+bool8 ScrCmd_loadbyte(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+
+ ctx->data[index] = ScriptReadByte(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_setptrbyte(struct ScriptContext *ctx)
+{
+ u8 index = ScriptReadByte(ctx);
+
+ *(u8 *)ScriptReadWord(ctx) = ctx->data[index];
+ return FALSE;
+}
+
+bool8 ScrCmd_copylocal(struct ScriptContext *ctx)
+{
+ u8 destIndex = ScriptReadByte(ctx);
+ u8 srcIndex = ScriptReadByte(ctx);
+
+ ctx->data[destIndex] = ctx->data[srcIndex];
+ return FALSE;
+}
+
+bool8 ScrCmd_copybyte(struct ScriptContext *ctx)
+{
+ u8 *ptr = (u8 *)ScriptReadWord(ctx);
+ *ptr = *(const u8 *)ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_setvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr = ScriptReadHalfword(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_copyvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr = *GetVarPointer(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_setorcopyvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr = VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+u8 compare_012(u16 a1, u16 a2)
+{
+ if (a1 < a2)
+ return 0;
+ if (a1 == a2)
+ return 1;
+ return 2;
+}
+
+// comparelocaltolocal
+bool8 ScrCmd_compare_local_to_local(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = ctx->data[ScriptReadByte(ctx)];
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+// comparelocaltoimm
+bool8 ScrCmd_compare_local_to_value(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = ScriptReadByte(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_local_to_addr(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = *(const u8 *)ScriptReadWord(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_local(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = ctx->data[ScriptReadByte(ctx)];
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_value(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = ScriptReadByte(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_addr(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = *(const u8 *)ScriptReadWord(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_var_to_value(struct ScriptContext *ctx)
+{
+ const u16 value1 = *GetVarPointer(ScriptReadHalfword(ctx));
+ const u16 value2 = ScriptReadHalfword(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_var_to_var(struct ScriptContext *ctx)
+{
+ const u16 *ptr1 = GetVarPointer(ScriptReadHalfword(ctx));
+ const u16 *ptr2 = GetVarPointer(ScriptReadHalfword(ctx));
+
+ ctx->comparisonResult = compare_012(*ptr1, *ptr2);
+ return FALSE;
+}
+
+bool8 ScrCmd_addvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr += ScriptReadHalfword(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_subvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr -= VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_random(struct ScriptContext *ctx)
+{
+ u16 max = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = Random() % max;
+ return FALSE;
+}
+
+bool8 ScrCmd_additem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = AddBagItem(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_removeitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = RemoveBagItem(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitemspace(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = CheckBagHasSpace(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = CheckBagHasItem(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitemtype(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = GetPocketByItemId(itemId);
+ return FALSE;
+}
+
+bool8 ScrCmd_addpcitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = AddPCItem(itemId, quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkpcitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = CheckPCHasItem(itemId, quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_adddecor(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = DecorationAdd(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_removedecor(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = DecorationRemove(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkdecor(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = DecorationCheckSpace(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_hasdecor(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = CheckHasDecoration(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_setflag(struct ScriptContext *ctx)
+{
+ FlagSet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_clearflag(struct ScriptContext *ctx)
+{
+ FlagClear(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_checkflag(struct ScriptContext *ctx)
+{
+ ctx->comparisonResult = FlagGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_incrementgamestat(struct ScriptContext *ctx)
+{
+ IncrementGameStat(ScriptReadByte(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_animdarklevel(struct ScriptContext *ctx)
+{
+ sub_80B009C(ScriptReadByte(ctx));
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_setdarklevel(struct ScriptContext *ctx)
+{
+ u16 flashLevel = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetFlashLevel(flashLevel);
+ return FALSE;
+}
+
+static bool8 IsPaletteNotActive(void)
+{
+ if (!gPaletteFade.active)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_fadescreen(struct ScriptContext *ctx)
+{
+ fade_screen(ScriptReadByte(ctx), 0);
+ SetupNativeScript(ctx, IsPaletteNotActive);
+ return TRUE;
+}
+
+bool8 ScrCmd_fadescreendelay(struct ScriptContext *ctx)
+{
+ u8 mode = ScriptReadByte(ctx);
+ u8 delay = ScriptReadByte(ctx);
+
+ fade_screen(mode, delay);
+ SetupNativeScript(ctx, IsPaletteNotActive);
+ return TRUE;
+}
+
+bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx)
+{
+ u8 mode = ScriptReadByte(ctx);
+
+ switch (mode)
+ {
+ case 1:
+ default:
+ CpuCopy32(gPlttBufferUnfaded, gPaletteDecompressionBuffer, PLTT_DECOMP_BUFFER_SIZE);
+ fade_screen(mode, 0);
+ break;
+ case 0:
+ case 2:
+ CpuCopy32(gPaletteDecompressionBuffer, gPlttBufferUnfaded, PLTT_DECOMP_BUFFER_SIZE);
+ fade_screen(mode, 0);
+ break;
+ }
+
+ SetupNativeScript(ctx, IsPaletteNotActive);
+ return TRUE;
+}
+
+static bool8 RunPauseTimer(void)
+{
+ sPauseCounter--;
+
+ if (sPauseCounter == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_delay(struct ScriptContext *ctx)
+{
+ sPauseCounter = ScriptReadHalfword(ctx);
+ SetupNativeScript(ctx, RunPauseTimer);
+ return TRUE;
+}
+
+bool8 ScrCmd_initclock(struct ScriptContext *ctx)
+{
+ u8 hour = VarGet(ScriptReadHalfword(ctx));
+ u8 minute = VarGet(ScriptReadHalfword(ctx));
+
+ RtcInitLocalTimeOffset(hour, minute);
+ return FALSE;
+}
+
+bool8 ScrCmd_dodailyevents(struct ScriptContext *ctx)
+{
+ DoTimeBasedEvents();
+ return FALSE;
+}
+
+bool8 ScrCmd_gettime(struct ScriptContext *ctx)
+{
+ RtcCalcLocalTime();
+ gSpecialVar_0x8000 = gLocalTime.hours;
+ gSpecialVar_0x8001 = gLocalTime.minutes;
+ gSpecialVar_0x8002 = gLocalTime.seconds;
+ return FALSE;
+}
+
+bool8 ScrCmd_setweather(struct ScriptContext *ctx)
+{
+ u16 weather = VarGet(ScriptReadHalfword(ctx));
+
+ SetSav1Weather(weather);
+ return FALSE;
+}
+
+bool8 ScrCmd_resetweather(struct ScriptContext *ctx)
+{
+ sub_80AEDBC();
+ return FALSE;
+}
+
+bool8 ScrCmd_doweather(struct ScriptContext *ctx)
+{
+ DoCurrentWeather();
+ return FALSE;
+}
+
+bool8 ScrCmd_tileeffect(struct ScriptContext *ctx)
+{
+ ActivatePerStepCallback(ScriptReadByte(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_setmaplayoutindex(struct ScriptContext *ctx)
+{
+ u16 value = VarGet(ScriptReadHalfword(ctx));
+
+ sub_8085524(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_warp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_80AF734();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpsilent(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sp13E_warp_to_last_warp();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpdoor(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_80AF7D0();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_warphole(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u16 x;
+ u16 y;
+
+ PlayerGetDestCoords(&x, &y);
+ if (mapGroup == 0xFF && mapNum == 0xFF)
+ sub_8084EBC(x - 7, y - 7);
+ else
+ Overworld_SetWarpDestination(mapGroup, mapNum, -1, x - 7, y - 7);
+ sp13F_fall_to_last_warp();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpteleport(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_80AF848();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpD7(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_80AF87C();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_setwarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdynamicwarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ saved_warp2_set_2(0, mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdivewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ sub_8084E2C(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setholewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ sub_8084E80(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setescapewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ sub_8084DD4(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_getplayerxy(struct ScriptContext *ctx)
+{
+ u16 *pX = GetVarPointer(ScriptReadHalfword(ctx));
+ u16 *pY = GetVarPointer(ScriptReadHalfword(ctx));
+
+ *pX = gSaveBlock1Ptr->pos.x;
+ *pY = gSaveBlock1Ptr->pos.y;
+ return FALSE;
+}
+
+bool8 ScrCmd_countpokemon(struct ScriptContext *ctx)
+{
+ gScriptResult = CalculatePlayerPartyCount();
+ return FALSE;
+}
+
+bool8 ScrCmd_playse(struct ScriptContext *ctx)
+{
+ PlaySE(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForSoundEffectFinish(void)
+{
+ if (!IsSEPlaying())
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitse(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, WaitForSoundEffectFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_playfanfare(struct ScriptContext *ctx)
+{
+ PlayFanfare(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForFanfareFinish(void)
+{
+ return IsFanfareTaskInactive();
+}
+
+bool8 ScrCmd_waitfanfare(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, WaitForFanfareFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_playbgm(struct ScriptContext *ctx)
+{
+ u16 songId = ScriptReadHalfword(ctx);
+ bool8 val = ScriptReadByte(ctx);
+
+ if (val == TRUE)
+ Overworld_SetSavedMusic(songId);
+ PlayNewMapMusic(songId);
+ return FALSE;
+}
+
+bool8 ScrCmd_savebgm(struct ScriptContext *ctx)
+{
+ Overworld_SetSavedMusic(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_fadedefaultbgm(struct ScriptContext *ctx)
+{
+ Overworld_ChangeMusicToDefault();
+ return FALSE;
+}
+
+bool8 ScrCmd_fadenewbgm(struct ScriptContext *ctx)
+{
+ Overworld_ChangeMusicTo(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_fadeoutbgm(struct ScriptContext *ctx)
+{
+ u8 speed = ScriptReadByte(ctx);
+
+ if (speed != 0)
+ FadeOutBGMTemporarily(4 * speed);
+ else
+ FadeOutBGMTemporarily(4);
+ SetupNativeScript(ctx, IsBGMPausedOrStopped);
+ return TRUE;
+}
+
+bool8 ScrCmd_fadeinbgm(struct ScriptContext *ctx)
+{
+ u8 speed = ScriptReadByte(ctx);
+
+ if (speed != 0)
+ FadeInBGM(4 * speed);
+ else
+ FadeInBGM(4);
+ return FALSE;
+}
+
+bool8 ScrCmd_applymovement(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ const void *movementScript = (const void *)ScriptReadWord(ctx);
+
+ ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript);
+ sMovingNpcId = localId;
+ return FALSE;
+}
+
+bool8 ScrCmd_applymovement_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ const void *movementScript = (const void *)ScriptReadWord(ctx);
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ ScriptMovement_StartObjectMovementScript(localId, mapNum, mapGroup, movementScript);
+ sMovingNpcId = localId;
+ return FALSE;
+}
+
+static bool8 WaitForMovementFinish(void)
+{
+ return ScriptMovement_IsObjectMovementFinished(sMovingNpcId, sMovingNpcMapId, sMovingNpcMapBank);
+}
+
+bool8 ScrCmd_waitmovement(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ if (localId != 0)
+ sMovingNpcId = localId;
+ sMovingNpcMapBank = gSaveBlock1Ptr->location.mapGroup;
+ sMovingNpcMapId = gSaveBlock1Ptr->location.mapNum;
+ SetupNativeScript(ctx, WaitForMovementFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_waitmovement_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapBank;
+ u8 mapId;
+
+ if (localId != 0)
+ sMovingNpcId = localId;
+ mapBank = ScriptReadByte(ctx);
+ mapId = ScriptReadByte(ctx);
+ sMovingNpcMapBank = mapBank;
+ sMovingNpcMapId = mapId;
+ SetupNativeScript(ctx, WaitForMovementFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_removeobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ RemoveFieldObjectByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_removeobject_at(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ RemoveFieldObjectByLocalIdAndMap(objectId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_addobject(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+
+ show_sprite(objectId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_addobject_at(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ show_sprite(objectId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectxy(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ sub_808EBA8(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectxyperm(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetMapObjTemplateCoords(localId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_moveobjectoffscreen(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ sub_808F254(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_showobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 0);
+ return FALSE;
+}
+
+bool8 ScrCmd_hideobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 1);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectpriority(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 priority = ScriptReadByte(ctx);
+
+ sub_808E78C(localId, mapNum, mapGroup, priority + 83);
+ return FALSE;
+}
+
+bool8 ScrCmd_resetobjectpriority(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ sub_808E7E4(localId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_faceplayer(struct ScriptContext *ctx)
+{
+ if (gMapObjects[gSelectedMapObject].active)
+ {
+ FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject],
+ player_get_direction_lower_nybble());
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_turnobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 direction = ScriptReadByte(ctx);
+
+ FieldObjectTurnByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 movementType = ScriptReadByte(ctx);
+
+ Overworld_SetMapObjTemplateMovementType(localId, movementType);
+ return FALSE;
+}
+
+bool8 ScrCmd_createvobject(struct ScriptContext *ctx)
+{
+ u8 graphicsId = ScriptReadByte(ctx);
+ u8 v2 = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u32 y = VarGet(ScriptReadHalfword(ctx));
+ u8 elevation = ScriptReadByte(ctx);
+ u8 direction = ScriptReadByte(ctx);
+
+ sprite_new(graphicsId, v2, x, y, elevation, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_turnvobject(struct ScriptContext *ctx)
+{
+ u8 v1 = ScriptReadByte(ctx);
+ u8 direction = ScriptReadByte(ctx);
+
+ sub_8097B78(v1, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_lockall(struct ScriptContext *ctx)
+{
+ if (is_c1_link_related_active())
+ {
+ return FALSE;
+ }
+ else
+ {
+ ScriptFreezeMapObjects();
+ SetupNativeScript(ctx, sub_80983C4);
+ return TRUE;
+ }
+}
+
+bool8 ScrCmd_lock(struct ScriptContext *ctx)
+{
+ if (is_c1_link_related_active())
+ {
+ return FALSE;
+ }
+ else
+ {
+ if (gMapObjects[gSelectedMapObject].active)
+ {
+ LockSelectedMapObject();
+ SetupNativeScript(ctx, sub_809847C);
+ }
+ else
+ {
+ ScriptFreezeMapObjects();
+ SetupNativeScript(ctx, sub_80983C4);
+ }
+ return TRUE;
+ }
+}
+
+bool8 ScrCmd_releaseall(struct ScriptContext *ctx)
+{
+ u8 objectId;
+
+ HideFieldMessageBox();
+ objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]);
+ sub_80D338C();
+ UnfreezeMapObjects();
+ return FALSE;
+}
+
+bool8 ScrCmd_release(struct ScriptContext *ctx)
+{
+ u8 objectId;
+
+ HideFieldMessageBox();
+ if (gMapObjects[gSelectedMapObject].active)
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedMapObject]);
+ objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]);
+ sub_80D338C();
+ UnfreezeMapObjects();
+ return FALSE;
+}
+
+bool8 ScrCmd_message(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ ShowFieldMessage(msg);
+ return FALSE;
+}
+
+bool8 ScrCmd_pokenavcall(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ sub_8098238(msg);
+ return FALSE;
+}
+
+bool8 ScrCmd_messageautoscroll(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ gTextFlags.flag_2 = TRUE;
+ gTextFlags.flag_3 = TRUE;
+ ShowFieldAutoScrollMessage(msg);
+ return FALSE;
+}
+
+bool8 ScrCmd_cmdDB(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ sub_81973A4();
+ sub_81973C4(0, 1);
+ PrintTextOnWindow(0, 1, msg, 0, 1, 0, 0);
+ return FALSE;
+}
+
+bool8 ScrCmd_waitmessage(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsFieldMessageBoxHidden);
+ return TRUE;
+}
+
+bool8 ScrCmd_closemessage(struct ScriptContext *ctx)
+{
+ HideFieldMessageBox();
+ return FALSE;
+}
+
+static bool8 WaitForAorBPress(void)
+{
+ if (gMain.newKeys & A_BUTTON)
+ return TRUE;
+ if (gMain.newKeys & B_BUTTON)
+ return TRUE;
+ return FALSE;
+}
+
+bool8 ScrCmd_waitbutton(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, WaitForAorBPress);
+ return TRUE;
+}
+
+bool8 ScrCmd_yesnobox(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+
+ if (ScriptMenu_YesNo(left, top) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_multichoice(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_multichoicedefault(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 defaultChoice = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_MultichoiceWithDefault(left, top, multichoiceId, ignoreBPress, defaultChoice) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_drawbox(struct ScriptContext *ctx)
+{
+ /*u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 right = ScriptReadByte(ctx);
+ u8 bottom = ScriptReadByte(ctx);
+
+ MenuDrawTextWindow(left, top, right, bottom);*/
+ return FALSE;
+}
+
+bool8 ScrCmd_multichoicegrid(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 numColumns = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_MultichoiceGrid(left, top, multichoiceId, ignoreBPress, numColumns) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_erasebox(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 right = ScriptReadByte(ctx);
+ u8 bottom = ScriptReadByte(ctx);
+
+ // MenuZeroFillWindowRect(left, top, right, bottom);
+ return FALSE;
+}
+
+bool8 ScrCmd_drawboxtext(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ /*if (Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }*/
+ return FALSE;
+}
+
+bool8 ScrCmd_drawpokepic(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ ScriptMenu_ShowPokemonPic(species, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_erasepokepic(struct ScriptContext *ctx)
+{
+ bool8 (*func)(void) = ScriptMenu_GetPicboxWaitFunc();
+
+ if (func == NULL)
+ return FALSE;
+ SetupNativeScript(ctx, func);
+ return TRUE;
+}
+
+bool8 ScrCmd_drawcontestwinner(struct ScriptContext *ctx)
+{
+ u8 v1 = ScriptReadByte(ctx);
+
+ if (v1)
+ sub_812FDA8(v1);
+ ShowContestWinner();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+// Lots of math, can't figure it out.
+/*
+bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
+{
+ u8 *ptr = (u8 *)ScriptReadWord(ctx);
+ struct WindowTemplate template1;
+ struct WindowTemplate template2;
+ int i;
+ u8 width;
+ u8 height;
+ int temp1;
+ int temp2;
+ u8 x;
+ u8 y;
+
+ StringExpandPlaceholders(gStringVar4, ptr + 6);
+
+ width = GetStringWidth(6, gStringVar4, -1) / 8;
+
+ if (width > 0x1C)
+ width = 0x1C;
+
+ for (i = 0, height = 4; gStringVar4[i] != 0xFF;)
+ {
+ if (gStringVar4[i++] == 0xFE)
+ height += 3;
+ }
+
+ if (height > 0x12)
+ height = 0x12;
+
+ x = width + 2;
+ temp1 = (0x1E - x) / 2;
+ x = temp1 + 1;
+ temp1 = ((x - temp1 - 1) * 8 + 3);
+
+ y = height + 2;
+ temp2 = (0x14 - y) / 2;
+ y = temp2 + 2;
+ temp2 = ((y - temp2 - 1) * 8);
+
+ sub_8198A50(&template1, 0, x, y, width, height, 0xF, 0x1);
+ template2 = template1;
+ gUnknown_03000F30 = AddWindow(&template2);
+ sub_809882C(gUnknown_03000F30, 0x214, 0xE0);
+ sub_81973FC(gUnknown_03000F30, 0);
+ PutWindowTilemap(gUnknown_03000F30);
+ FillWindowPixelBuffer(gUnknown_03000F30, 0x11);
+ PrintTextOnWindow(gUnknown_03000F30, 6, gStringVar4, temp1, temp2, 0xFF, 0x0);
+ CopyWindowToVram(gUnknown_03000F30, 3);
+ return FALSE;
+}*/
+__attribute__((naked))
+bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
+{
+ asm("push {r4-r7,lr}\n\
+ mov r7, r8\n\
+ push {r7}\n\
+ sub sp, #0x20\n\
+ bl ScriptReadWord\n\
+ add r1, r0, #0\n\
+ ldr r4, =gStringVar4\n\
+ add r1, #0x6\n\
+ add r0, r4, #0\n\
+ bl StringExpandPlaceholders\n\
+ mov r2, #0x1\n\
+ neg r2, r2\n\
+ mov r0, #0x6\n\
+ add r1, r4, #0\n\
+ bl GetStringWidth\n\
+ lsr r0, #3\n\
+ lsl r0, #24\n\
+ lsr r7, r0, #24\n\
+ cmp r7, #0x1C\n\
+ bls _0809AE9C\n\
+ mov r7, #0x1C\n\
+_0809AE9C:\n\
+ mov r5, #0x4\n\
+ ldrb r0, [r4]\n\
+ add r2, r7, #0x2\n\
+ add r1, sp, #0x18\n\
+ mov r8, r1\n\
+ cmp r0, #0xFF\n\
+ beq _0809AEC0\n\
+ add r1, r4, #0\n\
+_0809AEAC:\n\
+ ldrb r0, [r1]\n\
+ add r1, #0x1\n\
+ cmp r0, #0xFE\n\
+ bne _0809AEBA\n\
+ add r0, r5, #0x3\n\
+ lsl r0, #24\n\
+ lsr r5, r0, #24\n\
+_0809AEBA:\n\
+ ldrb r0, [r1]\n\
+ cmp r0, #0xFF\n\
+ bne _0809AEAC\n\
+_0809AEC0:\n\
+ cmp r5, #0x12\n\
+ bls _0809AEC6\n\
+ mov r5, #0x12\n\
+_0809AEC6:\n\
+ lsl r0, r2, #24\n\
+ lsr r0, #24\n\
+ mov r2, #0x1E\n\
+ sub r2, r0\n\
+ lsr r0, r2, #31\n\
+ add r2, r0\n\
+ asr r2, #1\n\
+ lsl r2, #24\n\
+ add r0, r5, #0x2\n\
+ lsl r0, #24\n\
+ lsr r0, #24\n\
+ mov r4, #0x14\n\
+ sub r4, r0\n\
+ lsr r0, r4, #31\n\
+ add r4, r0\n\
+ asr r4, #1\n\
+ lsl r4, #24\n\
+ lsr r6, r2, #24\n\
+ mov r0, #0x80\n\
+ lsl r0, #17\n\
+ add r2, r0\n\
+ lsr r2, #24\n\
+ lsr r3, r4, #24\n\
+ mov r1, #0x80\n\
+ lsl r1, #18\n\
+ add r4, r1\n\
+ lsr r4, #24\n\
+ sub r6, r2, r6\n\
+ sub r6, #0x1\n\
+ lsl r6, #3\n\
+ add r6, #0x3\n\
+ lsl r6, #24\n\
+ lsr r6, #24\n\
+ sub r4, r3\n\
+ sub r4, #0x1\n\
+ lsl r4, #27\n\
+ lsr r4, #24\n\
+ add r3, #0x1\n\
+ lsl r3, #24\n\
+ lsr r3, #24\n\
+ str r7, [sp]\n\
+ str r5, [sp, #0x4]\n\
+ mov r0, #0xF\n\
+ str r0, [sp, #0x8]\n\
+ mov r0, #0x1\n\
+ str r0, [sp, #0xC]\n\
+ add r0, sp, #0x10\n\
+ mov r1, #0\n\
+ bl sub_8198A50\n\
+ ldr r0, [sp, #0x10]\n\
+ ldr r1, [sp, #0x14]\n\
+ str r0, [sp, #0x18]\n\
+ str r1, [sp, #0x1C]\n\
+ ldr r5, =gUnknown_03000F30\n\
+ mov r0, r8\n\
+ bl AddWindow\n\
+ strb r0, [r5]\n\
+ ldrb r0, [r5]\n\
+ mov r1, #0x85\n\
+ lsl r1, #2\n\
+ mov r2, #0xE0\n\
+ bl sub_809882C\n\
+ ldrb r0, [r5]\n\
+ mov r1, #0\n\
+ bl sub_81973FC\n\
+ ldrb r0, [r5]\n\
+ bl PutWindowTilemap\n\
+ ldrb r0, [r5]\n\
+ mov r1, #0x11\n\
+ bl FillWindowPixelBuffer\n\
+ ldrb r0, [r5]\n\
+ ldr r2, =gStringVar4\n\
+ str r4, [sp]\n\
+ mov r1, #0xFF\n\
+ str r1, [sp, #0x4]\n\
+ mov r1, #0\n\
+ str r1, [sp, #0x8]\n\
+ mov r1, #0x6\n\
+ add r3, r6, #0\n\
+ bl PrintTextOnWindow\n\
+ ldrb r0, [r5]\n\
+ mov r1, #0x3\n\
+ bl CopyWindowToVram\n\
+ mov r0, #0\n\
+ add sp, #0x20\n\
+ pop {r3}\n\
+ mov r8, r3\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .pool");
+}
+
+bool8 ScrCmd_cmdDA(struct ScriptContext *ctx)
+{
+ sub_809BDB4();
+ return FALSE;
+}
+
+bool8 ScrCmd_vmessage(struct ScriptContext *ctx)
+{
+ u32 v1 = ScriptReadWord(ctx);
+
+ ShowFieldMessage((u8 *)(v1 - gUnknown_020375C4));
+ return FALSE;
+}
+
+bool8 ScrCmd_getspeciesname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gSpeciesNames[species]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getfirstpartypokename(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+
+ u8 *dest = sScriptStringVars[stringVarIndex];
+ u8 partyIndex = GetLeadMonIndex();
+ u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
+ StringCopy(dest, gSpeciesNames[species]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getpartypokename(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, sScriptStringVars[stringVarIndex]);
+ StringGetEnd10(sScriptStringVars[stringVarIndex]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getitemname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+
+ CopyItemName(itemId, sScriptStringVars[stringVarIndex]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getitemnameplural(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ CopyItemNameHandlePlural(itemId, sScriptStringVars[stringVarIndex], quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_getdecorname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 decorId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gDecorations[decorId].name);
+ return FALSE;
+}
+
+bool8 ScrCmd_getmovename(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 moveId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gMoveNames[moveId]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getnumberstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 v1 = VarGet(ScriptReadHalfword(ctx));
+ u8 v2 = sub_80EF370(v1);
+
+ ConvertIntToDecimalStringN(sScriptStringVars[stringVarIndex], v1, 0, v2);
+ return FALSE;
+}
+
+bool8 ScrCmd_getstdstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gUnknown_0858BAF0[index]);
+ return FALSE;
+}
+
+bool8 ScrCmd_getcontesttype(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ sub_818E868(sScriptStringVars[stringVarIndex], index);
+ return FALSE;
+}
+
+bool8 ScrCmd_getstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ const u8 *text = (u8 *)ScriptReadWord(ctx);
+
+ StringCopy(sScriptStringVars[stringVarIndex], text);
+ return FALSE;
+}
+
+bool8 ScrCmd_vloadword(struct ScriptContext *ctx)
+{
+ const u8 *ptr = (u8 *)(ScriptReadWord(ctx) - gUnknown_020375C4);
+
+ StringExpandPlaceholders(gStringVar4, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_vgetstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u32 addr = ScriptReadWord(ctx);
+
+ const u8 *src = (u8 *)(addr - gUnknown_020375C4);
+ u8 *dest = sScriptStringVars[stringVarIndex];
+ StringCopy(dest, src);
+ return FALSE;
+}
+
+bool8 ScrCmd_getboxname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 boxId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], GetBoxNamePtr(boxId));
+ return FALSE;
+}
+
+bool8 ScrCmd_givepoke(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u8 level = ScriptReadByte(ctx);
+ u16 item = VarGet(ScriptReadHalfword(ctx));
+ u32 unkParam1 = ScriptReadWord(ctx);
+ u32 unkParam2 = ScriptReadWord(ctx);
+ u8 unkParam3 = ScriptReadByte(ctx);
+
+ gScriptResult = ScriptGiveMon(species, level, item, unkParam1, unkParam2, unkParam3);
+ return FALSE;
+}
+
+bool8 ScrCmd_giveegg(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = ScriptGiveEgg(species);
+ return FALSE;
+}
+
+bool8 ScrCmd_setpokemove(struct ScriptContext *ctx)
+{
+ u8 partyIndex = ScriptReadByte(ctx);
+ u8 slot = ScriptReadByte(ctx);
+ u16 move = ScriptReadHalfword(ctx);
+
+ ScriptSetMonMoveSlot(partyIndex, move, slot);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkpokemove(struct ScriptContext *ctx)
+{
+ u8 i;
+ u16 moveId = ScriptReadHalfword(ctx);
+
+ gScriptResult = 6;
+ for (i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL);
+ if (!species)
+ break;
+ // UB: GetMonData() arguments don't match function definition
+ if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) && pokemon_has_move(&gPlayerParty[i], moveId) == TRUE)
+ {
+ gScriptResult = i;
+ gSpecialVar_0x8004 = species;
+ break;
+ }
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_givemoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ AddMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_takemoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ RemoveMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkmoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ gScriptResult = IsEnoughMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_showmoneybox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ DrawMoneyBox(GetMoney(&gSaveBlock1Ptr->money), x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx)
+{
+ /*u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);*/
+
+ HideMoneyBox();
+ return FALSE;
+}
+
+bool8 ScrCmd_updatemoneybox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ ChangeAmountInMoneyBox(GetMoney(&gSaveBlock1Ptr->money));
+ return FALSE;
+}
+
+bool8 ScrCmd_showcoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ ShowCoinsWindow(GetCoins(), x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ HideCoinsWindow();
+ return FALSE;
+}
+
+bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ PrintCoinsString(GetCoins());
+ return FALSE;
+}
+
+bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr);
+ return FALSE;
+}
+
+bool8 ScrCmd_battlebegin(struct ScriptContext *ctx)
+{
+ BattleSetup_StartTrainerBattle();
+ return TRUE;
+}
+
+bool8 ScrCmd_ontrainerbattleend(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle();
+ return FALSE;
+}
+
+bool8 ScrCmd_ontrainerbattleendgoto(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript();
+ return FALSE;
+}
+
+bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ ctx->comparisonResult = HasTrainerAlreadyBeenFought(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_settrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ trainer_flag_set(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_cleartrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ trainer_flag_clear(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx)
+{
+ u16 species = ScriptReadHalfword(ctx);
+ u8 level = ScriptReadByte(ctx);
+ u16 item = ScriptReadHalfword(ctx);
+
+ CreateScriptedWildMon(species, level, item);
+ return FALSE;
+}
+
+bool8 ScrCmd_dowildbattle(struct ScriptContext *ctx)
+{
+ BattleSetup_StartScriptedWildBattle();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemart(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreatePokemartMenu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemartdecor(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreateDecorationShop1Menu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemartbp(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreateDecorationShop2Menu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_playslotmachine(struct ScriptContext *ctx)
+{
+ u8 slotMachineIndex = VarGet(ScriptReadHalfword(ctx));
+
+ PlaySlotMachine(slotMachineIndex, c2_exit_to_overworld_1_continue_scripts_restart_music);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_plantberrytree(struct ScriptContext *ctx)
+{
+ u8 treeId = ScriptReadByte(ctx);
+ u8 berry = ScriptReadByte(ctx);
+ u8 growthStage = ScriptReadByte(ctx);
+
+ if (berry == 0)
+ PlantBerryTree(treeId, 0, growthStage, FALSE);
+ else
+ PlantBerryTree(treeId, berry, growthStage, FALSE);
+ return FALSE;
+}
+
+bool8 ScrCmd_getpricereduction(struct ScriptContext *ctx)
+{
+ u16 value = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = GetPriceReduction(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_choosecontestpkmn(struct ScriptContext *ctx)
+{
+ sub_81B9404();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+
+bool8 ScrCmd_startcontest(struct ScriptContext *ctx)
+{
+ sub_80F840C();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx)
+{
+ sub_80F8484();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_contestlinktransfer(struct ScriptContext *ctx)
+{
+ sub_80F84C4(gScriptContestCategory);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_dofieldeffect(struct ScriptContext *ctx)
+{
+ u16 effectId = VarGet(ScriptReadHalfword(ctx));
+
+ sFieldEffectScriptId = effectId;
+ FieldEffectStart(sFieldEffectScriptId);
+ return FALSE;
+}
+
+bool8 ScrCmd_setfieldeffect(struct ScriptContext *ctx)
+{
+ u8 argNum = ScriptReadByte(ctx);
+
+ gFieldEffectArguments[argNum] = (s16)VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForFieldEffectFinish(void)
+{
+ if (!FieldEffectActiveListContains(sFieldEffectScriptId))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitfieldeffect(struct ScriptContext *ctx)
+{
+ sFieldEffectScriptId = VarGet(ScriptReadHalfword(ctx));
+ SetupNativeScript(ctx, WaitForFieldEffectFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_sethealplace(struct ScriptContext *ctx)
+{
+ u16 healLocationId = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetHealLocationWarp(healLocationId);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkplayergender(struct ScriptContext *ctx)
+{
+ gScriptResult = gSaveBlock2Ptr->playerGender;
+ return FALSE;
+}
+
+bool8 ScrCmd_playpokecry(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u16 mode = VarGet(ScriptReadHalfword(ctx));
+
+ PlayCry5(species, mode);
+ return FALSE;
+}
+
+bool8 ScrCmd_waitpokecry(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsCryFinished);
+ return TRUE;
+}
+
+bool8 ScrCmd_setmaptile(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ u16 tileId = VarGet(ScriptReadHalfword(ctx));
+ u16 v8 = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ if (!v8)
+ MapGridSetMetatileIdAt(x, y, tileId);
+ else
+ MapGridSetMetatileIdAt(x, y, tileId | 0xC00);
+ return FALSE;
+}
+
+bool8 ScrCmd_opendoor(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ PlaySE(GetDoorSoundEffect(x, y));
+ FieldAnimateDoorOpen(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_closedoor(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldAnimateDoorClose(x, y);
+ return FALSE;
+}
+
+static bool8 IsDoorAnimationStopped(void)
+{
+ if (!FieldIsDoorAnimationRunning())
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitdooranim(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsDoorAnimationStopped);
+ return TRUE;
+}
+
+bool8 ScrCmd_setdooropen(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldSetDoorOpened(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldSetDoorClosed(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_addelevmenuitem(struct ScriptContext *ctx)
+{
+ u8 v3 = ScriptReadByte(ctx);
+ u16 v5 = VarGet(ScriptReadHalfword(ctx));
+ u16 v7 = VarGet(ScriptReadHalfword(ctx));
+ u16 v9 = VarGet(ScriptReadHalfword(ctx));
+
+ //ScriptAddElevatorMenuItem(v3, v5, v7, v9);
+ return FALSE;
+}
+
+bool8 ScrCmd_showelevmenu(struct ScriptContext *ctx)
+{
+ /*ScriptShowElevatorMenu();
+ ScriptContext1_Stop();
+ return TRUE;*/
+ return FALSE;
+}
+
+bool8 ScrCmd_checkcoins(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr = GetCoins();
+ return FALSE;
+}
+
+bool8 ScrCmd_givecoins(struct ScriptContext *ctx)
+{
+ u16 coins = VarGet(ScriptReadHalfword(ctx));
+
+ if (GiveCoins(coins) == TRUE)
+ gScriptResult = 0;
+ else
+ gScriptResult = 1;
+ return FALSE;
+}
+
+bool8 ScrCmd_takecoins(struct ScriptContext *ctx)
+{
+ u16 coins = VarGet(ScriptReadHalfword(ctx));
+
+ if (TakeCoins(coins) == TRUE)
+ gScriptResult = 0;
+ else
+ gScriptResult = 1;
+ return FALSE;
+}
+
+bool8 ScrCmd_mossdeepgym1(struct ScriptContext *ctx)
+{
+ u16 v1 = VarGet(ScriptReadHalfword(ctx));
+
+ sMovingNpcId = sub_81A89A0(v1);
+ return FALSE;
+}
+
+bool8 ScrCmd_mossdeepgym2(struct ScriptContext *ctx)
+{
+ sub_81A8AF8();
+ return FALSE;
+}
+
+bool8 ScrCmd_mossdeepgym3(struct ScriptContext *ctx)
+{
+ u16 v1 = VarGet(ScriptReadHalfword(ctx));
+
+ sub_81A8934(v1);
+ return FALSE;
+}
+
+bool8 ScrCmd_mossdeepgym4(struct ScriptContext *ctx)
+{
+ sub_81A895C();
+ return FALSE;
+}
+
+bool8 ScrCmd_cmdD8(struct ScriptContext *ctx)
+{
+ gSelectedMapObject = sub_80B47BC();
+ return FALSE;
+}
+
+bool8 ScrCmd_cmdD9(struct ScriptContext *ctx)
+{
+ if (is_c1_link_related_active())
+ {
+ return FALSE;
+ }
+ else
+ {
+ if (gMapObjects[gSelectedMapObject].active)
+ {
+ sub_8098630();
+ SetupNativeScript(ctx, sub_8098734);
+ }
+ return TRUE;
+ }
+}
+
+// This command will force the Pokémon to be obedient, you don't get to choose which value to set its obedience to
+bool8 ScrCmd_setpokeobedient(struct ScriptContext *ctx)
+{
+ bool8 obedient = TRUE;
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ SetMonData(&gPlayerParty[partyIndex], MON_DATA_OBEDIENCE, &obedient);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkpokeobedience(struct ScriptContext *ctx)
+{
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ gScriptResult = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OBEDIENCE, NULL);
+ return FALSE;
+}
+
+bool8 ScrCmd_cmdCF(struct ScriptContext *ctx)
+{
+ const u8* v1 = sub_8099244();
+
+ if (v1)
+ {
+ ((u8*)gUnknown_020375C0) = ctx->scriptPtr;
+ ScriptJump(ctx, v1);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_warpD1(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_808D074(player_get_direction_lower_nybble());
+ sub_80B0244();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
+
+bool8 ScrCmd_setpokemetlocation(struct ScriptContext *ctx)
+{
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+ u8 location = ScriptReadByte(ctx);
+
+ if (partyIndex < PARTY_SIZE)
+ SetMonData(&gPlayerParty[partyIndex], MON_DATA_MET_LOCATION, &location);
+ return FALSE;
+}
+
+void sub_809BDB4(void)
+{
+ sub_819746C(gUnknown_03000F30, 1);
+ RemoveWindow(gUnknown_03000F30);
+}
+
+bool8 ScrCmd_gettrainerclass(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 trainerClassId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], GetTrainerClassNameFromId(trainerClassId));
+ return FALSE;
+}
+
+bool8 ScrCmd_gettrainername(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 trainerClassId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], GetTrainerNameFromId(trainerClassId));
+ return FALSE;
+}
+
+void sub_809BE48(u16 npcId)
+{
+ sMovingNpcId = npcId;
+}
-// .rodata
+bool8 ScrCmd_warpE0(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
-// .text
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_80AF79C();
+ player_avatar_init_params_reset();
+ return TRUE;
+}
diff --git a/src/script.c b/src/script.c
index b2809a137..5a1c5daa9 100644
--- a/src/script.c
+++ b/src/script.c
@@ -134,12 +134,12 @@ const u8 *ScriptPop(struct ScriptContext *ctx)
return ctx->stack[ctx->stackDepth];
}
-void ScriptJump(struct ScriptContext *ctx, u8 *ptr)
+void ScriptJump(struct ScriptContext *ctx, const u8 *ptr)
{
ctx->scriptPtr = ptr;
}
-void ScriptCall(struct ScriptContext *ctx, u8 *ptr)
+void ScriptCall(struct ScriptContext *ctx, const u8 *ptr)
{
ScriptPush(ctx, ctx->scriptPtr);
ctx->scriptPtr = ptr;
diff --git a/src/sprite.c b/src/sprite.c
index 17b0f181a..daa019019 100644
--- a/src/sprite.c
+++ b/src/sprite.c
@@ -594,7 +594,7 @@ u8 CreateSpriteAt(u8 index, const struct SpriteTemplate *template, s16 x, s16 y,
return index;
}
-u8 CreateSpriteAndAnimate(struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
+u8 CreateSpriteAndAnimate(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
{
u8 i;
diff --git a/src/text.c b/src/text.c
index 7cc46cd92..8108a6867 100644
--- a/src/text.c
+++ b/src/text.c
@@ -145,7 +145,7 @@ void DeactivateAllTextPrinters (void)
gTextPrinters[printer].sub_union.sub.active = 0;
}
-u16 PrintTextOnWindow(u8 windowId, u8 fontId, u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextSubPrinter *, u16))
+u16 PrintTextOnWindow(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextSubPrinter *, u16))
{
struct TextSubPrinter subPrinter;
diff --git a/src/tv.c b/src/tv.c
index 73b346068..7f64b46ac 100644
--- a/src/tv.c
+++ b/src/tv.c
@@ -2,7 +2,7 @@
// Includes
#include "global.h"
#include "rtc.h"
-#include "rom4.h"
+#include "overworld.h"
#include "map_constants.h"
#include "rng.h"
#include "event_data.h"
@@ -838,7 +838,7 @@ void UpdateTVScreensOnMap(int width, int height)
}
else if (FlagGet(SYS_TV_START) && (FindAnyTVShowOnTheAir() != 0xff || FindAnyTVNewsOnTheAir() != 0xff || IsTVShowInSearchOfTrainersAiring()))
{
- FlagReset(SYS_TV_WATCH);
+ FlagClear(SYS_TV_WATCH);
SetTVMetatilesOnMap(width, height, 0x3);
}
break;
@@ -1263,7 +1263,7 @@ void InterviewAfter_ContestLiveUpdates(void)
show2->contestLiveUpdates.kind = TVSHOW_CONTEST_LIVE_UPDATES;
show2->contestLiveUpdates.active = TRUE;
StringCopy(show2->contestLiveUpdates.playerName, gSaveBlock2Ptr->playerName);
- show2->contestLiveUpdates.category = gUnknown_02039F2C;
+ show2->contestLiveUpdates.category = gScriptContestCategory;
show2->contestLiveUpdates.species = GetMonData(&gPlayerParty[gUnknown_02039F24], MON_DATA_SPECIES, NULL);
show2->contestLiveUpdates.winningSpecies = show->contestLiveUpdates.winningSpecies;
show2->contestLiveUpdates.appealFlags2 = show->contestLiveUpdates.appealFlags2;
@@ -1527,7 +1527,7 @@ void BravoTrainerPokemonProfile_BeforeInterview2(u8 a0)
if (sCurTVShowSlot != -1)
{
show->bravoTrainer.contestResult = a0;
- show->bravoTrainer.contestCategory = gUnknown_02039F2C;
+ show->bravoTrainer.contestCategory = gScriptContestCategory;
show->bravoTrainer.contestRank = gUnknown_02039F2E;
show->bravoTrainer.species = GetMonData(&gPlayerParty[gUnknown_02039F24], MON_DATA_SPECIES, NULL);
GetMonData(&gPlayerParty[gUnknown_02039F24], MON_DATA_NICKNAME, show->bravoTrainer.pokemonNickname);
@@ -1675,7 +1675,7 @@ void InterviewAfter_FanClubLetter(void)
show->fanclubLetter.kind = TVSHOW_FAN_CLUB_LETTER;
show->fanclubLetter.active = TRUE;
StringCopy(show->fanclubLetter.playerName, gSaveBlock2Ptr->playerName);
- show->fanclubLetter.species = GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_SPECIES, NULL);
+ show->fanclubLetter.species = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL);
tv_store_id_2x(show);
show->fanclubLetter.language = gGameLanguage;
}
@@ -1700,21 +1700,21 @@ void InterviewAfter_PkmnFanClubOpinions(void)
show = &gSaveBlock1Ptr->tvShows[sCurTVShowSlot];
show->fanclubOpinions.kind = TVSHOW_PKMN_FAN_CLUB_OPINIONS;
show->fanclubOpinions.active = TRUE;
- show->fanclubOpinions.friendshipHighNybble = GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_FRIENDSHIP, NULL) >> 4;
+ show->fanclubOpinions.friendshipHighNybble = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_FRIENDSHIP, NULL) >> 4;
show->fanclubOpinions.questionAsked = gSpecialVar_0x8007;
StringCopy(show->fanclubOpinions.playerName, gSaveBlock2Ptr->playerName);
- GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_NICKNAME, show->fanclubOpinions.nickname);
+ GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_NICKNAME, show->fanclubOpinions.nickname);
StripExtCtrlCodes(show->fanclubOpinions.nickname);
- show->fanclubOpinions.species = GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_SPECIES, NULL);
+ show->fanclubOpinions.species = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL);
tv_store_id_2x(show);
show->fanclubOpinions.language = gGameLanguage;
- if (gGameLanguage == LANGUAGE_JAPANESE || GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_LANGUAGE) == LANGUAGE_JAPANESE)
+ if (gGameLanguage == LANGUAGE_JAPANESE || GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_LANGUAGE) == LANGUAGE_JAPANESE)
{
show->fanclubOpinions.pokemonNameLanguage = LANGUAGE_JAPANESE;
}
else
{
- show->fanclubOpinions.pokemonNameLanguage = GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_LANGUAGE);
+ show->fanclubOpinions.pokemonNameLanguage = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_LANGUAGE);
}
}
@@ -3073,7 +3073,7 @@ void TV_PrintIntToStringVar(u8 varIdx, int value)
ConvertIntToDecimalStringN(gTVStringVarPtrs[varIdx], value, STR_CONV_MODE_LEFT_ALIGN, nDigits);
}
-int sub_80EF370(int value)
+size_t sub_80EF370(int value)
{
if (value / 10 == 0)
{
@@ -3246,7 +3246,7 @@ void InterviewBefore_FanClubLetter(void)
FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_FAN_CLUB_LETTER);
if (!gScriptResult)
{
- StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_SPECIES, NULL)]);
+ StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL)]);
InitializeEasyChatWordArray(gSaveBlock1Ptr->tvShows[sCurTVShowSlot].fanclubLetter.words, 6);
}
}
@@ -3265,8 +3265,8 @@ void InterviewBefore_PkmnFanClubOpinions(void)
FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_PKMN_FAN_CLUB_OPINIONS);
if (!gScriptResult)
{
- StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_SPECIES, NULL)]);
- GetMonData(&gPlayerParty[GetIdxOfFirstPartyMemberThatIsNotAnEgg()], MON_DATA_NICKNAME, gStringVar2);
+ StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL)]);
+ GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_NICKNAME, gStringVar2);
StringGetEnd10(gStringVar2);
InitializeEasyChatWordArray(gSaveBlock1Ptr->tvShows[sCurTVShowSlot].fanclubOpinions.words, 2);
}
@@ -3336,7 +3336,7 @@ bool8 sub_80EF88C(u8 monIdx)
bool8 sub_80EF8F8(void)
{
- return sub_80EF88C(GetIdxOfFirstPartyMemberThatIsNotAnEgg());
+ return sub_80EF88C(GetLeadMonIndex());
}
void DeleteTVShowInArrayByIdx(TVShow *shows, u8 idx)
diff --git a/src/walda_phrase.c b/src/walda_phrase.c
new file mode 100644
index 000000000..7e06d1319
--- /dev/null
+++ b/src/walda_phrase.c
@@ -0,0 +1,257 @@
+#include "global.h"
+#include "walda_phrase.h"
+#include "string_util.h"
+#include "event_data.h"
+#include "naming_screen.h"
+#include "main.h"
+#include "text.h"
+#include "new_game.h"
+
+extern void (*gFieldCallback)(void);
+
+extern const u8 gText_Peekaboo[];
+
+extern u8 *GetWaldaPhrasePtr(void);
+extern bool32 IsWaldaPhraseEmpty(void);
+extern void sub_80AF168(void);
+extern void c2_exit_to_overworld_2_switch(void);
+extern void SetWaldaPhrase(const u8 *src);
+extern void SetWaldaWallpaperPatternId(u8 patternId);
+extern void SetWaldaWallpaperIconId(u8 iconId);
+extern void SetWaldaWallpaperColors(u16 backgroundColor, u16 foregroundColor);
+extern void SetWaldaWallpaperLockedOrUnlocked(bool32 unlocked);
+
+// this file's functions
+static void CB2_HandleGivenWaldaPhrase(void);
+static u32 GetWaldaPhraseInputCase(u8 *inputPtr);
+static bool32 TryCalculateWallpaper(u16* backgroundClr, u16 *foregroundClr, u8 *iconId, u8 *patternId, u16 trainerId, u8 *phrase);
+static void sub_81D9D5C(u8 *array, u8 *letterTableIds, u32 arg2, u32 arg3, u32 loopCount);
+static u32 sub_81D9DAC(u8 *array, u32 arg1, u32 loopCount);
+static void sub_81D9C90(u8 *array, s32 arg1, s32 arg2);
+static void sub_81D9CDC(u8 *array, u32 loopCount, u8 arg2);
+
+// only consonants are allowed, no vowels, some lowercase letters are missing
+static const u8 sWaldaLettersTable[] =
+{
+ CHAR_B, CHAR_C, CHAR_D, CHAR_F, CHAR_G, CHAR_H, CHAR_J, CHAR_K, CHAR_L, CHAR_M, CHAR_N, CHAR_P, CHAR_Q, CHAR_R, CHAR_S, CHAR_T, CHAR_V, CHAR_W, CHAR_Z,
+ CHAR_b, CHAR_c, CHAR_d, CHAR_f, CHAR_g, CHAR_h, CHAR_j, CHAR_k, CHAR_m, CHAR_n, CHAR_p, CHAR_q, CHAR_s
+};
+
+enum
+{
+ PHRASE_GIVEN_NEW,
+ PHRASE_NO_CHANGE,
+ PHRASE_FIRST_ATTEMPT
+};
+
+u16 TryBufferWaldaPhrase(void)
+{
+ if (IsWaldaPhraseEmpty())
+ return FALSE;
+
+ StringCopy(gStringVar1, GetWaldaPhrasePtr());
+ return TRUE;
+}
+
+void DoWaldaNamingScreen(void)
+{
+ StringCopy(gStringVar2, GetWaldaPhrasePtr());
+ DoNamingScreen(NAMING_SCREEN_WALDA, gStringVar2, 0, 0, 0, CB2_HandleGivenWaldaPhrase);
+}
+
+static void CB2_HandleGivenWaldaPhrase(void)
+{
+ gSpecialVar_0x8004 = GetWaldaPhraseInputCase(gStringVar2);
+
+ switch (gSpecialVar_0x8004)
+ {
+ case PHRASE_FIRST_ATTEMPT:
+ if (IsWaldaPhraseEmpty())
+ SetWaldaPhrase(gText_Peekaboo);
+ else
+ gSpecialVar_0x8004 = PHRASE_NO_CHANGE;
+ break;
+ case PHRASE_GIVEN_NEW:
+ SetWaldaPhrase(gStringVar2);
+ break;
+ case PHRASE_NO_CHANGE:
+ break;
+ }
+
+ StringCopy(gStringVar1, GetWaldaPhrasePtr());
+ gFieldCallback = sub_80AF168;
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+}
+
+static u32 GetWaldaPhraseInputCase(u8 *inputPtr)
+{
+ if (inputPtr[0] == EOS)
+ return PHRASE_FIRST_ATTEMPT;
+ if (StringCompare(inputPtr, GetWaldaPhrasePtr()) == 0)
+ return PHRASE_NO_CHANGE;
+
+ return PHRASE_GIVEN_NEW;
+}
+
+u16 TryGetWallpaperWithWaldaPhrase(void)
+{
+ u16 backgroundClr, foregroundClr;
+ u8 patternId, iconId;
+ u16 trainerId = ReadUnalignedWord(gSaveBlock2Ptr->playerTrainerId);
+ gScriptResult = TryCalculateWallpaper(&backgroundClr, &foregroundClr, &iconId, &patternId, trainerId, GetWaldaPhrasePtr());
+
+ if (gScriptResult)
+ {
+ SetWaldaWallpaperPatternId(patternId);
+ SetWaldaWallpaperIconId(iconId);
+ SetWaldaWallpaperColors(backgroundClr, foregroundClr);
+ }
+
+ SetWaldaWallpaperLockedOrUnlocked(gScriptResult);
+ return (bool8)(gScriptResult);
+}
+
+static u8 GetLetterTableId(u8 letter)
+{
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(sWaldaLettersTable); i++)
+ {
+ if (sWaldaLettersTable[i] == letter)
+ return i;
+ }
+
+ return ARRAY_COUNT(sWaldaLettersTable);
+}
+
+static bool32 TryCalculateWallpaper(u16* backgroundClr, u16 *foregroundClr, u8 *iconId, u8 *patternId, u16 trainerId, u8 *phrase)
+{
+ s32 i;
+ ALIGNED(2) u8 array[12];
+ u8 charsByTableId[16];
+ u16 *ptr;
+
+ if (StringLength(phrase) != 15)
+ return FALSE;
+
+ for (i = 0; i < 15; i++)
+ {
+ charsByTableId[i] = GetLetterTableId(phrase[i]);
+ if (charsByTableId[i] == ARRAY_COUNT(sWaldaLettersTable))
+ return FALSE;
+ }
+
+ for (i = 0; i < 14; i++)
+ {
+ sub_81D9D5C(array, charsByTableId, (5 * i), 3 + (8 * i), 5);
+ }
+
+ sub_81D9D5C(array, charsByTableId, 70, 115, 2);
+
+ if (sub_81D9DAC(array, 0, 3) != sub_81D9DAC(charsByTableId, 117, 3))
+ return FALSE;
+
+ sub_81D9C90(array, 9, 21);
+ sub_81D9C90(array, 8, array[8] & 0xF);
+ sub_81D9CDC(array, 8, array[8] >> 4);
+
+ if (array[6] != (array[0] ^ array[2] ^ array[4] ^ (trainerId >> 8)))
+ return FALSE;
+
+ if (array[7] != (array[1] ^ array[3] ^ array[5] ^ (trainerId & 0xFF)))
+ return FALSE;
+
+ ptr = (u16*)(&array[0]);
+ *backgroundClr = *ptr;
+
+ ptr = (u16*)(&array[2]);
+ *foregroundClr = *ptr;
+
+ *iconId = array[4];
+ *patternId = array[5];
+
+ return TRUE;
+}
+
+static void sub_81D9C90(u8 *array, s32 arg1, s32 arg2)
+{
+ s32 i, j;
+ u8 var1, var2;
+
+ for (i = arg2 - 1; i != -1; i--)
+ {
+ var1 = (array[0] & 0x80) >> 7;
+
+ var1++; var1--; // needed to match
+
+ for (j = arg1 - 1; j >= 0; j--)
+ {
+ var2 = array[j] & 0x80;
+ array[j] <<= 1;
+ array[j] |= var1;
+ var1 = var2 >> 7;
+ }
+ }
+}
+
+static void sub_81D9CDC(u8 *array, u32 loopCount, u8 arg2)
+{
+ u32 i;
+
+ arg2 |= (arg2 << 4);
+
+ for (i = 0; i < loopCount; i++)
+ {
+ array[i] ^= arg2;
+ }
+}
+
+static bool8 sub_81D9D0C(u8 *array, u32 arg1)
+{
+ u32 arrayId = arg1 >> 3;
+ u32 bits = 0x80 >> (7 & arg1);
+
+ return ((array[arrayId] & bits) != 0);
+}
+
+static void sub_81D9D28(u8 *array, u32 arg1)
+{
+ u32 arrayId = arg1 >> 3;
+ u8 bits = 0x80 >> (7 & arg1);
+
+ array[arrayId] |= bits;
+}
+
+static void sub_81D9D40(u8 *array, u32 arg1)
+{
+ u32 arrayId = arg1 >> 3;
+ u8 bits = ~(0x80 >> (7 & arg1));
+
+ array[arrayId] &= bits;
+}
+
+static void sub_81D9D5C(u8 *array, u8 *letterTableIds, u32 arg2, u32 arg3, u32 loopCount)
+{
+ u32 i;
+
+ for (i = 0; i < loopCount; i++)
+ {
+ if (sub_81D9D0C(letterTableIds, arg3 + i))
+ sub_81D9D28(array, arg2 + i);
+ else
+ sub_81D9D40(array, arg2 + i);
+ }
+}
+
+static u32 sub_81D9DAC(u8 *array, u32 arg1, u32 loopCount)
+{
+ u32 ret, i;
+
+ for (ret = 0, i = 0; i < loopCount; i++)
+ {
+ ret <<= 1;
+ ret |= sub_81D9D0C(array, arg1 + i);
+ }
+
+ return ret;
+}