diff options
Diffstat (limited to 'src/field/party_menu.c')
-rw-r--r-- | src/field/party_menu.c | 4487 |
1 files changed, 4322 insertions, 165 deletions
diff --git a/src/field/party_menu.c b/src/field/party_menu.c index 39477e293..86ad9ecc9 100644 --- a/src/field/party_menu.c +++ b/src/field/party_menu.c @@ -3,20 +3,29 @@ #include "battle.h" #include "battle_interface.h" #include "battle_party_menu.h" +#include "choose_party.h" #include "data2.h" +#include "decompress.h" #include "event_data.h" +#include "evolution_scene.h" #include "item.h" #include "item_use.h" +#include "item_menu.h" +#include "items.h" #include "mail_data.h" #include "main.h" #include "menu.h" +#include "menu_helpers.h" +#include "moves.h" #include "palette.h" #include "pokemon.h" +#include "pokemon_icon.h" #include "pokemon_item_effect.h" #include "pokemon_menu.h" #include "pokemon_summary_screen.h" #include "rom_8077ABC.h" #include "rom_8094928.h" +#include "script_pokemon_80F9.h" #include "songs.h" #include "sound.h" #include "species.h" @@ -24,14 +33,435 @@ #include "string_util.h" #include "strings.h" #include "task.h" -#include "sprite.h" -#include "palette.h" -#include "event_data.h" -#include "main.h" -#include "item.h" -#include "battle_interface.h" -#include "species.h" -#include "party_menu.h" +#include "unknown_task.h" +#include "util.h" + +struct Coords8 +{ + u8 x; + u8 y; +}; + +struct PartyMenuWindowCoords +{ + u8 left; + u8 top; + u8 right; + u8 bottom; +}; + +struct PartyMonTextSettingsStruct +{ + u8 xOffset; + u8 yOffset; + const u16 *oamSettings; +}; + +struct PartyMenuHandlersStruct +{ + /*0x0*/TaskFunc menuHandler; + /*0x4*/bool8 (*menuSetup)(void); + /*0x8*/u8 initialPromptTextId; // element in PartyMenuPromptTexts +}; + +static void nullsub_12(u8 monIndex, struct Pokemon *pokemon); +static void TryPrintPartyMenuMonNickname(u8 monIndex, struct Pokemon *pokemon); +static void PartyMenuTryPrintHP(u8 monIndex, struct Pokemon *pokemon); +static void sub_806D05C(u8 taskId); +static void sub_806D15C(u8 taskId); +static void sub_806D198(u8 taskId); +static void sub_806E884(u8 taskId); +static void sub_8070D90(u8 taskId); +static void sub_806D5B8(u8 taskId); +static void sub_806D014(u8 taskId); +static void sub_806D118(u8 taskId); +static void CB2_InitPartyMenu(void); +static void ReDrawPartyMonBackgrounds(void); +static void sub_806BA94(s16 a, u16 b, u8 c, u8 d); +static void sub_806B9A4(s16 a, u16 b, u8 c); +static void sub_806CA18(u8 taskId, u8 b); +static void ChangeDoubleBattlePartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed); +static void ChangeDefaultPartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed); +static void ChangeLinkDoubleBattlePartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed); +static void UpdateMonIconFrame_806DA0C(struct Sprite *sprite); +static void UpdateMonIconFrame_806DA38(struct Sprite *sprite); +static void UpdateMonIconFrame_806DA44(u8 taskId, u8 monIndex, u8 c); +static u8 sub_806CA00(u8 taskId); +static void SpriteCB_sub_806D37C(struct Sprite *sprite); +static u8 GetMonIconSpriteId(u8 taskId, u8 monIndex); +static void SpriteCB_UpdateHeldItemIconPosition(struct Sprite *sprite); +static void ItemUseMoveMenu_HandleMoveSelection(u8 taskId); +static void ItemUseMoveMenu_HandleCancel(u8 taskId); +static bool8 SetupDefaultPartyMenu(void); +static void sub_806B4A8(void); +static void VBlankCB_PartyMenu(void); +static bool8 LoadPartyMenuGraphics(u8 a); +static void sub_806BF24(const u8 *a, u8 monIndex, u8 c, u8 d); +static void sub_806BB9C(u8 a); +static void sub_806BBEC(u8 a); + +const u16 TMHMMoves[] = { + MOVE_FOCUS_PUNCH, + MOVE_DRAGON_CLAW, + MOVE_WATER_PULSE, + MOVE_CALM_MIND, + MOVE_ROAR, + MOVE_TOXIC, + MOVE_HAIL, + MOVE_BULK_UP, + MOVE_BULLET_SEED, + MOVE_HIDDEN_POWER, + MOVE_SUNNY_DAY, + MOVE_TAUNT, + MOVE_ICE_BEAM, + MOVE_BLIZZARD, + MOVE_HYPER_BEAM, + MOVE_LIGHT_SCREEN, + MOVE_PROTECT, + MOVE_RAIN_DANCE, + MOVE_GIGA_DRAIN, + MOVE_SAFEGUARD, + MOVE_FRUSTRATION, + MOVE_SOLAR_BEAM, + MOVE_IRON_TAIL, + MOVE_THUNDERBOLT, + MOVE_THUNDER, + MOVE_EARTHQUAKE, + MOVE_RETURN, + MOVE_DIG, + MOVE_PSYCHIC, + MOVE_SHADOW_BALL, + MOVE_BRICK_BREAK, + MOVE_DOUBLE_TEAM, + MOVE_REFLECT, + MOVE_SHOCK_WAVE, + MOVE_FLAMETHROWER, + MOVE_SLUDGE_BOMB, + MOVE_SANDSTORM, + MOVE_FIRE_BLAST, + MOVE_ROCK_TOMB, + MOVE_AERIAL_ACE, + MOVE_TORMENT, + MOVE_FACADE, + MOVE_SECRET_POWER, + MOVE_REST, + MOVE_ATTRACT, + MOVE_THIEF, + MOVE_STEEL_WING, + MOVE_SKILL_SWAP, + MOVE_SNATCH, + MOVE_OVERHEAT, + MOVE_CUT, + MOVE_FLY, + MOVE_SURF, + MOVE_STRENGTH, + MOVE_FLASH, + MOVE_ROCK_SMASH, + MOVE_WATERFALL, + MOVE_DIVE, +}; + +//FIXME +//const u8 *unrefTileBuffer = gTileBuffer; +asm(".4byte gTileBuffer\n"); + +static const u8 MenuGfx_HoldIcons[] = INCBIN_U8("graphics/interface/hold_icons.4bpp"); +static const u16 MenuPal_HoldIcons[] = INCBIN_U16("graphics/interface/hold_icons.gbapal"); + +static const struct SpriteSheet HeldItemsSpriteSheet = { + MenuGfx_HoldIcons, + sizeof MenuGfx_HoldIcons, + 0xd750 +}; + +static const struct SpritePalette HeldItemsPalette = { + MenuPal_HoldIcons, + 0xd750 +}; + +static const struct OamData gOamData_83765EC = +{ + .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 union AnimCmd gSpriteAnim_83765F4[] = { + ANIMCMD_FRAME(0, 1), + ANIMCMD_END +}; + +static const union AnimCmd gSpriteAnim_83765FC[] = { + ANIMCMD_FRAME(1, 1), + ANIMCMD_END +}; + +static const union AnimCmd *const gSpriteAnimTable_8376604[] = { + gSpriteAnim_83765F4, + gSpriteAnim_83765FC, +}; + +static const struct SpriteTemplate gSpriteTemplate_837660C = { + 55120, + 55120, + &gOamData_83765EC, + gSpriteAnimTable_8376604, + NULL, + gDummySpriteAffineAnimTable, + SpriteCB_UpdateHeldItemIconPosition +}; + +// Texts that can be displayed in the bottom of the party menu. +static const u8 *const PartyMenuPromptTexts[] = { + OtherText_ChoosePoke, + OtherText_MovePokeTo, + OtherText_TeachWhat, + OtherText_UseWhat, + OtherText_GiveWhat, + OtherText_DoWhat, + OtherText_NothingToCut, + OtherText_CantSurf, + OtherText_AlreadySurfing, + OtherText_CantUseThatHere, + OtherText_RestoreWhatMove, + OtherText_BoostPP, + gOtherText_CancelWithTerminator, + OtherText_DoWhatWithItem, + OtherText_NoPokeForBattle, + OtherText_ChoosePoke2, + OtherText_NotEnoughHP, + OtherText_ThreePokeNeeded, + OtherText_PokeCantBeSame, + OtherText_NoIdenticalHoldItems, + OtherText_TeachWhichPoke, +}; + +static const struct Coords8 gUnknown_08376678[8][6] = { + {{16, 40}, {104, 18}, {104, 42}, {104, 66}, {104, 90}, {104, 114}}, // PARTY_MENU_TYPE_STANDARD + {{16, 24}, { 16, 80}, {104, 18}, {104, 50}, {104, 82}, {104, 114}}, // PARTY_MENU_TYPE_BATTLE + {{16, 24}, { 16, 80}, {104, 26}, {104, 50}, {104, 82}, {104, 106}}, // PARTY_MENU_TYPE_CONTEST + {{16, 24}, {104, 26}, {104, 50}, { 16, 80}, {104, 82}, {104, 106}}, // PARTY_MENU_TYPE_IN_GAME_TRADE + {{ 5, 4}, { 16, 1}, { 16, 4}, { 16, 7}, { 16, 10}, { 16, 13}}, // PARTY_MENU_TYPE_BATTLE_TOWER + {{ 5, 2}, { 5, 9}, { 16, 1}, { 16, 5}, { 16, 9}, { 16, 13}}, // PARTY_MENU_TYPE_LINK_MULTI_BATTLE + {{ 5, 2}, { 5, 9}, { 16, 2}, { 16, 5}, { 16, 9}, { 16, 12}}, // PARTY_MENU_TYPE_DAYCARE + {{ 5, 2}, { 16, 2}, { 16, 5}, { 5, 9}, { 16, 9}, { 16, 12}}, // PARTY_MENU_TYPE_MOVE_TUTOR +}; + +static const struct Coords8 gUnknown_08376738[12][6] = { + {{6, 5}, {17, 2}, {17, 5}, {17, 8}, {17, 11}, {17, 14}}, + {{6, 3}, { 6, 10}, {17, 2}, {17, 6}, {17, 10}, {17, 14}}, + {{6, 3}, { 6, 10}, {17, 3}, {17, 6}, {17, 10}, {17, 13}}, + {{6, 3}, {17, 3}, {17, 6}, { 6, 10}, {17, 10}, {17, 13}}, + {{3, 7}, {22, 2}, {22, 5}, {22, 8}, {22, 11}, {22, 14}}, + {{3, 5}, { 3, 12}, {22, 2}, {22, 6}, {22, 10}, {22, 14}}, + {{3, 5}, { 3, 12}, {22, 3}, {22, 6}, {22, 10}, {22, 13}}, + {{3, 5}, {22, 3}, {22, 6}, { 3, 12}, {22, 10}, {22, 13}}, + {{7, 7}, {26, 2}, {26, 5}, {26, 8}, {26, 11}, {26, 14}}, + {{7, 5}, { 7, 12}, {26, 2}, {26, 6}, {26, 10}, {26, 14}}, + {{7, 5}, { 7, 12}, {26, 3}, {26, 6}, {26, 10}, {26, 13}}, + {{7, 5}, {26, 3}, {26, 6}, { 7, 12}, {26, 10}, {26, 13}}, +}; + +static u16 *const gUnknown_08376858[4][6] = { + {(u16*)(BG_VRAM + 0xF1C8), (u16*)(BG_VRAM + 0xF0AE), (u16*)(BG_VRAM + 0xF16E), (u16*)(BG_VRAM + 0xF22E), (u16*)(BG_VRAM + 0xF2EE), (u16*)(BG_VRAM + 0xF3AE)}, // PARTY_MENU_STANDARD + {(u16*)(BG_VRAM + 0xF148), (u16*)(BG_VRAM + 0xF308), (u16*)(BG_VRAM + 0xF0AE), (u16*)(BG_VRAM + 0xF1AE), (u16*)(BG_VRAM + 0xF2AE), (u16*)(BG_VRAM + 0xF3AE)}, // PARTY_MENU_LAYOUT_DOUBLE_BATTLE + {(u16*)(BG_VRAM + 0xF148), (u16*)(BG_VRAM + 0xF308), (u16*)(BG_VRAM + 0xF0EE), (u16*)(BG_VRAM + 0xF1AE), (u16*)(BG_VRAM + 0xF2AE), (u16*)(BG_VRAM + 0xF36E)}, // PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE + {(u16*)(BG_VRAM + 0xF148), (u16*)(BG_VRAM + 0xF0EE), (u16*)(BG_VRAM + 0xF1AE), (u16*)(BG_VRAM + 0xF308), (u16*)(BG_VRAM + 0xF2AE), (u16*)(BG_VRAM + 0xF36E)}, // PARTY_MENU_LAYOUT_MULTI_BATTLE +}; + +static const struct Coords8 gUnknown_083768B8[3][8] = { + {{8, 44}, {92, 22}, {92, 46}, {92, 70}, {92, 94}, {92, 118}, {196, 136}, {196, 152}}, // PARTY_MENU_LAYOUT_STANDARD + {{8, 28}, { 8, 84}, {92, 22}, {92, 54}, {92, 86}, {92, 118}, {196, 136}, {196, 152}}, // PARTY_MENU_LAYOUT_DOUBLE_BATTLE + {{8, 28}, { 8, 84}, {92, 30}, {92, 54}, {92, 86}, {92, 110}, {196, 136}, {196, 152}}, // PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE +}; + +static u16 *const gUnknown_08376918[2][PARTY_SIZE] = { + {(u16*)(BG_VRAM + 0xF1C6), (u16*)(BG_VRAM + 0xF06C), (u16*)(BG_VRAM + 0xF12C), (u16*)(BG_VRAM + 0xF1EC), (u16*)(BG_VRAM + 0xF2AC), (u16*)(BG_VRAM + 0xF36C)}, + {(u16*)(BG_VRAM + 0xF148), (u16*)(BG_VRAM + 0xF308), (u16*)(BG_VRAM + 0xF0AE), (u16*)(BG_VRAM + 0xF1AE), (u16*)(BG_VRAM + 0xF2AE), (u16*)(BG_VRAM + 0xF3AE)}, +}; + +static const struct PartyMenuWindowCoords gUnknown_08376948[2][6] = { + {{2, 4, 10, 9}, {16, 1, 29, 3}, {16, 4, 29, 6}, {16, 7, 29, 9}, {16, 10, 29, 12}, {16, 13, 29, 15}}, + {{2, 2, 10, 7}, { 2, 9, 10, 14}, {16, 1, 29, 3}, {16, 5, 29, 7}, {16, 9, 29, 11}, {16, 13, 29, 15}}, +}; + +static const struct PartyMenuWindowCoords gUnknown_08376978[2][6] = { + {{2, 7, 10, 9}, {21, 1, 29, 3}, {21, 4, 29, 6}, {21, 7, 29, 9}, {21, 10, 29, 12}, {21, 13, 29, 15}}, + {{2, 2, 10, 7}, { 2, 9, 10, 14}, {16, 1, 29, 3}, {16, 5, 29, 7}, {16, 9, 29, 11}, {16, 13, 29, 15}}, +}; + +// This is actually a 2x6x2 array, but the code reads it as a flat array. +static const u8 gUnknown_083769A8[] = { + 0, 3, 11, 1, 11, 4, 11, 7, 11, 10, 11, 13, + 0, 1, 0, 8, 11, 1, 11, 5, 11, 9, 11, 13, // Double battle +}; + +// This is actually a 2x6x2 array, but the code reads it as a flat array. +//FIXME: sub_806B908() accesses this data via gUnknown_083769A8 (directly above this). This means these +// two arrays might be a struct, rather than separate arrays. +static const u8 gUnknown_083769C0[] = { + 0, 1, 0, 8, 11, 2, 11, 5, 11, 9, 11, 12, + 0, 1, 0, 8, 11, 2, 11, 5, 11, 9, 11, 12, // Double battle +}; + +static const u8 gUnknown_083769D8[] = { + 0x24,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x27, + 0x34,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x37, + 0x34,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x37, + 0x34,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x37, + 0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x47, + 0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x47, + 0x54,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x57, +}; + +static const u8 gUnknown_08376A25[] = { + 0x50,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x53, + 0x60,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x63, + 0x70,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x73, +}; + +static const u8 gUnknown_08376A5E[] = { + 0x20,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x23, + 0x30,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x33, + 0x40,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x43, +}; + +static const u8 gUnusedData_08376A97[] = { + 0x0C,0x0D,0x0E,0x0F,0x00,0x01,0x02,0x03,0x04,0x05,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x0F,0x06,0x05,0x01,0x07, + 0x08,0x09,0x0F,0x16,0x15,0x11,0x17,0x18,0x19,0x0F,0x09, + 0x0A,0x0B,0x05,0x0C,0x0F,0x0F,0x19,0x1A,0x1B,0x15,0x1C, + 0x0F,0x0F,0x0D,0x0B,0x05,0x0C,0x0F,0x0F,0x0F,0x1D,0x1B, + 0x15,0x1C,0x0F,0x0F,0x0F,0x06,0x05,0x0B,0x05,0x0C,0x0F, + 0x0F,0x16,0x15,0x1B,0x15,0x1C,0x0F,0x0F,0x0F,0x0F,0x20, + 0x0C,0x09,0x0F,0x0F,0x0F,0x1F,0x30,0x1C,0x19,0x0F,0x0F, + 0x0F,0x25,0x0F,0x22,0x24,0x0F,0x0F,0x0F,0x35,0x41,0x32, + 0x34,0x0F,0x0F,0x0F,0x26,0x0F,0x23,0x0E,0x0F,0x0F,0x0F, + 0x36,0x43,0x33,0x1E,0x0F,0x0F,0x27,0x28,0x29,0x03,0x2A, + 0x0F,0x0F,0x37,0x38,0x39,0x13,0x3A,0x0F,0x0F,0x27,0x28, + 0x29,0x03,0x04,0x05,0x0F,0x37,0x38,0x39,0x13,0x14,0x15, + 0x0F,0x2B,0x2C,0x02,0x28,0x29,0x2D,0x21,0x3B,0x3C,0x12, + 0x38,0x39,0x3D,0x31,0x2B,0x2C,0x02,0x28,0x29,0x08,0x09, + 0x3B,0x3C,0x12,0x38,0x39,0x18,0x19,0x2E,0x2F,0x2B,0x2C, + 0x02,0x27,0x2D,0x3E,0x3F,0x3B,0x3C,0x12,0x45,0x3D, +}; + +static const TaskFunc gUnknown_08376B54[] = { + ItemUseMoveMenu_HandleMoveSelection, + ItemUseMoveMenu_HandleCancel, +}; + +#define PartyMonOAMSettings(x, y, palette, shape, size, priority, tileOffset) \ + ((shape) << 14) | (y), \ + ((size) << 14) | (x), \ + ((palette) << 12) | ((priority) << 10) | (tileOffset) + +static const u16 PartyMonOAMSettings_LeftColumn[] = { + PartyMonOAMSettings(24, 0, 15, ST_OAM_H_RECTANGLE, 1, 1, 0), + PartyMonOAMSettings(56, 0, 15, ST_OAM_H_RECTANGLE, 1, 1, 4), + PartyMonOAMSettings(24, 8, 15, ST_OAM_H_RECTANGLE, 1, 1, 8), + PartyMonOAMSettings(56, 8, 15, ST_OAM_H_RECTANGLE, 1, 1, 12), + PartyMonOAMSettings(32, 16, 15, ST_OAM_H_RECTANGLE, 1, 1, 16), + PartyMonOAMSettings(37, 32, 15, ST_OAM_H_RECTANGLE, 1, 1, 24), + PartyMonOAMSettings(69, 32, 15, ST_OAM_H_RECTANGLE, 1, 1, 28), + 0xFFFF, +}; + +static const u16 PartyMonOAMSettings_RightColumn[] = { + PartyMonOAMSettings( 24, 0, 15, ST_OAM_H_RECTANGLE, 1, 1, 0), + PartyMonOAMSettings( 56, 0, 15, ST_OAM_H_RECTANGLE, 1, 1, 4), + PartyMonOAMSettings( 24, 8, 15, ST_OAM_H_RECTANGLE, 1, 1, 8), + PartyMonOAMSettings( 56, 8, 15, ST_OAM_H_RECTANGLE, 1, 1, 12), + PartyMonOAMSettings( 32, 16, 15, ST_OAM_H_RECTANGLE, 1, 1, 16), + PartyMonOAMSettings(101, 16, 15, ST_OAM_H_RECTANGLE, 1, 1, 24), + PartyMonOAMSettings(133, 16, 15, ST_OAM_H_RECTANGLE, 1, 1, 28), + 0xFFFF, +}; + +// Controls where and how the mons' text appears in the party menu screen (nickname, HP, and level). +static struct PartyMonTextSettingsStruct const PartyMonTextSettings[4][6] = { + { // PARTY_MENU_LAYOUT_STANDARD + { 1, 4, PartyMonOAMSettings_LeftColumn}, + {12, 1, PartyMonOAMSettings_RightColumn}, + {12, 4, PartyMonOAMSettings_RightColumn}, + {12, 7, PartyMonOAMSettings_RightColumn}, + {12, 10, PartyMonOAMSettings_RightColumn}, + {12, 13, PartyMonOAMSettings_RightColumn}, + }, + { // PARTY_MENU_LAYOUT_DOUBLE_BATTLE + { 1, 2, PartyMonOAMSettings_LeftColumn}, + { 1, 9, PartyMonOAMSettings_LeftColumn}, + {12, 1, PartyMonOAMSettings_RightColumn}, + {12, 5, PartyMonOAMSettings_RightColumn}, + {12, 9, PartyMonOAMSettings_RightColumn}, + {12, 13, PartyMonOAMSettings_RightColumn}, + }, + { // PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE + { 1, 2, PartyMonOAMSettings_LeftColumn}, + { 1, 9, PartyMonOAMSettings_LeftColumn}, + {12, 2, PartyMonOAMSettings_RightColumn}, + {12, 5, PartyMonOAMSettings_RightColumn}, + {12, 9, PartyMonOAMSettings_RightColumn}, + {12, 12, PartyMonOAMSettings_RightColumn}, + }, + { // PARTY_MENU_LAYOUT_MULTI_BATTLE + { 1, 2, PartyMonOAMSettings_LeftColumn}, + {12, 2, PartyMonOAMSettings_RightColumn}, + {12, 5, PartyMonOAMSettings_RightColumn}, + { 1, 9, PartyMonOAMSettings_LeftColumn}, + {12, 9, PartyMonOAMSettings_RightColumn}, + {12, 12, PartyMonOAMSettings_RightColumn}, + }, +}; + +static const struct PartyMenuHandlersStruct PartyMenuHandlers[] = { + {HandleDefaultPartyMenu, SetupDefaultPartyMenu, 0}, // PARTY_MENU_TYPE_STANDARD + {HandleBattlePartyMenu, SetUpBattlePartyMenu, 0}, // PARTY_MENU_TYPE_BATTLE + {HandleSelectPartyMenu, SetupContestPartyMenu, 0}, // PARTY_MENU_TYPE_CONTEST + {HandleSelectPartyMenu, SetupDefaultPartyMenu, 0}, // PARTY_MENU_TYPE_IN_GAME_TRADE + {HandleBattleTowerPartyMenu, SetupBattleTowerPartyMenu, 0}, // PARTY_MENU_TYPE_BATTLE_TOWER + {HandleLinkMultiBattlePartyMenu, SetupLinkMultiBattlePartyMenu, 0xFF}, // PARTY_MENU_TYPE_LINK_MULTI_BATTLE + {HandleDaycarePartyMenu, SetupDefaultPartyMenu, 0x0F}, // PARTY_MENU_TYPE_DAYCARE + {HandleMoveTutorPartyMenu, SetupMoveTutorPartyMenu, 0}, // PARTY_MENU_TYPE_MOVE_TUTOR +}; + +static const u16 gUnknown_08376CD4[] = { + 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, +}; + +static const u16 gUnknown_08376CEC[] = { + 0x2A, 0x0B, 0x0C, 0x0D, 0x0E, 0x2F, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, +}; + +static const u8 *const StatNames[] = { + gOtherText_HP, + gOtherText_Attack, + gOtherText_Defense, + gOtherText_SpAtk, + gOtherText_SpDef, + gOtherText_Speed, +}; + +static const u8 StatDataTypes[] = { + MON_DATA_MAX_HP, + MON_DATA_ATK, + MON_DATA_DEF, + MON_DATA_SPATK, + MON_DATA_SPDEF, + MON_DATA_SPD, +}; struct Unk201C000 { @@ -46,65 +476,3352 @@ struct Unk201C000 /*0x14*/ TaskFunc unk14; }; -struct Unk201F000 +struct Unk201FE00 { - u8 filler0[0xE00]; - u8 unkE00[3]; // not sure if this is an array or struct, or how big it is -}; - -struct UnknownStruct5 -{ - u8 unk0; - u8 unk1; - u16 *unk4; + u8 unkE00; // not sure if this is an array or struct, or how big it is + u8 unkE01; + u8 unkE02; }; #define ewram1C000 (*(struct Unk201C000 *)(ewram + 0x1C000)) -#define ewram1F000 (*(struct Unk201F000 *)(ewram + 0x1F000)) +#define ewram1FE00 (*(struct Unk201FE00 *)(ewram + 0x1FE00)) +extern u16 gBattleTypeFlags; +extern u8 gTileBuffer[]; extern u8 gUnknown_0202E8F4; extern u8 gUnknown_0202E8F6; extern u16 gUnknown_0202E8F8; -extern u8 gUnknown_0202E8FA; +extern u8 gPartyMenuType; extern u8 gLastFieldPokeMenuOpened; extern u8 gPlayerPartyCount; extern s32 gBattleMoveDamage; +extern u16 gMoveToLearn; -//extern const u16 gUnknown_083769A8[][6]; -//extern const u8 gUnknown_083769A8[][12]; -extern void *const gUnknown_08376858[][6]; -extern const u8 gUnknown_083769A8[]; -extern const u8 gUnknown_08376D1C[DATA_COUNT]; -extern const u16 gUnknown_08376504[]; -extern void (*const gUnknown_08376B54[])(u8); -extern const u8 *const gUnknown_08376D04[DATA_COUNT]; -extern const struct UnknownStruct5 gUnknown_08376BB4[][6]; +extern u16 gUnknown_08E9A300[]; +extern struct Coords8 const gUnknown_08376738[12][6]; +extern const u8 gUnknown_083769C0[]; +extern u8 gUnknown_02039460[]; +extern struct Window gUnknown_03004210; + +extern const u8 gPartyMenuMisc_Gfx[]; +extern const u8 gPartyMenuMisc_Tilemap[]; +extern const u8 gPartyMenuMisc_Pal[]; +extern const u8 gFontDefaultPalette[]; +extern const u8 gPartyMenuHpBar_Gfx[]; +extern const u8 gPartyMenuOrderText_Gfx[]; +extern const u8 gStatusGfx_Icons[]; +extern const u8 gStatusPal_Icons[]; + +#if ENGLISH +#define WINDOW_LEFT (3) +#define WINDOW_RIGHT (26) +#elif GERMAN +#define WINDOW_LEFT (0) +#define WINDOW_RIGHT (29) +#endif -static void sub_806E884(u8 taskId); -/* -void sub_806AEDC(void) +#ifdef NONMATCHING +// Main handler for the party menu. +void CB2_PartyMenuMain(void) { - const struct UnknownStruct5 *r5; + const struct PartyMonTextSettingsStruct *textSettings; s32 i; AnimateSprites(); BuildOamBuffer(); - r5 = gUnknown_08376BB4[gUnknown_0202E8FA]; - for (i = 0; i < 6; i++) - sub_800142C(r5[i].unk0 * 8, r5[i].unk1 * 8, r5[i].unk4, 0, (i << 5) | 0x200); + + textSettings = PartyMonTextSettings[gPartyMenuType]; + for (i = 0; i < PARTY_SIZE; i++) + { + // Draw mon name, level, and hp sprites + DrawPartyMenuMonText( + textSettings[i].xOffset * 8, + textSettings[i].yOffset * 8, + textSettings[i].oamSettings, + 0, + (i << 5) | 0x200); + } + RunTasks(); UpdatePaletteFade(); } -*/ +#else +__attribute__((naked)) +void CB2_PartyMenuMain(void) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + sub sp, 0x4\n\ + bl AnimateSprites\n\ + bl BuildOamBuffer\n\ + ldr r0, _0806AF2C @ =gPartyMenuType\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 4\n\ + ldr r1, _0806AF30 @ =PartyMonTextSettings\n\ + adds r5, r0, r1\n\ + movs r6, 0\n\ +_0806AEF8:\n\ + ldrb r0, [r5]\n\ + lsls r0, 3\n\ + ldrb r1, [r5, 0x1]\n\ + lsls r1, 3\n\ + ldr r2, [r5, 0x4]\n\ + lsls r3, r6, 5\n\ + movs r4, 0x80\n\ + lsls r4, 2\n\ + orrs r3, r4\n\ + str r3, [sp]\n\ + movs r3, 0\n\ + bl DrawPartyMenuMonText\n\ + adds r5, 0x8\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + ble _0806AEF8\n\ + bl RunTasks\n\ + bl UpdatePaletteFade\n\ + add sp, 0x4\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806AF2C: .4byte gPartyMenuType\n\ +_0806AF30: .4byte PartyMonTextSettings\n\ + .syntax divided\n"); +} +#endif // NONMATCHING -#if ENGLISH -#define WINDOW_LEFT (3) -#define WINDOW_RIGHT (26) -#elif GERMAN -#define WINDOW_LEFT (0) -#define WINDOW_RIGHT (29) -#endif +void VBlankCB_PartyMenu(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + ReDrawPartyMonBackgrounds(); +} + +void SetPartyMenuSettings(u8 menuType, u8 battleTypeFlags, TaskFunc menuHandlerFunc, u8 textId) +{ + if (battleTypeFlags != 0xFF) + { + gBattleTypeFlags = battleTypeFlags; + } + + ewram1B000.menuType = menuType; + ewram1B000.menuHandler = menuHandlerFunc; + ewram1B000.promptTextId = textId; +} + +void DoOpenPartyMenu(u8 menuType, u8 battleFlags, TaskFunc menuHandlerFunc, u8 textId) +{ + SetPartyMenuSettings(menuType, battleFlags, menuHandlerFunc, textId); + SetMainCallback2(CB2_InitPartyMenu); +} + +void OpenPartyMenu(u8 menuType, u8 battleFlags) +{ + DoOpenPartyMenu(menuType, battleFlags, PartyMenuHandlers[menuType].menuHandler, PartyMenuHandlers[menuType].initialPromptTextId); +} + +// This is a Task which is repeatedly called until it eventually returns TRUE when finished. +bool8 SetupDefaultPartyMenu(void) +{ + switch (ewram1B000_alt.setupState) + { + case 0: + if (ewram1B000_alt.monIndex < gPlayerPartyCount) { + TryCreatePartyMenuMonIcon(ewram1B000_alt.menuHandlerTaskId, ewram1B000_alt.monIndex, &gPlayerParty[ewram1B000_alt.monIndex]); + ewram1B000_alt.monIndex++; + } else { + ewram1B000_alt.monIndex = 0; + ewram1B000_alt.setupState++; + } + + break; + case 1: + LoadHeldItemIconGraphics(); + ewram1B000_alt.setupState++; + break; + case 2: + CreateHeldItemIcons_806DC34(ewram1B000_alt.menuHandlerTaskId); + ewram1B000_alt.setupState++; + break; + case 3: + if (sub_806BD58(ewram1B000_alt.menuHandlerTaskId, ewram1B000_alt.monIndex) != 1) + { + ewram1B000_alt.monIndex++; + } + else + { + ewram1B000_alt.monIndex = 0; + ewram1B000_alt.setupState++; + } + + break; + case 4: + PartyMenuPrintMonsLevelOrStatus(); + ewram1B000_alt.setupState++; + break; + case 5: + PrintPartyMenuMonNicknames(); + ewram1B000_alt.setupState++; + break; + case 6: + PartyMenuTryPrintMonsHP(); + ewram1B000_alt.setupState++; + break; + case 7: + nullsub_13(); + ewram1B000_alt.setupState++; + break; + case 8: + PartyMenuDrawHPBars(); + ewram1B000_alt.setupState++; + break; + case 9: + if (DrawPartyMonBackground(ewram1B000_alt.monIndex) == 1) + { + ewram1B000_alt.monIndex = 0; + ewram1B000_alt.setupState = 0; + return TRUE; + } + else + { + ewram1B000_alt.monIndex++; + break; + } + } + + return FALSE; +} + +bool8 InitPartyMenu(void) +{ + u8 *addr; + u32 size; + + switch (gMain.state) + { + case 0: + SetVBlankCallback(NULL); + addr = (u8 *)VRAM; + size = VRAM_SIZE; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); + + gPaletteFade.bufferTransferDisabled = 1; + gMain.state++; + break; + case 1: + remove_some_task(); + gMain.state++; + break; + case 2: + sub_806B4A8(); + ewram1B000_alt.setupState = 0; + ewram1B000_alt.monIndex = 0; + ewram1B000_alt.unk268 = 0; + gMain.state++; + break; + case 3: + ResetSpriteData(); + gMain.state++; + break; + case 4: + if (ewram1B000.menuType != PARTY_MENU_TYPE_BATTLE && ewram1B000.menuType != PARTY_MENU_TYPE_LINK_MULTI_BATTLE) + { + ResetTasks(); + } + + gMain.state++; + break; + case 5: + FreeAllSpritePalettes(); + gMain.state++; + break; + case 6: + ewram1B000.menuHandlerTaskId = CreateTask(ewram1B000.menuHandler, 0); + gMain.state++; + break; + case 7: + SetUpWindowConfig(&gWindowConfig_81E6C90); + gMain.state++; + break; + case 8: + InitWindowFromConfig(&gUnknown_03004210, &gWindowConfig_81E6C90); + MultistepInitWindowTileData(&gUnknown_03004210, 1); + gMain.state++; + break; + case 9: + if (MultistepLoadFont()) + { + ewram1B000_alt.setupState = 1; + gMain.state++; + } + break; + case 10: + if (LoadPartyMenuGraphics(ewram1B000_alt.setupState) == TRUE) + { + ewram1B000_alt.setupState = 0; + gMain.state++; + } + else + { + ewram1B000_alt.setupState++; + } + break; + case 11: + sub_809D51C(); + gMain.state++; + break; + case 12: + if (PartyMenuHandlers[ewram1B000.menuType].menuSetup() == TRUE) + { + gMain.state++; + } + break; + case 13: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6CC8); + gMain.state++; + break; + case 14: + if (MultistepInitMenuWindowContinue()) + { + gMain.state++; + } + break; + case 15: + PrintPartyMenuPromptText(ewram1B000.promptTextId, 0); + gMain.state++; + break; + case 16: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0); + gPaletteFade.bufferTransferDisabled = 0; + gMain.state++; + break; + case 17: + SetVBlankCallback(VBlankCB_PartyMenu); + return TRUE; + } + + return FALSE; +} + +void CB2_InitPartyMenu(void) +{ + while (InitPartyMenu() != TRUE) + { + if (sub_80F9344() == TRUE) + { + return; + } + } + + if (ewram1B000.menuType != PARTY_MENU_TYPE_LINK_MULTI_BATTLE) + { + ChangePartyMenuSelection(ewram1B000.menuHandlerTaskId, 0); + } + + SetMainCallback2(CB2_PartyMenuMain); +} + +void sub_806B4A8(void) +{ + SetHBlankCallback(NULL); + REG_DISPCNT = 8000; + REG_BG0CNT = 0x1E05; + REG_BG1CNT = 0x703; + REG_BG2CNT = 0xF08; + REG_BG3CNT = 0x602; + REG_BLDCNT = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BG3VOFS = -1; +} + +bool8 IsLinkDoubleBattle() +{ + if ((gBattleTypeFlags & BATTLE_TYPE_LINK_DOUBLE) == BATTLE_TYPE_LINK_DOUBLE) + return TRUE; + else + return FALSE; +} + +// Draws the blue rectangular regions surrounding each of the party mons. +void ReDrawPartyMonBackgrounds(void) +{ + if (ewram1B000.unk261) + { + const void *src = gBGTilemapBuffers[2]; + void *dest = (void *)(BG_VRAM + 0x3000); + DmaCopy16(3, src, dest, 0x800); + + if (ewram1B000.unk261 == 2) + { + ewram1B000.unk261 = 0; + } + } +} + +bool8 DrawPartyMonBackground(u8 monIndex) +{ + const u8 *arr; + + if (!IsDoubleBattle()) + gPartyMenuType = PARTY_MENU_LAYOUT_STANDARD; + else if (IsLinkDoubleBattle() == TRUE) + gPartyMenuType = PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE; + else + gPartyMenuType = PARTY_MENU_LAYOUT_DOUBLE_BATTLE; + + arr = &gUnknown_083769A8[gPartyMenuType * 12]; + + switch (monIndex) + { + case 0: + memset(&gBGTilemapBuffers[2], 0, 0x800); + break; + case 1: + sub_806B9A4(arr[0], arr[1], 3); + sub_806BF24(&arr[0], 0, 3, 0); + break; + case 2: + if (!IsDoubleBattle()) { + if (gPlayerPartyCount > 1) { + sub_806BA94(arr[2], arr[3], 0, 3); + sub_806BF24(&arr[2], 1, 3, 0); + } else { + sub_806BA94(arr[2], arr[3], 1, 3); + } + } else if (IsLinkDoubleBattle() == TRUE) { + sub_806B9A4(arr[2], arr[3], 4); + sub_806BF24(&arr[2], 1, 4, 0); + } else { + sub_806B9A4(arr[2], arr[3], 3); + sub_806BF24(&arr[2], 1, 3, 0); + } + + break; + case 3: + if (!IsDoubleBattle()) { + if (gPlayerPartyCount > 2) { + sub_806BA94(arr[4], arr[5], 0, 3); + sub_806BF24(&arr[4], 2, 3, 0); + } else { + sub_806BA94(arr[4], arr[5], 1, 3); + } + } else if (IsLinkDoubleBattle() == TRUE) { + if (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES)) { + sub_806BA94(arr[4], arr[5], 0, 3); + sub_806BF24(&arr[4], 2, 3, 0); + } else { + sub_806BA94(arr[4], arr[5], 1, 3); + } + } else if (gPlayerPartyCount > 2) { + sub_806BA94(arr[4], arr[5], 0, 3); + sub_806BF24(&arr[4], 2, 3, 0); + } else { + sub_806BA94(arr[4], arr[5], 1, 3); + } + + break; + case 4: + if (!IsDoubleBattle()) { + if (gPlayerPartyCount > 3) { + sub_806BA94(arr[6], arr[7], 0, 3); + sub_806BF24(&arr[6], 3, 3, 0); + } else { + sub_806BA94(arr[6], arr[7], 1, 3); + } + } else if (IsLinkDoubleBattle() == TRUE) { + if (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES)) { + sub_806BA94(arr[6], arr[7], 0, 3); + sub_806BF24(&arr[6], 3, 3, 0); + } else { + sub_806BA94(arr[6], arr[7], 1, 3); + } + } else if (gPlayerPartyCount > 3) { + sub_806BA94(arr[6], arr[7], 0, 3); + sub_806BF24(&arr[6], 3, 3, 0); + } else { + sub_806BA94(arr[6], arr[7], 1, 3); + } + + break; + case 5: + if (!IsDoubleBattle()) { + if (gPlayerPartyCount > 4) { + sub_806BA94(arr[8], arr[9], 0, 3); + sub_806BF24(&arr[8], 4, 3, 0); + } else { + sub_806BA94(arr[8], arr[9], 1, 3); + } + } else if (IsLinkDoubleBattle() == TRUE) { + if (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES)) { + sub_806BA94(arr[8], arr[9], 0, 4); + sub_806BF24(&arr[8], 4, 4, 0); + } else { + sub_806BA94(arr[8], arr[9], 1, 4); + } + } else if (gPlayerPartyCount > 4) { + sub_806BA94(arr[8], arr[9], 0, 3); + sub_806BF24(&arr[8], 4, 3, 0); + } else { + sub_806BA94(arr[8], arr[9], 1, 3); + } + + break; + case 6: + if (!IsDoubleBattle()) { + if (gPlayerPartyCount > 5) { + sub_806BA94(arr[10], arr[11], 0, 3); + sub_806BF24(&arr[10], 5, 3, 0); + } else { + sub_806BA94(arr[10], arr[11], 1, 3); + } + } else if (IsLinkDoubleBattle() == TRUE) { + if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES)) { + sub_806BA94(arr[10], arr[11], 0, 4); + sub_806BF24(&arr[10], 5, 4, 0); + } else { + sub_806BA94(arr[10], arr[11], 1, 4); + } + } else if (gPlayerPartyCount > 5) { + sub_806BA94(arr[10], arr[11], 0, 3); + sub_806BF24(&arr[10], 5, 3, 0); + } else { + sub_806BA94(arr[10], arr[11], 1, 3); + } + + break; + case 7: + if (ewram1B000.menuType == PARTY_MENU_TYPE_BATTLE_TOWER) { + sub_806BB9C(1); + } + + sub_806BBEC(1); + break; + case 8: + ewram1B000.unk261 = 2; + return TRUE; + } + + return FALSE; +} + +#ifdef NONMATCHING +void sub_806B908(void) +{ + memset(&gBGTilemapBuffers[2], 0, 0x800); + gPartyMenuType = PARTY_MENU_LAYOUT_MULTI_BATTLE; + sub_806B9A4(gUnknown_083769C0[12], gUnknown_083769C0[13], 3); + + if (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES)) + sub_806BA94(gUnknown_083769C0[16], gUnknown_083769C0[17], 0, 3); + else + sub_806BA94(gUnknown_083769C0[16], gUnknown_083769C0[17], 1, 3); + + if (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES)) + sub_806BA94(gUnknown_083769C0[18], gUnknown_083769C0[19], 0, 3); + else + sub_806BA94(gUnknown_083769C0[18], gUnknown_083769C0[19], 1, 3); + + ewram1B000.unk261 = 2; +} +#else +__attribute__((naked)) +void sub_806B908(void) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + ldr r0, _0806B948 @ =gBGTilemapBuffers + 0x1000\n\ + movs r2, 0x80\n\ + lsls r2, 4\n\ + movs r1, 0\n\ + bl memset\n\ + ldr r1, _0806B94C @ =gPartyMenuType\n\ + movs r0, 0x3\n\ + strb r0, [r1]\n\ + ldr r0, _0806B950 @ =gUnknown_083769A8\n\ + adds r4, r0, 0\n\ + adds r4, 0x24\n\ + ldr r5, _0806B954 @ =gPlayerParty + 1 * 0x64\n\ + ldrb r0, [r4]\n\ + ldrb r1, [r4, 0x1]\n\ + movs r2, 0x3\n\ + bl sub_806B9A4\n\ + adds r0, r5, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806B958\n\ + ldrb r0, [r4, 0x4]\n\ + ldrb r1, [r4, 0x5]\n\ + movs r2, 0\n\ + movs r3, 0x3\n\ + bl sub_806BA94\n\ + b _0806B964\n\ + .align 2, 0\n\ +_0806B948: .4byte gBGTilemapBuffers + 0x1000\n\ +_0806B94C: .4byte gPartyMenuType\n\ +_0806B950: .4byte gUnknown_083769A8\n\ +_0806B954: .4byte gPlayerParty + 1 * 0x64\n\ +_0806B958:\n\ + ldrb r0, [r4, 0x4]\n\ + ldrb r1, [r4, 0x5]\n\ + movs r2, 0x1\n\ + movs r3, 0x3\n\ + bl sub_806BA94\n\ +_0806B964:\n\ + adds r0, r5, 0\n\ + adds r0, 0x64\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806B980\n\ + ldrb r0, [r4, 0x6]\n\ + ldrb r1, [r4, 0x7]\n\ + movs r2, 0\n\ + movs r3, 0x3\n\ + bl sub_806BA94\n\ + b _0806B98C\n\ +_0806B980:\n\ + ldrb r0, [r4, 0x6]\n\ + ldrb r1, [r4, 0x7]\n\ + movs r2, 0x1\n\ + movs r3, 0x3\n\ + bl sub_806BA94\n\ +_0806B98C:\n\ + ldr r0, _0806B99C @ =0x0201b000\n\ + ldr r1, _0806B9A0 @ =0x00000261\n\ + adds r0, r1\n\ + movs r1, 0x2\n\ + strb r1, [r0]\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806B99C: .4byte 0x0201b000\n\ +_0806B9A0: .4byte 0x00000261\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void sub_806B9A4(s16 a, u16 b, u8 c) +{ + u8 i; + u16 var1 = b * 32; + + for (i = 0; i <= 6; i++) + { + u8 j = 0; + + if (a <= 0x1F) + { + for (; j <= 10 && a + j <= 0x1F; j++) + { + if (a + j >= 0) + { + gBGTilemapBuffers[2][var1 + (i * 32) + (a + j)] = (c << 12) | gUnknown_083769D8[i * 11 + j]; + } + } + } + } +} + +void sub_806BA34(s16 a, u16 b) +{ + u8 i; + u16 var1 = b * 32; + + for (i = 0; i <= 6; i++) + { + u8 j = 0; + + if (a <= 0x1F) + { + for (; j <= 10 && a + j <= 0x1F; j++) + { + if (a + j >= 0) + { + gBGTilemapBuffers[2][var1 + (i * 32) + (a + j)] = 0; + } + } + } + } +} + +void sub_806BA94(s16 a, u16 b, u8 c, u8 d) +{ + u8 i; + const u8 *arr; + u16 var1; + + arr = gUnknown_08376A5E; + if (c == 0) + { + arr = gUnknown_08376A25; + } + + var1 = b * 32; + + + for (i = 0; i < 3; i++) + { + u8 j = 0; + + if (a <= 0x1F) + { + while (j <= 0x12 && a + j <= 0x1F) + { + if (a + j >= 0) + { + gBGTilemapBuffers[2][var1 + (i * 32) + (a + j)] = (d << 12) | arr[i * 19 + j]; + } + + j++; + } + } + } +} + +void sub_806BB3C(s16 a, u16 b) +{ + u8 i; + u16 var1 = (b * 32); + + for (i = 0; i < 3; i++) + { + u8 j = 0; + + if (a <= 0x1F) + { + for (; j <= 0x12 && a + j <= 0x1F; j++) + { + if (a + j >= 0) + { + gBGTilemapBuffers[2][var1 + (i * 32) + (a + j)] = 0; + } + } + } + } +} + +void sub_806BB9C(u8 a) +{ + u8 i; + u16 *vramPtr; + const u16 arr[12]; + + memcpy(&arr, gUnknown_08376CD4, sizeof gUnknown_08376CD4); + + vramPtr = (u16 *)(BG_VRAM + 0x3C30); + for (i = 0; i < PARTY_SIZE; i++) + { + vramPtr[i] = arr[i] + (a << 12); + vramPtr[i + 0x20] = arr[i + PARTY_SIZE] + (a << 12); + } +} + +void sub_806BBEC(u8 a) +{ + u8 i; + u16 *vramPtr; + const u16 arr[12]; + + memcpy(&arr, gUnknown_08376CEC, sizeof gUnknown_08376CEC); + + vramPtr = (u16 *)(BG_VRAM + 0x3CB0); + for (i = 0; i < PARTY_SIZE; i++) + { + vramPtr[i] = arr[i] + (a << 12); + vramPtr[i + 0x20] = arr[i + PARTY_SIZE] + (a << 12); + } +} + +#ifdef NONMATCHING +// The original THUMB is preserving r8 for seemingly no reason. Unsure how to match. +void sub_806BC3C(u8 monIndex, u8 b) +{ + u16 *vramPtr = gUnknown_08376918[IsDoubleBattle()][monIndex]; + u8 i; + u16 var1; + + for (i = 0, var1 = (b / 7) * 32; i <= PARTY_SIZE; i++) + { + u32 offset = i + var1; + vramPtr[i] = gUnknown_08E9A300[offset] + 0x10C; + vramPtr[i + 0x20] = gUnknown_08E9A300[offset + 0x20] + 0x10C; + } +} +#else +__attribute__((naked)) +void sub_806BC3C(u8 monIndex, u8 b) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + adds r4, r0, 0\n\ + adds r5, r1, 0\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + lsls r5, 24\n\ + lsrs r5, 24\n\ + ldr r6, _0806BCB0 @ =gUnknown_08376918\n\ + bl IsDoubleBattle\n\ + lsls r4, 2\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, r0, 1\n\ + adds r1, r0\n\ + lsls r1, 3\n\ + adds r4, r1\n\ + adds r4, r6\n\ + ldr r7, [r4]\n\ + movs r6, 0\n\ + adds r0, r5, 0\n\ + movs r1, 0x7\n\ + bl __udivsi3\n\ + lsls r0, 24\n\ + lsrs r4, r0, 19\n\ + ldr r5, _0806BCB4 @ =gUnknown_08E9A300\n\ + movs r0, 0x86\n\ + lsls r0, 1\n\ + adds r3, r0, 0\n\ +_0806BC7C:\n\ + adds r1, r6, r4\n\ + lsls r2, r6, 1\n\ + adds r2, r7\n\ + lsls r0, r1, 1\n\ + adds r0, r5\n\ + ldrh r0, [r0]\n\ + adds r0, r3, r0\n\ + strh r0, [r2]\n\ + adds r2, 0x40\n\ + adds r1, 0x20\n\ + lsls r1, 1\n\ + adds r1, r5\n\ + ldrh r1, [r1]\n\ + adds r0, r3, r1\n\ + strh r0, [r2]\n\ + adds r0, r6, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + cmp r6, 0x6\n\ + bls _0806BC7C\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806BCB0: .4byte gUnknown_08376918\n\ +_0806BCB4: .4byte gUnknown_08E9A300\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void unref_sub_806BCB8(u8 a) +{ + u8 i; + + for (i = 0; i < gPlayerPartyCount; i++) + { + sub_806BC3C(i, a); + } +} + +// This is ultimately unreferenced, since it's caller is unreferenced. +void sub_806BCE8() +{ + u8 i; + + for (i = 0; i < gPlayerPartyCount; i++) + { + if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + u8 gender = GetMonGender(&gPlayerParty[i]); + switch (gender) + { + case MON_MALE: + sub_806BC3C(i, 0x54); + break; + case MON_FEMALE: + sub_806BC3C(i, 0x62); + break; + default: + sub_806BC3C(i, 0x46); + break; + } + } + else + { + sub_806BC3C(i, 0x46); + } + } +} + +u8 sub_806BD58(u8 taskId, u8 b) +{ + u8 spriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy); + sub_806CA18(taskId, spriteId); + return 1; +} + +#ifdef NONMATCHING +u16 HandleDefaultPartyMenuInput(u8 taskId) +{ + s8 menuDirectionPressed = 0x0; + + switch (gMain.newAndRepeatedKeys) + { + case DPAD_UP: + menuDirectionPressed = -1; + break; + case DPAD_DOWN: + menuDirectionPressed = 1; + break; + case DPAD_LEFT: + menuDirectionPressed = -2; + break; + case DPAD_RIGHT: + menuDirectionPressed = 2; + break; + } + + if (menuDirectionPressed == 0) + { + u8 var1 = sub_80F92BC(); + switch (var1) + { + case 1: + menuDirectionPressed = -1; + break; + case 2: + menuDirectionPressed = 1; + break; + } + + if (menuDirectionPressed == 0) + { + if ((gMain.newKeys & A_BUTTON) && gSprites[sub_806CA00(taskId)].data0 == 7) + { + // Selected "CANCEL" + return B_BUTTON; + } + else + { + return gMain.newKeys & (A_BUTTON | B_BUTTON); + } + } + } + + ChangePartyMenuSelection(taskId, menuDirectionPressed); + return gMain.newAndRepeatedKeys; +} +#else +__attribute__((naked)) +u16 HandleDefaultPartyMenuInput(u8 taskId) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r4, 0\n\ + ldr r0, _0806BD9C @ =gMain\n\ + ldrh r0, [r0, 0x30]\n\ + cmp r0, 0x20\n\ + beq _0806BDB2\n\ + cmp r0, 0x20\n\ + bgt _0806BDA0\n\ + cmp r0, 0x10\n\ + beq _0806BDB6\n\ + b _0806BDB8\n\ + .align 2, 0\n\ +_0806BD9C: .4byte gMain\n\ +_0806BDA0:\n\ + cmp r0, 0x40\n\ + beq _0806BDAA\n\ + cmp r0, 0x80\n\ + beq _0806BDAE\n\ + b _0806BDB8\n\ +_0806BDAA:\n\ + movs r4, 0xFF\n\ + b _0806BDB8\n\ +_0806BDAE:\n\ + movs r4, 0x1\n\ + b _0806BDB8\n\ +_0806BDB2:\n\ + movs r4, 0xFE\n\ + b _0806BDB8\n\ +_0806BDB6:\n\ + movs r4, 0x2\n\ +_0806BDB8:\n\ + lsls r0, r4, 24\n\ + cmp r0, 0\n\ + bne _0806BDDC\n\ + bl sub_80F92BC\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + beq _0806BDD0\n\ + cmp r0, 0x2\n\ + beq _0806BDD4\n\ + b _0806BDD6\n\ +_0806BDD0:\n\ + movs r4, 0xFF\n\ + b _0806BDD6\n\ +_0806BDD4:\n\ + movs r4, 0x1\n\ +_0806BDD6:\n\ + lsls r0, r4, 24\n\ + cmp r0, 0\n\ + beq _0806BDF0\n\ +_0806BDDC:\n\ + asrs r1, r0, 24\n\ + adds r0, r5, 0\n\ + bl ChangePartyMenuSelection\n\ + ldr r0, _0806BDEC @ =gMain\n\ + ldrh r0, [r0, 0x30]\n\ + b _0806BE2C\n\ + .align 2, 0\n\ +_0806BDEC: .4byte gMain\n\ +_0806BDF0:\n\ + ldr r0, _0806BE1C @ =gMain\n\ + ldrh r1, [r0, 0x2E]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0806BE24\n\ + ldr r4, _0806BE20 @ =gSprites\n\ + adds r0, r5, 0\n\ + bl sub_806CA00\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, r0, 4\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r4\n\ + movs r2, 0x2E\n\ + ldrsh r0, [r1, r2]\n\ + cmp r0, 0x7\n\ + bne _0806BE24\n\ + movs r0, 0x2\n\ + b _0806BE2C\n\ + .align 2, 0\n\ +_0806BE1C: .4byte gMain\n\ +_0806BE20: .4byte gSprites\n\ +_0806BE24:\n\ + ldr r0, _0806BE34 @ =gMain\n\ + ldrh r1, [r0, 0x2E]\n\ + movs r0, 0x3\n\ + ands r0, r1\n\ +_0806BE2C:\n\ + pop {r4,r5}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_0806BE34: .4byte gMain\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +u16 HandleBattleTowerPartyMenuInput(u8 taskId) +{ + u8 menuDirectionPressed = 0x0; + + switch (gMain.newAndRepeatedKeys) + { + case DPAD_UP: + menuDirectionPressed = 0xFF; + break; + case DPAD_DOWN: + menuDirectionPressed = 0x1; + break; + case DPAD_LEFT: + menuDirectionPressed = 0xFE; + break; + case DPAD_RIGHT: + menuDirectionPressed = 0x2; + break; + } + + if (menuDirectionPressed == 0) + { + u8 var1 = sub_80F92BC(); + switch (var1) + { + case 1: + menuDirectionPressed = 0xFF; + break; + case 2: + menuDirectionPressed = 0x1; + break; + } + } + + if (gMain.newKeys & START_BUTTON) + { + SelectBattleTowerOKButton(taskId); + return START_BUTTON; + } + else + { + s8 signedMenuDirection = menuDirectionPressed; + if (signedMenuDirection) + { + ChangeBattleTowerPartyMenuSelection(taskId, signedMenuDirection); + return gMain.newAndRepeatedKeys; + } + else + { + if (gMain.newKeys & A_BUTTON) + { + if (gSprites[sub_806CA00(taskId)].data0 == 7) + { + return B_BUTTON; + } + } + } + } + + return gMain.newKeys & (A_BUTTON | B_BUTTON); +} + +void task_pc_turn_off(const u8 *a, u8 b) +{ + if (a[0]) + sub_806BA94(a[0], a[1], 0, b); + else + sub_806B9A4(a[0], a[1], b); +} + +void sub_806BF24(const u8 *a, u8 monIndex, u8 c, u8 d) +{ + if (GetMonData(&gPlayerParty[monIndex], MON_DATA_SPECIES) && GetMonData(&gPlayerParty[monIndex], MON_DATA_HP) == 0) + c = PARTY_SIZE - 1; + + if (d == 1) + c += 4; + + task_pc_turn_off(a, c); +} + +void ChangePartyMenuSelection(u8 taskId, s8 directionPressed) +{ + bool8 isLinkDoubleBattle; + u8 spriteId = sub_806CA00(taskId); + u8 menuIndex = gSprites[spriteId].data0; + + UpdateMonIconFrame_806DA44(taskId, menuIndex, 0); + + isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == 1) + { + if (menuIndex == 0 || menuIndex == 2 || menuIndex == 3) + sub_806BF24(&gUnknown_083769C0[menuIndex * 2], menuIndex, 3, 0); + if (menuIndex == 1 || menuIndex == 4 || menuIndex == 5) + sub_806BF24(&gUnknown_083769C0[menuIndex * 2], menuIndex, 4, 0); + if (menuIndex == 7) + sub_806BBEC(1); + + ChangeLinkDoubleBattlePartyMenuSelection(spriteId, menuIndex, directionPressed); + + if (gSprites[spriteId].data0 == 0 || gSprites[spriteId].data0 == 2 || gSprites[spriteId].data0 == 3) + sub_806BF24(&gUnknown_083769C0[gSprites[spriteId].data0 * 2], gSprites[spriteId].data0, 3, 1); + if (gSprites[spriteId].data0 == 1 || gSprites[spriteId].data0 == 4 || gSprites[spriteId].data0 == 5) + sub_806BF24(&gUnknown_083769C0[gSprites[spriteId].data0 * 2], gSprites[spriteId].data0, 4, 1); + if (gSprites[spriteId].data0 == 7) + sub_806BBEC(2); + + ewram1B000.unk261 = 2; + + gSprites[spriteId].pos1.x = gUnknown_083768B8[PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE][gSprites[spriteId].data0].x; + gSprites[spriteId].pos1.y = gUnknown_083768B8[PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE][gSprites[spriteId].data0].y; + } + else + { + u8 isDoubleBattle = IsDoubleBattle(); + + if (menuIndex < PARTY_SIZE) + { + sub_806BF24(&gUnknown_083769A8[isDoubleBattle * 12 + menuIndex * 2], menuIndex, 3, 0); + } + else + { + sub_806BBEC(1); + } + + if (!isDoubleBattle) + { + ChangeDefaultPartyMenuSelection(spriteId, menuIndex, directionPressed); + } + else + { + ChangeDoubleBattlePartyMenuSelection(spriteId, menuIndex, directionPressed); + } + + if (gSprites[spriteId].data0 < PARTY_SIZE) + { + sub_806BF24(&gUnknown_083769A8[isDoubleBattle * 12 + gSprites[spriteId].data0 * 2], gSprites[spriteId].data0, 3, 1); + } + else + { + sub_806BBEC(2); + } + + ewram1B000.unk261 = 2; + + gSprites[spriteId].pos1.x = gUnknown_083768B8[isDoubleBattle][gSprites[spriteId].data0].x; + gSprites[spriteId].pos1.y = gUnknown_083768B8[isDoubleBattle][gSprites[spriteId].data0].y; + } + + UpdateMonIconFrame_806DA44(taskId, gSprites[spriteId].data0, 1); + + if (menuIndex != gSprites[spriteId].data0) + { + PlaySE(5); + } +} + +void ChangeDefaultPartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed) +{ + u8 nextIndex; + s8 menuMovement = directionPressed + 2; + + switch (menuMovement) + { + case 2: // no movement + gSprites[spriteId].data1 = 0; + break; + case 1: // moving up + if (menuIndex == 0) { + gSprites[spriteId].data0 = 7; + } else if (menuIndex == 7) { + gSprites[spriteId].data0 = gPlayerPartyCount - 1; + } else { + s8 diff = directionPressed; + gSprites[spriteId].data0 += diff; + } + + gSprites[spriteId].data1 = 0; + break; + case 3: // moving down + if (menuIndex == gPlayerPartyCount - 1) { + gSprites[spriteId].data0 = 7; + } else if (menuIndex == 7) { + gSprites[spriteId].data0 = 0; + } else { + s8 diff = directionPressed; + gSprites[spriteId].data0 += diff; + } + + gSprites[spriteId].data1 = 0; + break; + case 4: // moving right + if (gPlayerPartyCount > 1 && menuIndex == 0) + { + if (gSprites[spriteId].data1 == 0) + gSprites[spriteId].data1 = 1; + + gSprites[spriteId].data0 = gSprites[spriteId].data1; + } + break; + case 0: // moving left + // Only move the selection to the left side if one of the mons in the right-hand column are currently selected + nextIndex = menuIndex - 1; + if (nextIndex <= 4) { + gSprites[spriteId].data0 = 0; + gSprites[spriteId].data1 = menuIndex; + } + break; + } +} + +void ChangeDoubleBattlePartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed) +{ + u8 var1; + s8 menuMovement = directionPressed + 2; + + switch(menuMovement) + { + case 2: // no movement + gSprites[spriteId].data1 = 0; + break; + case 3: // moving down + if (menuIndex == 7) { + gSprites[spriteId].data0 = 0; + } else if (menuIndex == gPlayerPartyCount - 1) { + gSprites[spriteId].data0 = 7; + } else { + s8 diff = directionPressed; + gSprites[spriteId].data0 += diff; + } + + gSprites[spriteId].data1 = 0; + break; + case 1: // moving up + if (menuIndex == 0) { + gSprites[spriteId].data0 = 7; + } else if (menuIndex == 7) { + gSprites[spriteId].data0 = gPlayerPartyCount - 1; + } else { + s8 diff = directionPressed; + gSprites[spriteId].data0 += diff; + } + + gSprites[spriteId].data1 = 0; + break; + case 4: // moving right + if (menuIndex == 0) { + if (gPlayerPartyCount > 2) { + u16 var1 = gSprites[spriteId].data1 - 2; + if (var1 > 1) + gSprites[spriteId].data0 = 2; + else + gSprites[spriteId].data0 = gSprites[spriteId].data1; + } + } + else if (menuIndex == 1) { + if (gPlayerPartyCount > 4) { + u16 var1 = gSprites[spriteId].data1 - 4; + if (var1 <= 1) + gSprites[spriteId].data0 = gSprites[spriteId].data1; + else + gSprites[spriteId].data0 = 4; + } + } + break; + case 0: // moving left + var1 = menuIndex - 2; + if (var1 <= 1) { + gSprites[spriteId].data0 = 0; + gSprites[spriteId].data1 = menuIndex; + } else { + u8 var2 = menuIndex - 4; + if (var2 <= 1) { + gSprites[spriteId].data0 = 1; + gSprites[spriteId].data1 = menuIndex; + } + } + break; + } +} + +#ifdef NONMATCHING +void ChangeLinkDoubleBattlePartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed) +{ + s8 menuMovement; + u16 var1; + u8 var2; + + menuMovement = directionPressed + 2; + switch (menuMovement) + { + case 2: // no movement + gSprites[spriteId].data1 = 0; + break; + case 3: // moving down + if (menuIndex == 7) { + gSprites[spriteId].data0 = 0; + } else { + while (menuIndex != PARTY_SIZE - 1) { + menuIndex++; + if (GetMonData(&gPlayerParty[menuIndex], MON_DATA_SPECIES)) + { + gSprites[spriteId].data0 = menuIndex; + gSprites[spriteId].data1 = 0; + return; + } + } + + gSprites[spriteId].data0 = 7; + } + + gSprites[spriteId].data1 = 0; + break; + case 1: // moving up + while (menuIndex != 0) { + menuIndex--; + if (menuIndex != PARTY_SIZE && GetMonData(gPlayerParty[menuIndex], MON_DATA_SPECIES)) + { + gSprites[spriteId].data0 = menuIndex; + gSprites[spriteId].data1 = 0; + return; + } + } + + gSprites[spriteId].data0 = 7; + gSprites[spriteId].data1 = 0; + break; + case 4: // moving right + if (menuIndex == 0) { + var1 = gSprites[spriteId].data1 - 2; + if (var1 > 1) { + if (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES)) { + gSprites[spriteId].data0 = 2; + } else if (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES)) { + gSprites[spriteId].data0 = 3; + } + } else { + gSprites[spriteId].data0 = 1; + } + } else if (menuIndex == 1) { + var1 = gSprites[spriteId].data1 - 4; + if (var1 <= 1) { + gSprites[spriteId].data0 = gSprites[spriteId].data1; + } else { + if (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES)) { + gSprites[spriteId].data0 = 4; + } else if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES)) { + gSprites[spriteId].data0 = 5; + } + } + } + break; + case 0: // moving left + var2 = menuIndex - 2; + if (var2 <= 1) { + gSprites[spriteId].data0 = 0; + gSprites[spriteId].data1 = menuIndex; + } else { + var2 = menuIndex - 4; + if (var2 <= 1) { + gSprites[spriteId].data0 = 1; + gSprites[spriteId].data1 = menuIndex; + } + } + + break; + } +} + +#else +__attribute__((naked)) +void ChangeLinkDoubleBattlePartyMenuSelection(u8 spriteId, u8 menuIndex, s8 directionPressed) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + lsls r1, 24\n\ + lsrs r4, r1, 24\n\ + lsls r2, 24\n\ + movs r0, 0x80\n\ + lsls r0, 18\n\ + adds r2, r0\n\ + asrs r0, r2, 24\n\ + cmp r0, 0x4\n\ + bls _0806C4AA\n\ + b _0806C64E\n\ +_0806C4AA:\n\ + lsls r0, 2\n\ + ldr r1, _0806C4B4 @ =_0806C4B8\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_0806C4B4: .4byte _0806C4B8\n\ + .align 2, 0\n\ +_0806C4B8:\n\ + .4byte _0806C618\n\ + .4byte _0806C524\n\ + .4byte _0806C4CC\n\ + .4byte _0806C4E0\n\ + .4byte _0806C57C\n\ +_0806C4CC:\n\ + ldr r0, _0806C4DC @ =gSprites\n\ + lsls r1, r5, 4\n\ + adds r1, r5\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + movs r0, 0\n\ + strh r0, [r1, 0x30]\n\ + b _0806C64E\n\ + .align 2, 0\n\ +_0806C4DC: .4byte gSprites\n\ +_0806C4E0:\n\ + cmp r4, 0x7\n\ + bne _0806C4FC\n\ + ldr r2, _0806C4F8 @ =gSprites\n\ + lsls r3, r5, 4\n\ + adds r0, r3, r5\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + movs r1, 0\n\ + strh r1, [r0, 0x2E]\n\ + adds r1, r2, 0\n\ + adds r6, r3, 0\n\ + b _0806C566\n\ + .align 2, 0\n\ +_0806C4F8: .4byte gSprites\n\ +_0806C4FC:\n\ + lsls r6, r5, 4\n\ + b _0806C518\n\ +_0806C500:\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + movs r0, 0x64\n\ + muls r0, r4\n\ + ldr r1, _0806C520 @ =gPlayerParty\n\ + adds r0, r1\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _0806C528\n\ +_0806C518:\n\ + cmp r4, 0x5\n\ + bne _0806C500\n\ + b _0806C558\n\ + .align 2, 0\n\ +_0806C520: .4byte gPlayerParty\n\ +_0806C524:\n\ + lsls r6, r5, 4\n\ + b _0806C554\n\ +_0806C528:\n\ + ldr r1, _0806C534 @ =gSprites\n\ + adds r0, r6, r5\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + strh r4, [r0, 0x2E]\n\ + b _0806C566\n\ + .align 2, 0\n\ +_0806C534: .4byte gSprites\n\ +_0806C538:\n\ + subs r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0x6\n\ + beq _0806C554\n\ + movs r0, 0x64\n\ + muls r0, r4\n\ + ldr r1, _0806C574 @ =gPlayerParty\n\ + adds r0, r1\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _0806C528\n\ +_0806C554:\n\ + cmp r4, 0\n\ + bne _0806C538\n\ +_0806C558:\n\ + ldr r0, _0806C578 @ =gSprites\n\ + adds r1, r6, r5\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + movs r2, 0x7\n\ + strh r2, [r1, 0x2E]\n\ + adds r1, r0, 0\n\ +_0806C566:\n\ + adds r0, r6, r5\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + movs r1, 0\n\ + strh r1, [r0, 0x30]\n\ + b _0806C64E\n\ + .align 2, 0\n\ +_0806C574: .4byte gPlayerParty\n\ +_0806C578: .4byte gSprites\n\ +_0806C57C:\n\ + cmp r4, 0\n\ + bne _0806C5C8\n\ + ldr r0, _0806C5AC @ =gSprites\n\ + lsls r1, r5, 4\n\ + adds r1, r5\n\ + lsls r1, 2\n\ + adds r4, r1, r0\n\ + ldrh r1, [r4, 0x30]\n\ + subs r0, r1, 0x2\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0x1\n\ + bls _0806C5E2\n\ + ldr r5, _0806C5B0 @ =gPlayerParty + 2 * 0x64\n\ + adds r0, r5, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806C5B4\n\ + movs r0, 0x2\n\ + strh r0, [r4, 0x2E]\n\ + b _0806C64E\n\ + .align 2, 0\n\ +_0806C5AC: .4byte gSprites\n\ +_0806C5B0: .4byte gPlayerParty + 2 * 0x64\n\ +_0806C5B4:\n\ + adds r0, r5, 0\n\ + adds r0, 0x64\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806C64E\n\ + movs r0, 0x3\n\ + strh r0, [r4, 0x2E]\n\ + b _0806C64E\n\ +_0806C5C8:\n\ + cmp r4, 0x1\n\ + bne _0806C64E\n\ + ldr r0, _0806C5E8 @ =gSprites\n\ + lsls r1, r5, 4\n\ + adds r1, r5\n\ + lsls r1, 2\n\ + adds r4, r1, r0\n\ + ldrh r1, [r4, 0x30]\n\ + subs r0, r1, 0x4\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0x1\n\ + bhi _0806C5EC\n\ +_0806C5E2:\n\ + strh r1, [r4, 0x2E]\n\ + b _0806C64E\n\ + .align 2, 0\n\ +_0806C5E8: .4byte gSprites\n\ +_0806C5EC:\n\ + ldr r5, _0806C600 @ =gPlayerParty + 4 * 0x64\n\ + adds r0, r5, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806C604\n\ + movs r0, 0x4\n\ + strh r0, [r4, 0x2E]\n\ + b _0806C64E\n\ + .align 2, 0\n\ +_0806C600: .4byte gPlayerParty + 4 * 0x64\n\ +_0806C604:\n\ + adds r0, r5, 0\n\ + adds r0, 0x64\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0806C64E\n\ + movs r0, 0x5\n\ + strh r0, [r4, 0x2E]\n\ + b _0806C64E\n\ +_0806C618:\n\ + subs r0, r4, 0x2\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bhi _0806C634\n\ + ldr r0, _0806C630 @ =gSprites\n\ + lsls r1, r5, 4\n\ + adds r1, r5\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + movs r0, 0\n\ + b _0806C64A\n\ + .align 2, 0\n\ +_0806C630: .4byte gSprites\n\ +_0806C634:\n\ + subs r0, r4, 0x4\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bhi _0806C64E\n\ + ldr r0, _0806C654 @ =gSprites\n\ + lsls r1, r5, 4\n\ + adds r1, r5\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + movs r0, 0x1\n\ +_0806C64A:\n\ + strh r0, [r1, 0x2E]\n\ + strh r4, [r1, 0x30]\n\ +_0806C64E:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806C654: .4byte gSprites\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void ChangeBattleTowerPartyMenuSelection(u8 taskId, s8 directionPressed) +{ + u16 newMenuIndex; + u8 newMenuIndex2; + u8 newMenuIndex3; + s8 menuMovement; + u8 spriteId = sub_806CA00(taskId); + u8 menuIndex = gSprites[spriteId].data0; + + UpdateMonIconFrame_806DA44(taskId, menuIndex, 0); + + if (menuIndex < PARTY_SIZE) + { + sub_806BF24(&gUnknown_083769A8[menuIndex * 2], menuIndex, 3, 0); + } + else if (menuIndex == PARTY_SIZE) + { + sub_806BB9C(1); + } + else + { + sub_806BBEC(1); + } + + menuMovement = directionPressed + 2; + + switch (menuMovement) + { + case 2: // no movement + gSprites[spriteId].data1 = 0; + break; + case 1: // moving up + if (menuIndex == 0) { + gSprites[spriteId].data0 = 7; + } else if (menuIndex == PARTY_SIZE) { + gSprites[spriteId].data0 = gPlayerPartyCount - 1; + } else { + gSprites[spriteId].data0 += directionPressed; + } + + gSprites[spriteId].data1 = 0; + break; + case 3: // moving down + if (menuIndex == gPlayerPartyCount - 1) { + gSprites[spriteId].data0 = 6; + } else if (menuIndex == 7) { + gSprites[spriteId].data0 = 0; + } else { + gSprites[spriteId].data0 += directionPressed; + } + + gSprites[spriteId].data1 = 0; + break; + case 4: // moving right + if (gPlayerPartyCount > 1 && menuIndex == 0) + { + if (gSprites[spriteId].data1 == 0) { + gSprites[spriteId].data1 = 1; + } + + gSprites[spriteId].data0 = gSprites[spriteId].data1; + } + break; + case 0: // moving left + newMenuIndex3 = menuIndex - 1; + if (newMenuIndex3 <= 4) + { + gSprites[spriteId].data0 = 0; + gSprites[spriteId].data1 = menuIndex; + } + break; + } + + gSprites[spriteId].pos1.x = gUnknown_083768B8[PARTY_MENU_LAYOUT_STANDARD][gSprites[spriteId].data0].x; + gSprites[spriteId].pos1.y = gUnknown_083768B8[PARTY_MENU_LAYOUT_STANDARD][gSprites[spriteId].data0].y; + + + newMenuIndex = gSprites[spriteId].data0; + if (gSprites[spriteId].data0 < PARTY_SIZE) + { + sub_806BF24(&gUnknown_083769A8[gSprites[spriteId].data0 * 2], newMenuIndex, 3, 1); + } + else if (gSprites[spriteId].data0 == PARTY_SIZE) + { + sub_806BB9C(2); + } + else + { + sub_806BBEC(2); + } + + ewram1B000.unk261 = 2; + + newMenuIndex2 = gSprites[spriteId].data0; + UpdateMonIconFrame_806DA44(taskId, newMenuIndex2, 1); + + if (menuIndex != gSprites[spriteId].data0) + { + PlaySE(5); + } +} + +// Selects the "OK" button in the Battle Tower party menu. +void SelectBattleTowerOKButton(u8 taskId) +{ + u8 spriteId = sub_806CA00(taskId); + + u8 menuIndex = gSprites[spriteId].data0; + if (menuIndex != 6) + { + UpdateMonIconFrame_806DA44(taskId, menuIndex, 0); + + if (menuIndex < PARTY_SIZE) + { + sub_806BF24(&gUnknown_083769A8[menuIndex * 2], menuIndex, 3, 0); + } + else + { + sub_806BBEC(1); + } + + gSprites[spriteId].data1 = 0; + gSprites[spriteId].data0 = 6; + gSprites[spriteId].pos1.x = gUnknown_083768B8[PARTY_MENU_LAYOUT_STANDARD][6].x; + gSprites[spriteId].pos1.y = gUnknown_083768B8[PARTY_MENU_LAYOUT_STANDARD][6].y; + + sub_806BB9C(2); + + ewram1B000.unk261 = 2; + PlaySE(5); + } +} + +void sub_806C92C(u8 spriteId) +{ + u8 menuIndex1 = gSprites[spriteId].data0; + u8 menuIndex2 = gSprites[spriteId].data1; + + if (!IsDoubleBattle()) + { + if (menuIndex1 < 1) { + if (menuIndex2 < 1) { + menuIndex2 = 1; + } + } else { + if (menuIndex2 >= 1) { + menuIndex2 = 0; + } + } + } else { + if (menuIndex1 < 2) { + if (menuIndex2 < 2) { + menuIndex2 = 2; + } + } else { + if (menuIndex2 >= 2) { + menuIndex2 = 0; + } + } + } + + gSprites[spriteId].data1 = menuIndex2; +} + +void sub_806C994(u8 taskId, u8 b) +{ + u8 spriteId = sub_806CA00(taskId); + + gSprites[spriteId].data0 = b; + sub_806C92C(spriteId); +} + +void sub_806C9C4(u8 taskId, u8 spriteId) +{ + u8 spriteId2 = sub_806CA00(taskId); + + gSprites[spriteId].pos1.x = gSprites[spriteId2].pos1.x; + gSprites[spriteId].pos1.y = gSprites[spriteId2].pos1.y; + gSprites[spriteId].data0 = gSprites[spriteId2].data0; +} + +u8 sub_806CA00(u8 taskId) +{ + return gTasks[taskId].data[3] >> 8; +} + +void sub_806CA18(u8 taskId, u8 b) +{ + u8 var1 = gTasks[taskId].data[3]; + gTasks[taskId].data[3] = var1 | (b << 8); +} + +u8 sub_806CA38(u8 taskId) +{ + u8 spriteId = sub_806CA00(taskId); + return gSprites[spriteId].data0; +} + +void SetupDefaultPartyMenuSwitchPokemon(u8 taskId) +{ + gTasks[taskId].func = TaskDummy; + ewram01000.unk0 = taskId; + + CreateTask(HandlePartyMenuSwitchPokemonInput, 0); + ewram01000.unk1 = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy); + + sub_806C9C4(taskId, ewram01000.unk1); + ewram01000.unk2 = sub_806CA00(taskId); + + PrintPartyMenuPromptText(ewram1B000_alt.unk272, 0); + + sub_806BF24(&gUnknown_083769A8[gSprites[ewram01000.unk1].data0 * 2], gSprites[ewram01000.unk1].data0, 6, 0); + ewram1B000.unk261 = 2; +} + +// Handles changing the the current mon selection when choosing mons to swap places. +void ChangePartyMenuSwitchPokemonSelection(u8 taskId, s16 menuDirectionPressed) +{ + struct Sprite *sprite1 = &gSprites[ewram01000.unk1]; + struct Sprite *sprite2 = &gSprites[ewram01000.unk2]; + + ChangePartyMenuSelection(taskId, menuDirectionPressed); + + if (sprite1->data0 != sprite2->data0) + { + sub_806BF24(&gUnknown_083769A8[sprite1->data0 * 2], sprite1->data0, 6, 1); + } + else + { + sub_806BF24(&gUnknown_083769A8[sprite1->data0 * 2], sprite1->data0, 6, 0); + } +} + +void HandlePartyMenuSwitchPokemonInput(u8 taskId) +{ + switch (gMain.newAndRepeatedKeys) + { + case DPAD_UP: + ChangePartyMenuSwitchPokemonSelection(ewram01000.unk0, -1); + break; + case DPAD_DOWN: + ChangePartyMenuSwitchPokemonSelection(ewram01000.unk0, 1); + break; + case DPAD_LEFT: + ChangePartyMenuSwitchPokemonSelection(ewram01000.unk0, -2); + break; + case DPAD_RIGHT: + ChangePartyMenuSwitchPokemonSelection(ewram01000.unk0, 2); + break; + } + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(5); + gTasks[taskId].func = ewram01000.unkC; + gTasks[taskId].func(taskId); + } + else if (gMain.newKeys == B_BUTTON) + { + PlaySE(5); + sub_806CD44(taskId); + } +} + +void sub_806CC2C(u8 taskId) +{ + DestroySprite(&gSprites[ewram01000.unk1]); + PrintPartyMenuPromptText(0, 0); + + ewram1B000.unk261 = 2; + SwitchTaskToFollowupFunc(ewram01000.unk0); + DestroyTask(taskId); +} + +void sub_806CC74(u8 taskId) +{ + sub_806BF24(&gUnknown_083769A8[gSprites[ewram01000.unk2].data0 * 2], gSprites[ewram01000.unk2].data0, 3, 1); + sub_806BF24(&gUnknown_083769A8[gSprites[ewram01000.unk1].data0 * 2], gSprites[ewram01000.unk1].data0, 3, 0); + sub_806CC2C(taskId); +} + +void sub_806CCE4() +{ + u8 monIndex1 = gSprites[ewram01000.unk1].data0; + u8 monIndex2 = gSprites[ewram01000.unk2].data0; + + if (monIndex1 <= 5) + { + sub_806BF24(&gUnknown_083769A8[monIndex1 * 2], monIndex1, 3, 0); + } + + if (monIndex2 <= 5) + { + sub_806BF24(&gUnknown_083769A8[monIndex2 * 2], monIndex2, 3, 1); + } +} + +void sub_806CD44(u8 taskId) +{ + sub_806CCE4(); + sub_806CC2C(taskId); +} + +void sub_806CD5C(u8 taskId) +{ + u8 monIndex1 = gSprites[ewram01000.unk1].data0; + u8 monIndex2 = gSprites[ewram01000.unk2].data0; + + if (monIndex1 == monIndex2 || monIndex1 == 7 || monIndex2 == 7) + { + sub_806CD44(taskId); + } + else + { + u8 var1; + + sub_806D5B8(monIndex1); + sub_806D5B8(monIndex2); + + if (monIndex1 > monIndex2) + { + ewram01000.unk5 = monIndex2; + ewram01000.unk6 = monIndex1; + } + else + { + ewram01000.unk5 = monIndex1; + ewram01000.unk6 = monIndex2; + } + + ewram01000.unk3 = GetMonIconSpriteId(ewram01000.unk0, ewram01000.unk5); + ewram01000.unk4 = GetMonIconSpriteId(ewram01000.unk0, ewram01000.unk6); + + var1 = ewram01000.unk5; + if (!var1) + { + gSprites[ewram01000.unk3].data0 = -8; + gSprites[ewram01000.unk3].data2 = -0xA8; + ewram01000.unk8 = var1; + ewram01000.unkA = 11; + + gTasks[taskId].func = sub_806D014; + ewram1B000.unk261 = 1; + } + else + { + gSprites[ewram01000.unk3].data0 = 8; + gSprites[ewram01000.unk3].data2 = 0xA8; + ewram01000.unk8 = 11; + ewram01000.unkA = 11; + + gTasks[taskId].func = sub_806D118; + ewram1B000.unk261 = 1; + } + + gSprites[ewram01000.unk3].callback = SpriteCB_sub_806D37C; + + gSprites[ewram01000.unk4].data0 = 8; + gSprites[ewram01000.unk4].data2 = 0xA8; + gSprites[ewram01000.unk4].callback = SpriteCB_sub_806D37C; + + gSprites[ewram01000.unk3].callback(&gSprites[ewram01000.unk3]); + gSprites[ewram01000.unk4].callback(&gSprites[ewram01000.unk4]); + } +} + +void SwapValues_s16(s16 *a, s16 *b) +{ + s16 temp = *a; + *a = *b; + *b = temp; +} + +#ifdef NONMATCHING +void sub_806CF04(void) +{ + SwapValues_s16(&gSprites[ewram01000.unk3].pos1.x, &gSprites[ewram01000.unk4].pos1.x); + SwapValues_s16(&gSprites[ewram01000.unk3].pos1.y, &gSprites[ewram01000.unk4].pos1.y); + SwapValues_s16(&gSprites[ewram01000.unk3].pos2.x, &gSprites[ewram01000.unk4].pos2.x); + SwapValues_s16(&gSprites[ewram01000.unk3].data0, &gSprites[ewram01000.unk4].data0); + + gSprites[ewram01000.unk3].callback = SpriteCB_sub_806D37C; + gSprites[ewram01000.unk4].callback = SpriteCB_sub_806D37C; +} +#else +__attribute__((naked)) +void sub_806CF04(void) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + ldr r4, _0806CF94 @ =0x02001000\n\ + ldrb r1, [r4, 0x3]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + ldr r5, _0806CF98 @ =gSprites + 0x20\n\ + adds r0, r5\n\ + ldrb r2, [r4, 0x4]\n\ + lsls r1, r2, 4\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r5\n\ + bl SwapValues_s16\n\ + ldrb r1, [r4, 0x3]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r3, r5, 0x2\n\ + adds r0, r3\n\ + ldrb r2, [r4, 0x4]\n\ + lsls r1, r2, 4\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r3\n\ + bl SwapValues_s16\n\ + ldrb r1, [r4, 0x3]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r3, r5, 0x4\n\ + adds r0, r3\n\ + ldrb r2, [r4, 0x4]\n\ + lsls r1, r2, 4\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r3\n\ + bl SwapValues_s16\n\ + ldrb r1, [r4, 0x3]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r3, r5, 0\n\ + adds r3, 0xE\n\ + adds r0, r3\n\ + ldrb r2, [r4, 0x4]\n\ + lsls r1, r2, 4\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r3\n\ + bl SwapValues_s16\n\ + ldrb r1, [r4, 0x3]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + subs r5, 0x4\n\ + adds r0, r5\n\ + ldr r2, _0806CF9C @ =SpriteCB_sub_806D37C\n\ + str r2, [r0]\n\ + ldrb r1, [r4, 0x4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + str r2, [r0]\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806CF94: .4byte 0x02001000\n\ +_0806CF98: .4byte gSprites + 0x20\n\ +_0806CF9C: .4byte SpriteCB_sub_806D37C\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void sub_806CFA0(u8 taskId, u8 b) +{ + u8 var1 = ((ewram01000.unk6 - 1) * 3) + 1; + + sub_806BA34(ewram01000.unk8, 3); + sub_806BB3C(ewram01000.unkA, var1); + + if (!b) + { + ewram01000.unk8--; + ewram01000.unkA++; + } + else + { + ewram01000.unk8++; + ewram01000.unkA--; + } + + sub_806B9A4(ewram01000.unk8, 3, 10); + sub_806BA94(ewram01000.unkA, var1, 0, 10); +} + +void sub_806D014(u8 taskId) +{ + sub_806CFA0(taskId, 0); + + if (ewram01000.unk8 < -13 && ewram01000.unkA > 32) + { + sub_806CF04(); + gTasks[taskId].func = sub_806D05C; + } +} + +void sub_806D05C(u8 taskId) +{ + sub_806CFA0(taskId, 1); + + if (ewram01000.unk8 == 0 && ewram01000.unkA == 11) + { + gTasks[taskId].func = sub_806D198; + } +} + +void sub_806D098(u8 a, u8 b) +{ + u8 var1 = ((ewram01000.unk5 - 1) * 3) + 1; + u8 var2 = ((ewram01000.unk6 - 1) * 3) + 1; + + sub_806BB3C(ewram01000.unk8, var1); + sub_806BB3C(ewram01000.unkA, var2); + + if (!b) + { + ewram01000.unk8++; + ewram01000.unkA++; + } + else + { + ewram01000.unk8--; + ewram01000.unkA--; + } + + sub_806BA94(ewram01000.unk8, var1, 0, 10); + sub_806BA94(ewram01000.unkA, var2, 0, 10); +} + +void sub_806D118(u8 taskId) +{ + sub_806D098(taskId, 0); + + if (ewram01000.unk8 > 32 && ewram01000.unkA > 32) + { + sub_806CF04(); + gTasks[taskId].func = sub_806D15C; + } +} + +void sub_806D15C(u8 taskId) +{ + sub_806D098(taskId, 1); + + if (ewram01000.unk8 == 11 && ewram01000.unkA == 11) + { + gTasks[taskId].func = sub_806D198; + } +} + +void sub_806D198(u8 taskId) +{ + u8 spriteId; + + SetMonIconSpriteId(ewram01000.unk0, ewram01000.unk5, ewram01000.unk4); + SetMonIconSpriteId(ewram01000.unk0, ewram01000.unk6, ewram01000.unk3); + + gSprites[ewram01000.unk3].pos1.x = gUnknown_08376678[IsDoubleBattle()][ewram01000.unk6].x; + gSprites[ewram01000.unk3].pos1.y = gUnknown_08376678[IsDoubleBattle()][ewram01000.unk6].y; + gSprites[ewram01000.unk3].pos2.x = 0; + gSprites[ewram01000.unk3].pos2.y = 0; + gSprites[ewram01000.unk3].callback = UpdateMonIconFrame_806DA38; + + gSprites[ewram01000.unk4].pos1.x = gUnknown_08376678[IsDoubleBattle()][ewram01000.unk5].x; + gSprites[ewram01000.unk4].pos1.y = gUnknown_08376678[IsDoubleBattle()][ewram01000.unk5].y; + gSprites[ewram01000.unk4].pos2.x = 0; + gSprites[ewram01000.unk4].pos2.y = 0; + gSprites[ewram01000.unk4].callback = UpdateMonIconFrame_806DA38; + + spriteId = GetMonIconSpriteId(ewram01000.unk0, gSprites[ewram01000.unk2].data0); + gSprites[spriteId].callback = UpdateMonIconFrame_806DA0C; + + SwapPokemon(&gPlayerParty[ewram01000.unk5], &gPlayerParty[ewram01000.unk6]); + + PartyMenuPrintMonLevelOrStatus(ewram01000.unk5, &gPlayerParty[ewram01000.unk5]); + TryPrintPartyMenuMonNickname(ewram01000.unk5, &gPlayerParty[ewram01000.unk5]); + PartyMenuTryPrintHP(ewram01000.unk5, &gPlayerParty[ewram01000.unk5]); + nullsub_12(ewram01000.unk5, &gPlayerParty[ewram01000.unk5]); + + PartyMenuPrintMonLevelOrStatus(ewram01000.unk6, &gPlayerParty[ewram01000.unk6]); + TryPrintPartyMenuMonNickname(ewram01000.unk6, &gPlayerParty[ewram01000.unk6]); + PartyMenuTryPrintHP(ewram01000.unk6, &gPlayerParty[ewram01000.unk6]); + nullsub_12(ewram01000.unk6, &gPlayerParty[ewram01000.unk6]); + + PartyMenuDrawHPBars(); + sub_806CC74(taskId); +} + +void SpriteCB_sub_806D37C(struct Sprite *sprite) +{ + UpdateMonIconFrame(sprite); + + if (sprite->pos2.x == sprite->data2) + { + sprite->data0 *= -1; + sprite->data2 = 0; + sprite->callback = UpdateMonIconFrame_806DA38; + } + else + { + sprite->pos2.x += sprite->data0; + } +} + +void sub_806D3B4(u8 taskId, u16 species1, u16 species2) +{ + const u8 *var1 = gUnknown_083769C0; + + sub_806BA34(var1[2] + gTasks[taskId].data[0], var1[3]); + sub_806BB3C(var1[8] + gTasks[taskId].data[0], var1[9]); + sub_806BB3C(var1[10] + gTasks[taskId].data[0], var1[11]); + + gTasks[taskId].data[0]--; + + sub_806B9A4(var1[2] + gTasks[taskId].data[0], var1[3], 4); + + if (species1) + { + sub_806BA94(var1[8] + gTasks[taskId].data[0], var1[9], 0, 4); + } + else + { + sub_806BA94(var1[8] + gTasks[taskId].data[0], var1[9], 1, 4); + } + + if (species2) + { + sub_806BA94(var1[10] + gTasks[taskId].data[0], var1[11], 0, 4); + } + else + { + sub_806BA94(var1[10] + gTasks[taskId].data[0], var1[11], 1, 4); + } +} + +void sub_806D4AC(u8 taskId, u16 species, u8 c) +{ + if (species) + { + u8 monIndex = c + 3; + u8 spriteId = GetMonIconSpriteId(taskId, monIndex); + + gSprites[spriteId].data0 = -8; + gSprites[spriteId].data2 = gTasks[taskId].data[0] * -8; + gSprites[spriteId].callback = SpriteCB_sub_806D37C; + } +} + +void sub_806D50C(u8 taskId, u8 monIndex) +{ + gSprites[GetMonIconSpriteId(taskId, monIndex)].pos1.x += 0xF0; +} + +void PrintPartyMenuPromptText(u8 textId, u8 b) +{ + if (textId != 0xFF) + { + switch (b) + { + case 0: + MenuDrawTextWindow(0, 16, 23, 19); + break; + case 1: + MenuDrawTextWindow(0, 16, 19, 19); + break; + case 2: + MenuDrawTextWindow(0, 16, 22, 19); + break; + case 3: + MenuDrawTextWindow(0, 16, 18, 19); + break; + } + + MenuPrint(PartyMenuPromptTexts[textId], 1, 17); + } +} + +void sub_806D5A4(void) +{ + MenuZeroFillWindowRect(0, 16, 29, 19); +} + +void sub_806D5B8(u8 monIndex) +{ + u32 var1; + u8 left = gUnknown_08376948[IsDoubleBattle()][monIndex].left; + u8 top = gUnknown_08376948[IsDoubleBattle()][monIndex].top; + u8 right = gUnknown_08376948[IsDoubleBattle()][monIndex].right; + u8 bottom = gUnknown_08376948[IsDoubleBattle()][monIndex].bottom; + + ZeroFillWindowRect(&gUnknown_03004210, left, top, right, bottom); + + var1 = 0; + CpuFastSet(&var1, (void *)(OBJ_VRAM1 + monIndex * 0x400), 0x1000100); +} + +void sub_806D668(u8 monIndex) +{ + u32 var1; + u8 left = gUnknown_08376978[IsDoubleBattle()][monIndex].left; + u8 top = gUnknown_08376978[IsDoubleBattle()][monIndex].top; + u8 right = gUnknown_08376978[IsDoubleBattle()][monIndex].right; + u8 bottom = gUnknown_08376978[IsDoubleBattle()][monIndex].bottom; + + ZeroFillWindowRect(&gUnknown_03004210, left, top, right, bottom); + + var1 = 0; + CpuFastSet(&var1, (void *)(OBJ_VRAM1 + 0x300 + monIndex * 0x400), 0x1000040); +} + +bool8 LoadPartyMenuGraphics(u8 a) +{ + u16 palette = 0x7FFF; + bool8 retVal = FALSE; + + if (a < 2) + { + LZDecompressVram(gPartyMenuMisc_Gfx, (void *)BG_VRAM); + } + + if (a == 2 || a == 0) + { + LZDecompressVram(gPartyMenuMisc_Tilemap, (void *)(BG_VRAM + 0x3800)); + } + + if (a == 3 || a == 0) + { + LoadCompressedPalette(gPartyMenuMisc_Pal, 0, 0x160); + } + + if (a == 4 || a == 0) + { + LoadPalette(&palette, 0, 2); + LoadPalette(gFontDefaultPalette, 0xF0, 0x20); + } + + if (a == 5 || a == 0) + { + LZDecompressVram(gPartyMenuHpBar_Gfx, (void *)(BG_VRAM + 0x6000)); + } + + if (a == 6 || a == 0) + { + LZDecompressVram(gPartyMenuOrderText_Gfx, (void *)(BG_VRAM + 0x6180)); + } + + if (a == 7 || a == 0) + { + LZDecompressVram(gStatusGfx_Icons, (void *)(BG_VRAM + 0x7180)); + } + + if (a == 8 || a == 0) + { + LoadCompressedPalette(gStatusPal_Icons, 0xB0, 0x20); + retVal = TRUE; + } + + return retVal; +} + +void SetMonIconAnimByHP(u8 spriteId, u16 currentHP, u16 maxHP) +{ + u8 hpBarLevel = GetHPBarLevel(currentHP, maxHP); + u8 animNum = 0; + + if (currentHP != maxHP) + { + if (hpBarLevel == 3) + { + animNum = 1; + } + else if (hpBarLevel == 2) + { + animNum = 2; + } + else if (hpBarLevel == 1) + { + animNum = 3; + } + else + { + animNum = 4; + } + } + + sub_809D824(&gSprites[spriteId], animNum); +} + +void SetMonIconAnim(u8 spriteId, struct Pokemon *pokemon) +{ + u16 currentHP = GetMonData(pokemon, MON_DATA_HP); + u16 maxHP = GetMonData(pokemon, MON_DATA_MAX_HP); + + SetMonIconAnimByHP(spriteId, currentHP, maxHP); +} + +void CreatePartyMenuMonIcon(u8 taskId, u8 monIndex, u8 menuType, struct Pokemon *pokemon) +{ + u8 x = gUnknown_08376678[menuType][monIndex].x; + u8 y = gUnknown_08376678[menuType][monIndex].y; + + u16 species2 = GetMonData(pokemon, MON_DATA_SPECIES2); + u32 personality = GetMonData(pokemon, MON_DATA_PERSONALITY); + + u8 spriteId = CreateMonIcon(species2, sub_809D62C, x, y, 5, personality); + SetMonIconSpriteId(taskId, monIndex, spriteId); + SetMonIconAnim(spriteId, pokemon); +} + +void TryCreatePartyMenuMonIcon(u8 taskId, u8 monIndex, struct Pokemon *pokemon) +{ + if (GetMonData(pokemon, MON_DATA_SPECIES)) + { + bool8 isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == TRUE) + { + CreatePartyMenuMonIcon(taskId, monIndex, PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE, pokemon); + } + else + { + CreatePartyMenuMonIcon(taskId, monIndex, IsDoubleBattle(), pokemon); + } + } +} + +void unref_sub_806D964(u8 taskId) +{ + u8 i; + for (i = 0; i < gPlayerPartyCount; i++) + { + TryCreatePartyMenuMonIcon(taskId, i, &gPlayerParty[i]); + } +} + +void CreateMonIcon_LinkMultiBattle(u8 taskId, u8 monIndex, u8 menuType, struct UnknownPokemonStruct2 *pokemon) +{ + u8 x = gUnknown_08376678[menuType][monIndex].x; + u8 y = gUnknown_08376678[menuType][monIndex].y; + + u8 spriteId = CreateMonIcon(pokemon->species, sub_809D62C, x, y, 5, pokemon->personality); + SetMonIconSpriteId(taskId, monIndex, spriteId); + SetMonIconAnimByHP(spriteId, pokemon->hp, pokemon->maxhp); +} + +void UpdateMonIconFrame_806DA0C(struct Sprite *sprite) +{ + u8 var1; + + var1 = UpdateMonIconFrame(sprite); + if (var1) + { + if (var1 & 1) + { + sprite->pos2.y = -3; + } + else + { + sprite->pos2.y = 1; + } + } +} + +void UpdateMonIconFrame_806DA38(struct Sprite *sprite) +{ + UpdateMonIconFrame(sprite); +} + +void UpdateMonIconFrame_806DA44(u8 taskId, u8 monIndex, u8 c) +{ + u8 spriteId; + + if (monIndex < PARTY_SIZE) + { + spriteId = GetMonIconSpriteId(taskId, monIndex); + gSprites[spriteId].pos2.y = 0; + gSprites[spriteId].data0 = 0; + + if (!c) + { + gSprites[spriteId].callback = UpdateMonIconFrame_806DA38; + } + else + { + gSprites[spriteId].callback = UpdateMonIconFrame_806DA0C; + } + } +} + +void LoadHeldItemIconGraphics(void) +{ + LoadSpriteSheet(&HeldItemsSpriteSheet); + LoadSpritePalette(&HeldItemsPalette); +} + +void SpriteCB_HeldItemIcon(struct Sprite *sprite) +{ + + u8 data7 = sprite->data7; + if (gSprites[data7].invisible) + { + sprite->invisible = 1; + } + else + { + sprite->invisible = 0; + sprite->pos1.x = gSprites[data7].pos1.x + gSprites[data7].pos2.x; + sprite->pos1.y = gSprites[data7].pos1.y + gSprites[data7].pos2.y; + } +} + +void CreateHeldItemIcon(u8 a, u8 b) +{ + u8 subPriority; + u8 spriteId; + + subPriority = gSprites[a].subpriority; + spriteId = CreateSprite(&gSpriteTemplate_837660C, 0xFA, 0xAA, subPriority - 1); + + gSprites[spriteId].pos2.x = 4; + gSprites[spriteId].pos2.y = 10; + gSprites[spriteId].callback = SpriteCB_HeldItemIcon; + gSprites[spriteId].data7 = a; + + StartSpriteAnim(&gSprites[spriteId], b); + gSprites[spriteId].callback(&gSprites[spriteId]); +} + +void CreateHeldItemIcons(u8 *a, u8 *b, u8 c) +{ + u16 i; + u16 heldItem; + + switch (c) + { + case 0: + i = 0; + while (i < a[0]) + { + heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + if (heldItem) + { + CreateHeldItemIcon(b[i], ItemIsMail(heldItem)); + } + + i++; + } + break; + case 1: + i = 0; + while (i < a[1]) + { + heldItem = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM); + if (heldItem) + { + CreateHeldItemIcon(b[i + 6], ItemIsMail(heldItem)); + } + + i++; + } + break; + } +} + +void CreateHeldItemIcons_806DC34(u8 taskId) +{ + u8 i; + u8 monIconSpriteId; + u8 heldItemSpriteId; + + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES)) + { + monIconSpriteId = GetMonIconSpriteId(taskId, i); + heldItemSpriteId = CreateSprite(&gSpriteTemplate_837660C, 0xFA, 0xAA, 4); + + gSprites[heldItemSpriteId].pos2.x = 4; + gSprites[heldItemSpriteId].pos2.y = 10; + gSprites[heldItemSpriteId].data7 = monIconSpriteId; + gSprites[monIconSpriteId].data7 = heldItemSpriteId; + + SetHeldItemIconVisibility(taskId, i); + gSprites[heldItemSpriteId].callback(&gSprites[heldItemSpriteId]); + } + } +} + +#ifdef NONMATCHING +void CreateHeldItemIcon_806DCD4(u8 taskId, u8 monIndex, u16 item) +{ + u8 monIconSpriteId; + u8 heldItemSpriteId; + + monIconSpriteId = GetMonIconSpriteId(taskId, monIndex); + heldItemSpriteId = CreateSprite(gSpriteTemplate_837660C, 0xFA, 0xAA, 4); + + gSprites[heldItemSpriteId].pos2.x = 4; + gSprites[heldItemSpriteId].pos2.y = 10; + gSprites[heldItemSpriteId].data7 = monIconSpriteId; + gSprites[monIconSpriteId].data7 = heldItemSpriteId; + + if (!item) + { + gSprites[heldItemSpriteId].invisible = 1; + } + else + { + if (ItemIsMail(item)) + { + StartSpriteAnim(&gSprites[heldItemSpriteId], 1); + } + else + { + StartSpriteAnim(&gSprites[heldItemSpriteId], 0); + } + + gSprites[heldItemSpriteId].invisible = 0; + } + + gSprites[heldItemSpriteId].callback(&gSprites[heldItemSpriteId]); +} +#else +__attribute__((naked)) +void CreateHeldItemIcon_806DCD4(u8 taskId, u8 monIndex, u16 item) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + lsls r2, 16\n\ + lsrs r7, r2, 16\n\ + bl GetMonIconSpriteId\n\ + adds r4, r0, 0\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + ldr r0, _0806DD2C @ =gSpriteTemplate_837660C\n\ + movs r1, 0xFA\n\ + movs r2, 0xAA\n\ + movs r3, 0x4\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldr r1, _0806DD30 @ =gSprites\n\ + lsls r0, r6, 4\n\ + adds r0, r6\n\ + lsls r0, 2\n\ + adds r5, r0, r1\n\ + movs r0, 0x4\n\ + strh r0, [r5, 0x24]\n\ + movs r0, 0xA\n\ + strh r0, [r5, 0x26]\n\ + strh r4, [r5, 0x3C]\n\ + lsls r0, r4, 4\n\ + adds r0, r4\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + strh r6, [r0, 0x3C]\n\ + cmp r7, 0\n\ + bne _0806DD34\n\ + adds r0, r5, 0\n\ + adds r0, 0x3E\n\ + ldrb r1, [r0]\n\ + movs r2, 0x4\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _0806DD5C\n\ + .align 2, 0\n\ +_0806DD2C: .4byte gSpriteTemplate_837660C\n\ +_0806DD30: .4byte gSprites\n\ +_0806DD34:\n\ + adds r0, r7, 0\n\ + bl ItemIsMail\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _0806DD46\n\ + adds r0, r5, 0\n\ + movs r1, 0x1\n\ + b _0806DD4A\n\ +_0806DD46:\n\ + adds r0, r5, 0\n\ + movs r1, 0\n\ +_0806DD4A:\n\ + bl StartSpriteAnim\n\ + adds r2, r5, 0\n\ + adds r2, 0x3E\n\ + ldrb r1, [r2]\n\ + movs r0, 0x5\n\ + negs r0, r0\n\ + ands r0, r1\n\ + strb r0, [r2]\n\ +_0806DD5C:\n\ + ldr r2, _0806DD78 @ =gSprites\n\ + lsls r0, r6, 4\n\ + adds r0, r6\n\ + lsls r0, 2\n\ + adds r1, r2, 0\n\ + adds r1, 0x1C\n\ + adds r1, r0, r1\n\ + adds r0, r2\n\ + ldr r1, [r1]\n\ + bl _call_via_r1\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806DD78: .4byte gSprites\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void SpriteCB_UpdateHeldItemIconPosition(struct Sprite *sprite) +{ + u8 spriteId = sprite->data7; + + sprite->pos1.x = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x; + sprite->pos1.y = gSprites[spriteId].pos1.y; +} + +u8 GetMonIconSpriteId(u8 taskId, u8 monIndex) +{ + switch (monIndex) + { + case 1: + return gTasks[taskId].data[0]; + break; + case 2: + return gTasks[taskId].data[1] >> 8; + break; + case 3: + return gTasks[taskId].data[1]; + break; + case 4: + return gTasks[taskId].data[2] >> 8; + break; + case 5: + return gTasks[taskId].data[2]; + break; + case 0: + default: + return gTasks[taskId].data[0] >> 8; + break; + } +} + +void SetMonIconSpriteId(u8 taskId, u8 monIndex, u8 spriteId) +{ + switch (monIndex) + { + case 0: + gTasks[taskId].data[0] = (u8)gTasks[taskId].data[0] | (spriteId << 8); + break; + case 1: + gTasks[taskId].data[0] = (gTasks[taskId].data[0] & -0x100) | spriteId; + break; + case 2: + gTasks[taskId].data[1] = (u8)gTasks[taskId].data[1] | (spriteId << 8); + break; + case 3: + gTasks[taskId].data[1] = (gTasks[taskId].data[1] & -0x100) | spriteId; + break; + case 4: + gTasks[taskId].data[2] = (u8)gTasks[taskId].data[2] | (spriteId << 8); + break; + case 5: + gTasks[taskId].data[2] = (gTasks[taskId].data[2] & -0x100) | spriteId; + break; + } +} + +u16 GetMonHeldItemIconSpriteId(u8 taskId, u8 monIndex) +{ + u8 spriteId = GetMonIconSpriteId(taskId, monIndex); + u8 retVal = gSprites[spriteId].data7; + return retVal; +} + +#ifdef NONMATCHING +void SetHeldItemIconVisibility(u8 taskId, u8 monIndex) +{ + u8 spriteId; + u16 heldItem; + + spriteId = GetMonHeldItemIconSpriteId(taskId, monIndex); + if (!GetMonData(&gPlayerParty[monIndex], MON_DATA_HELD_ITEM)) + { + gSprites[spriteId].invisible = 1; + } + else + { + struct Sprite *sprite; + + heldItem = GetMonData(&gPlayerParty[monIndex], MON_DATA_HELD_ITEM); + sprite = &gSprites[spriteId]; + if (ItemIsMail(heldItem)) + { + StartSpriteAnim(sprite, 1); + } + else + { + StartSpriteAnim(sprite, 0); + } + + sprite->invisible = 0; + } +} +#else +__attribute__((naked)) +void SetHeldItemIconVisibility(u8 a, u8 monIndex) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + adds r4, r1, 0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + adds r1, r4, 0\n\ + bl GetMonHeldItemIconSpriteId\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + adds r6, r5, 0\n\ + movs r0, 0x64\n\ + adds r1, r4, 0\n\ + muls r1, r0\n\ + ldr r0, _0806DFA4 @ =gPlayerParty\n\ + adds r4, r1, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _0806DFAC\n\ + ldr r1, _0806DFA8 @ =gSprites\n\ + lsls r0, r5, 4\n\ + adds r0, r5\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + adds r0, 0x3E\n\ + ldrb r1, [r0]\n\ + movs r2, 0x4\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _0806DFF6\n\ + .align 2, 0\n\ +_0806DFA4: .4byte gPlayerParty\n\ +_0806DFA8: .4byte gSprites\n\ +_0806DFAC:\n\ + adds r0, r4, 0\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + bl ItemIsMail\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _0806DFD8\n\ + lsls r4, r5, 4\n\ + adds r4, r5\n\ + lsls r4, 2\n\ + ldr r0, _0806DFD4 @ =gSprites\n\ + adds r4, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0x1\n\ + b _0806DFE6\n\ + .align 2, 0\n\ +_0806DFD4: .4byte gSprites\n\ +_0806DFD8:\n\ + lsls r4, r6, 4\n\ + adds r4, r6\n\ + lsls r4, 2\n\ + ldr r0, _0806DFFC @ =gSprites\n\ + adds r4, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0\n\ +_0806DFE6:\n\ + bl StartSpriteAnim\n\ + adds r4, 0x3E\n\ + ldrb r1, [r4]\n\ + movs r0, 0x5\n\ + negs r0, r0\n\ + ands r0, r1\n\ + strb r0, [r4]\n\ +_0806DFF6:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806DFFC: .4byte gSprites\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void PartyMenuDoPrintMonNickname(u8 monIndex, int b, const u8 *nameBuffer) +{ + u32 var1 = 0; + CpuFastSet(&var1, gTileBuffer, 0x1000100); + sub_8004E3C((struct WindowConfig *)&gWindowConfig_81E6CAC, gTileBuffer, nameBuffer); + CpuFastSet(gTileBuffer, (void *)(OBJ_VRAM1 + (monIndex * 0x400)), 128); +} + +void PrintPartyMenuMonNickname(u8 monIndex, u8 b, struct Pokemon *pokemon) +{ + u8 nameBuffer[12]; + GetMonNickname(pokemon, nameBuffer); + PartyMenuDoPrintMonNickname(monIndex, b, nameBuffer); +} + +void TryPrintPartyMenuMonNickname(u8 monIndex, struct Pokemon *pokemon) +{ + if (GetMonData(pokemon, MON_DATA_SPECIES)) + { + bool8 isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == TRUE) + { + PrintPartyMenuMonNickname(monIndex, PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE, pokemon); + } + else + { + PrintPartyMenuMonNickname(monIndex, IsDoubleBattle(), pokemon); + } + } +} + +void PrintPartyMenuMonNicknames(void) +{ + u8 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + TryPrintPartyMenuMonNickname(i, &gPlayerParty[i]); + } +} + +u8 *GetMonNickname(struct Pokemon *pokemon, u8 *stringBuffer) +{ + GetMonData(pokemon, MON_DATA_NICKNAME, stringBuffer); + return StringGetEnd10(stringBuffer); +} + +void PartyMenuPutStatusTilemap(u8 monIndex, u8 menuLayout, u8 status) +{ + u8 i; + u8 x = gUnknown_08376738[menuLayout][monIndex].x - 1; + u8 y = gUnknown_08376738[menuLayout][monIndex].y + 1; + u16 *vramPtr = (u16*)(VRAM + 0xF000) + (x + y * 32); + u8 var1 = status * 4; + + for (i = 0; i < 4; i++) + { + vramPtr[i] = (0x18C + var1 + i) | -0x5000; + } +} + +static void PartyMenuClearLevelStatusTilemap(u8 monIndex) +{ + bool8 isLinkDoubleBattle; + u8 menuLayout; + u8 x; + u8 y; + u16 *vramPtr; + u8 i; + + isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == TRUE) + { + menuLayout = PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE; + } + else + { + menuLayout = IsDoubleBattle(); + } + + x = gUnknown_08376738[menuLayout][monIndex].x - 1; + y = gUnknown_08376738[menuLayout][monIndex].y + 1; + + vramPtr = (u16*)(VRAM + 0xF000) + (x + y * 32); + for (i = 0; i < 4; i++) + { + vramPtr[i] = 0; + } +} + +static void PartyMenuWriteTilemap(u8 a, u8 x, u8 y) +{ + u16 *vramPtr = (u16*)(VRAM + 0xF000) + (x + y * 32); + *vramPtr = a + 0x10C; +} + +void PartyMenuDoPrintLevel(u8 monIndex, u8 menuLayout, u8 level) +{ + u8 *stringVar; + u32 var1; + u8 x = gUnknown_08376738[menuLayout][monIndex].x; + u8 y = gUnknown_08376738[menuLayout][monIndex].y; + + PartyMenuWriteTilemap(0x40, x - 1, y + 1); + + stringVar = gStringVar1; + stringVar[0] = 0xFC; + stringVar[1] = 0x12; + stringVar[2] = 0x8; + + ConvertIntToDecimalString(&stringVar[3], level); + + var1 = 0; + CpuFastSet(&var1, gUnknown_02039460, 0x1000020); + sub_8004E3C((struct WindowConfig *)&gWindowConfig_81E6CAC, gUnknown_02039460 - 0x100 /*gTileBuffer*/, gStringVar1); + CpuFastSet(gUnknown_02039460, (void *)(OBJ_VRAM1 + 0x200 + (monIndex * 0x400)), 32); +} + +void PartyMenuPrintLevel(u8 monIndex, u8 menuLayout, struct Pokemon *pokemon) +{ + u16 level = GetMonData(pokemon, MON_DATA_LEVEL); + PartyMenuDoPrintLevel(monIndex, menuLayout, level); +} + +void PartyMenuPrintMonLevelOrStatus(u8 monIndex, struct Pokemon *pokemon) +{ + if (GetMonData(pokemon, MON_DATA_SPECIES) && !GetMonData(pokemon, MON_DATA_IS_EGG)) + { + u8 statusAndPkrs; + bool8 isLinkDoubleBattle; + u8 menuLayout; + + statusAndPkrs = GetMonStatusAndPokerus(pokemon); + + isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == TRUE) + { + menuLayout = PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE; + } + else + { + menuLayout = IsDoubleBattle(); + } + + if (statusAndPkrs != 0 && statusAndPkrs != 6) + { + PartyMenuPutStatusTilemap(monIndex, menuLayout, statusAndPkrs - 1); + } + else + { + PartyMenuPrintLevel(monIndex, menuLayout, pokemon); + } + + PartyMenuPrintGenderIcon(monIndex, menuLayout, pokemon); + } +} + +void PartyMenuPrintMonsLevelOrStatus(void) +{ + u8 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + PartyMenuPrintMonLevelOrStatus(i, &gPlayerParty[i]); + } +} + +void PartyMenuDoPrintGenderIcon(u16 species, u8 gender, u8 menuLayout, u8 monIndex, u8 *nickname) +{ + if (!ShouldHideGenderIcon(species, nickname)) + { + u8 x = gUnknown_08376738[menuLayout][monIndex].x + 3; + u8 y = gUnknown_08376738[menuLayout][monIndex].y + 1; + + switch (gender) + { + case MON_MALE: + PartyMenuWriteTilemap(0x42, x, y); + break; + case MON_FEMALE: + PartyMenuWriteTilemap(0x44, x, y); + break; + } + } +} + +void PartyMenuPrintGenderIcon(u8 monIndex, u8 menuLayout, struct Pokemon *pokemon) +{ + u16 species2; + u8 gender; + + GetMonNickname(pokemon, gStringVar1); + species2 = GetMonData(pokemon, MON_DATA_SPECIES2); + gender = GetMonGender(pokemon); + PartyMenuDoPrintGenderIcon(species2, gender, menuLayout, monIndex, gStringVar1); +} + +void PartyMenuDoPrintHP(u8 monIndex, u8 b, u16 currentHP, u16 maxHP) +{ + u32 *var; + register u8 *stringVar1 asm("r2") = gStringVar1; + register u8 *textPtr asm("r2") = sub_8072C14(stringVar1, currentHP, 15, 1); + textPtr[0] = CHAR_SLASH; + + sub_8072C14(++textPtr, maxHP, 35, 1); + var = 0; + + CpuFastSet(&var, gUnknown_02039460, 0x1000040); + sub_8004E3C((struct WindowConfig *)&gWindowConfig_81E6CAC, gUnknown_02039460 - 0x100 /*gTileBuffer*/, gStringVar1); + CpuFastSet(gUnknown_02039460, (void *)(OBJ_VRAM1 + 0x300 + (monIndex * 0x400)), 64); +} + +void PartyMenuPrintHP(u8 monIndex, u8 b, struct Pokemon *pokemon) +{ + u16 currentHP; + u16 maxHP; + + currentHP = GetMonData(pokemon, MON_DATA_HP); + maxHP = GetMonData(pokemon, MON_DATA_MAX_HP); + + PartyMenuDoPrintHP(monIndex, b, currentHP, maxHP); +} + +void PartyMenuTryPrintHP(u8 monIndex, struct Pokemon *pokemon) +{ + if (GetMonData(pokemon, MON_DATA_SPECIES) && !GetMonData(pokemon, MON_DATA_IS_EGG)) + { + bool8 isLinkDoubleBattle = IsLinkDoubleBattle(); + if (isLinkDoubleBattle == TRUE) + { + PartyMenuPrintHP(monIndex, PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE, pokemon); + } + else + { + PartyMenuPrintHP(monIndex, IsDoubleBattle(), pokemon); + } + } +} + +void PartyMenuTryPrintMonsHP(void) +{ + u8 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + PartyMenuTryPrintHP(i, &gPlayerParty[i]); + } +} + +void unref_sub_806E564(void) { } +void unref_sub_806E568(void) { } +void nullsub_12(u8 monIndex, struct Pokemon *pokemon) { } +void nullsub_13(void) { } + +void PartyMenuDoDrawHPBar(u8 monIndex, u8 menuLayout, u16 currentHP, u16 maxHP) +{ + u8 hpBarLevel; + u16 *vramPtr; + int var = -32768; + struct BattleInterfaceStruct1 battleInterface; + battleInterface.unk0 = maxHP; + battleInterface.unk4 = currentHP; + battleInterface.unk8 = 0; + + hpBarLevel = GetHPBarLevel(currentHP, maxHP); + if (hpBarLevel > 2) + { + battleInterface.unkC_0 = 4; + } + if (hpBarLevel == 2) + { + battleInterface.unkC_0 = 5; + } + if (hpBarLevel < 2) + { + battleInterface.unkC_0 = 6; + } + + battleInterface.unk10 = 0x100; + + vramPtr = gUnknown_08376858[menuLayout][monIndex]; + sub_80460C8(&battleInterface, &var, vramPtr, 0); + + vramPtr -= 2; + + vramPtr[0] = 0x3109; + vramPtr[1] = 0x310A; + vramPtr[8] = 0x310B; +} + +void PartyMenuDrawHPBar(u8 monIndex, u8 menuLayout, struct Pokemon *pokemon) +{ + u16 currentHP = GetMonData(pokemon, MON_DATA_HP); + u16 maxHP = GetMonData(pokemon, MON_DATA_MAX_HP); + + PartyMenuDoDrawHPBar(monIndex, menuLayout, currentHP, maxHP); +} + +void PartyMenuTryDrawHPBar(u8 monIndex, struct Pokemon *pokemon) +{ + if (GetMonData(pokemon, MON_DATA_SPECIES) && !GetMonData(pokemon, MON_DATA_IS_EGG)) + { + bool8 isDoubleBattle = IsLinkDoubleBattle(); + if (isDoubleBattle == TRUE) + { + PartyMenuDrawHPBar(monIndex, PARTY_MENU_LAYOUT_LINK_DOUBLE_BATTLE, pokemon); + } + else + { + PartyMenuDrawHPBar(monIndex, IsDoubleBattle(), pokemon); + } + } +} + +void PartyMenuDrawHPBars(void) +{ + u8 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + PartyMenuTryDrawHPBar(i, &gPlayerParty[i]); + } +} + +void SwapPokemon(struct Pokemon *a, struct Pokemon *b) +{ + struct Pokemon temp = *a; + *a = *b; + *b = temp; +} + +void SetPartyPopupMenuOffsets(u8 menuIndex, u8 *left, u8 *top, const struct PartyPopupMenu *menu) +{ + u8 bottomOffset = (2 * menu[menuIndex].numChoices) + 2; + u8 rightOffset = menu[menuIndex].width + 1; + + *left = 30 - rightOffset; + *top = 20 - bottomOffset; +} + +void ShowPartyPopupMenu(u8 menuIndex, const struct PartyPopupMenu *menu, const struct MenuAction2 *menuActions, u8 cursorPos) +{ + u8 left; + u8 top; + + SetPartyPopupMenuOffsets(menuIndex, &left, &top, menu); + sub_8089C50(left, top, menu[menuIndex].width, menu[menuIndex].numChoices, menuActions, menu[menuIndex].items); + + InitMenu(0, left + 1, top + 1, menu[menuIndex].numChoices, cursorPos, menu[menuIndex].width - 1); +} + +void ClosePartyPopupMenu(u8 index, const struct PartyPopupMenu *menu) +{ + u8 left; + u8 top; + + SetPartyPopupMenuOffsets(index, &left, &top, menu); + + MenuZeroFillWindowRect(left, top, left + menu[index].width, menu[index].numChoices * 2 + top + 1); + HandleDestroyMenuCursors(); +} + +TaskFunc PartyMenuGetPopupMenuFunc(u8 menuIndex, const struct PartyPopupMenu *menus, const struct MenuAction2 *menuActions, u8 itemIndex) +{ + u8 action = menus[menuIndex].items[itemIndex]; + return menuActions[action].func; +} u8 sub_806E834(const u8 *message, u8 arg1) { @@ -274,19 +3991,19 @@ void DisplayGiveHeldItemMessage(u8 a, u16 b, u8 c) sub_806E834(gStringVar4, c); } - -// Not sure about this one for now. -/* void PartyMenuTryGiveMonMail(u8 taskId, TaskFunc func) { + u32 var1; u16 currentItem; - struct MailStruct *r4; + struct MailStruct *mail; gTasks[taskId].func = TaskDummy; sub_806E8D0(taskId, 0, func); currentItem = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); gUnknown_0202E8F4 = 0; - r4 = &gSaveBlock1.mail[ewram1F000.unkE00[0] + ewram1F000.unkE00[2]]; + var1 = ewram1FE00.unkE00 + 6; + mail = &gSaveBlock1.mail[var1 + ewram1FE00.unkE02]; + if (currentItem != 0) { sub_806E834(gOtherText_PokeHoldingItemCantMail, 1); @@ -294,88 +4011,12 @@ void PartyMenuTryGiveMonMail(u8 taskId, TaskFunc func) } else { - GiveMailToMon2(ewram1C000.pokemon, r4); - ClearMailStruct(r4); + GiveMailToMon2(ewram1C000.pokemon, mail); + ClearMailStruct(mail); sub_806E834(gOtherText_MailTransferredMailbox, 1); CreateTask(party_menu_link_mon_held_item_object, 5); } } -*/ -__attribute__((naked)) -void PartyMenuTryGiveMonMail(u8 taskId, TaskFunc func) -{ - asm(".syntax unified\n\ - push {r4,r5,lr}\n\ - adds r2, r1, 0\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - ldr r3, _0806ECA0 @ =gTasks\n\ - lsls r1, r0, 2\n\ - adds r1, r0\n\ - lsls r1, 3\n\ - adds r1, r3\n\ - ldr r3, _0806ECA4 @ =TaskDummy\n\ - str r3, [r1]\n\ - movs r1, 0\n\ - bl sub_806E8D0\n\ - ldr r5, _0806ECA8 @ =0x0201c000\n\ - ldr r0, [r5]\n\ - movs r1, 0xC\n\ - bl GetMonData\n\ - lsls r0, 16\n\ - ldr r2, _0806ECAC @ =gUnknown_0202E8F4\n\ - movs r1, 0\n\ - strb r1, [r2]\n\ - movs r1, 0xF8\n\ - lsls r1, 6\n\ - adds r2, r5, r1\n\ - ldrb r1, [r2]\n\ - adds r1, 0x6\n\ - ldrb r2, [r2, 0x2]\n\ - adds r1, r2\n\ - lsls r2, r1, 3\n\ - adds r2, r1\n\ - lsls r2, 2\n\ - ldr r1, _0806ECB0 @ =gSaveBlock1 + 0x2B4C\n\ - adds r4, r2, r1\n\ - cmp r0, 0\n\ - beq _0806ECBC\n\ - ldr r0, _0806ECB4 @ =gOtherText_PokeHoldingItemCantMail\n\ - movs r1, 0x1\n\ - bl sub_806E834\n\ - ldr r0, _0806ECB8 @ =party_menu_link_mon_held_item_object\n\ - movs r1, 0x5\n\ - bl CreateTask\n\ - b _0806ECDA\n\ - .align 2, 0\n\ -_0806ECA0: .4byte gTasks\n\ -_0806ECA4: .4byte TaskDummy\n\ -_0806ECA8: .4byte 0x0201c000\n\ -_0806ECAC: .4byte gUnknown_0202E8F4\n\ -_0806ECB0: .4byte gSaveBlock1 + 0x2B4C\n\ -_0806ECB4: .4byte gOtherText_PokeHoldingItemCantMail\n\ -_0806ECB8: .4byte party_menu_link_mon_held_item_object\n\ -_0806ECBC:\n\ - ldr r0, [r5]\n\ - adds r1, r4, 0\n\ - bl GiveMailToMon2\n\ - adds r0, r4, 0\n\ - bl ClearMailStruct\n\ - ldr r0, _0806ECE0 @ =gOtherText_MailTransferredMailbox\n\ - movs r1, 0x1\n\ - bl sub_806E834\n\ - ldr r0, _0806ECE4 @ =party_menu_link_mon_held_item_object\n\ - movs r1, 0x5\n\ - bl CreateTask\n\ -_0806ECDA:\n\ - pop {r4,r5}\n\ - pop {r0}\n\ - bx r0\n\ - .align 2, 0\n\ -_0806ECE0: .4byte gOtherText_MailTransferredMailbox\n\ -_0806ECE4: .4byte party_menu_link_mon_held_item_object\n\ - .syntax divided\n"); -} void PartyMenuTryGiveMonHeldItem_806ECE8(u8 taskId, TaskFunc func) { @@ -503,9 +4144,8 @@ void Task_ConfirmTakeHeldMail(u8 taskId) u16 ItemIdToBattleMoveId(u16 item) { - u16 moveId = item - 289; - - return gUnknown_08376504[moveId]; + u16 machineNumber = item - ITEM_TM01; + return TMHMMoves[machineNumber]; } bool8 pokemon_has_move(struct Pokemon *pkmn, u16 move) @@ -593,7 +4233,7 @@ void Task_TeamMonTMMove4(u8 taskId) SetHeldItemIconVisibility(ewram1C000.unk4, ewram1C000.unk5); if (ewram1B000.unk282 == 1) { - sub_8070C54(taskId); + TeachMonMoveInPartyMenu(taskId); } else { @@ -611,7 +4251,7 @@ void sub_806F2FC(u8 taskId) SetHeldItemIconVisibility(ewram1C000.unk4, ewram1C000.unk5); if (ewram1B000.unk282 == 1) { - sub_8070C54(taskId); + TeachMonMoveInPartyMenu(taskId); } else { @@ -760,11 +4400,12 @@ bool8 IsHMMove(u16 move) { u8 i; - for (i = 0; i < 8; i++) + for (i = 0; i < NUM_HIDDEN_MACHINES; i++) { - if (gUnknown_08376504[50 + i] == move) + if (TMHMMoves[NUM_TECHNICAL_MACHINES + i] == move) return TRUE; } + return FALSE; } @@ -811,7 +4452,7 @@ void sub_806F8AC(u8 taskId) StringExpandPlaceholders(gStringVar4, gOtherText_HPRestoredBy); else StringExpandPlaceholders(gStringVar4, gOtherText_RegainedHealth); - SetMonIconAnim(GetMonIconSpriteId_maybe(ewram1C000.unk4, ewram1C000.unk5), ewram1C000.pokemon); + SetMonIconAnim(GetMonIconSpriteId(ewram1C000.unk4, ewram1C000.unk5), ewram1C000.pokemon); task_pc_turn_off(&gUnknown_083769A8[IsDoubleBattle() * 12 + ewram1C000.unk5 * 2], 7); ewram1B000.unk261 = 2; sub_806E834(gStringVar4, 1); @@ -838,7 +4479,7 @@ void sub_806FA18(u8 taskId) ewram1C000.unkC = 0; gTasks[taskId].data[11] -= gTasks[taskId].data[12]; SetMonData(ewram1C000.pokemon, MON_DATA_HP, (u8 *)&gTasks[taskId].data[11]); - SetMonIconAnim(GetMonIconSpriteId_maybe(ewram1C000.unk4, ewram01000.unk1), ewram1C000.pokemon); + SetMonIconAnim(GetMonIconSpriteId(ewram1C000.unk4, ewram01000.unk1), ewram1C000.pokemon); ewram1C000.unk5 = gSprites[ewram01000.unk2].data0; ewram1C000.pokemon = &gPlayerParty[ewram1C000.unk5]; gTasks[taskId].data[10] = GetMonData(ewram1C000.pokemon, MON_DATA_MAX_HP); @@ -876,10 +4517,10 @@ bool8 IsHPRecoveryItem(u16 item) { const u8 *itemEffect; - if (item == 0xAF) + if (item == ITEM_ENIGMA_BERRY) itemEffect = gSaveBlock1.enigmaBerry.itemEffect; else - itemEffect = gItemEffectTable[item - 13]; + itemEffect = gItemEffectTable[item - ITEM_POTION]; if (itemEffect[4] & 4) return TRUE; @@ -887,10 +4528,10 @@ bool8 IsHPRecoveryItem(u16 item) return FALSE; } -void PartyMenuUpdateLevelOrStatus(struct Pokemon *pkmn, u8 b) +void PartyMenuUpdateLevelOrStatus(struct Pokemon *pkmn, u8 monIndex) { - PartyMenuClearLevelStatusTilemap(b); - PartyMenuPrintMonLevelOrStatus(b, pkmn); + PartyMenuClearLevelStatusTilemap(monIndex); + PartyMenuPrintMonLevelOrStatus(monIndex, pkmn); } void GetMedicineItemEffectMessage(u16 item) @@ -1189,18 +4830,18 @@ void Task_HandleItemUseMoveMenuInput(u8 taskId) } } -void DoPPRecoveryItemEffect(u8 taskId, u16 b, TaskFunc c) +void DoPPRecoveryItemEffect(u8 taskId, u16 item, TaskFunc c) { const u8 *itemEffect; u8 taskId2; - if (b == 0xAF) + if (item == ITEM_ENIGMA_BERRY) itemEffect = gSaveBlock1.enigmaBerry.itemEffect; else - itemEffect = gItemEffectTable[b - 13]; + itemEffect = gItemEffectTable[item - ITEM_POTION]; gTasks[taskId].func = TaskDummy; taskId2 = CreateTask(TaskDummy, 5); - sub_806E8D0(taskId, b, c); + sub_806E8D0(taskId, item, c); if (!(itemEffect[4] & 0x10)) { gTasks[taskId2].data[11] = 0; @@ -1209,7 +4850,7 @@ void DoPPRecoveryItemEffect(u8 taskId, u16 b, TaskFunc c) else { PlaySE(SE_SELECT); - sub_806D538(10, 3); + PrintPartyMenuPromptText(10, 3); CreateItemUseMoveMenu(ewram1C000.unk5); gTasks[taskId2].func = Task_HandleItemUseMoveMenuInput; gMain.newKeys = 0; @@ -1230,10 +4871,10 @@ void ItemUseMoveMenu_HandleCancel(u8 taskId) HandleDestroyMenuCursors(); MenuZeroFillWindowRect(19, 10, 29, 19); if (gMain.inBattle) - gTasks[ewram1C000.unk4].func = SetUpBattlePokemonMenu; + gTasks[ewram1C000.unk4].func = HandleBattlePartyMenu; else gTasks[ewram1C000.unk4].func = sub_808B0C0; - sub_806D538(3, 0); + PrintPartyMenuPromptText(3, 0); DestroyTask(taskId); } @@ -1265,7 +4906,7 @@ void DoPPUpItemEffect(u8 taskId, u16 b, TaskFunc c) gTasks[taskId].func = TaskDummy; sub_806E8D0(taskId, b, c); PlaySE(SE_SELECT); - sub_806D538(11, 3); + PrintPartyMenuPromptText(11, 3); CreateItemUseMoveMenu(ewram1C000.unk5); CreateTask(Task_HandleItemUseMoveMenuInput, 5); gMain.newKeys = 0; @@ -1282,7 +4923,7 @@ void DoRareCandyItemEffect(u8 taskId, u16 b, TaskFunc c) if (GetMonData(ewram1C000.pokemon, MON_DATA_LEVEL) != 100) { for (i = 0; i < 6; i++) - ewram1B000.unk264[i] = GetMonData(ewram1C000.pokemon, gUnknown_08376D1C[i]); + ewram1B000.statGrowths[i] = GetMonData(ewram1C000.pokemon, StatDataTypes[i]); r0 = ExecuteTableBasedItemEffect__(ewram1C000.unk5, b, 0); } else @@ -1301,7 +4942,7 @@ void DoRareCandyItemEffect(u8 taskId, u16 b, TaskFunc c) gUnknown_0202E8F4 = 1; PlayFanfareByFanfareNum(0); - sub_8070A20(ewram1C000.unk5, ewram1C000.pokemon); + RedrawPokemonInfoInMenu(ewram1C000.unk5, ewram1C000.pokemon); RemoveBagItem(b, 1); GetMonNickname(ewram1C000.pokemon, gStringVar1); level = GetMonData(ewram1C000.pokemon, MON_DATA_LEVEL); @@ -1319,7 +4960,7 @@ void Task_RareCandy1(u8 taskId) if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) { PlaySE(SE_SELECT); - sub_8070848(taskId); + PrintStatGrowthsInLevelUpWindow(taskId); gTasks[taskId].func = Task_RareCandy2; } } @@ -1330,33 +4971,33 @@ void Task_RareCandy2(u8 taskId) if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) { PlaySE(SE_SELECT); - sub_8070968(taskId); + PrintNewStatsInLevelUpWindow(taskId); gTasks[taskId].func = Task_RareCandy3; } } #if ENGLISH -void sub_8070848(u8 taskId) +void PrintStatGrowthsInLevelUpWindow(u8 taskId) { u8 i; MenuDrawTextWindow(11, 0, 29, 7); - for (i = 0; i < DATA_COUNT; i++) + for (i = 0; i < NUM_STATS; i++) { u8 x; u8 y; u32 stat; - stat = GetMonData(ewram1C000.pokemon, gUnknown_08376D1C[i]); + stat = GetMonData(ewram1C000.pokemon, StatDataTypes[i]); - ewram1B000.unk264[i + DATA_COUNT] = stat; - ewram1B000.unk264[i] = stat - ewram1B000.unk264[i]; + ewram1B000.statGrowths[i + NUM_STATS] = stat; + ewram1B000.statGrowths[i] = stat - ewram1B000.statGrowths[i]; x = (i / 3) * 9 + 11; y = ((i % 3) << 1) + 1; - MenuPrint_PixelCoords(gUnknown_08376D04[i], (x + 1) * 8, y * 8, 1); + MenuPrint_PixelCoords(StatNames[i], (x + 1) * 8, y * 8, 1); if (i == 2) MenuPrint_PixelCoords(gOtherText_TallPlusAndRightArrow, (x + 6) * 8 + 6, y * 8, 0); @@ -1367,14 +5008,14 @@ void sub_8070848(u8 taskId) gStringVar1[1] = 0x14; gStringVar1[2] = 0x06; - ConvertIntToDecimalStringN(gStringVar1 + 3, ewram1B000.unk264[i], 1, 2); + ConvertIntToDecimalStringN(gStringVar1 + 3, ewram1B000.statGrowths[i], 1, 2); MenuPrint_PixelCoords(gStringVar1, (x + 6) * 8 + 12, y * 8, 0); } } #elif GERMAN __attribute__((naked)) -void sub_8070848(u8 taskId) { +void PrintStatGrowthsInLevelUpWindow(u8 taskId) { asm(".syntax unified\n\ push {r4-r7,lr}\n\ mov r7, r10\n\ @@ -1396,7 +5037,7 @@ void sub_8070848(u8 taskId) { _0807086C:\n\ ldr r1, _08070930 @ =0x0201c000\n\ ldr r0, [r1]\n\ - ldr r1, _08070934 @ =gUnknown_08376D1C\n\ + ldr r1, _08070934 @ =StatDataTypes\n\ adds r1, r7, r1\n\ ldrb r1, [r1]\n\ bl GetMonData\n\ @@ -1428,7 +5069,7 @@ _0807086C:\n\ adds r5, 0x1\n\ lsls r5, 24\n\ lsrs r5, 24\n\ - ldr r1, _0807093C @ =gUnknown_08376D04\n\ + ldr r1, _0807093C @ =StatNames\n\ lsls r0, r7, 2\n\ adds r0, r1\n\ ldr r1, [r0]\n\ @@ -1485,10 +5126,526 @@ _0807086C:\n\ .align 2, 0\n\ _0807092C: .4byte gStringVar1\n\ _08070930: .4byte 0x0201c000\n\ -_08070934: .4byte gUnknown_08376D1C\n\ +_08070934: .4byte StatDataTypes\n\ _08070938: .4byte 0x0201b264\n\ -_0807093C: .4byte gUnknown_08376D04\n\ +_0807093C: .4byte StatNames\n\ _08070940: .4byte gOtherText_TallPlusAndRightArrow\n\ .syntax divided\n"); } #endif + +void PrintNewStatsInLevelUpWindow(u8 taskId) +{ + u8 i; + + for (i = 0; i < NUM_STATS; i++) + { + u8 x; + u8 y; + u32 stat; + u32 newStatIndex; + + stat = GetMonData(ewram1C000.pokemon, StatDataTypes[i]); + newStatIndex = i + 6; + ewram1B000.statGrowths[newStatIndex] = stat; + + x = ((i / 3) * 9) + 11; + y = ((i % 3) << 1) + 1; + + gStringVar1[0] = EXT_CTRL_CODE_BEGIN; + gStringVar1[1] = 0x14; + gStringVar1[2] = 0x06; + + ConvertIntToDecimalStringN(gStringVar1 + 3, ewram1B000.statGrowths[newStatIndex], 1, 3); + MenuPrint_PixelCoords(gStringVar1, (x + 6) * 8 + 6, y * 8, 0); + } +} + +void RedrawPokemonInfoInMenu(u8 monIndex, struct Pokemon *pokemon) +{ + u8 statusAndPkrs; + bool8 isDoubleBattle; + u16 currentHP; + u16 maxHP; + u8 icon; + + statusAndPkrs = GetMonStatusAndPokerus(pokemon); + if (statusAndPkrs == 0 || statusAndPkrs == 6) + { + PartyMenuUpdateLevelOrStatus(pokemon, monIndex); + } + + isDoubleBattle = IsDoubleBattle(); + + currentHP = GetMonData(pokemon, MON_DATA_HP); + maxHP = GetMonData(pokemon, MON_DATA_MAX_HP); + + PartyMenuDoPrintHP(monIndex, isDoubleBattle, currentHP, maxHP); + PartyMenuTryDrawHPBar(monIndex, pokemon); + + icon = GetMonIconSpriteId(ewram1C000.unk4, monIndex); + SetMonIconAnim(icon, pokemon); + + task_pc_turn_off(&gUnknown_083769A8[IsDoubleBattle() * 12 + monIndex * 2], 7); + ewram1B000.unk261 = 2; +} + +void Task_RareCandy3(u8 taskId) +{ + if (WaitFanfare(0)) + { + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + u16 learnedMove; + u16 evolutionSpecies; + + MenuZeroFillWindowRect(11, 0, 29, 7); + + learnedMove = MonTryLearningNewMove(ewram1C000.pokemon, TRUE); + ewram1B000.unk282 = 1; + + switch (learnedMove) + { + case 0: + // No move is learned. + evolutionSpecies = GetEvolutionTargetSpecies(ewram1C000.pokemon, 0, 0); + if (evolutionSpecies != 0) + { + gCB2_AfterEvolution = sub_80A53F8; + BeginEvolutionScene(ewram1C000.pokemon, evolutionSpecies, TRUE, ewram1C000.unk5); + DestroyTask(taskId); + } + else + { + sub_8070D90(taskId); + } + break; + case 0xFFFF: + // Mon already knows 4 moves. + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[gMoveToLearn]); + + StringExpandPlaceholders(gStringVar4, gOtherText_WantsToLearn); + sub_806E834(gStringVar4, 1); + + ewram1C000.unk8 = gMoveToLearn; + gTasks[taskId].func = sub_806F358; + break; + case 0xFFFE: + // Move was already known by the mon. + gTasks[taskId].func = TeachMonMoveInPartyMenu; + break; + default: + // Mon automatically learned a move because it knew less than four moves. + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[learnedMove]); + + StringExpandPlaceholders(gStringVar4, gOtherText_LearnedMove); + sub_806E834(gStringVar4, 1); + + gTasks[taskId].func = Task_TeamMonTMMove3; + break; + } + } + } +} + +void TeachMonMoveInPartyMenu(u8 taskId) +{ + u16 learnedMove; + u16 evolutionSpecies; + + learnedMove = MonTryLearningNewMove(ewram1C000.pokemon, FALSE); + switch (learnedMove) + { + case 0: + // No move is learned. + evolutionSpecies = GetEvolutionTargetSpecies(ewram1C000.pokemon, 0, 0); + if (evolutionSpecies != 0) + { + gCB2_AfterEvolution = sub_80A53F8; + BeginEvolutionScene(ewram1C000.pokemon, evolutionSpecies, TRUE, ewram1C000.unk5); + DestroyTask(taskId); + } + else + { + sub_8070D90(taskId); + } + break; + case 0xFFFF: + // Mon already knows 4 moves. + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[gMoveToLearn]); + + StringExpandPlaceholders(gStringVar4, gOtherText_WantsToLearn); + sub_806E834(gStringVar4, 1); + + ewram1C000.unk8 = gMoveToLearn; + gTasks[taskId].func = sub_806F358; + break; + case 0xFFFE: + // Move was already known by the mon. Go on the the next move to be learned. + TeachMonMoveInPartyMenu(taskId); + break; + default: + // Mon automatically learned a move because it knew less than four moves. + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[learnedMove]); + + StringExpandPlaceholders(gStringVar4, gOtherText_LearnedMove); + sub_806E834(gStringVar4, 1); + + gTasks[taskId].func = Task_TeamMonTMMove3; + break; + } +} + +static void sub_8070D90(u8 taskId) +{ + gTasks[ewram1C000.unk4].func = ewram1C000.unk10; + DestroyTask(taskId); +} + +void DoEvolutionStoneItemEffect(u8 taskId, u16 evolutionStoneItem, TaskFunc c) +{ + PlaySE(SE_SELECT); + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, evolutionStoneItem, c); + + gCB2_AfterEvolution = sub_80A53F8; + + if (ExecuteTableBasedItemEffect__(ewram1C000.unk5, evolutionStoneItem, 0)) + { + gUnknown_0202E8F4 = 0; + sub_806E834(gOtherText_WontHaveAnyEffect, 1); + + CreateTask(sub_806FB0C, 5); + } + else + { + RemoveBagItem(evolutionStoneItem, 1); + } +} + +#ifdef NONMATCHING +u8 GetItemEffectType(u16 item) +{ + const u8 *itemEffect; + register u8 itemEffect0 asm("r1"); + u8 mask; + + // Read the item's effect properties. + if (item == ITEM_ENIGMA_BERRY) + { + itemEffect = gSaveBlock1.enigmaBerry.itemEffect; + } + else + { + itemEffect = gItemEffectTable[item - ITEM_POTION]; + } + + itemEffect0 = itemEffect[0]; + mask = 0x3F; + + if ((itemEffect0 & mask) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & 0x80)) + { + return 0; + } + else if (itemEffect0 & 0x40) + { + return 10; + } + else if (itemEffect[3] & 0x40) + { + return 1; + } + else if ((itemEffect[3] & mask) || (itemEffect0 >> 7)) + { + if ((itemEffect[3] & mask) == 0x20) + { + return 4; + } + else if ((itemEffect[3] & mask) == 0x10) + { + return 3; + } + else if ((itemEffect[3] & mask) == 0x8) + { + return 5; + } + else if ((itemEffect[3] & mask) == 0x4) + { + return 6; + } + else if ((itemEffect[3] & mask) == 0x2) + { + return 7; + } + else if ((itemEffect[3] & mask) == 0x1) + { + return 8; + } + else if ((itemEffect0 >> 7) != 0 && (itemEffect[3] & mask) == 0) + { + return 9; + } + else + { + return 11; + } + } + else if (itemEffect[4] & 0x44) + { + return 2; + } + else if (itemEffect[4] & 0x2) + { + return 12; + } + else if (itemEffect[4] & 0x1) + { + return 13; + } + else if (itemEffect[5] & 0x8) + { + return 14; + } + else if (itemEffect[5] & 0x4) + { + return 15; + } + else if (itemEffect[5] & 0x2) + { + return 16; + } + else if (itemEffect[5] & 0x1) + { + return 17; + } + else if (itemEffect[4] & 0x80) + { + return 18; + } + else if (itemEffect[4] & 0x20) + { + return 19; + } + else if (itemEffect[5] & 0x10) + { + return 20; + } + else if (itemEffect[4] & 0x18) + { + return 21; + } + else + { + return 22; + } +} +#else +__attribute__((naked)) +u8 GetItemEffectType(u16 item) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xAF\n\ + bne _08070E5C\n\ + ldr r4, _08070E58 @ =gSaveBlock1 + 0x3676\n\ + b _08070E66\n\ + .align 2, 0\n\ +_08070E58: .4byte gSaveBlock1 + 0x3676\n\ +_08070E5C:\n\ + ldr r1, _08070E8C @ =gItemEffectTable\n\ + subs r0, 0xD\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r4, [r0]\n\ +_08070E66:\n\ + ldrb r1, [r4]\n\ + movs r5, 0x3F\n\ + adds r0, r5, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08070E88\n\ + ldrb r0, [r4, 0x1]\n\ + cmp r0, 0\n\ + bne _08070E88\n\ + ldrb r0, [r4, 0x2]\n\ + cmp r0, 0\n\ + bne _08070E88\n\ + ldrb r3, [r4, 0x3]\n\ + movs r0, 0x80\n\ + ands r0, r3\n\ + cmp r0, 0\n\ + beq _08070E90\n\ +_08070E88:\n\ + movs r0, 0\n\ + b _08070F8A\n\ + .align 2, 0\n\ +_08070E8C: .4byte gItemEffectTable\n\ +_08070E90:\n\ + movs r2, 0x40\n\ + adds r0, r2, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070E9E\n\ + movs r0, 0xA\n\ + b _08070F8A\n\ +_08070E9E:\n\ + adds r0, r2, 0\n\ + ands r0, r3\n\ + cmp r0, 0\n\ + beq _08070EAA\n\ + movs r0, 0x1\n\ + b _08070F8A\n\ +_08070EAA:\n\ + adds r2, r5, 0\n\ + ands r2, r3\n\ + cmp r2, 0\n\ + bne _08070EB8\n\ + lsrs r0, r1, 7\n\ + cmp r0, 0\n\ + beq _08070EFA\n\ +_08070EB8:\n\ + cmp r2, 0x20\n\ + bne _08070EC0\n\ + movs r0, 0x4\n\ + b _08070F8A\n\ +_08070EC0:\n\ + cmp r2, 0x10\n\ + bne _08070EC8\n\ + movs r0, 0x3\n\ + b _08070F8A\n\ +_08070EC8:\n\ + cmp r2, 0x8\n\ + bne _08070ED0\n\ + movs r0, 0x5\n\ + b _08070F8A\n\ +_08070ED0:\n\ + cmp r2, 0x4\n\ + bne _08070ED8\n\ + movs r0, 0x6\n\ + b _08070F8A\n\ +_08070ED8:\n\ + cmp r2, 0x2\n\ + bne _08070EE0\n\ + movs r0, 0x7\n\ + b _08070F8A\n\ +_08070EE0:\n\ + cmp r2, 0x1\n\ + bne _08070EE8\n\ + movs r0, 0x8\n\ + b _08070F8A\n\ +_08070EE8:\n\ + lsrs r0, r1, 7\n\ + cmp r0, 0\n\ + beq _08070EF6\n\ + cmp r2, 0\n\ + bne _08070EF6\n\ + movs r0, 0x9\n\ + b _08070F8A\n\ +_08070EF6:\n\ + movs r0, 0xB\n\ + b _08070F8A\n\ +_08070EFA:\n\ + ldrb r1, [r4, 0x4]\n\ + movs r0, 0x44\n\ + ands r0, r1\n\ + adds r2, r1, 0\n\ + cmp r0, 0\n\ + beq _08070F0A\n\ + movs r0, 0x2\n\ + b _08070F8A\n\ +_08070F0A:\n\ + movs r5, 0x2\n\ + adds r0, r5, 0\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08070F18\n\ + movs r0, 0xC\n\ + b _08070F8A\n\ +_08070F18:\n\ + movs r3, 0x1\n\ + adds r0, r3, 0\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08070F26\n\ + movs r0, 0xD\n\ + b _08070F8A\n\ +_08070F26:\n\ + ldrb r1, [r4, 0x5]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070F34\n\ + movs r0, 0xE\n\ + b _08070F8A\n\ +_08070F34:\n\ + movs r0, 0x4\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070F40\n\ + movs r0, 0xF\n\ + b _08070F8A\n\ +_08070F40:\n\ + adds r0, r5, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070F4C\n\ + movs r0, 0x10\n\ + b _08070F8A\n\ +_08070F4C:\n\ + adds r0, r3, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070F58\n\ + movs r0, 0x11\n\ + b _08070F8A\n\ +_08070F58:\n\ + movs r0, 0x80\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08070F64\n\ + movs r0, 0x12\n\ + b _08070F8A\n\ +_08070F64:\n\ + movs r0, 0x20\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08070F70\n\ + movs r0, 0x13\n\ + b _08070F8A\n\ +_08070F70:\n\ + movs r0, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08070F7C\n\ + movs r0, 0x14\n\ + b _08070F8A\n\ +_08070F7C:\n\ + movs r0, 0x18\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _08070F88\n\ + movs r0, 0x16\n\ + b _08070F8A\n\ +_08070F88:\n\ + movs r0, 0x15\n\ +_08070F8A:\n\ + pop {r4,r5}\n\ + pop {r1}\n\ + bx r1\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +void unref_sub_8070F90(void) +{ + FlagSet(SYS_POKEDEX_GET); + FlagSet(SYS_POKEMON_GET); + FlagSet(SYS_POKENAV_GET); +} |