summaryrefslogtreecommitdiff
path: root/src/pokenav_match_call_gfx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pokenav_match_call_gfx.c')
-rwxr-xr-xsrc/pokenav_match_call_gfx.c1301
1 files changed, 1301 insertions, 0 deletions
diff --git a/src/pokenav_match_call_gfx.c b/src/pokenav_match_call_gfx.c
new file mode 100755
index 000000000..056ab2f1d
--- /dev/null
+++ b/src/pokenav_match_call_gfx.c
@@ -0,0 +1,1301 @@
+#include "global.h"
+#include "bg.h"
+#include "data.h"
+#include "decompress.h"
+#include "dma3.h"
+#include "international_string_util.h"
+#include "main.h"
+#include "match_call.h"
+#include "menu.h"
+#include "overworld.h"
+#include "palette.h"
+#include "pokenav.h"
+#include "region_map.h"
+#include "sound.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "text.h"
+#include "text_window.h"
+#include "trig.h"
+#include "window.h"
+#include "constants/game_stat.h"
+#include "constants/region_map_sections.h"
+#include "constants/songs.h"
+
+#define GFXTAG_CURSOR 7
+#define GFXTAG_TRAINER_PIC 8
+#define PALTAG_CURSOR 12
+#define PALTAG_TRAINER_PIC 13
+
+struct Pokenav_MatchCallGfx
+{
+ bool32 (*isTaskActiveCB)(void);
+ u32 loopTaskId;
+ u8 filler8[6];
+ bool8 skipHangUpSE;
+ bool8 newRematchRequest;
+ u16 locWindowId;
+ u16 infoBoxWindowId;
+ u16 msgBoxWindowId;
+ s16 pageDelta;
+ u8 unused18;
+ u8 unused19;
+ u16 trainerPicPalOffset;
+ struct Sprite *optionsCursorSprite;
+ struct Sprite *trainerPicSprite;
+ u8 bgTilemapBuffer1[BG_SCREEN_SIZE];
+ u8 unusedTilemapBuffer[BG_SCREEN_SIZE];
+ u8 bgTilemapBuffer2[BG_SCREEN_SIZE];
+ u8 *trainerPicGfxPtr;
+ u8 trainerPicGfx[0x800];
+ u8 trainerPicPal[0x20];
+};
+
+static bool32 GetCurrentLoopedTaskActive(void);
+static u32 LoopedTask_OpenMatchCall(s32);
+static void CreateMatchCallList(void);
+static void DestroyMatchCallList(void);
+static void FreeMatchCallSprites(void);
+static void LoadCallWindowAndFade(struct Pokenav_MatchCallGfx *);
+static void DrawMatchCallLeftColumnWindows(struct Pokenav_MatchCallGfx *);
+static void UpdateMatchCallInfoBox(struct Pokenav_MatchCallGfx *);
+static void PrintMatchCallLocation(struct Pokenav_MatchCallGfx *, int);
+static void AllocMatchCallSprites(void);
+static void SetPokeballIconsFlashing(bool32);
+static void PrintMatchCallSelectionOptions(struct Pokenav_MatchCallGfx *);
+static bool32 ShowOptionsCursor(struct Pokenav_MatchCallGfx *);
+static void UpdateCursorGfxPos(struct Pokenav_MatchCallGfx *, int);
+static bool32 IsDma3ManagerBusyWithBgCopy1(struct Pokenav_MatchCallGfx *);
+static void UpdateWindowsReturnToTrainerList(struct Pokenav_MatchCallGfx *);
+static void DrawMsgBoxForMatchCallMsg(struct Pokenav_MatchCallGfx *);
+static bool32 IsDma3ManagerBusyWithBgCopy2(struct Pokenav_MatchCallGfx *);
+static void PrintCallingDots(struct Pokenav_MatchCallGfx *);
+static bool32 WaitForCallingDotsText(struct Pokenav_MatchCallGfx *);
+static void PrintMatchCallMessage(struct Pokenav_MatchCallGfx *);
+static bool32 WaitForMatchCallMessageText(struct Pokenav_MatchCallGfx *);
+static void DrawMsgBoxForCloseByMsg(struct Pokenav_MatchCallGfx *);
+static void PrintTrainerIsCloseBy(struct Pokenav_MatchCallGfx *);
+static bool32 WaitForTrainerIsCloseByText(struct Pokenav_MatchCallGfx *);
+static void EraseCallMessageBox(struct Pokenav_MatchCallGfx *);
+static bool32 WaitForCallMessageBoxErase(struct Pokenav_MatchCallGfx *);
+static void UpdateWindowsToShowCheckPage(struct Pokenav_MatchCallGfx *);
+static void LoadCheckPageTrainerPic(struct Pokenav_MatchCallGfx *);
+static bool32 WaitForTrainerPic(struct Pokenav_MatchCallGfx *);
+static void TrainerPicSlideOffscreen(struct Pokenav_MatchCallGfx *);
+static void Task_FlashPokeballIcons(u8);
+static void TryDrawRematchPokeballIcon(u16, u32, u32);
+static void PrintNumberRegisteredLabel(u16);
+static void PrintNumberRegistered(u16);
+static void PrintNumberOfBattlesLabel(u16);
+static void PrintNumberOfBattles(u16);
+static void PrintMatchCallInfoLabel(u16, const u8 *, int);
+static void PrintMatchCallInfoNumber(u16, const u8 *, int);
+static void CreateOptionsCursorSprite(struct Pokenav_MatchCallGfx *, int);
+static void CloseMatchCallSelectOptionsWindow(struct Pokenav_MatchCallGfx *);
+static struct Sprite *CreateTrainerPicSprite(void);
+static void SpriteCB_TrainerPicSlideOnscreen(struct Sprite *);
+static void SpriteCB_TrainerPicSlideOffscreen(struct Sprite *);
+static void SpriteCB_OptionsCursor(struct Sprite *);
+static u32 MatchCallListCursorDown(s32);
+static u32 MatchCallListCursorUp(s32);
+static u32 MatchCallListPageDown(s32);
+static u32 MatchCallListPageUp(s32);
+static u32 SelectMatchCallEntry(s32);
+static u32 MoveMatchCallOptionsCursor(s32);
+static u32 CancelMatchCallSelection(s32);
+static u32 DoMatchCallMessage(s32);
+static u32 DoTrainerCloseByMessage(s32);
+static u32 CloseMatchCallMessage(s32);
+static u32 ShowCheckPage(s32);
+static u32 ShowCheckPageUp(s32);
+static u32 ShowCheckPageDown(s32);
+static u32 ExitCheckPage(s32);
+static u32 ExitMatchCall(s32);
+
+static const u16 sMatchCallUI_Pal[] = INCBIN_U16("graphics/pokenav/match_call/ui.gbapal");
+static const u32 sMatchCallUI_Gfx[] = INCBIN_U32("graphics/pokenav/match_call/ui.4bpp.lz");
+static const u32 sMatchCallUI_Tilemap[] = INCBIN_U32("graphics/pokenav/match_call/ui.bin.lz");
+static const u16 sOptionsCursor_Pal[] = INCBIN_U16("graphics/pokenav/match_call/options_cursor.gbapal");
+static const u32 sOptionsCursor_Gfx[] = INCBIN_U32("graphics/pokenav/match_call/options_cursor.4bpp.lz");
+static const u16 sCallWindow_Pal[] = INCBIN_U16("graphics/pokenav/match_call/call_window.gbapal");
+static const u16 sListWindow_Pal[] = INCBIN_U16("graphics/pokenav/match_call/list_window.gbapal");
+static const u16 sPokeball_Pal[] = INCBIN_U16("graphics/pokenav/match_call/pokeball.gbapal");
+static const u32 sPokeball_Gfx[] = INCBIN_U32("graphics/pokenav/match_call/pokeball.4bpp.lz");
+
+static const struct BgTemplate sMatchCallBgTemplates[3] =
+{
+ {
+ .bg = 1,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 0x1F,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0
+ },
+ {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 0x06,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x80
+ },
+ {
+ .bg = 3,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 0x07,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0
+ }
+};
+
+static const LoopedTask sMatchCallLoopTaskFuncs[] =
+{
+ [POKENAV_MC_FUNC_NONE] = NULL,
+ [POKENAV_MC_FUNC_DOWN] = MatchCallListCursorDown,
+ [POKENAV_MC_FUNC_UP] = MatchCallListCursorUp,
+ [POKENAV_MC_FUNC_PG_DOWN] = MatchCallListPageDown,
+ [POKENAV_MC_FUNC_PG_UP] = MatchCallListPageUp,
+ [POKENAV_MC_FUNC_SELECT] = SelectMatchCallEntry,
+ [POKENAV_MC_FUNC_MOVE_OPTIONS_CURSOR] = MoveMatchCallOptionsCursor,
+ [POKENAV_MC_FUNC_CANCEL] = CancelMatchCallSelection,
+ [POKENAV_MC_FUNC_CALL_MSG] = DoMatchCallMessage,
+ [POKENAV_MC_FUNC_NEARBY_MSG] = DoTrainerCloseByMessage,
+ [POKENAV_MC_FUNC_EXIT_CALL] = CloseMatchCallMessage,
+ [POKENAV_MC_FUNC_SHOW_CHECK_PAGE] = ShowCheckPage,
+ [POKENAV_MC_FUNC_CHECK_PAGE_UP] = ShowCheckPageUp,
+ [POKENAV_MC_FUNC_CHECK_PAGE_DOWN] = ShowCheckPageDown,
+ [POKENAV_MC_FUNC_EXIT_CHECK_PAGE] = ExitCheckPage,
+ [POKENAV_MC_FUNC_EXIT] = ExitMatchCall
+};
+
+static const struct WindowTemplate sMatchCallLocationWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 0,
+ .tilemapTop = 5,
+ .width = 11,
+ .height = 2,
+ .paletteNum = 2,
+ .baseBlock = 16
+};
+
+static const struct WindowTemplate sMatchCallInfoBoxWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 0,
+ .tilemapTop = 9,
+ .width = 11,
+ .height = 8,
+ .paletteNum = 2,
+ .baseBlock = 38
+};
+
+static const u8 *const sMatchCallOptionTexts[MATCH_CALL_OPTION_COUNT] =
+{
+ [MATCH_CALL_OPTION_CALL] = gText_Call,
+ [MATCH_CALL_OPTION_CHECK] = gText_Check,
+ [MATCH_CALL_OPTION_CANCEL] = gText_Cancel6
+};
+
+// The series of 5 dots that appear when someone is called with Match Call
+static const u8 sText_CallingDots[] = _("·{PAUSE 4}·{PAUSE 4}·{PAUSE 4}·{PAUSE 4}·\p");
+
+static const struct WindowTemplate sCallMsgBoxWindowTemplate =
+{
+ .bg = 1,
+ .tilemapLeft = 1,
+ .tilemapTop = 12,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 1,
+ .baseBlock = 10
+};
+
+static const struct CompressedSpriteSheet sOptionsCursorSpriteSheets[1] =
+{
+ {sOptionsCursor_Gfx, 0x40, GFXTAG_CURSOR}
+};
+
+static const struct SpritePalette sOptionsCursorSpritePalettes[2] =
+{
+ {sOptionsCursor_Pal, PALTAG_CURSOR}
+};
+
+static const struct OamData sOptionsCursorOamData =
+{
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(8x16),
+ .x = 0,
+ .size = SPRITE_SIZE(8x16),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+};
+
+static const struct SpriteTemplate sOptionsCursorSpriteTemplate =
+{
+ .tileTag = GFXTAG_CURSOR,
+ .paletteTag = PALTAG_CURSOR,
+ .oam = &sOptionsCursorOamData,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_OptionsCursor,
+};
+
+static const struct OamData sTrainerPicOamData =
+{
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+};
+
+static const struct SpriteTemplate sTrainerPicSpriteTemplate =
+{
+ .tileTag = GFXTAG_TRAINER_PIC,
+ .paletteTag = PALTAG_TRAINER_PIC,
+ .oam = &sTrainerPicOamData,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+bool32 OpenMatchCall(void)
+{
+ struct Pokenav_MatchCallGfx *gfx = AllocSubstruct(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN, sizeof(struct Pokenav_MatchCallGfx));
+ if (!gfx)
+ return FALSE;
+
+ gfx->unused19 = 0;
+ gfx->loopTaskId = CreateLoopedTask(LoopedTask_OpenMatchCall, 1);
+ gfx->isTaskActiveCB = GetCurrentLoopedTaskActive;
+ return TRUE;
+}
+
+void CreateMatchCallLoopedTask(s32 index)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ gfx->loopTaskId = CreateLoopedTask(sMatchCallLoopTaskFuncs[index], 1);
+ gfx->isTaskActiveCB = GetCurrentLoopedTaskActive;
+}
+
+bool32 IsMatchCallLoopedTaskActive(void)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ return gfx->isTaskActiveCB();
+}
+
+void FreeMatchCallSubstruct2(void)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ FreeMatchCallSprites();
+ DestroyMatchCallList();
+ RemoveWindow(gfx->infoBoxWindowId);
+ RemoveWindow(gfx->locWindowId);
+ RemoveWindow(gfx->msgBoxWindowId);
+ FreePokenavSubstruct(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+}
+
+static bool32 GetCurrentLoopedTaskActive(void)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ return IsLoopedTaskActive(gfx->loopTaskId);
+}
+
+static u32 LoopedTask_OpenMatchCall(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ InitBgTemplates(sMatchCallBgTemplates, ARRAY_COUNT(sMatchCallBgTemplates));
+ ChangeBgX(2, 0, BG_COORD_SET);
+ ChangeBgY(2, 0, BG_COORD_SET);
+ DecompressAndCopyTileDataToVram(2, sMatchCallUI_Gfx, 0, 0, 0);
+ SetBgTilemapBuffer(2, gfx->bgTilemapBuffer2);
+ CopyToBgTilemapBuffer(2, sMatchCallUI_Tilemap, 0, 0);
+ CopyBgTilemapBufferToVram(2);
+ CopyPaletteIntoBufferUnfaded(sMatchCallUI_Pal, 0x20, 0x20);
+ CopyBgTilemapBufferToVram(2);
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (FreeTempTileDataBuffersIfPossible())
+ return LT_PAUSE;
+
+ BgDmaFill(1, 0, 0, 1);
+ SetBgTilemapBuffer(1, gfx->bgTilemapBuffer1);
+ FillBgTilemapBufferRect_Palette0(1, 0x1000, 0, 0, 32, 20);
+ CopyPaletteIntoBufferUnfaded(sCallWindow_Pal, 0x10, 0x20);
+ CopyBgTilemapBufferToVram(1);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ if (FreeTempTileDataBuffersIfPossible())
+ return LT_PAUSE;
+
+ LoadCallWindowAndFade(gfx);
+ DecompressAndCopyTileDataToVram(3, sPokeball_Gfx, 0, 0, 0);
+ CopyPaletteIntoBufferUnfaded(sListWindow_Pal, 0x30, 0x20);
+ CopyPaletteIntoBufferUnfaded(sPokeball_Pal, 0x50, 0x20);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (FreeTempTileDataBuffersIfPossible() || !IsMatchCallListInitFinished())
+ return LT_PAUSE;
+
+ CreateMatchCallList();
+ return LT_INC_AND_PAUSE;
+ case 4:
+ if (IsCreatePokenavListTaskActive())
+ return LT_PAUSE;
+
+ DrawMatchCallLeftColumnWindows(gfx);
+ return LT_INC_AND_PAUSE;
+ case 5:
+ UpdateMatchCallInfoBox(gfx);
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 6:
+ ChangeBgX(1, 0, BG_COORD_SET);
+ ChangeBgY(1, 0, BG_COORD_SET);
+ ShowBg(2);
+ ShowBg(3);
+ ShowBg(1);
+ AllocMatchCallSprites();
+ LoadLeftHeaderGfxForIndex(3);
+ ShowLeftHeaderGfx(POKENAV_GFX_MATCH_CALL_MENU, 1, 0);
+ PokenavFadeScreen(POKENAV_FADE_FROM_BLACK);
+ return LT_INC_AND_PAUSE;
+ case 7:
+ if (IsPaletteFadeActive() || AreLeftHeaderSpritesMoving())
+ return LT_PAUSE;
+
+ SetPokeballIconsFlashing(TRUE);
+ return LT_FINISH;
+ default:
+ return LT_FINISH;
+ }
+}
+
+static u32 MatchCallListCursorDown(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ switch (PokenavList_MoveCursorDown())
+ {
+ case 0:
+ break;
+ case 1:
+ PlaySE(SE_SELECT);
+ return LT_SET_STATE(2);
+ case 2:
+ PlaySE(SE_SELECT);
+ // fall through
+ default:
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (PokenavList_IsMoveWindowTaskActive())
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return LT_PAUSE;
+ break;
+ }
+ return LT_FINISH;
+}
+
+static u32 MatchCallListCursorUp(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ switch (PokenavList_MoveCursorUp())
+ {
+ case 0:
+ break;
+ case 1:
+ PlaySE(SE_SELECT);
+ return LT_SET_STATE(2);
+ case 2:
+ PlaySE(SE_SELECT);
+ // fall through
+ default:
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (PokenavList_IsMoveWindowTaskActive())
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return LT_PAUSE;
+ break;
+ }
+ return LT_FINISH;
+}
+
+static u32 MatchCallListPageDown(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ switch (PokenavList_PageDown())
+ {
+ case 0:
+ break;
+ case 1:
+ PlaySE(SE_SELECT);
+ return LT_SET_STATE(2);
+ case 2:
+ PlaySE(SE_SELECT);
+ // fall through
+ default:
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (PokenavList_IsMoveWindowTaskActive())
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return LT_PAUSE;
+ break;
+ }
+ return LT_FINISH;
+}
+
+static u32 MatchCallListPageUp(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ switch (PokenavList_PageUp())
+ {
+ case 0:
+ break;
+ case 1:
+ PlaySE(SE_SELECT);
+ return LT_SET_STATE(2);
+ case 2:
+ PlaySE(SE_SELECT);
+ // fall through
+ default:
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (PokenavList_IsMoveWindowTaskActive())
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintMatchCallLocation(gfx, 0);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return LT_PAUSE;
+ break;
+ }
+ return LT_FINISH;
+}
+
+static u32 SelectMatchCallEntry(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ PrintMatchCallSelectionOptions(gfx);
+ PrintHelpBarText(HELPBAR_MC_CALL_MENU);
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (ShowOptionsCursor(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 MoveMatchCallOptionsCursor(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx;
+ u16 cursorPos;
+
+ PlaySE(SE_SELECT);
+ gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ cursorPos = GetMatchCallOptionCursorPos();
+ UpdateCursorGfxPos(gfx, cursorPos);
+ return LT_FINISH;
+}
+
+static u32 CancelMatchCallSelection(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ UpdateWindowsReturnToTrainerList(gfx);
+ PrintHelpBarText(HELPBAR_MC_TRAINER_LIST);
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy1(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 DoMatchCallMessage(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PokenavList_ToggleVerticalArrows(TRUE);
+ DrawMsgBoxForMatchCallMsg(gfx);
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy2(gfx))
+ return LT_PAUSE;
+
+ PrintCallingDots(gfx);
+ PlaySE(SE_POKENAV_CALL);
+ gfx->skipHangUpSE = FALSE;
+ return LT_INC_AND_PAUSE;
+ case 2:
+ if (WaitForCallingDotsText(gfx))
+ return LT_PAUSE;
+
+ PrintMatchCallMessage(gfx);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (WaitForMatchCallMessageText(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 DoTrainerCloseByMessage(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ DrawMsgBoxForCloseByMsg(gfx);
+ PokenavList_ToggleVerticalArrows(TRUE);
+ gfx->skipHangUpSE = TRUE;
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy2(gfx))
+ return LT_PAUSE;
+
+ PrintTrainerIsCloseBy(gfx);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ if (WaitForTrainerIsCloseByText(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 CloseMatchCallMessage(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ u32 result = LT_INC_AND_PAUSE;
+
+ switch (state)
+ {
+ case 0:
+ if (!gfx->skipHangUpSE)
+ PlaySE(SE_POKENAV_HANG_UP);
+
+ PlaySE(SE_SELECT);
+ break;
+ case 1:
+ EraseCallMessageBox(gfx);
+ break;
+ case 2:
+ if (WaitForCallMessageBoxErase(gfx))
+ result = LT_PAUSE;
+ break;
+ case 3:
+ UpdateWindowsReturnToTrainerList(gfx);
+ break;
+ case 4:
+ if (IsDma3ManagerBusyWithBgCopy1(gfx))
+ result = LT_PAUSE;
+
+ PrintHelpBarText(HELPBAR_MC_TRAINER_LIST);
+ break;
+ case 5:
+ if (WaitForHelpBar())
+ {
+ result = LT_PAUSE;
+ }
+ else
+ {
+ if (gfx->newRematchRequest)
+ {
+ // This call was a new rematch request,
+ // add the Pokéball icon to their entry
+ PokenavList_DrawCurrentItemIcon();
+ result = LT_INC_AND_CONTINUE;
+ }
+ else
+ {
+ PokenavList_ToggleVerticalArrows(FALSE);
+ result = LT_FINISH;
+ }
+ }
+ break;
+ case 6:
+ if (IsDma3ManagerBusyWithBgCopy())
+ {
+ result = LT_PAUSE;
+ }
+ else
+ {
+ PokenavList_ToggleVerticalArrows(FALSE);
+ result = LT_FINISH;
+ }
+ break;
+ }
+
+ return result;
+}
+
+static u32 ShowCheckPage(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ PokenavList_EraseListForCheckPage();
+ UpdateWindowsToShowCheckPage(gfx);
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (PokenavList_IsTaskActive() || IsDma3ManagerBusyWithBgCopy1(gfx))
+ return LT_PAUSE;
+
+ PrintHelpBarText(HELPBAR_MC_CHECK_PAGE);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintCheckPageInfo(0);
+ LoadCheckPageTrainerPic(gfx);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ if (PokenavList_IsTaskActive() || WaitForTrainerPic(gfx) || WaitForHelpBar())
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 ShowCheckPageDown(s32 state)
+{
+ int topId;
+ int delta;
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ topId = PokenavList_GetTopIndex();
+ delta = GetIndexDeltaOfNextCheckPageDown(topId);
+ if (delta)
+ {
+ PlaySE(SE_SELECT);
+ gfx->pageDelta = delta;
+ TrainerPicSlideOffscreen(gfx);
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (WaitForTrainerPic(gfx))
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, gfx->pageDelta);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintCheckPageInfo(gfx->pageDelta);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ LoadCheckPageTrainerPic(gfx);
+ return LT_INC_AND_PAUSE;
+ case 4:
+ if (PokenavList_IsTaskActive() || WaitForTrainerPic(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 ExitCheckPage(s32 state)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ TrainerPicSlideOffscreen(gfx);
+ PokenavList_ReshowListFromCheckPage();
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (PokenavList_IsTaskActive() || WaitForTrainerPic(gfx))
+ return LT_PAUSE;
+
+ PrintHelpBarText(HELPBAR_MC_TRAINER_LIST);
+ UpdateMatchCallInfoBox(gfx);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 ShowCheckPageUp(s32 state)
+{
+ int topId;
+ int delta;
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ switch (state)
+ {
+ case 0:
+ topId = PokenavList_GetTopIndex();
+ delta = GetIndexDeltaOfNextCheckPageUp(topId);
+ if (delta)
+ {
+ PlaySE(SE_SELECT);
+ gfx->pageDelta = delta;
+ TrainerPicSlideOffscreen(gfx);
+ return LT_INC_AND_PAUSE;
+ }
+ break;
+ case 1:
+ if (WaitForTrainerPic(gfx))
+ return LT_PAUSE;
+
+ PrintMatchCallLocation(gfx, gfx->pageDelta);
+ return LT_INC_AND_PAUSE;
+ case 2:
+ PrintCheckPageInfo(gfx->pageDelta);
+ return LT_INC_AND_PAUSE;
+ case 3:
+ LoadCheckPageTrainerPic(gfx);
+ return LT_INC_AND_PAUSE;
+ case 4:
+ if (PokenavList_IsTaskActive() || WaitForTrainerPic(gfx))
+ return LT_PAUSE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static u32 ExitMatchCall(s32 state)
+{
+ switch (state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ SetPokeballIconsFlashing(FALSE);
+ PokenavFadeScreen(POKENAV_FADE_TO_BLACK);
+ SlideMenuHeaderDown();
+ return LT_INC_AND_PAUSE;
+ case 1:
+ if (IsPaletteFadeActive() || MainMenuLoopedTaskIsBusy())
+ return LT_PAUSE;
+
+ SetLeftHeaderSpritesInvisibility();
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+static void CreateMatchCallList(void)
+{
+ struct PokenavListTemplate template;
+ template.list = (struct PokenavListItem *)GetMatchCallList();
+ template.count = GetNumberRegistered();
+ template.itemSize = sizeof(struct PokenavListItem);
+ template.startIndex = 0;
+ template.item_X = 13;
+ template.windowWidth = 16;
+ template.listTop = 1;
+ template.maxShowed = 8;
+ template.fillValue = 3;
+ template.fontId = FONT_NARROW;
+ template.bufferItemFunc = (PokenavListBufferItemFunc)BufferMatchCallNameAndDesc;
+ template.iconDrawFunc = TryDrawRematchPokeballIcon;
+ CreatePokenavList(&sMatchCallBgTemplates[2], &template, 2);
+ CreateTask(Task_FlashPokeballIcons, 7);
+}
+
+static void DestroyMatchCallList(void)
+{
+ DestroyPokenavList();
+ DestroyTask(FindTaskIdByFunc(Task_FlashPokeballIcons));
+}
+
+#define tSinIdx data[0]
+#define tSinVal data[1]
+#define tActive data[15]
+
+static void SetPokeballIconsFlashing(bool32 active)
+{
+ u8 taskId = FindTaskIdByFunc(Task_FlashPokeballIcons);
+ if (taskId != TASK_NONE)
+ gTasks[taskId].tActive = active;
+}
+
+static void Task_FlashPokeballIcons(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (tActive)
+ {
+ tSinIdx += 4;
+ tSinIdx &= 0x7F;
+ tSinVal = gSineTable[tSinIdx] >> 4;
+ PokenavCopyPalette(sPokeball_Pal, &sPokeball_Pal[0x10], 0x10, 0x10, tSinVal, &gPlttBufferUnfaded[0x50]);
+ if (!gPaletteFade.active)
+ CpuCopy32(&gPlttBufferUnfaded[0x50], &gPlttBufferFaded[0x50], 0x20);
+ }
+}
+
+#undef tSinIdx
+#undef tSinVal
+#undef tActive
+
+enum {
+ POKEBALL_ICON_TOP = 0x5000,
+ POKEBALL_ICON_BOTTOM,
+ POKEBALL_ICON_EMPTY,
+};
+
+static void TryDrawRematchPokeballIcon(u16 windowId, u32 rematchId, u32 tileOffset)
+{
+ u8 bg = GetWindowAttribute(windowId, WINDOW_BG);
+ u16 *tilemap = GetBgTilemapBuffer(bg);
+ tilemap += tileOffset * 64 + 0x1D;
+ if (ShouldDrawRematchPokeballIcon(rematchId))
+ {
+ tilemap[0] = POKEBALL_ICON_TOP;
+ tilemap[0x20] = POKEBALL_ICON_BOTTOM;
+ }
+ else
+ {
+ tilemap[0] = POKEBALL_ICON_EMPTY;
+ tilemap[0x20] = POKEBALL_ICON_EMPTY;
+ }
+}
+
+void ClearRematchPokeballIcon(u16 windowId, u32 tileOffset)
+{
+ u8 bg = GetWindowAttribute(windowId, WINDOW_BG);
+ u16 *tilemap = GetBgTilemapBuffer(bg);
+ tilemap += tileOffset * 64 + 0x1D;
+ tilemap[0] = POKEBALL_ICON_EMPTY;
+ tilemap[0x20] = POKEBALL_ICON_EMPTY;
+}
+
+static void DrawMatchCallLeftColumnWindows(struct Pokenav_MatchCallGfx *gfx)
+{
+ gfx->locWindowId = AddWindow(&sMatchCallLocationWindowTemplate);
+ gfx->infoBoxWindowId = AddWindow(&sMatchCallInfoBoxWindowTemplate);
+ FillWindowPixelBuffer(gfx->locWindowId, PIXEL_FILL(1));
+ PutWindowTilemap(gfx->locWindowId);
+ FillWindowPixelBuffer(gfx->infoBoxWindowId, PIXEL_FILL(1));
+ PutWindowTilemap(gfx->infoBoxWindowId);
+ CopyWindowToVram(gfx->locWindowId, COPYWIN_MAP);
+}
+
+static void UpdateMatchCallInfoBox(struct Pokenav_MatchCallGfx *gfx)
+{
+ FillWindowPixelBuffer(gfx->infoBoxWindowId, PIXEL_FILL(1));
+ PrintNumberRegisteredLabel(gfx->infoBoxWindowId);
+ PrintNumberRegistered(gfx->infoBoxWindowId);
+ PrintNumberOfBattlesLabel(gfx->infoBoxWindowId);
+ PrintNumberOfBattles(gfx->infoBoxWindowId);
+ CopyWindowToVram(gfx->infoBoxWindowId, COPYWIN_GFX);
+}
+
+static void PrintNumberRegisteredLabel(u16 windowId)
+{
+ PrintMatchCallInfoLabel(windowId, gText_NumberRegistered, 0);
+}
+
+static void PrintNumberRegistered(u16 windowId)
+{
+ u8 str[3];
+ ConvertIntToDecimalStringN(str, GetNumberRegistered(), STR_CONV_MODE_LEFT_ALIGN, 3);
+ PrintMatchCallInfoNumber(windowId, str, 1);
+}
+
+static void PrintNumberOfBattlesLabel(u16 windowId)
+{
+ PrintMatchCallInfoLabel(windowId, gText_NumberOfBattles, 2);
+}
+
+static void PrintNumberOfBattles(u16 windowId)
+{
+ u8 str[5];
+ int numTrainerBattles = GetGameStat(GAME_STAT_TRAINER_BATTLES);
+ if (numTrainerBattles > 99999)
+ numTrainerBattles = 99999;
+
+ ConvertIntToDecimalStringN(str, numTrainerBattles, STR_CONV_MODE_LEFT_ALIGN, 5);
+ PrintMatchCallInfoNumber(windowId, str, 3);
+}
+
+static void PrintMatchCallInfoLabel(u16 windowId, const u8 *str, int top)
+{
+ int y = top * 16 + 1;
+ AddTextPrinterParameterized(windowId, FONT_NARROW, str, 2, y, TEXT_SKIP_DRAW, NULL);
+}
+
+static void PrintMatchCallInfoNumber(u16 windowId, const u8 *str, int top)
+{
+ int x = GetStringRightAlignXOffset(FONT_NARROW, str, 86);
+ int y = top * 16 + 1;
+ AddTextPrinterParameterized(windowId, FONT_NARROW, str, x, y, TEXT_SKIP_DRAW, NULL);
+}
+
+static void PrintMatchCallLocation(struct Pokenav_MatchCallGfx *gfx, int delta)
+{
+ u8 mapName[32];
+ int x;
+ int index = PokenavList_GetSelectedIndex() + delta;
+ int mapSec = GetMatchCallMapSec(index);
+ if (mapSec != MAPSEC_NONE)
+ GetMapName(mapName, mapSec, 0);
+ else
+ StringCopy(mapName, gText_Unknown);
+
+ x = GetStringCenterAlignXOffset(FONT_NARROW, mapName, 88);
+ FillWindowPixelBuffer(gfx->locWindowId, PIXEL_FILL(1));
+ AddTextPrinterParameterized(gfx->locWindowId, FONT_NARROW, mapName, x, 1, 0, NULL);
+}
+
+static void PrintMatchCallSelectionOptions(struct Pokenav_MatchCallGfx *gfx)
+{
+ u32 i;
+
+ FillWindowPixelBuffer(gfx->infoBoxWindowId, PIXEL_FILL(1));
+ for (i = 0; i < MATCH_CALL_OPTION_COUNT; i++)
+ {
+ int optionText = GetMatchCallOptionId(i);
+ if (optionText == MATCH_CALL_OPTION_COUNT)
+ break;
+
+ AddTextPrinterParameterized(gfx->infoBoxWindowId, FONT_NARROW, sMatchCallOptionTexts[optionText], 16, i * 16 + 1, TEXT_SKIP_DRAW, NULL);
+ }
+
+ CopyWindowToVram(gfx->infoBoxWindowId, COPYWIN_GFX);
+}
+
+static bool32 ShowOptionsCursor(struct Pokenav_MatchCallGfx *gfx)
+{
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ CreateOptionsCursorSprite(gfx, GetMatchCallOptionCursorPos());
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void UpdateWindowsReturnToTrainerList(struct Pokenav_MatchCallGfx *gfx)
+{
+ CloseMatchCallSelectOptionsWindow(gfx);
+ UpdateMatchCallInfoBox(gfx);
+}
+
+static bool32 IsDma3ManagerBusyWithBgCopy1(struct Pokenav_MatchCallGfx *gfx)
+{
+ return IsDma3ManagerBusyWithBgCopy();
+}
+
+static void UpdateWindowsToShowCheckPage(struct Pokenav_MatchCallGfx *gfx)
+{
+ CloseMatchCallSelectOptionsWindow(gfx);
+ FillWindowPixelBuffer(gfx->infoBoxWindowId, PIXEL_FILL(1));
+ CopyWindowToVram(gfx->infoBoxWindowId, COPYWIN_GFX);
+}
+
+static void LoadCallWindowAndFade(struct Pokenav_MatchCallGfx *gfx)
+{
+ gfx->msgBoxWindowId = AddWindow(&sCallMsgBoxWindowTemplate);
+ LoadMatchCallWindowGfx(gfx->msgBoxWindowId, 1, 4);
+ FadeToBlackExceptPrimary();
+}
+
+static void DrawMsgBoxForMatchCallMsg(struct Pokenav_MatchCallGfx *gfx)
+{
+ struct Sprite *sprite;
+ LoadMatchCallWindowGfx(gfx->msgBoxWindowId, 1, 4);
+ DrawMatchCallTextBoxBorder(gfx->msgBoxWindowId, 1, 4);
+ FillWindowPixelBuffer(gfx->msgBoxWindowId, PIXEL_FILL(1));
+ PutWindowTilemap(gfx->msgBoxWindowId);
+ CopyWindowToVram(gfx->msgBoxWindowId, COPYWIN_FULL);
+ sprite = GetSpinningPokenavSprite();
+ sprite->x = 24;
+ sprite->y = 112;
+ sprite->y2 = 0;
+}
+
+static void DrawMsgBoxForCloseByMsg(struct Pokenav_MatchCallGfx *gfx)
+{
+ LoadUserWindowBorderGfx(gfx->msgBoxWindowId, 1, 0x40);
+ DrawTextBorderOuter(gfx->msgBoxWindowId, 1, 4);
+ FillWindowPixelBuffer(gfx->msgBoxWindowId, PIXEL_FILL(1));
+ PutWindowTilemap(gfx->msgBoxWindowId);
+ CopyWindowToVram(gfx->msgBoxWindowId, COPYWIN_FULL);
+}
+
+static bool32 IsDma3ManagerBusyWithBgCopy2(struct Pokenav_MatchCallGfx *gfx)
+{
+ return IsDma3ManagerBusyWithBgCopy();
+}
+
+static void PrintCallingDots(struct Pokenav_MatchCallGfx *gfx)
+{
+ AddTextPrinterParameterized(gfx->msgBoxWindowId, FONT_NORMAL, sText_CallingDots, 32, 1, 1, NULL);
+}
+
+static bool32 WaitForCallingDotsText(struct Pokenav_MatchCallGfx *gfx)
+{
+ RunTextPrinters();
+ return IsTextPrinterActive(gfx->msgBoxWindowId);
+}
+
+static void PrintTrainerIsCloseBy(struct Pokenav_MatchCallGfx *gfx)
+{
+ AddTextPrinterParameterized(gfx->msgBoxWindowId, FONT_NORMAL, gText_TrainerCloseBy, 0, 1, 1, NULL);
+}
+
+static bool32 WaitForTrainerIsCloseByText(struct Pokenav_MatchCallGfx *gfx)
+{
+ RunTextPrinters();
+ return IsTextPrinterActive(gfx->msgBoxWindowId);
+}
+
+static void PrintMatchCallMessage(struct Pokenav_MatchCallGfx *gfx)
+{
+ int index = PokenavList_GetSelectedIndex();
+ const u8 *str = GetMatchCallMessageText(index, &gfx->newRematchRequest);
+ u8 speed = GetPlayerTextSpeedDelay();
+ AddTextPrinterParameterized(gfx->msgBoxWindowId, FONT_NORMAL, str, 32, 1, speed, NULL);
+}
+
+static bool32 WaitForMatchCallMessageText(struct Pokenav_MatchCallGfx *gfx)
+{
+ if (JOY_HELD(A_BUTTON))
+ gTextFlags.canABSpeedUpPrint = TRUE;
+ else
+ gTextFlags.canABSpeedUpPrint = FALSE;
+
+ RunTextPrinters();
+ return IsTextPrinterActive(gfx->msgBoxWindowId);
+}
+
+static void EraseCallMessageBox(struct Pokenav_MatchCallGfx *gfx)
+{
+ HideSpinningPokenavSprite();
+ FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 32, 20);
+ CopyBgTilemapBufferToVram(1);
+}
+
+static bool32 WaitForCallMessageBoxErase(struct Pokenav_MatchCallGfx *gfx)
+{
+ return IsDma3ManagerBusyWithBgCopy();
+}
+
+static void AllocMatchCallSprites(void)
+{
+ int i;
+ u8 paletteNum;
+ struct SpriteSheet spriteSheet;
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+
+ // Load options cursor gfx
+ for (i = 0; i < ARRAY_COUNT(sOptionsCursorSpriteSheets); i++)
+ LoadCompressedSpriteSheet(&sOptionsCursorSpriteSheets[i]);
+ Pokenav_AllocAndLoadPalettes(sOptionsCursorSpritePalettes);
+ gfx->optionsCursorSprite = NULL;
+
+ // Load trainer pic gfx
+ spriteSheet.data = gfx->trainerPicGfx;
+ spriteSheet.size = sizeof(gfx->trainerPicGfx);
+ spriteSheet.tag = GFXTAG_TRAINER_PIC;
+ gfx->trainerPicGfxPtr = (u8 *)OBJ_VRAM0 + LoadSpriteSheet(&spriteSheet) * 0x20;
+ paletteNum = AllocSpritePalette(PALTAG_TRAINER_PIC);
+ gfx->trainerPicPalOffset = 0x100 + paletteNum * 0x10;
+ gfx->trainerPicSprite = CreateTrainerPicSprite();
+ gfx->trainerPicSprite->invisible = TRUE;
+}
+
+static void FreeMatchCallSprites(void)
+{
+ struct Pokenav_MatchCallGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_OPEN);
+ if (gfx->optionsCursorSprite)
+ DestroySprite(gfx->optionsCursorSprite);
+ if (gfx->trainerPicSprite)
+ DestroySprite(gfx->trainerPicSprite);
+
+ FreeSpriteTilesByTag(GFXTAG_TRAINER_PIC);
+ FreeSpriteTilesByTag(GFXTAG_CURSOR);
+ FreeSpritePaletteByTag(PALTAG_CURSOR);
+ FreeSpritePaletteByTag(PALTAG_TRAINER_PIC);
+}
+
+static void CreateOptionsCursorSprite(struct Pokenav_MatchCallGfx *gfx, int top)
+{
+ if (!gfx->optionsCursorSprite)
+ {
+ u8 spriteId = CreateSprite(&sOptionsCursorSpriteTemplate, 4, 80, 5);
+ gfx->optionsCursorSprite = &gSprites[spriteId];
+ UpdateCursorGfxPos(gfx, top);
+ }
+}
+
+static void CloseMatchCallSelectOptionsWindow(struct Pokenav_MatchCallGfx *gfx)
+{
+ DestroySprite(gfx->optionsCursorSprite);
+ gfx->optionsCursorSprite = NULL;
+}
+
+static void UpdateCursorGfxPos(struct Pokenav_MatchCallGfx *gfx, int top)
+{
+ gfx->optionsCursorSprite->y2 = top * 16;
+}
+
+static void SpriteCB_OptionsCursor(struct Sprite *sprite)
+{
+ if (++sprite->data[0] > 3)
+ {
+ sprite->data[0] = 0;
+ sprite->x2 = (sprite->x2 + 1) & 7;
+ }
+}
+
+static struct Sprite *CreateTrainerPicSprite(void)
+{
+ u8 spriteId = CreateSprite(&sTrainerPicSpriteTemplate, 44, 104, 6);
+ return &gSprites[spriteId];
+}
+
+static void LoadCheckPageTrainerPic(struct Pokenav_MatchCallGfx *gfx)
+{
+ u16 cursor;
+ int trainerPic = GetMatchCallTrainerPic(PokenavList_GetSelectedIndex());
+ if (trainerPic >= 0)
+ {
+ DecompressPicFromTable(&gTrainerFrontPicTable[trainerPic], gfx->trainerPicGfx, SPECIES_NONE);
+ LZ77UnCompWram(gTrainerFrontPicPaletteTable[trainerPic].data, gfx->trainerPicPal);
+ cursor = RequestDma3Copy(gfx->trainerPicGfx, gfx->trainerPicGfxPtr, sizeof(gfx->trainerPicGfx), 1);
+ LoadPalette(gfx->trainerPicPal, gfx->trainerPicPalOffset, sizeof(gfx->trainerPicPal));
+ gfx->trainerPicSprite->data[0] = 0;
+ gfx->trainerPicSprite->data[7] = cursor;
+ gfx->trainerPicSprite->callback = SpriteCB_TrainerPicSlideOnscreen;
+ }
+}
+
+static void TrainerPicSlideOffscreen(struct Pokenav_MatchCallGfx *gfx)
+{
+ gfx->trainerPicSprite->callback = SpriteCB_TrainerPicSlideOffscreen;
+}
+
+static bool32 WaitForTrainerPic(struct Pokenav_MatchCallGfx *gfx)
+{
+ return gfx->trainerPicSprite->callback != SpriteCallbackDummy;
+}
+
+static void SpriteCB_TrainerPicSlideOnscreen(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ if (CheckForSpaceForDma3Request(sprite->data[7]) != -1)
+ {
+ sprite->x2 = -80;
+ sprite->invisible = FALSE;
+ sprite->data[0]++;
+ }
+ break;
+ case 1:
+ sprite->x2 += 8;
+ if (sprite->x2 >= 0)
+ {
+ sprite->x2 = 0;
+ sprite->callback = SpriteCallbackDummy;
+ }
+ break;
+ }
+}
+
+static void SpriteCB_TrainerPicSlideOffscreen(struct Sprite *sprite)
+{
+ sprite->x2 -= 8;
+ if (sprite->x2 <= -80)
+ {
+ sprite->invisible = TRUE;
+ sprite->callback = SpriteCallbackDummy;
+ }
+}