summaryrefslogtreecommitdiff
path: root/src/battle_interface.c
diff options
context:
space:
mode:
authorDiegoisawesome <Diegoisawesome@users.noreply.github.com>2017-10-20 12:39:55 -0500
committerGitHub <noreply@github.com>2017-10-20 12:39:55 -0500
commit35a96cb0c007545ecc87732f8dc8b2eb93e3ecc2 (patch)
tree79174cee322cfcaac7dec1ac43f668fa747d99c3 /src/battle_interface.c
parentae5aa3c4dfd81fc25e5abeef1b915bb2da68b8d1 (diff)
parentccd7e8b3b1d942b2e1289611639f4e9a188cdc20 (diff)
Merge pull request #88 from DizzyEggg/decompile_battle_interface
decompile battle interface
Diffstat (limited to 'src/battle_interface.c')
-rw-r--r--src/battle_interface.c2632
1 files changed, 2632 insertions, 0 deletions
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);
+}