From ffe2970e30f64f46a7539ac69d61ab4ea353a92c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 12 Nov 2021 17:13:50 -0500 Subject: Rename pokenav menu handler files --- src/pokenav_menu_handler.c | 513 +++++++++++++++ src/pokenav_menu_handler_1.c | 513 --------------- src/pokenav_menu_handler_2.c | 1371 ---------------------------------------- src/pokenav_menu_handler_gfx.c | 1371 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1884 insertions(+), 1884 deletions(-) create mode 100644 src/pokenav_menu_handler.c delete mode 100644 src/pokenav_menu_handler_1.c delete mode 100644 src/pokenav_menu_handler_2.c create mode 100644 src/pokenav_menu_handler_gfx.c (limited to 'src') diff --git a/src/pokenav_menu_handler.c b/src/pokenav_menu_handler.c new file mode 100644 index 000000000..b72247742 --- /dev/null +++ b/src/pokenav_menu_handler.c @@ -0,0 +1,513 @@ +#include "global.h" +#include "pokenav.h" +#include "event_data.h" +#include "main.h" +#include "sound.h" +#include "constants/songs.h" + +struct Pokenav_Menu +{ + u16 menuType; + s16 cursorPos; + u16 currMenuItem; + u16 helpBarIndex; + u32 menuId; + u32 (*callback)(struct Pokenav_Menu*); +}; + +static bool32 UpdateMenuCursorPos(struct Pokenav_Menu *); +static void ReturnToConditionMenu(struct Pokenav_Menu *); +static void ReturnToMainMenu(struct Pokenav_Menu *); +static u32 GetMenuId(struct Pokenav_Menu *); +static void SetMenuIdAndCB(struct Pokenav_Menu *, u32); +static u32 CB2_ReturnToConditionMenu(struct Pokenav_Menu *); +static u32 CB2_ReturnToMainMenu(struct Pokenav_Menu *); +static u32 HandleConditionSearchMenuInput(struct Pokenav_Menu *); +static u32 HandleConditionMenuInput(struct Pokenav_Menu *); +static u32 HandleCantOpenRibbonsInput(struct Pokenav_Menu *); +static u32 HandleMainMenuInputEndTutorial(struct Pokenav_Menu *); +static u32 HandleMainMenuInputTutorial(struct Pokenav_Menu *); +static u32 HandleMainMenuInput(struct Pokenav_Menu *); +static u32 (*GetMainMenuInputHandler(void))(struct Pokenav_Menu*); +static void SetMenuInputHandler(struct Pokenav_Menu *); + +// Number of entries - 1 for that menu type +static const u8 sLastCursorPositions[] = +{ + [POKENAV_MENU_TYPE_DEFAULT] = 2, + [POKENAV_MENU_TYPE_UNLOCK_MC] = 3, + [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = 4, + [POKENAV_MENU_TYPE_CONDITION] = 2, + [POKENAV_MENU_TYPE_CONDITION_SEARCH] = 5 +}; + +static const u8 sMenuItems[][MAX_POKENAV_MENUITEMS] = +{ + [POKENAV_MENU_TYPE_DEFAULT] = + { + POKENAV_MENUITEM_MAP, + POKENAV_MENUITEM_CONDITION, + [2 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF + }, + [POKENAV_MENU_TYPE_UNLOCK_MC] = + { + POKENAV_MENUITEM_MAP, + POKENAV_MENUITEM_CONDITION, + POKENAV_MENUITEM_MATCH_CALL, + [3 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF + }, + [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = + { + POKENAV_MENUITEM_MAP, + POKENAV_MENUITEM_CONDITION, + POKENAV_MENUITEM_MATCH_CALL, + POKENAV_MENUITEM_RIBBONS, + [4 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF + }, + [POKENAV_MENU_TYPE_CONDITION] = + { + POKENAV_MENUITEM_CONDITION_PARTY, + POKENAV_MENUITEM_CONDITION_SEARCH, + POKENAV_MENUITEM_CONDITION_CANCEL, + [3 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF + }, + [POKENAV_MENU_TYPE_CONDITION_SEARCH] = + { + POKENAV_MENUITEM_CONDITION_SEARCH_COOL, + POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY, + POKENAV_MENUITEM_CONDITION_SEARCH_CUTE, + POKENAV_MENUITEM_CONDITION_SEARCH_SMART, + POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH, + POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL + }, +}; + +static u8 GetPokenavMainMenuType(void) +{ + u8 menuType = POKENAV_MENU_TYPE_DEFAULT; + + if (FlagGet(FLAG_ADDED_MATCH_CALL_TO_POKENAV)) + { + menuType = POKENAV_MENU_TYPE_UNLOCK_MC; + + if (FlagGet(FLAG_SYS_RIBBON_GET)) + menuType = POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS; + } + + return menuType; +} + +bool32 PokenavCallback_Init_MainMenuCursorOnMap(void) +{ + struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); + if (!menu) + return FALSE; + + menu->menuType = GetPokenavMainMenuType(); + menu->cursorPos = POKENAV_MENUITEM_MAP; + menu->currMenuItem = POKENAV_MENUITEM_MAP; + menu->helpBarIndex = HELPBAR_NONE; + SetMenuInputHandler(menu); + return TRUE; +} + +bool32 PokenavCallback_Init_MainMenuCursorOnMatchCall(void) +{ + struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); + if (!menu) + return FALSE; + + menu->menuType = GetPokenavMainMenuType(); + menu->cursorPos = POKENAV_MENUITEM_MATCH_CALL; + menu->currMenuItem = POKENAV_MENUITEM_MATCH_CALL; + menu->helpBarIndex = HELPBAR_NONE; + SetMenuInputHandler(menu); + return TRUE; +} + +bool32 PokenavCallback_Init_MainMenuCursorOnRibbons(void) +{ + struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); + if (!menu) + return FALSE; + + menu->menuType = GetPokenavMainMenuType(); + menu->cursorPos = POKENAV_MENUITEM_RIBBONS; + menu->currMenuItem = POKENAV_MENUITEM_RIBBONS; + SetMenuInputHandler(menu); + return TRUE; +} + +bool32 PokenavCallback_Init_ConditionMenu(void) +{ + struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); + if (!menu) + return FALSE; + + menu->menuType = POKENAV_MENU_TYPE_CONDITION; + menu->cursorPos = 0; //party + menu->currMenuItem = POKENAV_MENUITEM_CONDITION_PARTY; + menu->helpBarIndex = HELPBAR_NONE; + SetMenuInputHandler(menu); + return TRUE; +} + +bool32 PokenavCallback_Init_ConditionSearchMenu(void) +{ + struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); + if (!menu) + return FALSE; + + menu->menuType = POKENAV_MENU_TYPE_CONDITION_SEARCH; + menu->cursorPos = GetSelectedConditionSearch(); + menu->currMenuItem = menu->cursorPos + POKENAV_MENUITEM_CONDITION_SEARCH_COOL; + menu->helpBarIndex = HELPBAR_NONE; + SetMenuInputHandler(menu); + return TRUE; +} + +static void SetMenuInputHandler(struct Pokenav_Menu *menu) +{ + switch (menu->menuType) + { + case POKENAV_MENU_TYPE_DEFAULT: + SetPokenavMode(POKENAV_MODE_NORMAL); + // fallthrough + case POKENAV_MENU_TYPE_UNLOCK_MC: + case POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS: + menu->callback = GetMainMenuInputHandler(); + break; + case POKENAV_MENU_TYPE_CONDITION: + menu->callback = HandleConditionMenuInput; + break; + case POKENAV_MENU_TYPE_CONDITION_SEARCH: + menu->callback = HandleConditionSearchMenuInput; + break; + } +} + +static u32 (*GetMainMenuInputHandler(void))(struct Pokenav_Menu*) +{ + switch (GetPokenavMode()) + { + default: + case POKENAV_MODE_NORMAL: + return HandleMainMenuInput; + case POKENAV_MODE_FORCE_CALL_READY: + return HandleMainMenuInputTutorial; + case POKENAV_MODE_FORCE_CALL_EXIT: + return HandleMainMenuInputEndTutorial; + } +} + +u32 GetMenuHandlerCallback(void) +{ + struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); + return menu->callback(menu); +} + +void FreeMenuHandlerSubstruct1(void) +{ + FreePokenavSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); +} + +static u32 HandleMainMenuInput(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + return POKENAV_MENU_FUNC_MOVE_CURSOR; + + if (JOY_NEW(A_BUTTON)) + { + switch (sMenuItems[menu->menuType][menu->cursorPos]) + { + case POKENAV_MENUITEM_MAP: + menu->helpBarIndex = gSaveBlock2Ptr->regionMapZoom ? HELPBAR_MAP_ZOOMED_IN : HELPBAR_MAP_ZOOMED_OUT; + SetMenuIdAndCB(menu, POKENAV_REGION_MAP); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + case POKENAV_MENUITEM_CONDITION: + menu->menuType = POKENAV_MENU_TYPE_CONDITION; + menu->cursorPos = 0; + menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION][0]; + menu->callback = HandleConditionMenuInput; + return POKENAV_MENU_FUNC_OPEN_CONDITION; + case POKENAV_MENUITEM_MATCH_CALL: + menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; + SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + case POKENAV_MENUITEM_RIBBONS: + if (CanViewRibbonsMenu()) + { + menu->helpBarIndex = HELPBAR_RIBBONS_MON_LIST; + SetMenuIdAndCB(menu, POKENAV_RIBBONS_MON_LIST); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + } + else + { + menu->callback = HandleCantOpenRibbonsInput; + return POKENAV_MENU_FUNC_NO_RIBBON_WINNERS; + } + case POKENAV_MENUITEM_SWITCH_OFF: + return POKENAV_MENU_FUNC_EXIT; + } + } + + if (JOY_NEW(B_BUTTON)) + return POKENAV_MENU_FUNC_EXIT; + + return POKENAV_MENU_FUNC_NONE; +} + +// Force the player to select Match Call during the call Mr. Stone pokenav tutorial +static u32 HandleMainMenuInputTutorial(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + return POKENAV_MENU_FUNC_MOVE_CURSOR; + + if (JOY_NEW(A_BUTTON)) + { + if (sMenuItems[menu->menuType][menu->cursorPos] == POKENAV_MENUITEM_MATCH_CALL) + { + menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; + SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + } + else + { + PlaySE(SE_FAILURE); + return POKENAV_MENU_FUNC_NONE; + } + } + + if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_FAILURE); + return POKENAV_MENU_FUNC_NONE; + } + + return POKENAV_MENU_FUNC_NONE; +} + +// After calling Mr. Stone during the pokenav tutorial, force player to exit or use Match Call again +static u32 HandleMainMenuInputEndTutorial(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + return POKENAV_MENU_FUNC_MOVE_CURSOR; + + if (JOY_NEW(A_BUTTON)) + { + u32 menuItem = sMenuItems[menu->menuType][menu->cursorPos]; + if (menuItem != POKENAV_MENUITEM_MATCH_CALL && menuItem != POKENAV_MENUITEM_SWITCH_OFF) + { + PlaySE(SE_FAILURE); + return POKENAV_MENU_FUNC_NONE; + } + else if (menuItem == POKENAV_MENUITEM_MATCH_CALL) + { + menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; + SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + } + else + { + return -1; + } + } + else if (JOY_NEW(B_BUTTON)) + { + return -1; + } + return POKENAV_MENU_FUNC_NONE; +} + +// Handles input after selecting Ribbons when there are no ribbon winners left +// Selecting it again just reprints the Ribbon description to replace the "No Ribbon winners" message +static u32 HandleCantOpenRibbonsInput(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + { + menu->callback = GetMainMenuInputHandler(); + return POKENAV_MENU_FUNC_MOVE_CURSOR; + } + + if (JOY_NEW(A_BUTTON | B_BUTTON)) + { + menu->callback = GetMainMenuInputHandler(); + return POKENAV_MENU_FUNC_RESHOW_DESCRIPTION; + } + + return POKENAV_MENU_FUNC_NONE; +} + +static u32 HandleConditionMenuInput(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + return POKENAV_MENU_FUNC_MOVE_CURSOR; + + if (JOY_NEW(A_BUTTON)) + { + switch (sMenuItems[menu->menuType][menu->cursorPos]) + { + case POKENAV_MENUITEM_CONDITION_SEARCH: + menu->menuType = POKENAV_MENU_TYPE_CONDITION_SEARCH; + menu->cursorPos = 0; + menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION_SEARCH][0]; + menu->callback = HandleConditionSearchMenuInput; + return POKENAV_MENU_FUNC_OPEN_CONDITION_SEARCH; + case POKENAV_MENUITEM_CONDITION_PARTY: + menu->helpBarIndex = 0; + SetMenuIdAndCB(menu, POKENAV_CONDITION_GRAPH_PARTY); + return POKENAV_MENU_FUNC_OPEN_FEATURE; + case POKENAV_MENUITEM_CONDITION_CANCEL: + PlaySE(SE_SELECT); + ReturnToMainMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_MAIN; + } + } + if (JOY_NEW(B_BUTTON)) + { + if (menu->cursorPos != sLastCursorPositions[menu->menuType]) + { + menu->cursorPos = sLastCursorPositions[menu->menuType]; + menu->callback = CB2_ReturnToMainMenu; + return POKENAV_MENU_FUNC_MOVE_CURSOR; + } + else + { + PlaySE(SE_SELECT); + ReturnToMainMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_MAIN; + } + } + + return POKENAV_MENU_FUNC_NONE; +} + +static u32 HandleConditionSearchMenuInput(struct Pokenav_Menu *menu) +{ + if (UpdateMenuCursorPos(menu)) + return POKENAV_MENU_FUNC_MOVE_CURSOR; + + if (JOY_NEW(A_BUTTON)) + { + u8 menuItem = sMenuItems[menu->menuType][menu->cursorPos]; + if (menuItem != POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL) + { + SetSelectedConditionSearch(menuItem - POKENAV_MENUITEM_CONDITION_SEARCH_COOL); + SetMenuIdAndCB(menu, POKENAV_CONDITION_SEARCH_RESULTS); + menu->helpBarIndex = HELPBAR_CONDITION_MON_LIST; + return POKENAV_MENU_FUNC_OPEN_FEATURE; + } + else + { + PlaySE(SE_SELECT); + ReturnToConditionMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; + } + } + if (JOY_NEW(B_BUTTON)) + { + if (menu->cursorPos != sLastCursorPositions[menu->menuType]) + { + menu->cursorPos = sLastCursorPositions[menu->menuType]; + menu->callback = CB2_ReturnToConditionMenu; + return POKENAV_MENU_FUNC_MOVE_CURSOR; + } + else + { + PlaySE(SE_SELECT); + ReturnToConditionMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; + } + } + return POKENAV_MENU_FUNC_NONE; +} + +static u32 CB2_ReturnToMainMenu(struct Pokenav_Menu *menu) +{ + ReturnToMainMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_MAIN; +} + +static u32 CB2_ReturnToConditionMenu(struct Pokenav_Menu *menu) +{ + ReturnToConditionMenu(menu); + return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; +} + +static void SetMenuIdAndCB(struct Pokenav_Menu *menu, u32 menuId) +{ + menu->menuId = menuId; + menu->callback = GetMenuId; +} + +static u32 GetMenuId(struct Pokenav_Menu *menu) +{ + return menu->menuId; +} + +static void ReturnToMainMenu(struct Pokenav_Menu *menu) +{ + menu->menuType = GetPokenavMainMenuType(); + menu->cursorPos = 1; + menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; + menu->callback = HandleMainMenuInput; +} + +static void ReturnToConditionMenu(struct Pokenav_Menu *menu) +{ + menu->menuType = POKENAV_MENU_TYPE_CONDITION; + menu->cursorPos = 1; + menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION][1]; + menu->callback = HandleConditionMenuInput; +} + +static bool32 UpdateMenuCursorPos(struct Pokenav_Menu *menu) +{ + if (JOY_NEW(DPAD_UP)) + { + if (--menu->cursorPos < 0) + menu->cursorPos = sLastCursorPositions[menu->menuType]; + + menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; + return TRUE; + } + else if (JOY_NEW(DPAD_DOWN)) + { + menu->cursorPos++; + if (menu->cursorPos > sLastCursorPositions[menu->menuType]) + menu->cursorPos = 0; + + menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; + return TRUE; + } + else + { + return FALSE; + } +} + +int GetPokenavMenuType(void) +{ + struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); + return menu->menuType; +} + +// Position of cursor relative to number of current menu options +int GetPokenavCursorPos(void) +{ + struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); + return menu->cursorPos; +} + +// ID of menu item the cursor is currently on +int GetCurrentMenuItemId(void) +{ + struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); + return menu->currMenuItem; +} + +u16 GetHelpBarTextId(void) +{ + struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); + return menu->helpBarIndex; +} diff --git a/src/pokenav_menu_handler_1.c b/src/pokenav_menu_handler_1.c deleted file mode 100644 index b72247742..000000000 --- a/src/pokenav_menu_handler_1.c +++ /dev/null @@ -1,513 +0,0 @@ -#include "global.h" -#include "pokenav.h" -#include "event_data.h" -#include "main.h" -#include "sound.h" -#include "constants/songs.h" - -struct Pokenav_Menu -{ - u16 menuType; - s16 cursorPos; - u16 currMenuItem; - u16 helpBarIndex; - u32 menuId; - u32 (*callback)(struct Pokenav_Menu*); -}; - -static bool32 UpdateMenuCursorPos(struct Pokenav_Menu *); -static void ReturnToConditionMenu(struct Pokenav_Menu *); -static void ReturnToMainMenu(struct Pokenav_Menu *); -static u32 GetMenuId(struct Pokenav_Menu *); -static void SetMenuIdAndCB(struct Pokenav_Menu *, u32); -static u32 CB2_ReturnToConditionMenu(struct Pokenav_Menu *); -static u32 CB2_ReturnToMainMenu(struct Pokenav_Menu *); -static u32 HandleConditionSearchMenuInput(struct Pokenav_Menu *); -static u32 HandleConditionMenuInput(struct Pokenav_Menu *); -static u32 HandleCantOpenRibbonsInput(struct Pokenav_Menu *); -static u32 HandleMainMenuInputEndTutorial(struct Pokenav_Menu *); -static u32 HandleMainMenuInputTutorial(struct Pokenav_Menu *); -static u32 HandleMainMenuInput(struct Pokenav_Menu *); -static u32 (*GetMainMenuInputHandler(void))(struct Pokenav_Menu*); -static void SetMenuInputHandler(struct Pokenav_Menu *); - -// Number of entries - 1 for that menu type -static const u8 sLastCursorPositions[] = -{ - [POKENAV_MENU_TYPE_DEFAULT] = 2, - [POKENAV_MENU_TYPE_UNLOCK_MC] = 3, - [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = 4, - [POKENAV_MENU_TYPE_CONDITION] = 2, - [POKENAV_MENU_TYPE_CONDITION_SEARCH] = 5 -}; - -static const u8 sMenuItems[][MAX_POKENAV_MENUITEMS] = -{ - [POKENAV_MENU_TYPE_DEFAULT] = - { - POKENAV_MENUITEM_MAP, - POKENAV_MENUITEM_CONDITION, - [2 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF - }, - [POKENAV_MENU_TYPE_UNLOCK_MC] = - { - POKENAV_MENUITEM_MAP, - POKENAV_MENUITEM_CONDITION, - POKENAV_MENUITEM_MATCH_CALL, - [3 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF - }, - [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = - { - POKENAV_MENUITEM_MAP, - POKENAV_MENUITEM_CONDITION, - POKENAV_MENUITEM_MATCH_CALL, - POKENAV_MENUITEM_RIBBONS, - [4 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF - }, - [POKENAV_MENU_TYPE_CONDITION] = - { - POKENAV_MENUITEM_CONDITION_PARTY, - POKENAV_MENUITEM_CONDITION_SEARCH, - POKENAV_MENUITEM_CONDITION_CANCEL, - [3 ... MAX_POKENAV_MENUITEMS - 1] = POKENAV_MENUITEM_SWITCH_OFF - }, - [POKENAV_MENU_TYPE_CONDITION_SEARCH] = - { - POKENAV_MENUITEM_CONDITION_SEARCH_COOL, - POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY, - POKENAV_MENUITEM_CONDITION_SEARCH_CUTE, - POKENAV_MENUITEM_CONDITION_SEARCH_SMART, - POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH, - POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL - }, -}; - -static u8 GetPokenavMainMenuType(void) -{ - u8 menuType = POKENAV_MENU_TYPE_DEFAULT; - - if (FlagGet(FLAG_ADDED_MATCH_CALL_TO_POKENAV)) - { - menuType = POKENAV_MENU_TYPE_UNLOCK_MC; - - if (FlagGet(FLAG_SYS_RIBBON_GET)) - menuType = POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS; - } - - return menuType; -} - -bool32 PokenavCallback_Init_MainMenuCursorOnMap(void) -{ - struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); - if (!menu) - return FALSE; - - menu->menuType = GetPokenavMainMenuType(); - menu->cursorPos = POKENAV_MENUITEM_MAP; - menu->currMenuItem = POKENAV_MENUITEM_MAP; - menu->helpBarIndex = HELPBAR_NONE; - SetMenuInputHandler(menu); - return TRUE; -} - -bool32 PokenavCallback_Init_MainMenuCursorOnMatchCall(void) -{ - struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); - if (!menu) - return FALSE; - - menu->menuType = GetPokenavMainMenuType(); - menu->cursorPos = POKENAV_MENUITEM_MATCH_CALL; - menu->currMenuItem = POKENAV_MENUITEM_MATCH_CALL; - menu->helpBarIndex = HELPBAR_NONE; - SetMenuInputHandler(menu); - return TRUE; -} - -bool32 PokenavCallback_Init_MainMenuCursorOnRibbons(void) -{ - struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); - if (!menu) - return FALSE; - - menu->menuType = GetPokenavMainMenuType(); - menu->cursorPos = POKENAV_MENUITEM_RIBBONS; - menu->currMenuItem = POKENAV_MENUITEM_RIBBONS; - SetMenuInputHandler(menu); - return TRUE; -} - -bool32 PokenavCallback_Init_ConditionMenu(void) -{ - struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); - if (!menu) - return FALSE; - - menu->menuType = POKENAV_MENU_TYPE_CONDITION; - menu->cursorPos = 0; //party - menu->currMenuItem = POKENAV_MENUITEM_CONDITION_PARTY; - menu->helpBarIndex = HELPBAR_NONE; - SetMenuInputHandler(menu); - return TRUE; -} - -bool32 PokenavCallback_Init_ConditionSearchMenu(void) -{ - struct Pokenav_Menu *menu = AllocSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER, sizeof(struct Pokenav_Menu)); - if (!menu) - return FALSE; - - menu->menuType = POKENAV_MENU_TYPE_CONDITION_SEARCH; - menu->cursorPos = GetSelectedConditionSearch(); - menu->currMenuItem = menu->cursorPos + POKENAV_MENUITEM_CONDITION_SEARCH_COOL; - menu->helpBarIndex = HELPBAR_NONE; - SetMenuInputHandler(menu); - return TRUE; -} - -static void SetMenuInputHandler(struct Pokenav_Menu *menu) -{ - switch (menu->menuType) - { - case POKENAV_MENU_TYPE_DEFAULT: - SetPokenavMode(POKENAV_MODE_NORMAL); - // fallthrough - case POKENAV_MENU_TYPE_UNLOCK_MC: - case POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS: - menu->callback = GetMainMenuInputHandler(); - break; - case POKENAV_MENU_TYPE_CONDITION: - menu->callback = HandleConditionMenuInput; - break; - case POKENAV_MENU_TYPE_CONDITION_SEARCH: - menu->callback = HandleConditionSearchMenuInput; - break; - } -} - -static u32 (*GetMainMenuInputHandler(void))(struct Pokenav_Menu*) -{ - switch (GetPokenavMode()) - { - default: - case POKENAV_MODE_NORMAL: - return HandleMainMenuInput; - case POKENAV_MODE_FORCE_CALL_READY: - return HandleMainMenuInputTutorial; - case POKENAV_MODE_FORCE_CALL_EXIT: - return HandleMainMenuInputEndTutorial; - } -} - -u32 GetMenuHandlerCallback(void) -{ - struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); - return menu->callback(menu); -} - -void FreeMenuHandlerSubstruct1(void) -{ - FreePokenavSubstruct(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); -} - -static u32 HandleMainMenuInput(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - return POKENAV_MENU_FUNC_MOVE_CURSOR; - - if (JOY_NEW(A_BUTTON)) - { - switch (sMenuItems[menu->menuType][menu->cursorPos]) - { - case POKENAV_MENUITEM_MAP: - menu->helpBarIndex = gSaveBlock2Ptr->regionMapZoom ? HELPBAR_MAP_ZOOMED_IN : HELPBAR_MAP_ZOOMED_OUT; - SetMenuIdAndCB(menu, POKENAV_REGION_MAP); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - case POKENAV_MENUITEM_CONDITION: - menu->menuType = POKENAV_MENU_TYPE_CONDITION; - menu->cursorPos = 0; - menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION][0]; - menu->callback = HandleConditionMenuInput; - return POKENAV_MENU_FUNC_OPEN_CONDITION; - case POKENAV_MENUITEM_MATCH_CALL: - menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; - SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - case POKENAV_MENUITEM_RIBBONS: - if (CanViewRibbonsMenu()) - { - menu->helpBarIndex = HELPBAR_RIBBONS_MON_LIST; - SetMenuIdAndCB(menu, POKENAV_RIBBONS_MON_LIST); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - } - else - { - menu->callback = HandleCantOpenRibbonsInput; - return POKENAV_MENU_FUNC_NO_RIBBON_WINNERS; - } - case POKENAV_MENUITEM_SWITCH_OFF: - return POKENAV_MENU_FUNC_EXIT; - } - } - - if (JOY_NEW(B_BUTTON)) - return POKENAV_MENU_FUNC_EXIT; - - return POKENAV_MENU_FUNC_NONE; -} - -// Force the player to select Match Call during the call Mr. Stone pokenav tutorial -static u32 HandleMainMenuInputTutorial(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - return POKENAV_MENU_FUNC_MOVE_CURSOR; - - if (JOY_NEW(A_BUTTON)) - { - if (sMenuItems[menu->menuType][menu->cursorPos] == POKENAV_MENUITEM_MATCH_CALL) - { - menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; - SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - } - else - { - PlaySE(SE_FAILURE); - return POKENAV_MENU_FUNC_NONE; - } - } - - if (JOY_NEW(B_BUTTON)) - { - PlaySE(SE_FAILURE); - return POKENAV_MENU_FUNC_NONE; - } - - return POKENAV_MENU_FUNC_NONE; -} - -// After calling Mr. Stone during the pokenav tutorial, force player to exit or use Match Call again -static u32 HandleMainMenuInputEndTutorial(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - return POKENAV_MENU_FUNC_MOVE_CURSOR; - - if (JOY_NEW(A_BUTTON)) - { - u32 menuItem = sMenuItems[menu->menuType][menu->cursorPos]; - if (menuItem != POKENAV_MENUITEM_MATCH_CALL && menuItem != POKENAV_MENUITEM_SWITCH_OFF) - { - PlaySE(SE_FAILURE); - return POKENAV_MENU_FUNC_NONE; - } - else if (menuItem == POKENAV_MENUITEM_MATCH_CALL) - { - menu->helpBarIndex = HELPBAR_MC_TRAINER_LIST; - SetMenuIdAndCB(menu, POKENAV_MATCH_CALL); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - } - else - { - return -1; - } - } - else if (JOY_NEW(B_BUTTON)) - { - return -1; - } - return POKENAV_MENU_FUNC_NONE; -} - -// Handles input after selecting Ribbons when there are no ribbon winners left -// Selecting it again just reprints the Ribbon description to replace the "No Ribbon winners" message -static u32 HandleCantOpenRibbonsInput(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - { - menu->callback = GetMainMenuInputHandler(); - return POKENAV_MENU_FUNC_MOVE_CURSOR; - } - - if (JOY_NEW(A_BUTTON | B_BUTTON)) - { - menu->callback = GetMainMenuInputHandler(); - return POKENAV_MENU_FUNC_RESHOW_DESCRIPTION; - } - - return POKENAV_MENU_FUNC_NONE; -} - -static u32 HandleConditionMenuInput(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - return POKENAV_MENU_FUNC_MOVE_CURSOR; - - if (JOY_NEW(A_BUTTON)) - { - switch (sMenuItems[menu->menuType][menu->cursorPos]) - { - case POKENAV_MENUITEM_CONDITION_SEARCH: - menu->menuType = POKENAV_MENU_TYPE_CONDITION_SEARCH; - menu->cursorPos = 0; - menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION_SEARCH][0]; - menu->callback = HandleConditionSearchMenuInput; - return POKENAV_MENU_FUNC_OPEN_CONDITION_SEARCH; - case POKENAV_MENUITEM_CONDITION_PARTY: - menu->helpBarIndex = 0; - SetMenuIdAndCB(menu, POKENAV_CONDITION_GRAPH_PARTY); - return POKENAV_MENU_FUNC_OPEN_FEATURE; - case POKENAV_MENUITEM_CONDITION_CANCEL: - PlaySE(SE_SELECT); - ReturnToMainMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_MAIN; - } - } - if (JOY_NEW(B_BUTTON)) - { - if (menu->cursorPos != sLastCursorPositions[menu->menuType]) - { - menu->cursorPos = sLastCursorPositions[menu->menuType]; - menu->callback = CB2_ReturnToMainMenu; - return POKENAV_MENU_FUNC_MOVE_CURSOR; - } - else - { - PlaySE(SE_SELECT); - ReturnToMainMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_MAIN; - } - } - - return POKENAV_MENU_FUNC_NONE; -} - -static u32 HandleConditionSearchMenuInput(struct Pokenav_Menu *menu) -{ - if (UpdateMenuCursorPos(menu)) - return POKENAV_MENU_FUNC_MOVE_CURSOR; - - if (JOY_NEW(A_BUTTON)) - { - u8 menuItem = sMenuItems[menu->menuType][menu->cursorPos]; - if (menuItem != POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL) - { - SetSelectedConditionSearch(menuItem - POKENAV_MENUITEM_CONDITION_SEARCH_COOL); - SetMenuIdAndCB(menu, POKENAV_CONDITION_SEARCH_RESULTS); - menu->helpBarIndex = HELPBAR_CONDITION_MON_LIST; - return POKENAV_MENU_FUNC_OPEN_FEATURE; - } - else - { - PlaySE(SE_SELECT); - ReturnToConditionMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; - } - } - if (JOY_NEW(B_BUTTON)) - { - if (menu->cursorPos != sLastCursorPositions[menu->menuType]) - { - menu->cursorPos = sLastCursorPositions[menu->menuType]; - menu->callback = CB2_ReturnToConditionMenu; - return POKENAV_MENU_FUNC_MOVE_CURSOR; - } - else - { - PlaySE(SE_SELECT); - ReturnToConditionMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; - } - } - return POKENAV_MENU_FUNC_NONE; -} - -static u32 CB2_ReturnToMainMenu(struct Pokenav_Menu *menu) -{ - ReturnToMainMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_MAIN; -} - -static u32 CB2_ReturnToConditionMenu(struct Pokenav_Menu *menu) -{ - ReturnToConditionMenu(menu); - return POKENAV_MENU_FUNC_RETURN_TO_CONDITION; -} - -static void SetMenuIdAndCB(struct Pokenav_Menu *menu, u32 menuId) -{ - menu->menuId = menuId; - menu->callback = GetMenuId; -} - -static u32 GetMenuId(struct Pokenav_Menu *menu) -{ - return menu->menuId; -} - -static void ReturnToMainMenu(struct Pokenav_Menu *menu) -{ - menu->menuType = GetPokenavMainMenuType(); - menu->cursorPos = 1; - menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; - menu->callback = HandleMainMenuInput; -} - -static void ReturnToConditionMenu(struct Pokenav_Menu *menu) -{ - menu->menuType = POKENAV_MENU_TYPE_CONDITION; - menu->cursorPos = 1; - menu->currMenuItem = sMenuItems[POKENAV_MENU_TYPE_CONDITION][1]; - menu->callback = HandleConditionMenuInput; -} - -static bool32 UpdateMenuCursorPos(struct Pokenav_Menu *menu) -{ - if (JOY_NEW(DPAD_UP)) - { - if (--menu->cursorPos < 0) - menu->cursorPos = sLastCursorPositions[menu->menuType]; - - menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; - return TRUE; - } - else if (JOY_NEW(DPAD_DOWN)) - { - menu->cursorPos++; - if (menu->cursorPos > sLastCursorPositions[menu->menuType]) - menu->cursorPos = 0; - - menu->currMenuItem = sMenuItems[menu->menuType][menu->cursorPos]; - return TRUE; - } - else - { - return FALSE; - } -} - -int GetPokenavMenuType(void) -{ - struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); - return menu->menuType; -} - -// Position of cursor relative to number of current menu options -int GetPokenavCursorPos(void) -{ - struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); - return menu->cursorPos; -} - -// ID of menu item the cursor is currently on -int GetCurrentMenuItemId(void) -{ - struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); - return menu->currMenuItem; -} - -u16 GetHelpBarTextId(void) -{ - struct Pokenav_Menu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU_HANDLER); - return menu->helpBarIndex; -} diff --git a/src/pokenav_menu_handler_2.c b/src/pokenav_menu_handler_2.c deleted file mode 100644 index 1738142ac..000000000 --- a/src/pokenav_menu_handler_2.c +++ /dev/null @@ -1,1371 +0,0 @@ -#include "global.h" -#include "malloc.h" -#include "decompress.h" -#include "bg.h" -#include "palette.h" -#include "trig.h" -#include "gpu_regs.h" -#include "menu.h" -#include "window.h" -#include "pokenav.h" -#include "graphics.h" -#include "sound.h" -#include "gym_leader_rematch.h" -#include "window.h" -#include "strings.h" -#include "scanline_effect.h" -#include "constants/songs.h" -#include "constants/rgb.h" - -#define GFXTAG_BLUE_LIGHT 1 -#define GFXTAG_OPTIONS 3 - -#define PALTAG_BLUE_LIGHT 3 -#define PALTAG_OPTIONS_DEFAULT 4 // Includes green for Smart/Region Map and yellow for Tough -#define PALTAG_OPTIONS_BLUE 5 -#define PALTAG_OPTIONS_PINK 6 -#define PALTAG_OPTIONS_BEIGE 7 -#define PALTAG_OPTIONS_RED 8 - -#define PALTAG_OPTIONS_START PALTAG_OPTIONS_DEFAULT - -#define NUM_OPTION_SUBSPRITES 4 - -#define OPTION_DEFAULT_X 140 -#define OPTION_SELECTED_X 130 -#define OPTION_EXIT_X (DISPLAY_WIDTH + 16) - -struct Pokenav_MenuGfx -{ - bool32 (*isTaskActiveCB)(void); - u32 loopedTaskId; - u16 optionDescWindowId; - u8 bg3ScrollTaskId; - u8 cursorPos; - u8 numIconsBlending; - bool8 pokenavAlreadyOpen; - bool32 iconVisible[MAX_POKENAV_MENUITEMS]; - struct Sprite * blueLightSprite; - struct Sprite * iconSprites[MAX_POKENAV_MENUITEMS][NUM_OPTION_SUBSPRITES]; - u8 bg1TilemapBuffer[BG_SCREEN_SIZE]; -}; - -static struct Pokenav_MenuGfx * OpenPokenavMenu(void); -static bool32 GetCurrentLoopedTaskActive(void); -static u32 LoopedTask_OpenMenu(s32); -static u32 LoopedTask_MoveMenuCursor(s32); -static u32 LoopedTask_OpenConditionMenu(s32); -static u32 LoopedTask_ReturnToMainMenu(s32); -static u32 LoopedTask_OpenConditionSearchMenu(s32); -static u32 LoopedTask_ReturnToConditionMenu(s32); -static u32 LoopedTask_SelectRibbonsNoWinners(s32); -static u32 LoopedTask_ReShowDescription(s32); -static u32 LoopedTask_OpenPokenavFeature(s32); -static void LoadPokenavOptionPalettes(void); -static void FreeAndDestroyMainMenuSprites(void); -static void CreateMenuOptionSprites(void); -static void DestroyMenuOptionSprites(void); -static void DrawCurrentMenuOptionLabels(void); -static void DrawOptionLabelGfx(const u16 *const *, s32, s32); -static void StartOptionAnimations_Enter(void); -static void StartOptionAnimations_CursorMoved(void); -static void StartOptionAnimations_Exit(void); -static void StartOptionSlide(struct Sprite **, s32, s32, s32); -static void StartOptionZoom(struct Sprite **); -static bool32 AreMenuOptionSpritesMoving(void); -static void SetOptionInvisibility(struct Sprite **, bool32); -static void SpriteCB_OptionSlide(struct Sprite *); -static void SpriteCB_OptionZoom(struct Sprite *); -static void Task_OptionBlend(u8); -static void CreateMatchCallBlueLightSprite(void); -static void SpriteCB_BlinkingBlueLight(struct Sprite *); -static void DestroyRematchBlueLightSprite(void); -static void AddOptionDescriptionWindow(void); -static void PrintCurrentOptionDescription(void); -static void PrintNoRibbonWinners(void); -static bool32 IsDma3ManagerBusyWithBgCopy_(void); -static void CreateMovingBgDotsTask(void); -static void DestroyMovingDotsBgTask(void); -static void Task_MoveBgDots(u8); -static void CreateBgDotPurplePalTask(void); -static void ChangeBgDotsColorToPurple(void); -static void CreateBgDotLightBluePalTask(void); -static bool32 IsTaskActive_UpdateBgDotsPalette(void); -static void Task_UpdateBgDotsPalette(u8); -static void SetupPokenavMenuScanlineEffects(void); -static void DestroyMenuOptionGlowTask(void); -static void ResetBldCnt(void); -static void InitMenuOptionGlow(void); -static void Task_CurrentMenuOptionGlow(u8); -static void SetMenuOptionGlow(void); - -static const u16 sPokenavBgDotsPal[] = INCBIN_U16("graphics/pokenav/bg_dots.gbapal"); -static const u32 sPokenavBgDotsTiles[] = INCBIN_U32("graphics/pokenav/bg_dots.4bpp.lz"); -static const u32 sPokenavBgDotsTilemap[] = INCBIN_U32("graphics/pokenav/bg_dots.bin.lz"); -static const u16 sPokenavDeviceBgPal[] = INCBIN_U16("graphics/pokenav/device_outline.gbapal"); -static const u32 sPokenavDeviceBgTiles[] = INCBIN_U32("graphics/pokenav/device_outline.4bpp.lz"); -static const u32 sPokenavDeviceBgTilemap[] = INCBIN_U32("graphics/pokenav/device_outline_map.bin.lz"); -static const u16 sMatchCallBlueLightPal[] = INCBIN_U16("graphics/pokenav/blue_light.gbapal"); -static const u32 sMatchCallBlueLightTiles[] = INCBIN_U32("graphics/pokenav/blue_light.4bpp.lz"); - -static const struct BgTemplate sPokenavMainMenuBgTemplates[] = { - { - .bg = 1, - .charBaseIndex = 1, - .mapBaseIndex = 15, - .screenSize = 0, - .paletteMode = 0, - .priority = 1, - .baseTile = 0x000 - }, { - .bg = 2, - .charBaseIndex = 2, - .mapBaseIndex = 23, - .screenSize = 0, - .paletteMode = 0, - .priority = 2, - .baseTile = 0x000 - }, { - .bg = 3, - .charBaseIndex = 3, - .mapBaseIndex = 31, - .screenSize = 0, - .paletteMode = 0, - .priority = 3, - .baseTile = 0x000 - } -}; - -static const LoopedTask sMenuHandlerLoopTaskFuncs[] = -{ - [POKENAV_MENU_FUNC_NONE] = NULL, - [POKENAV_MENU_FUNC_MOVE_CURSOR] = LoopedTask_MoveMenuCursor, - [POKENAV_MENU_FUNC_OPEN_CONDITION] = LoopedTask_OpenConditionMenu, - [POKENAV_MENU_FUNC_RETURN_TO_MAIN] = LoopedTask_ReturnToMainMenu, - [POKENAV_MENU_FUNC_OPEN_CONDITION_SEARCH] = LoopedTask_OpenConditionSearchMenu, - [POKENAV_MENU_FUNC_RETURN_TO_CONDITION] = LoopedTask_ReturnToConditionMenu, - [POKENAV_MENU_FUNC_NO_RIBBON_WINNERS] = LoopedTask_SelectRibbonsNoWinners, - [POKENAV_MENU_FUNC_RESHOW_DESCRIPTION] = LoopedTask_ReShowDescription, - [POKENAV_MENU_FUNC_OPEN_FEATURE] = LoopedTask_OpenPokenavFeature -}; - -static const struct CompressedSpriteSheet sPokenavOptionsSpriteSheets[] = -{ - { - .data = gPokenavOptions_Gfx, - .size = 0x3400, - .tag = GFXTAG_OPTIONS - }, - { - .data = sMatchCallBlueLightTiles, - .size = 0x0100, - .tag = GFXTAG_BLUE_LIGHT - } -}; - -static const struct SpritePalette sPokenavOptionsSpritePalettes[] = -{ - {&gPokenavOptions_Pal[0x00], PALTAG_OPTIONS_DEFAULT}, - {&gPokenavOptions_Pal[0x10], PALTAG_OPTIONS_BLUE}, - {&gPokenavOptions_Pal[0x20], PALTAG_OPTIONS_PINK}, - {&gPokenavOptions_Pal[0x30], PALTAG_OPTIONS_BEIGE}, - {&gPokenavOptions_Pal[0x40], PALTAG_OPTIONS_RED}, - {sMatchCallBlueLightPal, PALTAG_BLUE_LIGHT}, - {} -}; - -// Tile number, palette tag offset -static const u16 sOptionsLabelGfx_RegionMap[] = {0x000, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Condition[] = {0x020, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_MatchCall[] = {0x040, PALTAG_OPTIONS_RED - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Ribbons[] = {0x060, PALTAG_OPTIONS_PINK - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_SwitchOff[] = {0x080, PALTAG_OPTIONS_BEIGE - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Party[] = {0x0A0, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Search[] = {0x0C0, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Cool[] = {0x0E0, PALTAG_OPTIONS_RED - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Beauty[] = {0x100, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Cute[] = {0x120, PALTAG_OPTIONS_PINK - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Smart[] = {0x140, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Tough[] = {0x160, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; -static const u16 sOptionsLabelGfx_Cancel[] = {0x180, PALTAG_OPTIONS_BEIGE - PALTAG_OPTIONS_START}; - -struct -{ - u16 yStart; - u16 deltaY; - const u16 *gfx[MAX_POKENAV_MENUITEMS]; -} static const sPokenavMenuOptionLabelGfx[POKENAV_MENU_TYPE_COUNT] = -{ - [POKENAV_MENU_TYPE_DEFAULT] = - { - .yStart = 42, - .deltaY = 20, - .gfx = { - sOptionsLabelGfx_RegionMap, - sOptionsLabelGfx_Condition, - sOptionsLabelGfx_SwitchOff - } - }, - [POKENAV_MENU_TYPE_UNLOCK_MC] = - { - .yStart = 42, - .deltaY = 20, - .gfx = { - sOptionsLabelGfx_RegionMap, - sOptionsLabelGfx_Condition, - sOptionsLabelGfx_MatchCall, - sOptionsLabelGfx_SwitchOff - } - }, - [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = - { - .yStart = 42, - .deltaY = 20, - .gfx = { - sOptionsLabelGfx_RegionMap, - sOptionsLabelGfx_Condition, - sOptionsLabelGfx_MatchCall, - sOptionsLabelGfx_Ribbons, - sOptionsLabelGfx_SwitchOff - } - }, - [POKENAV_MENU_TYPE_CONDITION] = - { - .yStart = 56, - .deltaY = 20, - .gfx = { - sOptionsLabelGfx_Party, - sOptionsLabelGfx_Search, - sOptionsLabelGfx_Cancel - } - }, - [POKENAV_MENU_TYPE_CONDITION_SEARCH] = - { - .yStart = 40, - .deltaY = 16, - .gfx = { - sOptionsLabelGfx_Cool, - sOptionsLabelGfx_Beauty, - sOptionsLabelGfx_Cute, - sOptionsLabelGfx_Smart, - sOptionsLabelGfx_Tough, - sOptionsLabelGfx_Cancel - } - }, -}; - -static const struct WindowTemplate sOptionDescWindowTemplate = -{ - .bg = 1, - .tilemapLeft = 3, - .tilemapTop = 17, - .width = 24, - .height = 2, - .paletteNum = 1, - .baseBlock = 8 -}; - -static const u8 *const sPageDescriptions[] = -{ - [POKENAV_MENUITEM_MAP] = gText_CheckMapOfHoenn, - [POKENAV_MENUITEM_CONDITION] = gText_CheckPokemonInDetail, - [POKENAV_MENUITEM_MATCH_CALL] = gText_CallRegisteredTrainer, - [POKENAV_MENUITEM_RIBBONS] = gText_CheckObtainedRibbons, - [POKENAV_MENUITEM_SWITCH_OFF] = gText_PutAwayPokenav, - [POKENAV_MENUITEM_CONDITION_PARTY] = gText_CheckPartyPokemonInDetail, - [POKENAV_MENUITEM_CONDITION_SEARCH] = gText_CheckAllPokemonInDetail, - [POKENAV_MENUITEM_CONDITION_CANCEL] = gText_ReturnToPokenavMenu, - [POKENAV_MENUITEM_CONDITION_SEARCH_COOL] = gText_FindCoolPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY] = gText_FindBeautifulPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_CUTE] = gText_FindCutePokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_SMART] = gText_FindSmartPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH] = gText_FindToughPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL] = gText_ReturnToConditionMenu -}; - -static const u8 sOptionDescTextColors[] = {TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_GREEN}; -static const u8 sOptionDescTextColors2[] = {TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_GREEN}; - -static const struct OamData sOamData_MenuOption = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_OFF, - .objMode = ST_OAM_OBJ_NORMAL, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(32x16), - .x = 0, - .size = SPRITE_SIZE(32x16), - .tileNum = 0, - .priority = 2, - .paletteNum = 0, -}; - -static const union AffineAnimCmd sAffineAnim_MenuOption_Normal[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_MenuOption_Zoom[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0x12), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_MenuOption[] = -{ - sAffineAnim_MenuOption_Normal, - sAffineAnim_MenuOption_Zoom -}; - -static const struct SpriteTemplate sMenuOptionSpriteTemplate = -{ - .tileTag = GFXTAG_OPTIONS, - .paletteTag = PALTAG_OPTIONS_START, - .oam = &sOamData_MenuOption, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_MenuOption, - .callback = SpriteCallbackDummy, -}; - -static const struct OamData sBlueLightOamData = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_OFF, - .objMode = ST_OAM_OBJ_NORMAL, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(32x16), - .x = 0, - .size = SPRITE_SIZE(32x16), - .tileNum = 0, - .priority = 2, - .paletteNum = 0, -}; - -static const struct SpriteTemplate sMatchCallBlueLightSpriteTemplate = -{ - .tileTag = GFXTAG_BLUE_LIGHT, - .paletteTag = PALTAG_BLUE_LIGHT, - .oam = &sBlueLightOamData, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCallbackDummy, -}; - -static const struct ScanlineEffectParams sPokenavMainMenuScanlineEffectParams = -{ - ®_WIN0H, - ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, - 1, - 0 -}; - -static bool32 AreAnyTrainerRematchesNearby(void) -{ - s32 i; - - for (i = 0; i < REMATCH_TABLE_ENTRIES; i++) - { - if (GetMatchTableMapSectionId(i) == gMapHeader.regionMapSectionId - && IsRematchEntryRegistered(i) - && gSaveBlock1Ptr->trainerRematches[i]) - return TRUE; - } - - return FALSE; -} - -bool32 OpenPokenavMenuInitial(void) -{ - struct Pokenav_MenuGfx * gfx = OpenPokenavMenu(); - - if (gfx == NULL) - return FALSE; - - gfx->pokenavAlreadyOpen = FALSE; - return TRUE; -} - -bool32 OpenPokenavMenuNotInitial(void) -{ - struct Pokenav_MenuGfx * gfx = OpenPokenavMenu(); - - if (gfx == NULL) - return FALSE; - - gfx->pokenavAlreadyOpen = TRUE; - return TRUE; -} - -static struct Pokenav_MenuGfx * OpenPokenavMenu(void) -{ - struct Pokenav_MenuGfx * gfx = AllocSubstruct(POKENAV_SUBSTRUCT_MENU_GFX, sizeof(struct Pokenav_MenuGfx)); - - if (gfx != NULL) - { - gfx->numIconsBlending = 0; - gfx->loopedTaskId = CreateLoopedTask(LoopedTask_OpenMenu, 1); - gfx->isTaskActiveCB = GetCurrentLoopedTaskActive; - } - - return gfx; -} - -void CreateMenuHandlerLoopedTask(s32 ltIdx) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - gfx->loopedTaskId = CreateLoopedTask(sMenuHandlerLoopTaskFuncs[ltIdx], 1); - gfx->isTaskActiveCB = GetCurrentLoopedTaskActive; -} - -bool32 IsMenuHandlerLoopedTaskActive(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - return gfx->isTaskActiveCB(); -} - -void FreeMenuHandlerSubstruct2(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - DestroyMovingDotsBgTask(); - RemoveWindow(gfx->optionDescWindowId); - FreeAndDestroyMainMenuSprites(); - DestroyMenuOptionGlowTask(); - FreePokenavSubstruct(POKENAV_SUBSTRUCT_MENU_GFX); -} - -static bool32 GetCurrentLoopedTaskActive(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - return IsLoopedTaskActive(gfx->loopedTaskId); -} - -static u32 LoopedTask_OpenMenu(s32 state) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - switch (state) - { - case 0: - InitBgTemplates(sPokenavMainMenuBgTemplates, ARRAY_COUNT(sPokenavMainMenuBgTemplates)); - DecompressAndCopyTileDataToVram(1, gPokenavMessageBox_Gfx, 0, 0, 0); - SetBgTilemapBuffer(1, gfx->bg1TilemapBuffer); - CopyToBgTilemapBuffer(1, gPokenavMessageBox_Tilemap, 0, 0); - CopyBgTilemapBufferToVram(1); - CopyPaletteIntoBufferUnfaded(gPokenavMessageBox_Pal, 0x10, 0x20); - ChangeBgX(1, 0, BG_COORD_SET); - ChangeBgY(1, 0, BG_COORD_SET); - ChangeBgX(2, 0, BG_COORD_SET); - ChangeBgY(2, 0, BG_COORD_SET); - ChangeBgX(3, 0, BG_COORD_SET); - ChangeBgY(3, 0, BG_COORD_SET); - return LT_INC_AND_PAUSE; - case 1: - if (FreeTempTileDataBuffersIfPossible()) - return LT_PAUSE; - DecompressAndCopyTileDataToVram(2, sPokenavDeviceBgTiles, 0, 0, 0); - DecompressAndCopyTileDataToVram(2, sPokenavDeviceBgTilemap, 0, 0, 1); - CopyPaletteIntoBufferUnfaded(sPokenavDeviceBgPal, 0x20, 0x20); - return LT_INC_AND_PAUSE; - case 2: - if (FreeTempTileDataBuffersIfPossible()) - return LT_PAUSE; - DecompressAndCopyTileDataToVram(3, sPokenavBgDotsTiles, 0, 0, 0); - DecompressAndCopyTileDataToVram(3, sPokenavBgDotsTilemap, 0, 0, 1); - CopyPaletteIntoBufferUnfaded(sPokenavBgDotsPal, 0x30, 0x20); - if (GetPokenavMenuType() == POKENAV_MENU_TYPE_CONDITION || GetPokenavMenuType() == POKENAV_MENU_TYPE_CONDITION_SEARCH) - ChangeBgDotsColorToPurple(); - return LT_INC_AND_PAUSE; - case 3: - if (FreeTempTileDataBuffersIfPossible()) - return LT_PAUSE; - AddOptionDescriptionWindow(); - CreateMovingBgDotsTask(); - return LT_INC_AND_CONTINUE; - case 4: - LoadPokenavOptionPalettes(); - return LT_INC_AND_CONTINUE; - case 5: - PrintCurrentOptionDescription(); - CreateMenuOptionSprites(); - CreateMatchCallBlueLightSprite(); - DrawCurrentMenuOptionLabels(); - return LT_INC_AND_PAUSE; - case 6: - if (IsDma3ManagerBusyWithBgCopy_()) - return LT_PAUSE; - return LT_INC_AND_CONTINUE; - case 7: - ShowBg(1); - ShowBg(2); - ShowBg(3); - if (gfx->pokenavAlreadyOpen) - PokenavFadeScreen(1); - else - { - PlaySE(SE_POKENAV_ON); - PokenavFadeScreen(3); - } - switch (GetPokenavMenuType()) - { - case POKENAV_MENU_TYPE_CONDITION_SEARCH: - LoadLeftHeaderGfxForIndex(7); - // fallthrough - case POKENAV_MENU_TYPE_CONDITION: - LoadLeftHeaderGfxForIndex(1); - break; - default: - LoadLeftHeaderGfxForIndex(0); - break; - } - return LT_INC_AND_PAUSE; - case 8: - if (IsPaletteFadeActive()) - return LT_PAUSE; - switch (GetPokenavMenuType()) - { - case POKENAV_MENU_TYPE_CONDITION_SEARCH: - ShowLeftHeaderGfx(7, FALSE, FALSE); - // fallthrough - case POKENAV_MENU_TYPE_CONDITION: - ShowLeftHeaderGfx(1, FALSE, FALSE); - break; - default: - ShowLeftHeaderGfx(0, FALSE, FALSE); - break; - } - StartOptionAnimations_Enter(); - SetupPokenavMenuScanlineEffects(); - return LT_INC_AND_CONTINUE; - case 9: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_MoveMenuCursor(s32 state) -{ - switch (state) - { - case 0: - SetMenuOptionGlow(); - StartOptionAnimations_CursorMoved(); - PrintCurrentOptionDescription(); - PlaySE(SE_SELECT); - return LT_INC_AND_PAUSE; - case 1: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (IsDma3ManagerBusyWithBgCopy_()) - return LT_PAUSE; - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_OpenConditionMenu(s32 state) -{ - switch (state) - { - case 0: - ResetBldCnt(); - StartOptionAnimations_Exit(); - HideMainOrSubMenuLeftHeader(POKENAV_GFX_MAIN_MENU, 0); - PlaySE(SE_SELECT); - return LT_INC_AND_PAUSE; - case 1: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - DrawCurrentMenuOptionLabels(); - LoadLeftHeaderGfxForIndex(1); - return LT_INC_AND_PAUSE; - case 2: - StartOptionAnimations_Enter(); - ShowLeftHeaderGfx(1, FALSE, FALSE); - CreateBgDotPurplePalTask(); - PrintCurrentOptionDescription(); - return LT_INC_AND_PAUSE; - case 3: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - if (IsTaskActive_UpdateBgDotsPalette()) - return LT_PAUSE; - if (IsDma3ManagerBusyWithBgCopy_()) - return LT_PAUSE; - InitMenuOptionGlow(); - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_ReturnToMainMenu(s32 state) -{ - switch (state) - { - case 0: - ResetBldCnt(); - StartOptionAnimations_Exit(); - HideMainOrSubMenuLeftHeader(POKENAV_GFX_CONDITION_MENU, 0); - return LT_INC_AND_PAUSE; - case 1: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - DrawCurrentMenuOptionLabels(); - LoadLeftHeaderGfxForIndex(0); - return LT_INC_AND_PAUSE; - case 2: - StartOptionAnimations_Enter(); - ShowLeftHeaderGfx(0, FALSE, FALSE); - CreateBgDotLightBluePalTask(); - PrintCurrentOptionDescription(); - return LT_INC_AND_PAUSE; - case 3: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - if (IsTaskActive_UpdateBgDotsPalette()) - return LT_PAUSE; - if (IsDma3ManagerBusyWithBgCopy_()) - return LT_PAUSE; - InitMenuOptionGlow(); - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_OpenConditionSearchMenu(s32 state) -{ - switch (state) - { - case 0: - ResetBldCnt(); - StartOptionAnimations_Exit(); - PlaySE(SE_SELECT); - return LT_INC_AND_PAUSE; - case 1: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - LoadLeftHeaderGfxForIndex(7); - DrawCurrentMenuOptionLabels(); - return LT_INC_AND_PAUSE; - case 2: - StartOptionAnimations_Enter(); - ShowLeftHeaderGfx(7, FALSE, FALSE); - PrintCurrentOptionDescription(); - return LT_INC_AND_PAUSE; - case 3: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - if (IsTaskActive_UpdateBgDotsPalette()) - return LT_PAUSE; - InitMenuOptionGlow(); - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_ReturnToConditionMenu(s32 state) -{ - switch (state) - { - case 0: - ResetBldCnt(); - StartOptionAnimations_Exit(); - HideMainOrSubMenuLeftHeader(POKENAV_GFX_SEARCH_MENU, 0); - return LT_INC_AND_PAUSE; - case 1: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - DrawCurrentMenuOptionLabels(); - return LT_INC_AND_PAUSE; - case 2: - StartOptionAnimations_Enter(); - PrintCurrentOptionDescription(); - return LT_INC_AND_PAUSE; - case 3: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (IsTaskActive_UpdateBgDotsPalette()) - return LT_PAUSE; - InitMenuOptionGlow(); - break; - } - return LT_FINISH; -} - -static u32 LoopedTask_SelectRibbonsNoWinners(s32 state) -{ - switch (state) - { - case 0: - PlaySE(SE_FAILURE); - PrintNoRibbonWinners(); - return LT_INC_AND_PAUSE; - case 1: - if (IsDma3ManagerBusyWithBgCopy()) - return LT_PAUSE; - break; - } - return LT_FINISH; -} - -// For redisplaying the Ribbons description to replace the No Ribbon Winners message -static u32 LoopedTask_ReShowDescription(s32 state) -{ - switch (state) - { - case 0: - PlaySE(SE_SELECT); - PrintCurrentOptionDescription(); - return LT_INC_AND_PAUSE; - case 1: - if (IsDma3ManagerBusyWithBgCopy()) - return LT_PAUSE; - break; - } - return LT_FINISH; -} - -// For selecting a feature option from a menu, e.g. the Map, Match Call, Beauty search, etc. -static u32 LoopedTask_OpenPokenavFeature(s32 state) -{ - switch (state) - { - case 0: - PrintHelpBarText(GetHelpBarTextId()); - return LT_INC_AND_PAUSE; - case 1: - if (WaitForHelpBar()) - return LT_PAUSE; - SlideMenuHeaderUp(); - ResetBldCnt(); - StartOptionAnimations_Exit(); - switch (GetPokenavMenuType()) - { - case POKENAV_MENU_TYPE_CONDITION_SEARCH: - HideMainOrSubMenuLeftHeader(POKENAV_GFX_SEARCH_MENU, FALSE); - // fallthrough - case POKENAV_MENU_TYPE_CONDITION: - HideMainOrSubMenuLeftHeader(POKENAV_GFX_CONDITION_MENU, FALSE); - break; - default: - HideMainOrSubMenuLeftHeader(POKENAV_GFX_MAIN_MENU, FALSE); - break; - } - PlaySE(SE_SELECT); - return LT_INC_AND_PAUSE; - case 2: - if (AreMenuOptionSpritesMoving()) - return LT_PAUSE; - if (AreLeftHeaderSpritesMoving()) - return LT_PAUSE; - PokenavFadeScreen(0); - return LT_INC_AND_PAUSE; - case 3: - if (IsPaletteFadeActive()) - return LT_PAUSE; - break; - } - return LT_FINISH; -} - -static void LoadPokenavOptionPalettes(void) -{ - s32 i; - - for (i = 0; i < ARRAY_COUNT(sPokenavOptionsSpriteSheets); i++) - LoadCompressedSpriteSheet(&sPokenavOptionsSpriteSheets[i]); - Pokenav_AllocAndLoadPalettes(sPokenavOptionsSpritePalettes); -} - -static void FreeAndDestroyMainMenuSprites(void) -{ - FreeSpriteTilesByTag(GFXTAG_OPTIONS); - FreeSpriteTilesByTag(GFXTAG_BLUE_LIGHT); - FreeSpritePaletteByTag(PALTAG_OPTIONS_DEFAULT); - FreeSpritePaletteByTag(PALTAG_OPTIONS_BLUE); - FreeSpritePaletteByTag(PALTAG_OPTIONS_PINK); - FreeSpritePaletteByTag(PALTAG_OPTIONS_BEIGE); - FreeSpritePaletteByTag(PALTAG_OPTIONS_RED); - FreeSpritePaletteByTag(PALTAG_BLUE_LIGHT); - DestroyMenuOptionSprites(); - DestroyRematchBlueLightSprite(); -} - -static void CreateMenuOptionSprites(void) -{ - s32 i, j; - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) - { - u8 spriteId = CreateSprite(&sMenuOptionSpriteTemplate, 0x8c, 20 * i + 40, 3); - gfx->iconSprites[i][j] = &gSprites[spriteId]; - gSprites[spriteId].x2 = 32 * j; - } - } -} - -static void DestroyMenuOptionSprites(void) -{ - s32 i, j; - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) - { - FreeSpriteOamMatrix(gfx->iconSprites[i][j]); - DestroySprite(gfx->iconSprites[i][j]); - } - } -} - -static void DrawCurrentMenuOptionLabels(void) -{ - s32 menuType = GetPokenavMenuType(); - DrawOptionLabelGfx(sPokenavMenuOptionLabelGfx[menuType].gfx, sPokenavMenuOptionLabelGfx[menuType].yStart, sPokenavMenuOptionLabelGfx[menuType].deltaY); -} - -static void DrawOptionLabelGfx(const u16 *const *optionGfx, s32 yPos, s32 deltaY) -{ - s32 i, j; - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - s32 baseTile = GetSpriteTileStartByTag(GFXTAG_OPTIONS); - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - if (*optionGfx != NULL) - { - for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) - { - gfx->iconSprites[i][j]->oam.tileNum = (*optionGfx)[0] + baseTile + 8 * j; - gfx->iconSprites[i][j]->oam.paletteNum = IndexOfSpritePaletteTag((*optionGfx)[1] + PALTAG_OPTIONS_START); - gfx->iconSprites[i][j]->invisible = TRUE; - gfx->iconSprites[i][j]->y = yPos; - gfx->iconSprites[i][j]->x = OPTION_DEFAULT_X; - gfx->iconSprites[i][j]->x2 = 32 * j; - } - gfx->iconVisible[i] = TRUE; - } - else - { - for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) - gfx->iconSprites[i][j]->invisible = TRUE; - - gfx->iconVisible[i] = FALSE; - } - optionGfx++; - yPos += deltaY; - } -} - -static void StartOptionAnimations_Enter(void) -{ - s32 i; - struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - s32 cursorPos = GetPokenavCursorPos(); - s32 iconCount = 0; - s32 x; - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - if (gfx->iconVisible[i]) - { - if (iconCount++ == cursorPos) - { - x = OPTION_SELECTED_X; - gfx->cursorPos = i; - } - else - { - // Not selected, set default position - x = OPTION_DEFAULT_X; - } - - // Slide new options in - StartOptionSlide(gfx->iconSprites[i], OPTION_EXIT_X, x, 12); - SetOptionInvisibility(gfx->iconSprites[i], FALSE); - } - else - { - SetOptionInvisibility(gfx->iconSprites[i], TRUE); - } - } -} - -static void StartOptionAnimations_CursorMoved(void) -{ - s32 i; - struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - s32 prevPos = GetPokenavCursorPos(); - s32 newPos; - - // Get the index of the next visible option - for (i = 0, newPos = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - if (gfx->iconVisible[i]) - { - if (newPos == prevPos) - { - newPos = i; - break; - } - newPos++; - } - } - - // The selected option slides out a bit and the previously - // selected option slides back to its original position. - StartOptionSlide(gfx->iconSprites[gfx->cursorPos], OPTION_SELECTED_X, OPTION_DEFAULT_X, 4); - StartOptionSlide(gfx->iconSprites[newPos], OPTION_DEFAULT_X, OPTION_SELECTED_X, 4); - gfx->cursorPos = newPos; -} - -static void StartOptionAnimations_Exit(void) -{ - s32 i; - struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - if (gfx->iconVisible[i]) - { - // Unselected options slide out, - // selected option zooms in - if (gfx->cursorPos != i) - StartOptionSlide(gfx->iconSprites[i], OPTION_DEFAULT_X, OPTION_EXIT_X, 8); - else - StartOptionZoom(gfx->iconSprites[i]); - } - } -} - -static bool32 AreMenuOptionSpritesMoving(void) -{ - s32 i; - struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) - { - if (gfx->iconSprites[i][0]->callback != SpriteCallbackDummy) - return TRUE; - } - - if (gfx->numIconsBlending != 0) - return TRUE; - - return FALSE; -} - -#define sSlideTime data[0] -#define sSlideAccel data[1] -#define sSlideSpeed data[2] -#define sSlideEndX data[7] - -static void StartOptionSlide(struct Sprite ** sprites, s32 startX, s32 endX, s32 time) -{ - s32 i; - - for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) - { - (*sprites)->x = startX; - (*sprites)->sSlideTime = time; - (*sprites)->sSlideAccel = 16 * (endX - startX) / time; - (*sprites)->sSlideSpeed = 16 * startX; - (*sprites)->sSlideEndX = endX; - (*sprites)->callback = SpriteCB_OptionSlide; - sprites++; - } -} - -#define sZoomDelay data[0] -#define sZoomSetAffine data[1] -#define sZoomSpeed data[2] -#define sZoomSubspriteId data[7] - -#define tBlendDelay data[0] -#define tBlendState data[1] -#define tBlendTarget1 data[2] -#define tBlendTarget2 data[3] -#define tBlendCounter data[4] - -// When an option is selected it zooms in and blends away as part -// of the transition to the next screen. -static void StartOptionZoom(struct Sprite ** sprites) -{ - s32 i; - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - u8 taskId; - - for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) - { - (*sprites)->oam.objMode = ST_OAM_OBJ_BLEND; - (*sprites)->oam.affineMode = ST_OAM_AFFINE_DOUBLE; - (*sprites)->callback = SpriteCB_OptionZoom; - (*sprites)->sZoomDelay = 8; - (*sprites)->sZoomSetAffine = FALSE; - (*sprites)->sZoomSubspriteId = i; - InitSpriteAffineAnim(sprites[0]); - StartSpriteAffineAnim(sprites[0], 0); - sprites++; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - taskId = CreateTask(Task_OptionBlend, 3); - gTasks[taskId].tBlendDelay = 8; - gfx->numIconsBlending++; -} - -static void SetOptionInvisibility(struct Sprite ** sprites, bool32 invisible) -{ - s32 i; - - for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) - { - (*sprites)->invisible = invisible; - sprites++; - } -} - -static void SpriteCB_OptionSlide(struct Sprite * sprite) -{ - sprite->sSlideTime--; - if (sprite->sSlideTime != -1) - { - sprite->sSlideSpeed += sprite->sSlideAccel; - sprite->x = sprite->sSlideSpeed >> 4; - } - else - { - sprite->x = sprite->sSlideEndX; - sprite->callback = SpriteCallbackDummy; - } -} - -#undef sSlideTime -#undef sSlideAccel -#undef sSlideSpeed -#undef sSlideEndX - -static void SpriteCB_OptionZoom(struct Sprite * sprite) -{ - s32 temp; - s32 x; - if (sprite->sZoomDelay == 0) - { - if (!sprite->sZoomSetAffine) - { - StartSpriteAffineAnim(sprite, 1); - sprite->sZoomSetAffine++; - sprite->sZoomSpeed = 0x100; - sprite->x += sprite->x2; - sprite->x2 = 0; - } - else - { - sprite->sZoomSpeed += 16; - temp = sprite->sZoomSpeed; - x = temp >> 3; - x = (x - 32) / 2; - - // Each subsprite needs to zoom to a different degree/direction - switch (sprite->sZoomSubspriteId) - { - case 0: - sprite->x2 = -x * 3; - break; - case 1: - sprite->x2 = -x; - break; - case 2: - sprite->x2 = x; - break; - case 3: - sprite->x2 = x * 3; - break; - } - if (sprite->affineAnimEnded) - { - sprite->invisible = TRUE; - FreeOamMatrix(sprite->oam.matrixNum); - CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, ST_OAM_AFFINE_OFF); - sprite->oam.affineMode = ST_OAM_AFFINE_OFF; - sprite->oam.objMode = ST_OAM_OBJ_NORMAL; - sprite->callback = SpriteCallbackDummy; - } - } - } - else - { - sprite->sZoomDelay--; - } -} - -#undef sZoomDelay -#undef sZoomSetAffine -#undef sZoomSpeed -#undef sZoomSubspriteId - -static void Task_OptionBlend(u8 taskId) -{ - s16 * data = gTasks[taskId].data; - - if (tBlendDelay == 0) - { - switch (tBlendState) - { - case 0: - tBlendTarget1 = 16; - tBlendTarget2 = 0; - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_NONE | BLDCNT_TGT2_ALL); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - tBlendState++; - break; - case 1: - if (tBlendCounter & 1) - { - tBlendTarget1 -= 3; - if (tBlendTarget1 < 0) - tBlendTarget1 = 0; - } - else - { - tBlendTarget2 += 3; - if (tBlendTarget2 > 16) - tBlendTarget2 = 16; - } - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(tBlendTarget1, tBlendTarget2)); - tBlendCounter++; - if (tBlendCounter == 12) - { - ((struct Pokenav_MenuGfx *)GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX))->numIconsBlending--; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); - DestroyTask(taskId); - } - break; - } - } - else - { - tBlendDelay--; - } -} - -#undef tBlendDelay -#undef tBlendState -#undef tBlendTarget1 -#undef tBlendTarget2 -#undef tBlendCounter - -// Blue light that blinks if there are available rematches nearby -static void CreateMatchCallBlueLightSprite(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - u8 spriteId = CreateSprite(&sMatchCallBlueLightSpriteTemplate, 0x10, 0x60, 4); - gfx->blueLightSprite = &gSprites[spriteId]; - if (AreAnyTrainerRematchesNearby()) - gfx->blueLightSprite->callback = SpriteCB_BlinkingBlueLight; - else - gfx->blueLightSprite->invisible = TRUE; -} - -static void DestroyRematchBlueLightSprite(void) -{ - struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - DestroySprite(gfx->blueLightSprite); -} - -static void SpriteCB_BlinkingBlueLight(struct Sprite * sprite) -{ - sprite->data[0]++; - if (sprite->data[0] > 8) - { - sprite->data[0] = 0; - sprite->invisible ^= 1; - } -} - -static void AddOptionDescriptionWindow(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - - gfx->optionDescWindowId = AddWindow(&sOptionDescWindowTemplate); - PutWindowTilemap(gfx->optionDescWindowId); - FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); - CopyWindowToVram(gfx->optionDescWindowId, COPYWIN_FULL); -} - -static void PrintCurrentOptionDescription(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - int menuItem = GetCurrentMenuItemId(); - const u8 * desc = sPageDescriptions[menuItem]; - u32 width = GetStringWidth(FONT_NORMAL, desc, -1); - FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); - AddTextPrinterParameterized3(gfx->optionDescWindowId, FONT_NORMAL, (192 - width) / 2, 1, sOptionDescTextColors, 0, desc); -} - -// Printed when Ribbons is selected if no PC/party mons have ribbons -// Can occur by obtaining a mon with a ribbon and then releasing all ribbon winners -static void PrintNoRibbonWinners(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - const u8 * s = gText_NoRibbonWinners; - u32 width = GetStringWidth(FONT_NORMAL, s, -1); - FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); - AddTextPrinterParameterized3(gfx->optionDescWindowId, FONT_NORMAL, (192 - width) / 2, 1, sOptionDescTextColors2, 0, s); -} - -static bool32 IsDma3ManagerBusyWithBgCopy_(void) -{ - return IsDma3ManagerBusyWithBgCopy(); -} - -static void CreateMovingBgDotsTask(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - gfx->bg3ScrollTaskId = CreateTask(Task_MoveBgDots, 2); -} - -static void DestroyMovingDotsBgTask(void) -{ - struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); - DestroyTask(gfx->bg3ScrollTaskId); -} - -static void Task_MoveBgDots(u8 taskId) -{ - ChangeBgX(3, 0x80, BG_COORD_ADD); -} - -static void CreateBgDotPurplePalTask(void) -{ - u8 taskId = CreateTask(Task_UpdateBgDotsPalette, 3); - SetWordTaskArg(taskId, 1, (uintptr_t)(sPokenavBgDotsPal + 1)); - SetWordTaskArg(taskId, 3, (uintptr_t)(sPokenavBgDotsPal + 7)); -} - -static void ChangeBgDotsColorToPurple(void) -{ - CopyPaletteIntoBufferUnfaded(sPokenavBgDotsPal + 7, 0x31, 4); -} - -static void CreateBgDotLightBluePalTask(void) -{ - u8 taskId = CreateTask(Task_UpdateBgDotsPalette, 3); - SetWordTaskArg(taskId, 1, (uintptr_t)(sPokenavBgDotsPal + 7)); - SetWordTaskArg(taskId, 3, (uintptr_t)(sPokenavBgDotsPal + 1)); -} - -static bool32 IsTaskActive_UpdateBgDotsPalette(void) -{ - return FuncIsActiveTask(Task_UpdateBgDotsPalette); -} - -static void Task_UpdateBgDotsPalette(u8 taskId) -{ - u16 sp8[2]; - s16 * data = gTasks[taskId].data; - const u16 * pal1 = (const u16 *)GetWordTaskArg(taskId, 1); - const u16 * pal2 = (const u16 *)GetWordTaskArg(taskId, 3); - - PokenavCopyPalette(pal1, pal2, 2, 12, ++data[0], sp8); - LoadPalette(sp8, 0x31, 4); - if (data[0] == 12) - DestroyTask(taskId); -} - -static void VBlankCB_PokenavMainMenu(void) -{ - TransferPlttBuffer(); - LoadOam(); - ProcessSpriteCopyRequests(); - ScanlineEffect_InitHBlankDmaTransfer(); -} - -static void SetupPokenavMenuScanlineEffects(void) -{ - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_LIGHTEN); - SetGpuReg(REG_OFFSET_BLDY, 0); - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON); - SetGpuRegBits(REG_OFFSET_WININ, WININ_WIN0_ALL); - SetGpuRegBits(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ); - SetGpuRegBits(REG_OFFSET_WIN0V, DISPLAY_HEIGHT); - ScanlineEffect_Stop(); - SetMenuOptionGlow(); - ScanlineEffect_SetParams(sPokenavMainMenuScanlineEffectParams); - SetVBlankCallback_(VBlankCB_PokenavMainMenu); - CreateTask(Task_CurrentMenuOptionGlow, 3); -} - -static void DestroyMenuOptionGlowTask(void) -{ - SetGpuReg(REG_OFFSET_BLDCNT, 0); - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON); - ScanlineEffect_Stop(); - DestroyTask(FindTaskIdByFunc(Task_CurrentMenuOptionGlow)); - SetPokenavVBlankCallback(); -} - -static void ResetBldCnt(void) -{ - SetGpuReg(REG_OFFSET_BLDCNT, 0); -} - -static void InitMenuOptionGlow(void) -{ - SetMenuOptionGlow(); - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_LIGHTEN); -} - -static void Task_CurrentMenuOptionGlow(u8 taskId) -{ - s16 * data = gTasks[taskId].data; - data[0]++; - if (data[0] > 0) - { - data[0] = 0; - data[1] += 3; - data[1] &= 0x7F; - SetGpuReg(REG_OFFSET_BLDY, gSineTable[data[1]] >> 5); - } -} - -static void SetMenuOptionGlow(void) -{ - int menuType = GetPokenavMenuType(); - int cursorPos = GetPokenavCursorPos(); - int r4 = sPokenavMenuOptionLabelGfx[menuType].deltaY * cursorPos + sPokenavMenuOptionLabelGfx[menuType].yStart - 8; - CpuFill16(0, gScanlineEffectRegBuffers[0], DISPLAY_HEIGHT * 2); - CpuFill16(0, gScanlineEffectRegBuffers[1], DISPLAY_HEIGHT * 2); - CpuFill16(RGB(16, 23, 28), &gScanlineEffectRegBuffers[0][r4], 0x20); - CpuFill16(RGB(16, 23, 28), &gScanlineEffectRegBuffers[1][r4], 0x20); -} - -void ResetBldCnt_(void) -{ - ResetBldCnt(); -} diff --git a/src/pokenav_menu_handler_gfx.c b/src/pokenav_menu_handler_gfx.c new file mode 100644 index 000000000..1738142ac --- /dev/null +++ b/src/pokenav_menu_handler_gfx.c @@ -0,0 +1,1371 @@ +#include "global.h" +#include "malloc.h" +#include "decompress.h" +#include "bg.h" +#include "palette.h" +#include "trig.h" +#include "gpu_regs.h" +#include "menu.h" +#include "window.h" +#include "pokenav.h" +#include "graphics.h" +#include "sound.h" +#include "gym_leader_rematch.h" +#include "window.h" +#include "strings.h" +#include "scanline_effect.h" +#include "constants/songs.h" +#include "constants/rgb.h" + +#define GFXTAG_BLUE_LIGHT 1 +#define GFXTAG_OPTIONS 3 + +#define PALTAG_BLUE_LIGHT 3 +#define PALTAG_OPTIONS_DEFAULT 4 // Includes green for Smart/Region Map and yellow for Tough +#define PALTAG_OPTIONS_BLUE 5 +#define PALTAG_OPTIONS_PINK 6 +#define PALTAG_OPTIONS_BEIGE 7 +#define PALTAG_OPTIONS_RED 8 + +#define PALTAG_OPTIONS_START PALTAG_OPTIONS_DEFAULT + +#define NUM_OPTION_SUBSPRITES 4 + +#define OPTION_DEFAULT_X 140 +#define OPTION_SELECTED_X 130 +#define OPTION_EXIT_X (DISPLAY_WIDTH + 16) + +struct Pokenav_MenuGfx +{ + bool32 (*isTaskActiveCB)(void); + u32 loopedTaskId; + u16 optionDescWindowId; + u8 bg3ScrollTaskId; + u8 cursorPos; + u8 numIconsBlending; + bool8 pokenavAlreadyOpen; + bool32 iconVisible[MAX_POKENAV_MENUITEMS]; + struct Sprite * blueLightSprite; + struct Sprite * iconSprites[MAX_POKENAV_MENUITEMS][NUM_OPTION_SUBSPRITES]; + u8 bg1TilemapBuffer[BG_SCREEN_SIZE]; +}; + +static struct Pokenav_MenuGfx * OpenPokenavMenu(void); +static bool32 GetCurrentLoopedTaskActive(void); +static u32 LoopedTask_OpenMenu(s32); +static u32 LoopedTask_MoveMenuCursor(s32); +static u32 LoopedTask_OpenConditionMenu(s32); +static u32 LoopedTask_ReturnToMainMenu(s32); +static u32 LoopedTask_OpenConditionSearchMenu(s32); +static u32 LoopedTask_ReturnToConditionMenu(s32); +static u32 LoopedTask_SelectRibbonsNoWinners(s32); +static u32 LoopedTask_ReShowDescription(s32); +static u32 LoopedTask_OpenPokenavFeature(s32); +static void LoadPokenavOptionPalettes(void); +static void FreeAndDestroyMainMenuSprites(void); +static void CreateMenuOptionSprites(void); +static void DestroyMenuOptionSprites(void); +static void DrawCurrentMenuOptionLabels(void); +static void DrawOptionLabelGfx(const u16 *const *, s32, s32); +static void StartOptionAnimations_Enter(void); +static void StartOptionAnimations_CursorMoved(void); +static void StartOptionAnimations_Exit(void); +static void StartOptionSlide(struct Sprite **, s32, s32, s32); +static void StartOptionZoom(struct Sprite **); +static bool32 AreMenuOptionSpritesMoving(void); +static void SetOptionInvisibility(struct Sprite **, bool32); +static void SpriteCB_OptionSlide(struct Sprite *); +static void SpriteCB_OptionZoom(struct Sprite *); +static void Task_OptionBlend(u8); +static void CreateMatchCallBlueLightSprite(void); +static void SpriteCB_BlinkingBlueLight(struct Sprite *); +static void DestroyRematchBlueLightSprite(void); +static void AddOptionDescriptionWindow(void); +static void PrintCurrentOptionDescription(void); +static void PrintNoRibbonWinners(void); +static bool32 IsDma3ManagerBusyWithBgCopy_(void); +static void CreateMovingBgDotsTask(void); +static void DestroyMovingDotsBgTask(void); +static void Task_MoveBgDots(u8); +static void CreateBgDotPurplePalTask(void); +static void ChangeBgDotsColorToPurple(void); +static void CreateBgDotLightBluePalTask(void); +static bool32 IsTaskActive_UpdateBgDotsPalette(void); +static void Task_UpdateBgDotsPalette(u8); +static void SetupPokenavMenuScanlineEffects(void); +static void DestroyMenuOptionGlowTask(void); +static void ResetBldCnt(void); +static void InitMenuOptionGlow(void); +static void Task_CurrentMenuOptionGlow(u8); +static void SetMenuOptionGlow(void); + +static const u16 sPokenavBgDotsPal[] = INCBIN_U16("graphics/pokenav/bg_dots.gbapal"); +static const u32 sPokenavBgDotsTiles[] = INCBIN_U32("graphics/pokenav/bg_dots.4bpp.lz"); +static const u32 sPokenavBgDotsTilemap[] = INCBIN_U32("graphics/pokenav/bg_dots.bin.lz"); +static const u16 sPokenavDeviceBgPal[] = INCBIN_U16("graphics/pokenav/device_outline.gbapal"); +static const u32 sPokenavDeviceBgTiles[] = INCBIN_U32("graphics/pokenav/device_outline.4bpp.lz"); +static const u32 sPokenavDeviceBgTilemap[] = INCBIN_U32("graphics/pokenav/device_outline_map.bin.lz"); +static const u16 sMatchCallBlueLightPal[] = INCBIN_U16("graphics/pokenav/blue_light.gbapal"); +static const u32 sMatchCallBlueLightTiles[] = INCBIN_U32("graphics/pokenav/blue_light.4bpp.lz"); + +static const struct BgTemplate sPokenavMainMenuBgTemplates[] = { + { + .bg = 1, + .charBaseIndex = 1, + .mapBaseIndex = 15, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0x000 + }, { + .bg = 2, + .charBaseIndex = 2, + .mapBaseIndex = 23, + .screenSize = 0, + .paletteMode = 0, + .priority = 2, + .baseTile = 0x000 + }, { + .bg = 3, + .charBaseIndex = 3, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0x000 + } +}; + +static const LoopedTask sMenuHandlerLoopTaskFuncs[] = +{ + [POKENAV_MENU_FUNC_NONE] = NULL, + [POKENAV_MENU_FUNC_MOVE_CURSOR] = LoopedTask_MoveMenuCursor, + [POKENAV_MENU_FUNC_OPEN_CONDITION] = LoopedTask_OpenConditionMenu, + [POKENAV_MENU_FUNC_RETURN_TO_MAIN] = LoopedTask_ReturnToMainMenu, + [POKENAV_MENU_FUNC_OPEN_CONDITION_SEARCH] = LoopedTask_OpenConditionSearchMenu, + [POKENAV_MENU_FUNC_RETURN_TO_CONDITION] = LoopedTask_ReturnToConditionMenu, + [POKENAV_MENU_FUNC_NO_RIBBON_WINNERS] = LoopedTask_SelectRibbonsNoWinners, + [POKENAV_MENU_FUNC_RESHOW_DESCRIPTION] = LoopedTask_ReShowDescription, + [POKENAV_MENU_FUNC_OPEN_FEATURE] = LoopedTask_OpenPokenavFeature +}; + +static const struct CompressedSpriteSheet sPokenavOptionsSpriteSheets[] = +{ + { + .data = gPokenavOptions_Gfx, + .size = 0x3400, + .tag = GFXTAG_OPTIONS + }, + { + .data = sMatchCallBlueLightTiles, + .size = 0x0100, + .tag = GFXTAG_BLUE_LIGHT + } +}; + +static const struct SpritePalette sPokenavOptionsSpritePalettes[] = +{ + {&gPokenavOptions_Pal[0x00], PALTAG_OPTIONS_DEFAULT}, + {&gPokenavOptions_Pal[0x10], PALTAG_OPTIONS_BLUE}, + {&gPokenavOptions_Pal[0x20], PALTAG_OPTIONS_PINK}, + {&gPokenavOptions_Pal[0x30], PALTAG_OPTIONS_BEIGE}, + {&gPokenavOptions_Pal[0x40], PALTAG_OPTIONS_RED}, + {sMatchCallBlueLightPal, PALTAG_BLUE_LIGHT}, + {} +}; + +// Tile number, palette tag offset +static const u16 sOptionsLabelGfx_RegionMap[] = {0x000, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Condition[] = {0x020, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_MatchCall[] = {0x040, PALTAG_OPTIONS_RED - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Ribbons[] = {0x060, PALTAG_OPTIONS_PINK - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_SwitchOff[] = {0x080, PALTAG_OPTIONS_BEIGE - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Party[] = {0x0A0, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Search[] = {0x0C0, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Cool[] = {0x0E0, PALTAG_OPTIONS_RED - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Beauty[] = {0x100, PALTAG_OPTIONS_BLUE - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Cute[] = {0x120, PALTAG_OPTIONS_PINK - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Smart[] = {0x140, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Tough[] = {0x160, PALTAG_OPTIONS_DEFAULT - PALTAG_OPTIONS_START}; +static const u16 sOptionsLabelGfx_Cancel[] = {0x180, PALTAG_OPTIONS_BEIGE - PALTAG_OPTIONS_START}; + +struct +{ + u16 yStart; + u16 deltaY; + const u16 *gfx[MAX_POKENAV_MENUITEMS]; +} static const sPokenavMenuOptionLabelGfx[POKENAV_MENU_TYPE_COUNT] = +{ + [POKENAV_MENU_TYPE_DEFAULT] = + { + .yStart = 42, + .deltaY = 20, + .gfx = { + sOptionsLabelGfx_RegionMap, + sOptionsLabelGfx_Condition, + sOptionsLabelGfx_SwitchOff + } + }, + [POKENAV_MENU_TYPE_UNLOCK_MC] = + { + .yStart = 42, + .deltaY = 20, + .gfx = { + sOptionsLabelGfx_RegionMap, + sOptionsLabelGfx_Condition, + sOptionsLabelGfx_MatchCall, + sOptionsLabelGfx_SwitchOff + } + }, + [POKENAV_MENU_TYPE_UNLOCK_MC_RIBBONS] = + { + .yStart = 42, + .deltaY = 20, + .gfx = { + sOptionsLabelGfx_RegionMap, + sOptionsLabelGfx_Condition, + sOptionsLabelGfx_MatchCall, + sOptionsLabelGfx_Ribbons, + sOptionsLabelGfx_SwitchOff + } + }, + [POKENAV_MENU_TYPE_CONDITION] = + { + .yStart = 56, + .deltaY = 20, + .gfx = { + sOptionsLabelGfx_Party, + sOptionsLabelGfx_Search, + sOptionsLabelGfx_Cancel + } + }, + [POKENAV_MENU_TYPE_CONDITION_SEARCH] = + { + .yStart = 40, + .deltaY = 16, + .gfx = { + sOptionsLabelGfx_Cool, + sOptionsLabelGfx_Beauty, + sOptionsLabelGfx_Cute, + sOptionsLabelGfx_Smart, + sOptionsLabelGfx_Tough, + sOptionsLabelGfx_Cancel + } + }, +}; + +static const struct WindowTemplate sOptionDescWindowTemplate = +{ + .bg = 1, + .tilemapLeft = 3, + .tilemapTop = 17, + .width = 24, + .height = 2, + .paletteNum = 1, + .baseBlock = 8 +}; + +static const u8 *const sPageDescriptions[] = +{ + [POKENAV_MENUITEM_MAP] = gText_CheckMapOfHoenn, + [POKENAV_MENUITEM_CONDITION] = gText_CheckPokemonInDetail, + [POKENAV_MENUITEM_MATCH_CALL] = gText_CallRegisteredTrainer, + [POKENAV_MENUITEM_RIBBONS] = gText_CheckObtainedRibbons, + [POKENAV_MENUITEM_SWITCH_OFF] = gText_PutAwayPokenav, + [POKENAV_MENUITEM_CONDITION_PARTY] = gText_CheckPartyPokemonInDetail, + [POKENAV_MENUITEM_CONDITION_SEARCH] = gText_CheckAllPokemonInDetail, + [POKENAV_MENUITEM_CONDITION_CANCEL] = gText_ReturnToPokenavMenu, + [POKENAV_MENUITEM_CONDITION_SEARCH_COOL] = gText_FindCoolPokemon, + [POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY] = gText_FindBeautifulPokemon, + [POKENAV_MENUITEM_CONDITION_SEARCH_CUTE] = gText_FindCutePokemon, + [POKENAV_MENUITEM_CONDITION_SEARCH_SMART] = gText_FindSmartPokemon, + [POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH] = gText_FindToughPokemon, + [POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL] = gText_ReturnToConditionMenu +}; + +static const u8 sOptionDescTextColors[] = {TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_GREEN}; +static const u8 sOptionDescTextColors2[] = {TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_GREEN}; + +static const struct OamData sOamData_MenuOption = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(32x16), + .x = 0, + .size = SPRITE_SIZE(32x16), + .tileNum = 0, + .priority = 2, + .paletteNum = 0, +}; + +static const union AffineAnimCmd sAffineAnim_MenuOption_Normal[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_MenuOption_Zoom[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0x12), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_MenuOption[] = +{ + sAffineAnim_MenuOption_Normal, + sAffineAnim_MenuOption_Zoom +}; + +static const struct SpriteTemplate sMenuOptionSpriteTemplate = +{ + .tileTag = GFXTAG_OPTIONS, + .paletteTag = PALTAG_OPTIONS_START, + .oam = &sOamData_MenuOption, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_MenuOption, + .callback = SpriteCallbackDummy, +}; + +static const struct OamData sBlueLightOamData = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(32x16), + .x = 0, + .size = SPRITE_SIZE(32x16), + .tileNum = 0, + .priority = 2, + .paletteNum = 0, +}; + +static const struct SpriteTemplate sMatchCallBlueLightSpriteTemplate = +{ + .tileTag = GFXTAG_BLUE_LIGHT, + .paletteTag = PALTAG_BLUE_LIGHT, + .oam = &sBlueLightOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +static const struct ScanlineEffectParams sPokenavMainMenuScanlineEffectParams = +{ + ®_WIN0H, + ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, + 1, + 0 +}; + +static bool32 AreAnyTrainerRematchesNearby(void) +{ + s32 i; + + for (i = 0; i < REMATCH_TABLE_ENTRIES; i++) + { + if (GetMatchTableMapSectionId(i) == gMapHeader.regionMapSectionId + && IsRematchEntryRegistered(i) + && gSaveBlock1Ptr->trainerRematches[i]) + return TRUE; + } + + return FALSE; +} + +bool32 OpenPokenavMenuInitial(void) +{ + struct Pokenav_MenuGfx * gfx = OpenPokenavMenu(); + + if (gfx == NULL) + return FALSE; + + gfx->pokenavAlreadyOpen = FALSE; + return TRUE; +} + +bool32 OpenPokenavMenuNotInitial(void) +{ + struct Pokenav_MenuGfx * gfx = OpenPokenavMenu(); + + if (gfx == NULL) + return FALSE; + + gfx->pokenavAlreadyOpen = TRUE; + return TRUE; +} + +static struct Pokenav_MenuGfx * OpenPokenavMenu(void) +{ + struct Pokenav_MenuGfx * gfx = AllocSubstruct(POKENAV_SUBSTRUCT_MENU_GFX, sizeof(struct Pokenav_MenuGfx)); + + if (gfx != NULL) + { + gfx->numIconsBlending = 0; + gfx->loopedTaskId = CreateLoopedTask(LoopedTask_OpenMenu, 1); + gfx->isTaskActiveCB = GetCurrentLoopedTaskActive; + } + + return gfx; +} + +void CreateMenuHandlerLoopedTask(s32 ltIdx) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + gfx->loopedTaskId = CreateLoopedTask(sMenuHandlerLoopTaskFuncs[ltIdx], 1); + gfx->isTaskActiveCB = GetCurrentLoopedTaskActive; +} + +bool32 IsMenuHandlerLoopedTaskActive(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + return gfx->isTaskActiveCB(); +} + +void FreeMenuHandlerSubstruct2(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + DestroyMovingDotsBgTask(); + RemoveWindow(gfx->optionDescWindowId); + FreeAndDestroyMainMenuSprites(); + DestroyMenuOptionGlowTask(); + FreePokenavSubstruct(POKENAV_SUBSTRUCT_MENU_GFX); +} + +static bool32 GetCurrentLoopedTaskActive(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + return IsLoopedTaskActive(gfx->loopedTaskId); +} + +static u32 LoopedTask_OpenMenu(s32 state) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + switch (state) + { + case 0: + InitBgTemplates(sPokenavMainMenuBgTemplates, ARRAY_COUNT(sPokenavMainMenuBgTemplates)); + DecompressAndCopyTileDataToVram(1, gPokenavMessageBox_Gfx, 0, 0, 0); + SetBgTilemapBuffer(1, gfx->bg1TilemapBuffer); + CopyToBgTilemapBuffer(1, gPokenavMessageBox_Tilemap, 0, 0); + CopyBgTilemapBufferToVram(1); + CopyPaletteIntoBufferUnfaded(gPokenavMessageBox_Pal, 0x10, 0x20); + ChangeBgX(1, 0, BG_COORD_SET); + ChangeBgY(1, 0, BG_COORD_SET); + ChangeBgX(2, 0, BG_COORD_SET); + ChangeBgY(2, 0, BG_COORD_SET); + ChangeBgX(3, 0, BG_COORD_SET); + ChangeBgY(3, 0, BG_COORD_SET); + return LT_INC_AND_PAUSE; + case 1: + if (FreeTempTileDataBuffersIfPossible()) + return LT_PAUSE; + DecompressAndCopyTileDataToVram(2, sPokenavDeviceBgTiles, 0, 0, 0); + DecompressAndCopyTileDataToVram(2, sPokenavDeviceBgTilemap, 0, 0, 1); + CopyPaletteIntoBufferUnfaded(sPokenavDeviceBgPal, 0x20, 0x20); + return LT_INC_AND_PAUSE; + case 2: + if (FreeTempTileDataBuffersIfPossible()) + return LT_PAUSE; + DecompressAndCopyTileDataToVram(3, sPokenavBgDotsTiles, 0, 0, 0); + DecompressAndCopyTileDataToVram(3, sPokenavBgDotsTilemap, 0, 0, 1); + CopyPaletteIntoBufferUnfaded(sPokenavBgDotsPal, 0x30, 0x20); + if (GetPokenavMenuType() == POKENAV_MENU_TYPE_CONDITION || GetPokenavMenuType() == POKENAV_MENU_TYPE_CONDITION_SEARCH) + ChangeBgDotsColorToPurple(); + return LT_INC_AND_PAUSE; + case 3: + if (FreeTempTileDataBuffersIfPossible()) + return LT_PAUSE; + AddOptionDescriptionWindow(); + CreateMovingBgDotsTask(); + return LT_INC_AND_CONTINUE; + case 4: + LoadPokenavOptionPalettes(); + return LT_INC_AND_CONTINUE; + case 5: + PrintCurrentOptionDescription(); + CreateMenuOptionSprites(); + CreateMatchCallBlueLightSprite(); + DrawCurrentMenuOptionLabels(); + return LT_INC_AND_PAUSE; + case 6: + if (IsDma3ManagerBusyWithBgCopy_()) + return LT_PAUSE; + return LT_INC_AND_CONTINUE; + case 7: + ShowBg(1); + ShowBg(2); + ShowBg(3); + if (gfx->pokenavAlreadyOpen) + PokenavFadeScreen(1); + else + { + PlaySE(SE_POKENAV_ON); + PokenavFadeScreen(3); + } + switch (GetPokenavMenuType()) + { + case POKENAV_MENU_TYPE_CONDITION_SEARCH: + LoadLeftHeaderGfxForIndex(7); + // fallthrough + case POKENAV_MENU_TYPE_CONDITION: + LoadLeftHeaderGfxForIndex(1); + break; + default: + LoadLeftHeaderGfxForIndex(0); + break; + } + return LT_INC_AND_PAUSE; + case 8: + if (IsPaletteFadeActive()) + return LT_PAUSE; + switch (GetPokenavMenuType()) + { + case POKENAV_MENU_TYPE_CONDITION_SEARCH: + ShowLeftHeaderGfx(7, FALSE, FALSE); + // fallthrough + case POKENAV_MENU_TYPE_CONDITION: + ShowLeftHeaderGfx(1, FALSE, FALSE); + break; + default: + ShowLeftHeaderGfx(0, FALSE, FALSE); + break; + } + StartOptionAnimations_Enter(); + SetupPokenavMenuScanlineEffects(); + return LT_INC_AND_CONTINUE; + case 9: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_MoveMenuCursor(s32 state) +{ + switch (state) + { + case 0: + SetMenuOptionGlow(); + StartOptionAnimations_CursorMoved(); + PrintCurrentOptionDescription(); + PlaySE(SE_SELECT); + return LT_INC_AND_PAUSE; + case 1: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (IsDma3ManagerBusyWithBgCopy_()) + return LT_PAUSE; + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_OpenConditionMenu(s32 state) +{ + switch (state) + { + case 0: + ResetBldCnt(); + StartOptionAnimations_Exit(); + HideMainOrSubMenuLeftHeader(POKENAV_GFX_MAIN_MENU, 0); + PlaySE(SE_SELECT); + return LT_INC_AND_PAUSE; + case 1: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + DrawCurrentMenuOptionLabels(); + LoadLeftHeaderGfxForIndex(1); + return LT_INC_AND_PAUSE; + case 2: + StartOptionAnimations_Enter(); + ShowLeftHeaderGfx(1, FALSE, FALSE); + CreateBgDotPurplePalTask(); + PrintCurrentOptionDescription(); + return LT_INC_AND_PAUSE; + case 3: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + if (IsTaskActive_UpdateBgDotsPalette()) + return LT_PAUSE; + if (IsDma3ManagerBusyWithBgCopy_()) + return LT_PAUSE; + InitMenuOptionGlow(); + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_ReturnToMainMenu(s32 state) +{ + switch (state) + { + case 0: + ResetBldCnt(); + StartOptionAnimations_Exit(); + HideMainOrSubMenuLeftHeader(POKENAV_GFX_CONDITION_MENU, 0); + return LT_INC_AND_PAUSE; + case 1: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + DrawCurrentMenuOptionLabels(); + LoadLeftHeaderGfxForIndex(0); + return LT_INC_AND_PAUSE; + case 2: + StartOptionAnimations_Enter(); + ShowLeftHeaderGfx(0, FALSE, FALSE); + CreateBgDotLightBluePalTask(); + PrintCurrentOptionDescription(); + return LT_INC_AND_PAUSE; + case 3: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + if (IsTaskActive_UpdateBgDotsPalette()) + return LT_PAUSE; + if (IsDma3ManagerBusyWithBgCopy_()) + return LT_PAUSE; + InitMenuOptionGlow(); + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_OpenConditionSearchMenu(s32 state) +{ + switch (state) + { + case 0: + ResetBldCnt(); + StartOptionAnimations_Exit(); + PlaySE(SE_SELECT); + return LT_INC_AND_PAUSE; + case 1: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + LoadLeftHeaderGfxForIndex(7); + DrawCurrentMenuOptionLabels(); + return LT_INC_AND_PAUSE; + case 2: + StartOptionAnimations_Enter(); + ShowLeftHeaderGfx(7, FALSE, FALSE); + PrintCurrentOptionDescription(); + return LT_INC_AND_PAUSE; + case 3: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + if (IsTaskActive_UpdateBgDotsPalette()) + return LT_PAUSE; + InitMenuOptionGlow(); + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_ReturnToConditionMenu(s32 state) +{ + switch (state) + { + case 0: + ResetBldCnt(); + StartOptionAnimations_Exit(); + HideMainOrSubMenuLeftHeader(POKENAV_GFX_SEARCH_MENU, 0); + return LT_INC_AND_PAUSE; + case 1: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + DrawCurrentMenuOptionLabels(); + return LT_INC_AND_PAUSE; + case 2: + StartOptionAnimations_Enter(); + PrintCurrentOptionDescription(); + return LT_INC_AND_PAUSE; + case 3: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (IsTaskActive_UpdateBgDotsPalette()) + return LT_PAUSE; + InitMenuOptionGlow(); + break; + } + return LT_FINISH; +} + +static u32 LoopedTask_SelectRibbonsNoWinners(s32 state) +{ + switch (state) + { + case 0: + PlaySE(SE_FAILURE); + PrintNoRibbonWinners(); + return LT_INC_AND_PAUSE; + case 1: + if (IsDma3ManagerBusyWithBgCopy()) + return LT_PAUSE; + break; + } + return LT_FINISH; +} + +// For redisplaying the Ribbons description to replace the No Ribbon Winners message +static u32 LoopedTask_ReShowDescription(s32 state) +{ + switch (state) + { + case 0: + PlaySE(SE_SELECT); + PrintCurrentOptionDescription(); + return LT_INC_AND_PAUSE; + case 1: + if (IsDma3ManagerBusyWithBgCopy()) + return LT_PAUSE; + break; + } + return LT_FINISH; +} + +// For selecting a feature option from a menu, e.g. the Map, Match Call, Beauty search, etc. +static u32 LoopedTask_OpenPokenavFeature(s32 state) +{ + switch (state) + { + case 0: + PrintHelpBarText(GetHelpBarTextId()); + return LT_INC_AND_PAUSE; + case 1: + if (WaitForHelpBar()) + return LT_PAUSE; + SlideMenuHeaderUp(); + ResetBldCnt(); + StartOptionAnimations_Exit(); + switch (GetPokenavMenuType()) + { + case POKENAV_MENU_TYPE_CONDITION_SEARCH: + HideMainOrSubMenuLeftHeader(POKENAV_GFX_SEARCH_MENU, FALSE); + // fallthrough + case POKENAV_MENU_TYPE_CONDITION: + HideMainOrSubMenuLeftHeader(POKENAV_GFX_CONDITION_MENU, FALSE); + break; + default: + HideMainOrSubMenuLeftHeader(POKENAV_GFX_MAIN_MENU, FALSE); + break; + } + PlaySE(SE_SELECT); + return LT_INC_AND_PAUSE; + case 2: + if (AreMenuOptionSpritesMoving()) + return LT_PAUSE; + if (AreLeftHeaderSpritesMoving()) + return LT_PAUSE; + PokenavFadeScreen(0); + return LT_INC_AND_PAUSE; + case 3: + if (IsPaletteFadeActive()) + return LT_PAUSE; + break; + } + return LT_FINISH; +} + +static void LoadPokenavOptionPalettes(void) +{ + s32 i; + + for (i = 0; i < ARRAY_COUNT(sPokenavOptionsSpriteSheets); i++) + LoadCompressedSpriteSheet(&sPokenavOptionsSpriteSheets[i]); + Pokenav_AllocAndLoadPalettes(sPokenavOptionsSpritePalettes); +} + +static void FreeAndDestroyMainMenuSprites(void) +{ + FreeSpriteTilesByTag(GFXTAG_OPTIONS); + FreeSpriteTilesByTag(GFXTAG_BLUE_LIGHT); + FreeSpritePaletteByTag(PALTAG_OPTIONS_DEFAULT); + FreeSpritePaletteByTag(PALTAG_OPTIONS_BLUE); + FreeSpritePaletteByTag(PALTAG_OPTIONS_PINK); + FreeSpritePaletteByTag(PALTAG_OPTIONS_BEIGE); + FreeSpritePaletteByTag(PALTAG_OPTIONS_RED); + FreeSpritePaletteByTag(PALTAG_BLUE_LIGHT); + DestroyMenuOptionSprites(); + DestroyRematchBlueLightSprite(); +} + +static void CreateMenuOptionSprites(void) +{ + s32 i, j; + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) + { + u8 spriteId = CreateSprite(&sMenuOptionSpriteTemplate, 0x8c, 20 * i + 40, 3); + gfx->iconSprites[i][j] = &gSprites[spriteId]; + gSprites[spriteId].x2 = 32 * j; + } + } +} + +static void DestroyMenuOptionSprites(void) +{ + s32 i, j; + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) + { + FreeSpriteOamMatrix(gfx->iconSprites[i][j]); + DestroySprite(gfx->iconSprites[i][j]); + } + } +} + +static void DrawCurrentMenuOptionLabels(void) +{ + s32 menuType = GetPokenavMenuType(); + DrawOptionLabelGfx(sPokenavMenuOptionLabelGfx[menuType].gfx, sPokenavMenuOptionLabelGfx[menuType].yStart, sPokenavMenuOptionLabelGfx[menuType].deltaY); +} + +static void DrawOptionLabelGfx(const u16 *const *optionGfx, s32 yPos, s32 deltaY) +{ + s32 i, j; + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + s32 baseTile = GetSpriteTileStartByTag(GFXTAG_OPTIONS); + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + if (*optionGfx != NULL) + { + for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) + { + gfx->iconSprites[i][j]->oam.tileNum = (*optionGfx)[0] + baseTile + 8 * j; + gfx->iconSprites[i][j]->oam.paletteNum = IndexOfSpritePaletteTag((*optionGfx)[1] + PALTAG_OPTIONS_START); + gfx->iconSprites[i][j]->invisible = TRUE; + gfx->iconSprites[i][j]->y = yPos; + gfx->iconSprites[i][j]->x = OPTION_DEFAULT_X; + gfx->iconSprites[i][j]->x2 = 32 * j; + } + gfx->iconVisible[i] = TRUE; + } + else + { + for (j = 0; j < NUM_OPTION_SUBSPRITES; j++) + gfx->iconSprites[i][j]->invisible = TRUE; + + gfx->iconVisible[i] = FALSE; + } + optionGfx++; + yPos += deltaY; + } +} + +static void StartOptionAnimations_Enter(void) +{ + s32 i; + struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + s32 cursorPos = GetPokenavCursorPos(); + s32 iconCount = 0; + s32 x; + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + if (gfx->iconVisible[i]) + { + if (iconCount++ == cursorPos) + { + x = OPTION_SELECTED_X; + gfx->cursorPos = i; + } + else + { + // Not selected, set default position + x = OPTION_DEFAULT_X; + } + + // Slide new options in + StartOptionSlide(gfx->iconSprites[i], OPTION_EXIT_X, x, 12); + SetOptionInvisibility(gfx->iconSprites[i], FALSE); + } + else + { + SetOptionInvisibility(gfx->iconSprites[i], TRUE); + } + } +} + +static void StartOptionAnimations_CursorMoved(void) +{ + s32 i; + struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + s32 prevPos = GetPokenavCursorPos(); + s32 newPos; + + // Get the index of the next visible option + for (i = 0, newPos = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + if (gfx->iconVisible[i]) + { + if (newPos == prevPos) + { + newPos = i; + break; + } + newPos++; + } + } + + // The selected option slides out a bit and the previously + // selected option slides back to its original position. + StartOptionSlide(gfx->iconSprites[gfx->cursorPos], OPTION_SELECTED_X, OPTION_DEFAULT_X, 4); + StartOptionSlide(gfx->iconSprites[newPos], OPTION_DEFAULT_X, OPTION_SELECTED_X, 4); + gfx->cursorPos = newPos; +} + +static void StartOptionAnimations_Exit(void) +{ + s32 i; + struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + if (gfx->iconVisible[i]) + { + // Unselected options slide out, + // selected option zooms in + if (gfx->cursorPos != i) + StartOptionSlide(gfx->iconSprites[i], OPTION_DEFAULT_X, OPTION_EXIT_X, 8); + else + StartOptionZoom(gfx->iconSprites[i]); + } + } +} + +static bool32 AreMenuOptionSpritesMoving(void) +{ + s32 i; + struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + for (i = 0; i < MAX_POKENAV_MENUITEMS; i++) + { + if (gfx->iconSprites[i][0]->callback != SpriteCallbackDummy) + return TRUE; + } + + if (gfx->numIconsBlending != 0) + return TRUE; + + return FALSE; +} + +#define sSlideTime data[0] +#define sSlideAccel data[1] +#define sSlideSpeed data[2] +#define sSlideEndX data[7] + +static void StartOptionSlide(struct Sprite ** sprites, s32 startX, s32 endX, s32 time) +{ + s32 i; + + for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) + { + (*sprites)->x = startX; + (*sprites)->sSlideTime = time; + (*sprites)->sSlideAccel = 16 * (endX - startX) / time; + (*sprites)->sSlideSpeed = 16 * startX; + (*sprites)->sSlideEndX = endX; + (*sprites)->callback = SpriteCB_OptionSlide; + sprites++; + } +} + +#define sZoomDelay data[0] +#define sZoomSetAffine data[1] +#define sZoomSpeed data[2] +#define sZoomSubspriteId data[7] + +#define tBlendDelay data[0] +#define tBlendState data[1] +#define tBlendTarget1 data[2] +#define tBlendTarget2 data[3] +#define tBlendCounter data[4] + +// When an option is selected it zooms in and blends away as part +// of the transition to the next screen. +static void StartOptionZoom(struct Sprite ** sprites) +{ + s32 i; + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + u8 taskId; + + for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) + { + (*sprites)->oam.objMode = ST_OAM_OBJ_BLEND; + (*sprites)->oam.affineMode = ST_OAM_AFFINE_DOUBLE; + (*sprites)->callback = SpriteCB_OptionZoom; + (*sprites)->sZoomDelay = 8; + (*sprites)->sZoomSetAffine = FALSE; + (*sprites)->sZoomSubspriteId = i; + InitSpriteAffineAnim(sprites[0]); + StartSpriteAffineAnim(sprites[0], 0); + sprites++; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + taskId = CreateTask(Task_OptionBlend, 3); + gTasks[taskId].tBlendDelay = 8; + gfx->numIconsBlending++; +} + +static void SetOptionInvisibility(struct Sprite ** sprites, bool32 invisible) +{ + s32 i; + + for (i = 0; i < NUM_OPTION_SUBSPRITES; i++) + { + (*sprites)->invisible = invisible; + sprites++; + } +} + +static void SpriteCB_OptionSlide(struct Sprite * sprite) +{ + sprite->sSlideTime--; + if (sprite->sSlideTime != -1) + { + sprite->sSlideSpeed += sprite->sSlideAccel; + sprite->x = sprite->sSlideSpeed >> 4; + } + else + { + sprite->x = sprite->sSlideEndX; + sprite->callback = SpriteCallbackDummy; + } +} + +#undef sSlideTime +#undef sSlideAccel +#undef sSlideSpeed +#undef sSlideEndX + +static void SpriteCB_OptionZoom(struct Sprite * sprite) +{ + s32 temp; + s32 x; + if (sprite->sZoomDelay == 0) + { + if (!sprite->sZoomSetAffine) + { + StartSpriteAffineAnim(sprite, 1); + sprite->sZoomSetAffine++; + sprite->sZoomSpeed = 0x100; + sprite->x += sprite->x2; + sprite->x2 = 0; + } + else + { + sprite->sZoomSpeed += 16; + temp = sprite->sZoomSpeed; + x = temp >> 3; + x = (x - 32) / 2; + + // Each subsprite needs to zoom to a different degree/direction + switch (sprite->sZoomSubspriteId) + { + case 0: + sprite->x2 = -x * 3; + break; + case 1: + sprite->x2 = -x; + break; + case 2: + sprite->x2 = x; + break; + case 3: + sprite->x2 = x * 3; + break; + } + if (sprite->affineAnimEnded) + { + sprite->invisible = TRUE; + FreeOamMatrix(sprite->oam.matrixNum); + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, ST_OAM_AFFINE_OFF); + sprite->oam.affineMode = ST_OAM_AFFINE_OFF; + sprite->oam.objMode = ST_OAM_OBJ_NORMAL; + sprite->callback = SpriteCallbackDummy; + } + } + } + else + { + sprite->sZoomDelay--; + } +} + +#undef sZoomDelay +#undef sZoomSetAffine +#undef sZoomSpeed +#undef sZoomSubspriteId + +static void Task_OptionBlend(u8 taskId) +{ + s16 * data = gTasks[taskId].data; + + if (tBlendDelay == 0) + { + switch (tBlendState) + { + case 0: + tBlendTarget1 = 16; + tBlendTarget2 = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_NONE | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + tBlendState++; + break; + case 1: + if (tBlendCounter & 1) + { + tBlendTarget1 -= 3; + if (tBlendTarget1 < 0) + tBlendTarget1 = 0; + } + else + { + tBlendTarget2 += 3; + if (tBlendTarget2 > 16) + tBlendTarget2 = 16; + } + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(tBlendTarget1, tBlendTarget2)); + tBlendCounter++; + if (tBlendCounter == 12) + { + ((struct Pokenav_MenuGfx *)GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX))->numIconsBlending--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + DestroyTask(taskId); + } + break; + } + } + else + { + tBlendDelay--; + } +} + +#undef tBlendDelay +#undef tBlendState +#undef tBlendTarget1 +#undef tBlendTarget2 +#undef tBlendCounter + +// Blue light that blinks if there are available rematches nearby +static void CreateMatchCallBlueLightSprite(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + u8 spriteId = CreateSprite(&sMatchCallBlueLightSpriteTemplate, 0x10, 0x60, 4); + gfx->blueLightSprite = &gSprites[spriteId]; + if (AreAnyTrainerRematchesNearby()) + gfx->blueLightSprite->callback = SpriteCB_BlinkingBlueLight; + else + gfx->blueLightSprite->invisible = TRUE; +} + +static void DestroyRematchBlueLightSprite(void) +{ + struct Pokenav_MenuGfx *gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + DestroySprite(gfx->blueLightSprite); +} + +static void SpriteCB_BlinkingBlueLight(struct Sprite * sprite) +{ + sprite->data[0]++; + if (sprite->data[0] > 8) + { + sprite->data[0] = 0; + sprite->invisible ^= 1; + } +} + +static void AddOptionDescriptionWindow(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + + gfx->optionDescWindowId = AddWindow(&sOptionDescWindowTemplate); + PutWindowTilemap(gfx->optionDescWindowId); + FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); + CopyWindowToVram(gfx->optionDescWindowId, COPYWIN_FULL); +} + +static void PrintCurrentOptionDescription(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + int menuItem = GetCurrentMenuItemId(); + const u8 * desc = sPageDescriptions[menuItem]; + u32 width = GetStringWidth(FONT_NORMAL, desc, -1); + FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); + AddTextPrinterParameterized3(gfx->optionDescWindowId, FONT_NORMAL, (192 - width) / 2, 1, sOptionDescTextColors, 0, desc); +} + +// Printed when Ribbons is selected if no PC/party mons have ribbons +// Can occur by obtaining a mon with a ribbon and then releasing all ribbon winners +static void PrintNoRibbonWinners(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + const u8 * s = gText_NoRibbonWinners; + u32 width = GetStringWidth(FONT_NORMAL, s, -1); + FillWindowPixelBuffer(gfx->optionDescWindowId, PIXEL_FILL(6)); + AddTextPrinterParameterized3(gfx->optionDescWindowId, FONT_NORMAL, (192 - width) / 2, 1, sOptionDescTextColors2, 0, s); +} + +static bool32 IsDma3ManagerBusyWithBgCopy_(void) +{ + return IsDma3ManagerBusyWithBgCopy(); +} + +static void CreateMovingBgDotsTask(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + gfx->bg3ScrollTaskId = CreateTask(Task_MoveBgDots, 2); +} + +static void DestroyMovingDotsBgTask(void) +{ + struct Pokenav_MenuGfx * gfx = GetSubstructPtr(POKENAV_SUBSTRUCT_MENU_GFX); + DestroyTask(gfx->bg3ScrollTaskId); +} + +static void Task_MoveBgDots(u8 taskId) +{ + ChangeBgX(3, 0x80, BG_COORD_ADD); +} + +static void CreateBgDotPurplePalTask(void) +{ + u8 taskId = CreateTask(Task_UpdateBgDotsPalette, 3); + SetWordTaskArg(taskId, 1, (uintptr_t)(sPokenavBgDotsPal + 1)); + SetWordTaskArg(taskId, 3, (uintptr_t)(sPokenavBgDotsPal + 7)); +} + +static void ChangeBgDotsColorToPurple(void) +{ + CopyPaletteIntoBufferUnfaded(sPokenavBgDotsPal + 7, 0x31, 4); +} + +static void CreateBgDotLightBluePalTask(void) +{ + u8 taskId = CreateTask(Task_UpdateBgDotsPalette, 3); + SetWordTaskArg(taskId, 1, (uintptr_t)(sPokenavBgDotsPal + 7)); + SetWordTaskArg(taskId, 3, (uintptr_t)(sPokenavBgDotsPal + 1)); +} + +static bool32 IsTaskActive_UpdateBgDotsPalette(void) +{ + return FuncIsActiveTask(Task_UpdateBgDotsPalette); +} + +static void Task_UpdateBgDotsPalette(u8 taskId) +{ + u16 sp8[2]; + s16 * data = gTasks[taskId].data; + const u16 * pal1 = (const u16 *)GetWordTaskArg(taskId, 1); + const u16 * pal2 = (const u16 *)GetWordTaskArg(taskId, 3); + + PokenavCopyPalette(pal1, pal2, 2, 12, ++data[0], sp8); + LoadPalette(sp8, 0x31, 4); + if (data[0] == 12) + DestroyTask(taskId); +} + +static void VBlankCB_PokenavMainMenu(void) +{ + TransferPlttBuffer(); + LoadOam(); + ProcessSpriteCopyRequests(); + ScanlineEffect_InitHBlankDmaTransfer(); +} + +static void SetupPokenavMenuScanlineEffects(void) +{ + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_LIGHTEN); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON); + SetGpuRegBits(REG_OFFSET_WININ, WININ_WIN0_ALL); + SetGpuRegBits(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ); + SetGpuRegBits(REG_OFFSET_WIN0V, DISPLAY_HEIGHT); + ScanlineEffect_Stop(); + SetMenuOptionGlow(); + ScanlineEffect_SetParams(sPokenavMainMenuScanlineEffectParams); + SetVBlankCallback_(VBlankCB_PokenavMainMenu); + CreateTask(Task_CurrentMenuOptionGlow, 3); +} + +static void DestroyMenuOptionGlowTask(void) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON); + ScanlineEffect_Stop(); + DestroyTask(FindTaskIdByFunc(Task_CurrentMenuOptionGlow)); + SetPokenavVBlankCallback(); +} + +static void ResetBldCnt(void) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); +} + +static void InitMenuOptionGlow(void) +{ + SetMenuOptionGlow(); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_LIGHTEN); +} + +static void Task_CurrentMenuOptionGlow(u8 taskId) +{ + s16 * data = gTasks[taskId].data; + data[0]++; + if (data[0] > 0) + { + data[0] = 0; + data[1] += 3; + data[1] &= 0x7F; + SetGpuReg(REG_OFFSET_BLDY, gSineTable[data[1]] >> 5); + } +} + +static void SetMenuOptionGlow(void) +{ + int menuType = GetPokenavMenuType(); + int cursorPos = GetPokenavCursorPos(); + int r4 = sPokenavMenuOptionLabelGfx[menuType].deltaY * cursorPos + sPokenavMenuOptionLabelGfx[menuType].yStart - 8; + CpuFill16(0, gScanlineEffectRegBuffers[0], DISPLAY_HEIGHT * 2); + CpuFill16(0, gScanlineEffectRegBuffers[1], DISPLAY_HEIGHT * 2); + CpuFill16(RGB(16, 23, 28), &gScanlineEffectRegBuffers[0][r4], 0x20); + CpuFill16(RGB(16, 23, 28), &gScanlineEffectRegBuffers[1][r4], 0x20); +} + +void ResetBldCnt_(void) +{ + ResetBldCnt(); +} -- cgit v1.2.3