5640 lines
168 KiB
C
5640 lines
168 KiB
C
|
#include "global.h"
|
||
|
#include "battle_main.h"
|
||
|
#include "bg.h"
|
||
|
#include "data.h"
|
||
|
#include "decompress.h"
|
||
|
#include "event_data.h"
|
||
|
#include "gpu_regs.h"
|
||
|
#include "graphics.h"
|
||
|
#include "international_string_util.h"
|
||
|
#include "main.h"
|
||
|
#include "malloc.h"
|
||
|
#include "menu.h"
|
||
|
#include "m4a.h"
|
||
|
#include "overworld.h"
|
||
|
#include "palette.h"
|
||
|
#include "pokedex.h"
|
||
|
#include "pokedex_area_screen.h"
|
||
|
#include "pokedex_cry_screen.h"
|
||
|
#include "scanline_effect.h"
|
||
|
#include "sound.h"
|
||
|
#include "sprite.h"
|
||
|
#include "string_util.h"
|
||
|
#include "strings.h"
|
||
|
#include "task.h"
|
||
|
#include "text_window.h"
|
||
|
#include "trainer_pokemon_sprites.h"
|
||
|
#include "trig.h"
|
||
|
#include "window.h"
|
||
|
#include "constants/rgb.h"
|
||
|
#include "constants/songs.h"
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
PAGE_MAIN,
|
||
|
PAGE_INFO,
|
||
|
PAGE_SEARCH,
|
||
|
PAGE_SEARCH_RESULTS,
|
||
|
PAGE_UNK,
|
||
|
PAGE_AREA,
|
||
|
PAGE_CRY,
|
||
|
PAGE_SIZE
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
AREA_SCREEN,
|
||
|
CRY_SCREEN,
|
||
|
SIZE_SCREEN,
|
||
|
CANCEL_SCREEN,
|
||
|
SCREEN_COUNT
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
SEARCH_NAME,
|
||
|
SEARCH_COLOR,
|
||
|
SEARCH_TYPE_LEFT,
|
||
|
SEARCH_TYPE_RIGHT,
|
||
|
SEARCH_ORDER,
|
||
|
SEARCH_MODE,
|
||
|
SEARCH_OK,
|
||
|
SEARCH_COUNT
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
SEARCH_TOPBAR_SEARCH,
|
||
|
SEARCH_TOPBAR_SHIFT,
|
||
|
SEARCH_TOPBAR_CANCEL,
|
||
|
SEARCH_TOPBAR_COUNT
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
ORDER_NUMERICAL,
|
||
|
ORDER_ALPHABETICAL,
|
||
|
ORDER_HEAVIEST,
|
||
|
ORDER_LIGHTEST,
|
||
|
ORDER_TALLEST,
|
||
|
ORDER_SMALLEST
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
NAME_ABC = 1,
|
||
|
NAME_DEF,
|
||
|
NAME_GHI,
|
||
|
NAME_JKL,
|
||
|
NAME_MNO,
|
||
|
NAME_PQR,
|
||
|
NAME_STU,
|
||
|
NAME_VWX,
|
||
|
NAME_YZ,
|
||
|
};
|
||
|
|
||
|
// For scrolling search parameter
|
||
|
#define MAX_SEARCH_PARAM_ON_SCREEN 6
|
||
|
#define MAX_SEARCH_PARAM_CURSOR_POS (MAX_SEARCH_PARAM_ON_SCREEN - 1)
|
||
|
|
||
|
#define MAX_MONS_ON_SCREEN 4
|
||
|
|
||
|
#define LIST_SCROLL_STEP 16
|
||
|
|
||
|
#define POKEBALL_ROTATION_TOP 64
|
||
|
#define POKEBALL_ROTATION_BOTTOM (POKEBALL_ROTATION_TOP - 16)
|
||
|
|
||
|
// Coordinates of the Pokémon sprite on its page (info/cry screens)
|
||
|
#define MON_PAGE_X 48
|
||
|
#define MON_PAGE_Y 56
|
||
|
|
||
|
static EWRAM_DATA struct PokedexView *sPokedexView = NULL;
|
||
|
static EWRAM_DATA u16 sLastSelectedPokemon = 0;
|
||
|
static EWRAM_DATA u8 sPokeBallRotation = 0;
|
||
|
static EWRAM_DATA struct PokedexListItem *sPokedexListItem = NULL;
|
||
|
|
||
|
// This is written to, but never read.
|
||
|
u8 gUnusedPokedexU8;
|
||
|
void (*gPokedexVBlankCB)(void);
|
||
|
|
||
|
struct SearchOptionText
|
||
|
{
|
||
|
const u8 *description;
|
||
|
const u8 *title;
|
||
|
};
|
||
|
|
||
|
struct SearchOption
|
||
|
{
|
||
|
const struct SearchOptionText *texts;
|
||
|
u8 taskDataCursorPos;
|
||
|
u8 taskDataScrollOffset;
|
||
|
u16 numOptions;
|
||
|
};
|
||
|
|
||
|
struct SearchMenuTopBarItem
|
||
|
{
|
||
|
const u8 *description;
|
||
|
u8 highlightX;
|
||
|
u8 highlightY;
|
||
|
u8 highlightWidth;
|
||
|
};
|
||
|
|
||
|
struct SearchMenuItem
|
||
|
{
|
||
|
const u8 *description;
|
||
|
u8 titleBgX;
|
||
|
u8 titleBgY;
|
||
|
u8 titleBgWidth;
|
||
|
u8 selectionBgX;
|
||
|
u8 selectionBgY;
|
||
|
u8 selectionBgWidth;
|
||
|
};
|
||
|
|
||
|
struct PokedexListItem
|
||
|
{
|
||
|
u16 dexNum;
|
||
|
u16 seen:1;
|
||
|
u16 owned:1;
|
||
|
};
|
||
|
|
||
|
struct PokedexView
|
||
|
{
|
||
|
struct PokedexListItem pokedexList[NATIONAL_DEX_COUNT + 1];
|
||
|
u16 pokemonListCount;
|
||
|
u16 selectedPokemon;
|
||
|
u16 selectedPokemonBackup;
|
||
|
u16 dexMode;
|
||
|
u16 dexModeBackup;
|
||
|
u16 dexOrder;
|
||
|
u16 dexOrderBackup;
|
||
|
u16 seenCount;
|
||
|
u16 ownCount;
|
||
|
u16 monSpriteIds[MAX_MONS_ON_SCREEN];
|
||
|
u16 selectedMonSpriteId;
|
||
|
u16 pokeBallRotationStep;
|
||
|
u16 pokeBallRotationBackup;
|
||
|
u8 pokeBallRotation;
|
||
|
u8 initialVOffset;
|
||
|
u8 scrollTimer;
|
||
|
u8 scrollDirection;
|
||
|
s16 listVOffset;
|
||
|
s16 listMovingVOffset;
|
||
|
u16 scrollMonIncrement;
|
||
|
u16 maxScrollTimer;
|
||
|
u16 scrollSpeed;
|
||
|
u16 unkArr1[4]; // Cleared, never read
|
||
|
u8 filler[8];
|
||
|
u8 currentPage;
|
||
|
u8 currentPageBackup;
|
||
|
bool8 isSearchResults:1;
|
||
|
u8 selectedScreen;
|
||
|
u8 screenSwitchState;
|
||
|
u8 menuIsOpen;
|
||
|
u16 menuCursorPos;
|
||
|
s16 menuY; //Menu Y position (inverted because we use REG_BG0VOFS for this)
|
||
|
u8 unkArr2[8]; // Cleared, never read
|
||
|
u8 unkArr3[8]; // Cleared, never read
|
||
|
};
|
||
|
|
||
|
// this file's functions
|
||
|
static void CB2_Pokedex(void);
|
||
|
static void Task_OpenPokedexMainPage(u8);
|
||
|
static void Task_HandlePokedexInput(u8);
|
||
|
static void Task_WaitForScroll(u8);
|
||
|
static void Task_HandlePokedexStartMenuInput(u8);
|
||
|
static void Task_OpenInfoScreenAfterMonMovement(u8);
|
||
|
static void Task_WaitForExitInfoScreen(u8);
|
||
|
static void Task_WaitForExitSearch(u8);
|
||
|
static void Task_ClosePokedex(u8);
|
||
|
static void Task_OpenSearchResults(u8);
|
||
|
static void Task_HandleSearchResultsInput(u8);
|
||
|
static void Task_WaitForSearchResultsScroll(u8);
|
||
|
static void Task_HandleSearchResultsStartMenuInput(u8);
|
||
|
static void Task_OpenSearchResultsInfoScreenAfterMonMovement(u8);
|
||
|
static void Task_WaitForExitSearchResultsInfoScreen(u8);
|
||
|
static void Task_ReturnToPokedexFromSearchResults(u8);
|
||
|
static void Task_ClosePokedexFromSearchResultsStartMenu(u8);
|
||
|
static bool8 LoadPokedexListPage(u8);
|
||
|
static void LoadPokedexBgPalette(bool8);
|
||
|
static void FreeWindowAndBgBuffers(void);
|
||
|
static void CreatePokedexList(u8, u8);
|
||
|
static void CreateMonDexNum(u16, u8, u8, u16);
|
||
|
static void CreateCaughtBall(u16, u8, u8, u16);
|
||
|
static u8 CreateMonName(u16, u8, u8);
|
||
|
static void ClearMonListEntry(u8 x, u8 y, u16 unused);
|
||
|
static void CreateMonSpritesAtPos(u16, u16);
|
||
|
static bool8 UpdateDexListScroll(u8, u8, u8);
|
||
|
static u16 TryDoPokedexScroll(u16, u16);
|
||
|
static void UpdateSelectedMonSpriteId(void);
|
||
|
static bool8 TryDoInfoScreenScroll(void);
|
||
|
static u8 ClearMonSprites(void);
|
||
|
static u16 GetPokemonSpriteToDisplay(u16);
|
||
|
static u32 CreatePokedexMonSprite(u16, s16, s16);
|
||
|
static void CreateInterfaceSprites(u8);
|
||
|
static void SpriteCB_MoveMonForInfoScreen(struct Sprite *sprite);
|
||
|
static void SpriteCB_Scrollbar(struct Sprite *sprite);
|
||
|
static void SpriteCB_ScrollArrow(struct Sprite *sprite);
|
||
|
static void SpriteCB_DexListInterfaceText(struct Sprite *sprite);
|
||
|
static void SpriteCB_RotatingPokeBall(struct Sprite *sprite);
|
||
|
static void SpriteCB_SeenOwnInfo(struct Sprite *sprite);
|
||
|
static void SpriteCB_DexListStartMenuCursor(struct Sprite *sprite);
|
||
|
static void SpriteCB_PokedexListMonSprite(struct Sprite *sprite);
|
||
|
static u8 LoadInfoScreen(struct PokedexListItem*, u8 monSpriteId);
|
||
|
static bool8 IsInfoScreenScrolling(u8);
|
||
|
static u8 StartInfoScreenScroll(struct PokedexListItem*, u8);
|
||
|
static void Task_LoadInfoScreen(u8);
|
||
|
static void Task_HandleInfoScreenInput(u8);
|
||
|
static void Task_SwitchScreensFromInfoScreen(u8);
|
||
|
static void Task_LoadInfoScreenWaitForFade(u8);
|
||
|
static void Task_ExitInfoScreen(u8);
|
||
|
static void Task_LoadAreaScreen(u8);
|
||
|
static void Task_WaitForAreaScreenInput(u8 taskId);
|
||
|
static void Task_SwitchScreensFromAreaScreen(u8);
|
||
|
static void Task_LoadCryScreen(u8);
|
||
|
static void Task_HandleCryScreenInput(u8);
|
||
|
static void Task_SwitchScreensFromCryScreen(u8);
|
||
|
static void LoadPlayArrowPalette(bool8);
|
||
|
static void Task_LoadSizeScreen(u8);
|
||
|
static void Task_HandleSizeScreenInput(u8);
|
||
|
static void Task_SwitchScreensFromSizeScreen(u8);
|
||
|
static void LoadScreenSelectBarMain(u16);
|
||
|
static void LoadScreenSelectBarSubmenu(u16);
|
||
|
static void HighlightScreenSelectBarItem(u8, u16);
|
||
|
static void HighlightSubmenuScreenSelectBarItem(u8, u16);
|
||
|
static void Task_DisplayCaughtMonDexPage(u8);
|
||
|
static void Task_HandleCaughtMonPageInput(u8);
|
||
|
static void Task_ExitCaughtMonPage(u8);
|
||
|
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite);
|
||
|
static void PrintMonInfo(u32 num, u32, u32 owned, u32 newEntry);
|
||
|
static void PrintMonHeight(u16 height, u8 left, u8 top);
|
||
|
static void PrintMonWeight(u16 weight, u8 left, u8 top);
|
||
|
static void ResetOtherVideoRegisters(u16);
|
||
|
static u8 PrintCryScreenSpeciesName(u8, u16, u8, u8);
|
||
|
static void DrawFootprint(u8 windowId, u16 dexNum);
|
||
|
static u16 CreateSizeScreenTrainerPic(u16, s16, s16, s8);
|
||
|
static u16 GetNextPosition(u8, u16, u16, u16);
|
||
|
static u8 LoadSearchMenu(void);
|
||
|
static void Task_LoadSearchMenu(u8);
|
||
|
static void Task_SwitchToSearchMenuTopBar(u8);
|
||
|
static void Task_HandleSearchTopBarInput(u8);
|
||
|
static void Task_SwitchToSearchMenu(u8);
|
||
|
static void Task_HandleSearchMenuInput(u8);
|
||
|
static void Task_StartPokedexSearch(u8);
|
||
|
static void Task_WaitAndCompleteSearch(u8);
|
||
|
static void Task_SearchCompleteWaitForInput(u8);
|
||
|
static void Task_SelectSearchMenuItem(u8);
|
||
|
static void Task_HandleSearchParameterInput(u8);
|
||
|
static void Task_ExitSearch(u8);
|
||
|
static void Task_ExitSearchWaitForFade(u8);
|
||
|
static void HighlightSelectedSearchTopBarItem(u8);
|
||
|
static void HighlightSelectedSearchMenuItem(u8, u8);
|
||
|
static void PrintSelectedSearchParameters(u8);
|
||
|
static void DrawOrEraseSearchParameterBox(bool8);
|
||
|
static void PrintSearchParameterText(u8);
|
||
|
static u8 GetSearchModeSelection(u8 taskId, u8 option);
|
||
|
static void SetDefaultSearchModeAndOrder(u8);
|
||
|
static void CreateSearchParameterScrollArrows(u8);
|
||
|
static void EraseAndPrintSearchTextBox(const u8*);
|
||
|
static void EraseSelectorArrow(u32);
|
||
|
static void PrintSelectorArrow(u32);
|
||
|
static void PrintSearchParameterTitle(u32, const u8*);
|
||
|
static void ClearSearchParameterBoxText(void);
|
||
|
|
||
|
// const rom data
|
||
|
#include "data/pokemon/pokedex_orders.h"
|
||
|
|
||
|
static const struct OamData sOamData_ScrollBar =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileNum = 0,
|
||
|
.priority = 1,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOamData_ScrollArrow =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(16x8),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(16x8),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOamData_InterfaceText =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(32x16),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(32x16),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOamData_RotatingPokeBall =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_WINDOW,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(32x32),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(32x32),
|
||
|
.tileNum = 0,
|
||
|
.priority = 1,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOamData_SeenOwnText =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(64x32),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(64x32),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOamData_Dex8x16 =
|
||
|
{
|
||
|
.y = DISPLAY_HEIGHT,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.mosaic = 0,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(8x16),
|
||
|
.x = 0,
|
||
|
.matrixNum = 0,
|
||
|
.size = SPRITE_SIZE(8x16),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
.affineParam = 0
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_ScrollBar[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(3, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_ScrollArrow[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(1, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_RotatingPokeBall[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(16, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_StartButton[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(48, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_SearchText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(40, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_SelectButton[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(32, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_MenuText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(56, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_SeenText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(64, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_OwnText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(96, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(160, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalText[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(168, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit0[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(128, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit1[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(130, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit2[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(132, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit3[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(134, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit4[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(136, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit5[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(138, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit6[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(140, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit7[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(142, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit8[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(144, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_HoennSeenOwnDigit9[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(146, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit0[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(176, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit1[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(178, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit2[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(180, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit3[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(182, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit4[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(184, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit5[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(186, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit6[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(188, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit7[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(190, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit8[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(192, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_NationalSeenOwnDigit9[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(194, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sSpriteAnim_DexListStartMenuCursor[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(4, 30),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_ScrollBar[] =
|
||
|
{
|
||
|
sSpriteAnim_ScrollBar
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_ScrollArrow[] =
|
||
|
{
|
||
|
sSpriteAnim_ScrollArrow
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_RotatingPokeBall[] =
|
||
|
{
|
||
|
sSpriteAnim_RotatingPokeBall
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_InterfaceText[] =
|
||
|
{
|
||
|
sSpriteAnim_StartButton,
|
||
|
sSpriteAnim_SearchText,
|
||
|
sSpriteAnim_SelectButton,
|
||
|
sSpriteAnim_MenuText
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_SeenOwnText[] =
|
||
|
{
|
||
|
sSpriteAnim_SeenText,
|
||
|
sSpriteAnim_OwnText
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_HoennNationalText[] =
|
||
|
{
|
||
|
sSpriteAnim_HoennText,
|
||
|
sSpriteAnim_NationalText
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_HoennSeenOwnNumber[] =
|
||
|
{
|
||
|
sSpriteAnim_HoennSeenOwnDigit0,
|
||
|
sSpriteAnim_HoennSeenOwnDigit1,
|
||
|
sSpriteAnim_HoennSeenOwnDigit2,
|
||
|
sSpriteAnim_HoennSeenOwnDigit3,
|
||
|
sSpriteAnim_HoennSeenOwnDigit4,
|
||
|
sSpriteAnim_HoennSeenOwnDigit5,
|
||
|
sSpriteAnim_HoennSeenOwnDigit6,
|
||
|
sSpriteAnim_HoennSeenOwnDigit7,
|
||
|
sSpriteAnim_HoennSeenOwnDigit8,
|
||
|
sSpriteAnim_HoennSeenOwnDigit9
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_NationalSeenOwnNumber[] =
|
||
|
{
|
||
|
sSpriteAnim_NationalSeenOwnDigit0,
|
||
|
sSpriteAnim_NationalSeenOwnDigit1,
|
||
|
sSpriteAnim_NationalSeenOwnDigit2,
|
||
|
sSpriteAnim_NationalSeenOwnDigit3,
|
||
|
sSpriteAnim_NationalSeenOwnDigit4,
|
||
|
sSpriteAnim_NationalSeenOwnDigit5,
|
||
|
sSpriteAnim_NationalSeenOwnDigit6,
|
||
|
sSpriteAnim_NationalSeenOwnDigit7,
|
||
|
sSpriteAnim_NationalSeenOwnDigit8,
|
||
|
sSpriteAnim_NationalSeenOwnDigit9
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sSpriteAnimTable_DexListStartMenuCursor[] =
|
||
|
{
|
||
|
sSpriteAnim_DexListStartMenuCursor
|
||
|
};
|
||
|
|
||
|
#define TAG_DEX_INTERFACE 4096 // Tile and pal tag used for all interface sprites.
|
||
|
|
||
|
static const struct SpriteTemplate sScrollBarSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_ScrollBar,
|
||
|
.anims = sSpriteAnimTable_ScrollBar,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_Scrollbar,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sScrollArrowSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_ScrollArrow,
|
||
|
.anims = sSpriteAnimTable_ScrollArrow,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_ScrollArrow,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sInterfaceTextSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_InterfaceText,
|
||
|
.anims = sSpriteAnimTable_InterfaceText,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_DexListInterfaceText,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sRotatingPokeBallSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_RotatingPokeBall,
|
||
|
.anims = sSpriteAnimTable_RotatingPokeBall,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_RotatingPokeBall,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSeenOwnTextSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_SeenOwnText,
|
||
|
.anims = sSpriteAnimTable_SeenOwnText,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_SeenOwnInfo,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sHoennNationalTextSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_InterfaceText,
|
||
|
.anims = sSpriteAnimTable_HoennNationalText,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_SeenOwnInfo,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sHoennDexSeenOwnNumberSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_Dex8x16,
|
||
|
.anims = sSpriteAnimTable_HoennSeenOwnNumber,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_SeenOwnInfo,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sNationalDexSeenOwnNumberSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_Dex8x16,
|
||
|
.anims = sSpriteAnimTable_NationalSeenOwnNumber,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_SeenOwnInfo,
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sDexListStartMenuCursorSpriteTemplate =
|
||
|
{
|
||
|
.tileTag = TAG_DEX_INTERFACE,
|
||
|
.paletteTag = TAG_DEX_INTERFACE,
|
||
|
.oam = &sOamData_Dex8x16,
|
||
|
.anims = sSpriteAnimTable_DexListStartMenuCursor,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_DexListStartMenuCursor,
|
||
|
};
|
||
|
|
||
|
static const struct CompressedSpriteSheet sInterfaceSpriteSheet[] =
|
||
|
{
|
||
|
{gPokedexInterface_Gfx, 0x2000, TAG_DEX_INTERFACE},
|
||
|
{0}
|
||
|
};
|
||
|
|
||
|
static const struct SpritePalette sInterfaceSpritePalette[] =
|
||
|
{
|
||
|
{gPokedexBgHoenn_Pal, TAG_DEX_INTERFACE},
|
||
|
{0}
|
||
|
};
|
||
|
|
||
|
// By scroll speed. Last element of each unused
|
||
|
static const u8 sScrollMonIncrements[] = {4, 8, 16, 32, 32};
|
||
|
static const u8 sScrollTimers[] = {8, 4, 2, 1, 1};
|
||
|
|
||
|
static const struct BgTemplate sPokedex_BgTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 0,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 12,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 0,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 1,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 13,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 1,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 14,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 2,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 3,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 15,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 3,
|
||
|
.baseTile = 0
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct WindowTemplate sPokemonList_WindowTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 0,
|
||
|
.width = 32,
|
||
|
.height = 32,
|
||
|
.paletteNum = 0,
|
||
|
.baseBlock = 1,
|
||
|
},
|
||
|
DUMMY_WIN_TEMPLATE
|
||
|
};
|
||
|
|
||
|
static const u8 sText_No000[] = _("{NO}000");
|
||
|
static const u8 sCaughtBall_Gfx[] = INCBIN_U8("graphics/pokedex/caught_ball.4bpp");
|
||
|
static const u8 sText_TenDashes[] = _("----------");
|
||
|
|
||
|
ALIGNED(4) static const u8 gExpandedPlaceholder_PokedexDescription[] = _("");
|
||
|
|
||
|
#include "data/pokemon/pokedex_text.h"
|
||
|
#include "data/pokemon/pokedex_entries.h"
|
||
|
|
||
|
static const u16 sSizeScreenSilhouette_Pal[] = INCBIN_U16("graphics/pokedex/size_silhouette.gbapal");
|
||
|
|
||
|
static const struct BgTemplate sInfoScreen_BgTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 0,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 12,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 3,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 1,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 13,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 0,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 14,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 1,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 3,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 15,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 2,
|
||
|
.baseTile = 0
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#define WIN_INFO 0
|
||
|
#define WIN_FOOTPRINT 1
|
||
|
#define WIN_CRY_WAVE 2
|
||
|
#define WIN_VU_METER 3
|
||
|
|
||
|
static const struct WindowTemplate sInfoScreen_WindowTemplates[] =
|
||
|
{
|
||
|
[WIN_INFO] =
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 0,
|
||
|
.width = 32,
|
||
|
.height = 20,
|
||
|
.paletteNum = 0,
|
||
|
.baseBlock = 1,
|
||
|
},
|
||
|
[WIN_FOOTPRINT] =
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 25,
|
||
|
.tilemapTop = 8,
|
||
|
.width = 2,
|
||
|
.height = 2,
|
||
|
.paletteNum = 15,
|
||
|
.baseBlock = 641,
|
||
|
},
|
||
|
[WIN_CRY_WAVE] =
|
||
|
{
|
||
|
.bg = 0,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 12,
|
||
|
.width = 32,
|
||
|
.height = 7,
|
||
|
.paletteNum = 8,
|
||
|
.baseBlock = 645,
|
||
|
},
|
||
|
[WIN_VU_METER] =
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 18,
|
||
|
.tilemapTop = 3,
|
||
|
.width = 10,
|
||
|
.height = 8,
|
||
|
.paletteNum = 9,
|
||
|
.baseBlock = 869,
|
||
|
},
|
||
|
DUMMY_WIN_TEMPLATE
|
||
|
};
|
||
|
|
||
|
static const struct BgTemplate sNewEntryInfoScreen_BgTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 14,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 2,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 3,
|
||
|
.charBaseIndex = 1,
|
||
|
.mapBaseIndex = 15,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 3,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static const struct WindowTemplate sNewEntryInfoScreen_WindowTemplates[] =
|
||
|
{
|
||
|
[WIN_INFO] =
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 0,
|
||
|
.width = 32,
|
||
|
.height = 20,
|
||
|
.paletteNum = 0,
|
||
|
.baseBlock = 1,
|
||
|
},
|
||
|
[WIN_FOOTPRINT] =
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 25,
|
||
|
.tilemapTop = 8,
|
||
|
.width = 2,
|
||
|
.height = 2,
|
||
|
.paletteNum = 15,
|
||
|
.baseBlock = 641,
|
||
|
},
|
||
|
DUMMY_WIN_TEMPLATE
|
||
|
};
|
||
|
|
||
|
static const u8 sText_TenDashes2[] = _("----------");
|
||
|
|
||
|
#include "data/pokemon_graphics/footprint_table.h"
|
||
|
|
||
|
// First character in range followed by number of characters in range for upper and lowercase
|
||
|
static const u8 sLetterSearchRanges[][4] =
|
||
|
{
|
||
|
{}, // Name not specified, shouldn't be reached
|
||
|
[NAME_ABC] = {CHAR_A, 3, CHAR_a, 3},
|
||
|
[NAME_DEF] = {CHAR_D, 3, CHAR_d, 3},
|
||
|
[NAME_GHI] = {CHAR_G, 3, CHAR_g, 3},
|
||
|
[NAME_JKL] = {CHAR_J, 3, CHAR_j, 3},
|
||
|
[NAME_MNO] = {CHAR_M, 3, CHAR_m, 3},
|
||
|
[NAME_PQR] = {CHAR_P, 3, CHAR_p, 3},
|
||
|
[NAME_STU] = {CHAR_S, 3, CHAR_s, 3},
|
||
|
[NAME_VWX] = {CHAR_V, 3, CHAR_v, 3},
|
||
|
[NAME_YZ] = {CHAR_Y, 2, CHAR_y, 2},
|
||
|
};
|
||
|
|
||
|
#define LETTER_IN_RANGE_UPPER(letter, range) \
|
||
|
((letter) >= sLetterSearchRanges[range][0] \
|
||
|
&& (letter) < sLetterSearchRanges[range][0] + sLetterSearchRanges[range][1]) \
|
||
|
|
||
|
#define LETTER_IN_RANGE_LOWER(letter, range) \
|
||
|
((letter) >= sLetterSearchRanges[range][2] \
|
||
|
&& (letter) < sLetterSearchRanges[range][2] + sLetterSearchRanges[range][3]) \
|
||
|
|
||
|
static const struct SearchMenuTopBarItem sSearchMenuTopBarItems[SEARCH_TOPBAR_COUNT] =
|
||
|
{
|
||
|
[SEARCH_TOPBAR_SEARCH] =
|
||
|
{
|
||
|
.description = gText_SearchForPkmnBasedOnParameters,
|
||
|
.highlightX = 0,
|
||
|
.highlightY = 0,
|
||
|
.highlightWidth = 5,
|
||
|
},
|
||
|
[SEARCH_TOPBAR_SHIFT] =
|
||
|
{
|
||
|
.description = gText_SwitchPokedexListings,
|
||
|
.highlightX = 6,
|
||
|
.highlightY = 0,
|
||
|
.highlightWidth = 5,
|
||
|
},
|
||
|
[SEARCH_TOPBAR_CANCEL] =
|
||
|
{
|
||
|
.description = gText_ReturnToPokedex,
|
||
|
.highlightX = 12,
|
||
|
.highlightY = 0,
|
||
|
.highlightWidth = 5,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static const struct SearchMenuItem sSearchMenuItems[SEARCH_COUNT] =
|
||
|
{
|
||
|
[SEARCH_NAME] =
|
||
|
{
|
||
|
.description = gText_ListByFirstLetter,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 2,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 5,
|
||
|
.selectionBgY = 2,
|
||
|
.selectionBgWidth = 12,
|
||
|
},
|
||
|
[SEARCH_COLOR] =
|
||
|
{
|
||
|
.description = gText_ListByBodyColor,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 4,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 5,
|
||
|
.selectionBgY = 4,
|
||
|
.selectionBgWidth = 12,
|
||
|
},
|
||
|
[SEARCH_TYPE_LEFT] =
|
||
|
{
|
||
|
.description = gText_ListByType,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 6,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 5,
|
||
|
.selectionBgY = 6,
|
||
|
.selectionBgWidth = 6,
|
||
|
},
|
||
|
[SEARCH_TYPE_RIGHT] =
|
||
|
{
|
||
|
.description = gText_ListByType,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 6,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 11,
|
||
|
.selectionBgY = 6,
|
||
|
.selectionBgWidth = 6,
|
||
|
},
|
||
|
[SEARCH_ORDER] =
|
||
|
{
|
||
|
.description = gText_SelectPokedexListingMode,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 8,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 5,
|
||
|
.selectionBgY = 8,
|
||
|
.selectionBgWidth = 12,
|
||
|
},
|
||
|
[SEARCH_MODE] =
|
||
|
{
|
||
|
.description = gText_SelectPokedexMode,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 10,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 5,
|
||
|
.selectionBgY = 10,
|
||
|
.selectionBgWidth = 12,
|
||
|
},
|
||
|
[SEARCH_OK] =
|
||
|
{
|
||
|
.description = gText_ExecuteSearchSwitch,
|
||
|
.titleBgX = 0,
|
||
|
.titleBgY = 12,
|
||
|
.titleBgWidth = 5,
|
||
|
.selectionBgX = 0,
|
||
|
.selectionBgY = 0,
|
||
|
.selectionBgWidth = 0,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
// Left, Right, Up, Down
|
||
|
static const u8 sSearchMovementMap_SearchNatDex[SEARCH_COUNT][4] =
|
||
|
{
|
||
|
[SEARCH_NAME] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_COLOR
|
||
|
},
|
||
|
[SEARCH_COLOR] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_NAME,
|
||
|
SEARCH_TYPE_LEFT
|
||
|
},
|
||
|
[SEARCH_TYPE_LEFT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
SEARCH_TYPE_RIGHT,
|
||
|
SEARCH_COLOR,
|
||
|
SEARCH_ORDER
|
||
|
},
|
||
|
[SEARCH_TYPE_RIGHT] =
|
||
|
{ SEARCH_TYPE_LEFT,
|
||
|
0xFF,
|
||
|
SEARCH_COLOR,
|
||
|
SEARCH_ORDER
|
||
|
},
|
||
|
[SEARCH_ORDER] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_TYPE_LEFT,
|
||
|
SEARCH_MODE
|
||
|
},
|
||
|
[SEARCH_MODE] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_ORDER,
|
||
|
SEARCH_OK
|
||
|
},
|
||
|
[SEARCH_OK] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_MODE,
|
||
|
0xFF
|
||
|
},
|
||
|
};
|
||
|
|
||
|
// Left, Right, Up, Down
|
||
|
static const u8 sSearchMovementMap_ShiftNatDex[SEARCH_COUNT][4] =
|
||
|
{
|
||
|
[SEARCH_NAME] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_COLOR] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_TYPE_LEFT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_TYPE_RIGHT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_ORDER] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_MODE
|
||
|
},
|
||
|
[SEARCH_MODE] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_ORDER,
|
||
|
SEARCH_OK
|
||
|
},
|
||
|
[SEARCH_OK] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_MODE,
|
||
|
0xFF
|
||
|
},
|
||
|
};
|
||
|
|
||
|
// Left, Right, Up, Down
|
||
|
static const u8 sSearchMovementMap_SearchHoennDex[SEARCH_COUNT][4] =
|
||
|
{
|
||
|
[SEARCH_NAME] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_COLOR
|
||
|
},
|
||
|
[SEARCH_COLOR] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_NAME,
|
||
|
SEARCH_TYPE_LEFT
|
||
|
},
|
||
|
[SEARCH_TYPE_LEFT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
SEARCH_TYPE_RIGHT,
|
||
|
SEARCH_COLOR,
|
||
|
SEARCH_ORDER
|
||
|
},
|
||
|
[SEARCH_TYPE_RIGHT] =
|
||
|
{ SEARCH_TYPE_LEFT,
|
||
|
0xFF,
|
||
|
SEARCH_COLOR,
|
||
|
SEARCH_ORDER
|
||
|
},
|
||
|
[SEARCH_ORDER] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_TYPE_LEFT,
|
||
|
SEARCH_OK
|
||
|
},
|
||
|
[SEARCH_MODE] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_OK] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_ORDER,
|
||
|
0xFF
|
||
|
},
|
||
|
};
|
||
|
|
||
|
// Left, Right, Up, Down
|
||
|
static const u8 sSearchMovementMap_ShiftHoennDex[SEARCH_COUNT][4] =
|
||
|
{
|
||
|
[SEARCH_NAME] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_COLOR] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_TYPE_LEFT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_TYPE_RIGHT] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_ORDER] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_OK
|
||
|
},
|
||
|
[SEARCH_MODE] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
0xFF
|
||
|
},
|
||
|
[SEARCH_OK] =
|
||
|
{
|
||
|
0xFF,
|
||
|
0xFF,
|
||
|
SEARCH_ORDER,
|
||
|
0xFF
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static const struct SearchOptionText sDexModeOptions[] =
|
||
|
{
|
||
|
[DEX_MODE_HOENN] = {gText_DexHoennDescription, gText_DexHoennTitle},
|
||
|
[DEX_MODE_NATIONAL] = {gText_DexNatDescription, gText_DexNatTitle},
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
static const struct SearchOptionText sDexOrderOptions[] =
|
||
|
{
|
||
|
[ORDER_NUMERICAL] = {gText_DexSortNumericalDescription, gText_DexSortNumericalTitle},
|
||
|
[ORDER_ALPHABETICAL] = {gText_DexSortAtoZDescription, gText_DexSortAtoZTitle},
|
||
|
[ORDER_HEAVIEST] = {gText_DexSortHeaviestDescription, gText_DexSortHeaviestTitle},
|
||
|
[ORDER_LIGHTEST] = {gText_DexSortLightestDescription, gText_DexSortLightestTitle},
|
||
|
[ORDER_TALLEST] = {gText_DexSortTallestDescription, gText_DexSortTallestTitle},
|
||
|
[ORDER_SMALLEST] = {gText_DexSortSmallestDescription, gText_DexSortSmallestTitle},
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
static const struct SearchOptionText sDexSearchNameOptions[] =
|
||
|
{
|
||
|
{gText_DexEmptyString, gText_DexSearchDontSpecify},
|
||
|
[NAME_ABC] = {gText_DexEmptyString, gText_DexSearchAlphaABC},
|
||
|
[NAME_DEF] = {gText_DexEmptyString, gText_DexSearchAlphaDEF},
|
||
|
[NAME_GHI] = {gText_DexEmptyString, gText_DexSearchAlphaGHI},
|
||
|
[NAME_JKL] = {gText_DexEmptyString, gText_DexSearchAlphaJKL},
|
||
|
[NAME_MNO] = {gText_DexEmptyString, gText_DexSearchAlphaMNO},
|
||
|
[NAME_PQR] = {gText_DexEmptyString, gText_DexSearchAlphaPQR},
|
||
|
[NAME_STU] = {gText_DexEmptyString, gText_DexSearchAlphaSTU},
|
||
|
[NAME_VWX] = {gText_DexEmptyString, gText_DexSearchAlphaVWX},
|
||
|
[NAME_YZ] = {gText_DexEmptyString, gText_DexSearchAlphaYZ},
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
static const struct SearchOptionText sDexSearchColorOptions[] =
|
||
|
{
|
||
|
{gText_DexEmptyString, gText_DexSearchDontSpecify},
|
||
|
[BODY_COLOR_RED + 1] = {gText_DexEmptyString, gText_DexSearchColorRed},
|
||
|
[BODY_COLOR_BLUE + 1] = {gText_DexEmptyString, gText_DexSearchColorBlue},
|
||
|
[BODY_COLOR_YELLOW + 1] = {gText_DexEmptyString, gText_DexSearchColorYellow},
|
||
|
[BODY_COLOR_GREEN + 1] = {gText_DexEmptyString, gText_DexSearchColorGreen},
|
||
|
[BODY_COLOR_BLACK + 1] = {gText_DexEmptyString, gText_DexSearchColorBlack},
|
||
|
[BODY_COLOR_BROWN + 1] = {gText_DexEmptyString, gText_DexSearchColorBrown},
|
||
|
[BODY_COLOR_PURPLE + 1] = {gText_DexEmptyString, gText_DexSearchColorPurple},
|
||
|
[BODY_COLOR_GRAY + 1] = {gText_DexEmptyString, gText_DexSearchColorGray},
|
||
|
[BODY_COLOR_WHITE + 1] = {gText_DexEmptyString, gText_DexSearchColorWhite},
|
||
|
[BODY_COLOR_PINK + 1] = {gText_DexEmptyString, gText_DexSearchColorPink},
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
static const struct SearchOptionText sDexSearchTypeOptions[NUMBER_OF_MON_TYPES + 1] = // + 2 for "None" and terminator, - 1 for Mystery
|
||
|
{
|
||
|
{gText_DexEmptyString, gText_DexSearchTypeNone},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_NORMAL]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_FIGHTING]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_FLYING]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_POISON]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_GROUND]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_ROCK]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_BUG]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_GHOST]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_STEEL]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_FIRE]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_WATER]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_GRASS]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_ELECTRIC]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_PSYCHIC]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_ICE]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_DRAGON]},
|
||
|
{gText_DexEmptyString, gTypeNames[TYPE_DARK]},
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
static const u8 sPokedexModes[] = {DEX_MODE_HOENN, DEX_MODE_NATIONAL};
|
||
|
static const u8 sOrderOptions[] =
|
||
|
{
|
||
|
ORDER_NUMERICAL,
|
||
|
ORDER_ALPHABETICAL,
|
||
|
ORDER_HEAVIEST,
|
||
|
ORDER_LIGHTEST,
|
||
|
ORDER_TALLEST,
|
||
|
ORDER_SMALLEST,
|
||
|
};
|
||
|
|
||
|
static const u8 sDexSearchTypeIds[NUMBER_OF_MON_TYPES] =
|
||
|
{
|
||
|
TYPE_NONE,
|
||
|
TYPE_NORMAL,
|
||
|
TYPE_FIGHTING,
|
||
|
TYPE_FLYING,
|
||
|
TYPE_POISON,
|
||
|
TYPE_GROUND,
|
||
|
TYPE_ROCK,
|
||
|
TYPE_BUG,
|
||
|
TYPE_GHOST,
|
||
|
TYPE_STEEL,
|
||
|
TYPE_FIRE,
|
||
|
TYPE_WATER,
|
||
|
TYPE_GRASS,
|
||
|
TYPE_ELECTRIC,
|
||
|
TYPE_PSYCHIC,
|
||
|
TYPE_ICE,
|
||
|
TYPE_DRAGON,
|
||
|
TYPE_DARK,
|
||
|
};
|
||
|
|
||
|
// Number pairs are the task data for tracking the cursor pos and scroll offset of each option list
|
||
|
// See task data defines above Task_LoadSearchMenu
|
||
|
static const struct SearchOption sSearchOptions[] =
|
||
|
{
|
||
|
[SEARCH_NAME] = {sDexSearchNameOptions, 6, 7, ARRAY_COUNT(sDexSearchNameOptions) - 1},
|
||
|
[SEARCH_COLOR] = {sDexSearchColorOptions, 8, 9, ARRAY_COUNT(sDexSearchColorOptions) - 1},
|
||
|
[SEARCH_TYPE_LEFT] = {sDexSearchTypeOptions, 10, 11, ARRAY_COUNT(sDexSearchTypeOptions) - 1},
|
||
|
[SEARCH_TYPE_RIGHT] = {sDexSearchTypeOptions, 12, 13, ARRAY_COUNT(sDexSearchTypeOptions) - 1},
|
||
|
[SEARCH_ORDER] = {sDexOrderOptions, 4, 5, ARRAY_COUNT(sDexOrderOptions) - 1},
|
||
|
[SEARCH_MODE] = {sDexModeOptions, 2, 3, ARRAY_COUNT(sDexModeOptions) - 1},
|
||
|
};
|
||
|
|
||
|
static const struct BgTemplate sSearchMenu_BgTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 0,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 12,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 0,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 1,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 13,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 1,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 14,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 2,
|
||
|
.baseTile = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 3,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 15,
|
||
|
.screenSize = 0,
|
||
|
.paletteMode = 0,
|
||
|
.priority = 3,
|
||
|
.baseTile = 0
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct WindowTemplate sSearchMenu_WindowTemplate[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 0,
|
||
|
.width = 32,
|
||
|
.height = 20,
|
||
|
.paletteNum = 0,
|
||
|
.baseBlock = 0x0001,
|
||
|
},
|
||
|
DUMMY_WIN_TEMPLATE
|
||
|
};
|
||
|
|
||
|
// .text
|
||
|
|
||
|
void ResetPokedex(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
sLastSelectedPokemon = 0;
|
||
|
sPokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
gUnusedPokedexU8 = 0;
|
||
|
gSaveBlock2Ptr->pokedex.mode = DEX_MODE_HOENN;
|
||
|
gSaveBlock2Ptr->pokedex.order = 0;
|
||
|
gSaveBlock2Ptr->pokedex.nationalMagic = 0;
|
||
|
gSaveBlock2Ptr->pokedex.unknown2 = 0;
|
||
|
gSaveBlock2Ptr->pokedex.unownPersonality = 0;
|
||
|
gSaveBlock2Ptr->pokedex.spindaPersonality = 0;
|
||
|
gSaveBlock2Ptr->pokedex.unknown3 = 0;
|
||
|
DisableNationalPokedex();
|
||
|
for (i = 0; i < DEX_FLAGS_NO; i++)
|
||
|
{
|
||
|
gSaveBlock2Ptr->pokedex.owned[i] = 0;
|
||
|
gSaveBlock2Ptr->pokedex.seen[i] = 0;
|
||
|
gSaveBlock1Ptr->seen1[i] = 0;
|
||
|
gSaveBlock1Ptr->seen2[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ResetPokedexScrollPositions(void)
|
||
|
{
|
||
|
sLastSelectedPokemon = 0;
|
||
|
sPokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
}
|
||
|
|
||
|
static void VBlankCB_Pokedex(void)
|
||
|
{
|
||
|
LoadOam();
|
||
|
ProcessSpriteCopyRequests();
|
||
|
TransferPlttBuffer();
|
||
|
}
|
||
|
|
||
|
static void ResetPokedexView(struct PokedexView *pokedexView)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
pokedexView->pokedexList[i].dexNum = 0xFFFF;
|
||
|
pokedexView->pokedexList[i].seen = FALSE;
|
||
|
pokedexView->pokedexList[i].owned = FALSE;
|
||
|
}
|
||
|
pokedexView->pokedexList[NATIONAL_DEX_COUNT].dexNum = 0;
|
||
|
pokedexView->pokedexList[NATIONAL_DEX_COUNT].seen = FALSE;
|
||
|
pokedexView->pokedexList[NATIONAL_DEX_COUNT].owned = FALSE;
|
||
|
pokedexView->pokemonListCount = 0;
|
||
|
pokedexView->selectedPokemon = 0;
|
||
|
pokedexView->selectedPokemonBackup = 0;
|
||
|
pokedexView->dexMode = DEX_MODE_HOENN;
|
||
|
pokedexView->dexModeBackup = DEX_MODE_HOENN;
|
||
|
pokedexView->dexOrder = ORDER_NUMERICAL;
|
||
|
pokedexView->dexOrderBackup = ORDER_NUMERICAL;
|
||
|
pokedexView->seenCount = 0;
|
||
|
pokedexView->ownCount = 0;
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
pokedexView->monSpriteIds[i] = 0xFFFF;
|
||
|
pokedexView->pokeBallRotationStep = 0;
|
||
|
pokedexView->pokeBallRotationBackup = 0;
|
||
|
pokedexView->pokeBallRotation = 0;
|
||
|
pokedexView->initialVOffset = 0;
|
||
|
pokedexView->scrollTimer = 0;
|
||
|
pokedexView->scrollDirection = 0;
|
||
|
pokedexView->listVOffset = 0;
|
||
|
pokedexView->listMovingVOffset = 0;
|
||
|
pokedexView->scrollMonIncrement = 0;
|
||
|
pokedexView->maxScrollTimer = 0;
|
||
|
pokedexView->scrollSpeed = 0;
|
||
|
for (i = 0; i < ARRAY_COUNT(pokedexView->unkArr1); i++)
|
||
|
pokedexView->unkArr1[i] = 0;
|
||
|
pokedexView->currentPage = PAGE_MAIN;
|
||
|
pokedexView->currentPageBackup = PAGE_MAIN;
|
||
|
pokedexView->isSearchResults = FALSE;
|
||
|
pokedexView->selectedScreen = AREA_SCREEN;
|
||
|
pokedexView->screenSwitchState = 0;
|
||
|
pokedexView->menuIsOpen = 0;
|
||
|
pokedexView->menuCursorPos = 0;
|
||
|
pokedexView->menuY = 0;
|
||
|
for (i = 0; i < ARRAY_COUNT(pokedexView->unkArr2); i++)
|
||
|
pokedexView->unkArr2[i] = 0;
|
||
|
for (i = 0; i < ARRAY_COUNT(pokedexView->unkArr3); i++)
|
||
|
pokedexView->unkArr3[i] = 0;
|
||
|
}
|
||
|
|
||
|
void CB2_OpenPokedex(void)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
SetVBlankCallback(NULL);
|
||
|
ResetOtherVideoRegisters(0);
|
||
|
DmaFillLarge16(3, 0, (u8 *)VRAM, VRAM_SIZE, 0x1000);
|
||
|
DmaClear32(3, OAM, OAM_SIZE);
|
||
|
DmaClear16(3, PLTT, PLTT_SIZE);
|
||
|
gMain.state = 1;
|
||
|
break;
|
||
|
case 1:
|
||
|
ScanlineEffect_Stop();
|
||
|
ResetTasks();
|
||
|
ResetSpriteData();
|
||
|
ResetPaletteFade();
|
||
|
FreeAllSpritePalettes();
|
||
|
gReservedSpritePaletteCount = 8;
|
||
|
ResetAllPicSprites();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
sPokedexView = AllocZeroed(sizeof(struct PokedexView));
|
||
|
ResetPokedexView(sPokedexView);
|
||
|
CreateTask(Task_OpenPokedexMainPage, 0);
|
||
|
sPokedexView->dexMode = gSaveBlock2Ptr->pokedex.mode;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
sPokedexView->dexMode = DEX_MODE_HOENN;
|
||
|
sPokedexView->dexOrder = gSaveBlock2Ptr->pokedex.order;
|
||
|
sPokedexView->selectedPokemon = sLastSelectedPokemon;
|
||
|
sPokedexView->pokeBallRotation = sPokeBallRotation;
|
||
|
sPokedexView->selectedScreen = AREA_SCREEN;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
{
|
||
|
sPokedexView->seenCount = GetHoennPokedexCount(FLAG_GET_SEEN);
|
||
|
sPokedexView->ownCount = GetHoennPokedexCount(FLAG_GET_CAUGHT);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sPokedexView->seenCount = GetNationalPokedexCount(FLAG_GET_SEEN);
|
||
|
sPokedexView->ownCount = GetNationalPokedexCount(FLAG_GET_CAUGHT);
|
||
|
}
|
||
|
sPokedexView->initialVOffset = 8;
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
EnableInterrupts(1);
|
||
|
SetVBlankCallback(VBlankCB_Pokedex);
|
||
|
SetMainCallback2(CB2_Pokedex);
|
||
|
CreatePokedexList(sPokedexView->dexMode, sPokedexView->dexOrder);
|
||
|
m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x80);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CB2_Pokedex(void)
|
||
|
{
|
||
|
RunTasks();
|
||
|
AnimateSprites();
|
||
|
BuildOamBuffer();
|
||
|
UpdatePaletteFade();
|
||
|
}
|
||
|
|
||
|
void Task_OpenPokedexMainPage(u8 taskId)
|
||
|
{
|
||
|
sPokedexView->isSearchResults = FALSE;
|
||
|
if (LoadPokedexListPage(PAGE_MAIN))
|
||
|
gTasks[taskId].func = Task_HandlePokedexInput;
|
||
|
}
|
||
|
|
||
|
#define tLoadScreenTaskId data[0]
|
||
|
|
||
|
static void Task_HandlePokedexInput(u8 taskId)
|
||
|
{
|
||
|
SetGpuReg(REG_OFFSET_BG0VOFS, sPokedexView->menuY);
|
||
|
|
||
|
if (sPokedexView->menuY)
|
||
|
{
|
||
|
sPokedexView->menuY -= 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON) && sPokedexView->pokedexList[sPokedexView->selectedPokemon].seen)
|
||
|
{
|
||
|
UpdateSelectedMonSpriteId();
|
||
|
BeginNormalPaletteFade(~(1 << (gSprites[sPokedexView->selectedMonSpriteId].oam.paletteNum + 16)), 0, 0, 0x10, RGB_BLACK);
|
||
|
gSprites[sPokedexView->selectedMonSpriteId].callback = SpriteCB_MoveMonForInfoScreen;
|
||
|
gTasks[taskId].func = Task_OpenInfoScreenAfterMonMovement;
|
||
|
PlaySE(SE_PIN);
|
||
|
FreeWindowAndBgBuffers();
|
||
|
}
|
||
|
else if (JOY_NEW(START_BUTTON))
|
||
|
{
|
||
|
sPokedexView->menuY = 0;
|
||
|
sPokedexView->menuIsOpen = TRUE;
|
||
|
sPokedexView->menuCursorPos = 0;
|
||
|
gTasks[taskId].func = Task_HandlePokedexStartMenuInput;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_NEW(SELECT_BUTTON))
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].tLoadScreenTaskId = LoadSearchMenu();
|
||
|
sPokedexView->screenSwitchState = 0;
|
||
|
sPokedexView->pokeBallRotationBackup = sPokedexView->pokeBallRotation;
|
||
|
sPokedexView->selectedPokemonBackup = sPokedexView->selectedPokemon;
|
||
|
sPokedexView->dexModeBackup = sPokedexView->dexMode;
|
||
|
sPokedexView->dexOrderBackup = sPokedexView->dexOrder;
|
||
|
gTasks[taskId].func = Task_WaitForExitSearch;
|
||
|
PlaySE(SE_PC_LOGIN);
|
||
|
FreeWindowAndBgBuffers();
|
||
|
}
|
||
|
else if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ClosePokedex;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Handle D-pad
|
||
|
sPokedexView->selectedPokemon = TryDoPokedexScroll(sPokedexView->selectedPokemon, 0xE);
|
||
|
if (sPokedexView->scrollTimer)
|
||
|
gTasks[taskId].func = Task_WaitForScroll;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForScroll(u8 taskId)
|
||
|
{
|
||
|
if (UpdateDexListScroll(sPokedexView->scrollDirection, sPokedexView->scrollMonIncrement, sPokedexView->maxScrollTimer))
|
||
|
gTasks[taskId].func = Task_HandlePokedexInput;
|
||
|
}
|
||
|
|
||
|
static void Task_HandlePokedexStartMenuInput(u8 taskId)
|
||
|
{
|
||
|
SetGpuReg(REG_OFFSET_BG0VOFS, sPokedexView->menuY);
|
||
|
|
||
|
//If menu is not open, slide it up, on screen
|
||
|
if (sPokedexView->menuY != 80)
|
||
|
{
|
||
|
sPokedexView->menuY += 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
switch (sPokedexView->menuCursorPos)
|
||
|
{
|
||
|
case 0: //BACK TO LIST
|
||
|
default:
|
||
|
gMain.newKeys |= START_BUTTON; //Exit menu
|
||
|
break;
|
||
|
case 1: //LIST TOP
|
||
|
sPokedexView->selectedPokemon = 0;
|
||
|
sPokedexView->pokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(sPokedexView->selectedPokemon, 0xE);
|
||
|
gMain.newKeys |= START_BUTTON; //Exit menu
|
||
|
break;
|
||
|
case 2: //LIST BOTTOM
|
||
|
sPokedexView->selectedPokemon = sPokedexView->pokemonListCount - 1;
|
||
|
sPokedexView->pokeBallRotation = sPokedexView->pokemonListCount * 16 + POKEBALL_ROTATION_BOTTOM;
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(sPokedexView->selectedPokemon, 0xE);
|
||
|
gMain.newKeys |= START_BUTTON; //Exit menu
|
||
|
break;
|
||
|
case 3: //CLOSE POKEDEX
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ClosePokedex;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Exit menu when Start or B is pressed
|
||
|
if (JOY_NEW(START_BUTTON | B_BUTTON))
|
||
|
{
|
||
|
sPokedexView->menuIsOpen = FALSE;
|
||
|
gTasks[taskId].func = Task_HandlePokedexInput;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_REPEAT(DPAD_UP) && sPokedexView->menuCursorPos != 0)
|
||
|
{
|
||
|
sPokedexView->menuCursorPos--;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_REPEAT(DPAD_DOWN) && sPokedexView->menuCursorPos < 3)
|
||
|
{
|
||
|
sPokedexView->menuCursorPos++;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Opening the info screen from list view. Pokémon sprite is moving to its new position, wait for it to arrive
|
||
|
static void Task_OpenInfoScreenAfterMonMovement(u8 taskId)
|
||
|
{
|
||
|
if (gSprites[sPokedexView->selectedMonSpriteId].x == MON_PAGE_X && gSprites[sPokedexView->selectedMonSpriteId].y == MON_PAGE_Y)
|
||
|
{
|
||
|
sPokedexView->currentPageBackup = sPokedexView->currentPage;
|
||
|
gTasks[taskId].tLoadScreenTaskId = LoadInfoScreen(&sPokedexView->pokedexList[sPokedexView->selectedPokemon], sPokedexView->selectedMonSpriteId);
|
||
|
gTasks[taskId].func = Task_WaitForExitInfoScreen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForExitInfoScreen(u8 taskId)
|
||
|
{
|
||
|
if (gTasks[gTasks[taskId].tLoadScreenTaskId].isActive)
|
||
|
{
|
||
|
// While active, handle scroll input
|
||
|
if (sPokedexView->currentPage == PAGE_INFO && !IsInfoScreenScrolling(gTasks[taskId].tLoadScreenTaskId) && TryDoInfoScreenScroll())
|
||
|
StartInfoScreenScroll(&sPokedexView->pokedexList[sPokedexView->selectedPokemon], gTasks[taskId].tLoadScreenTaskId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Exiting, back to list view
|
||
|
sLastSelectedPokemon = sPokedexView->selectedPokemon;
|
||
|
sPokeBallRotation = sPokedexView->pokeBallRotation;
|
||
|
gTasks[taskId].func = Task_OpenPokedexMainPage;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForExitSearch(u8 taskId)
|
||
|
{
|
||
|
if (!gTasks[gTasks[taskId].tLoadScreenTaskId].isActive)
|
||
|
{
|
||
|
ClearMonSprites();
|
||
|
|
||
|
// Search produced results
|
||
|
if (sPokedexView->screenSwitchState != 0)
|
||
|
{
|
||
|
sPokedexView->selectedPokemon = 0;
|
||
|
sPokedexView->pokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
gTasks[taskId].func = Task_OpenSearchResults;
|
||
|
}
|
||
|
// Search didn't produce results
|
||
|
else
|
||
|
{
|
||
|
sPokedexView->pokeBallRotation = sPokedexView->pokeBallRotationBackup;
|
||
|
sPokedexView->selectedPokemon = sPokedexView->selectedPokemonBackup;
|
||
|
sPokedexView->dexMode = sPokedexView->dexModeBackup;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
sPokedexView->dexMode = DEX_MODE_HOENN;
|
||
|
sPokedexView->dexOrder = sPokedexView->dexOrderBackup;
|
||
|
gTasks[taskId].func = Task_OpenPokedexMainPage;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ClosePokedex(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
gSaveBlock2Ptr->pokedex.mode = sPokedexView->dexMode;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
gSaveBlock2Ptr->pokedex.mode = DEX_MODE_HOENN;
|
||
|
gSaveBlock2Ptr->pokedex.order = sPokedexView->dexOrder;
|
||
|
ClearMonSprites();
|
||
|
FreeWindowAndBgBuffers();
|
||
|
DestroyTask(taskId);
|
||
|
SetMainCallback2(CB2_ReturnToFieldWithOpenMenu);
|
||
|
m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100);
|
||
|
Free(sPokedexView);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_OpenSearchResults(u8 taskId)
|
||
|
{
|
||
|
sPokedexView->isSearchResults = TRUE;
|
||
|
if (LoadPokedexListPage(PAGE_SEARCH_RESULTS))
|
||
|
gTasks[taskId].func = Task_HandleSearchResultsInput;
|
||
|
}
|
||
|
|
||
|
static void Task_HandleSearchResultsInput(u8 taskId)
|
||
|
{
|
||
|
SetGpuReg(REG_OFFSET_BG0VOFS, sPokedexView->menuY);
|
||
|
|
||
|
if (sPokedexView->menuY)
|
||
|
{
|
||
|
sPokedexView->menuY -= 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON) && sPokedexView->pokedexList[sPokedexView->selectedPokemon].seen)
|
||
|
{
|
||
|
u32 a;
|
||
|
|
||
|
UpdateSelectedMonSpriteId();
|
||
|
a = (1 << (gSprites[sPokedexView->selectedMonSpriteId].oam.paletteNum + 16));
|
||
|
gSprites[sPokedexView->selectedMonSpriteId].callback = SpriteCB_MoveMonForInfoScreen;
|
||
|
BeginNormalPaletteFade(~a, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_OpenSearchResultsInfoScreenAfterMonMovement;
|
||
|
PlaySE(SE_PIN);
|
||
|
FreeWindowAndBgBuffers();
|
||
|
}
|
||
|
else if (JOY_NEW(START_BUTTON))
|
||
|
{
|
||
|
sPokedexView->menuY = 0;
|
||
|
sPokedexView->menuIsOpen = TRUE;
|
||
|
sPokedexView->menuCursorPos = 0;
|
||
|
gTasks[taskId].func = Task_HandleSearchResultsStartMenuInput;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_NEW(SELECT_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].tLoadScreenTaskId = LoadSearchMenu();
|
||
|
sPokedexView->screenSwitchState = 0;
|
||
|
gTasks[taskId].func = Task_WaitForExitSearch;
|
||
|
PlaySE(SE_PC_LOGIN);
|
||
|
FreeWindowAndBgBuffers();
|
||
|
}
|
||
|
else if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ReturnToPokedexFromSearchResults;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Handle D-pad
|
||
|
sPokedexView->selectedPokemon = TryDoPokedexScroll(sPokedexView->selectedPokemon, 0xE);
|
||
|
if (sPokedexView->scrollTimer)
|
||
|
gTasks[taskId].func = Task_WaitForSearchResultsScroll;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForSearchResultsScroll(u8 taskId)
|
||
|
{
|
||
|
if (UpdateDexListScroll(sPokedexView->scrollDirection, sPokedexView->scrollMonIncrement, sPokedexView->maxScrollTimer))
|
||
|
gTasks[taskId].func = Task_HandleSearchResultsInput;
|
||
|
}
|
||
|
|
||
|
static void Task_HandleSearchResultsStartMenuInput(u8 taskId)
|
||
|
{
|
||
|
SetGpuReg(REG_OFFSET_BG0VOFS, sPokedexView->menuY);
|
||
|
|
||
|
if (sPokedexView->menuY != 96)
|
||
|
{
|
||
|
sPokedexView->menuY += 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
switch (sPokedexView->menuCursorPos)
|
||
|
{
|
||
|
case 0: //BACK TO LIST
|
||
|
default:
|
||
|
gMain.newKeys |= START_BUTTON;
|
||
|
break;
|
||
|
case 1: //LIST TOP
|
||
|
sPokedexView->selectedPokemon = 0;
|
||
|
sPokedexView->pokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(sPokedexView->selectedPokemon, 0xE);
|
||
|
gMain.newKeys |= START_BUTTON;
|
||
|
break;
|
||
|
case 2: //LIST BOTTOM
|
||
|
sPokedexView->selectedPokemon = sPokedexView->pokemonListCount - 1;
|
||
|
sPokedexView->pokeBallRotation = sPokedexView->pokemonListCount * 16 + POKEBALL_ROTATION_BOTTOM;
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(sPokedexView->selectedPokemon, 0xE);
|
||
|
gMain.newKeys |= START_BUTTON;
|
||
|
break;
|
||
|
case 3: //BACK TO POKEDEX
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ReturnToPokedexFromSearchResults;
|
||
|
PlaySE(SE_TRUCK_DOOR);
|
||
|
break;
|
||
|
case 4: //CLOSE POKEDEX
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ClosePokedexFromSearchResultsStartMenu;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Exit menu when Start or B is pressed
|
||
|
if (JOY_NEW(START_BUTTON | B_BUTTON))
|
||
|
{
|
||
|
sPokedexView->menuIsOpen = FALSE;
|
||
|
gTasks[taskId].func = Task_HandleSearchResultsInput;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_REPEAT(DPAD_UP) && sPokedexView->menuCursorPos)
|
||
|
{
|
||
|
sPokedexView->menuCursorPos--;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
else if (JOY_REPEAT(DPAD_DOWN) && sPokedexView->menuCursorPos < 4)
|
||
|
{
|
||
|
sPokedexView->menuCursorPos++;
|
||
|
PlaySE(SE_SELECT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_OpenSearchResultsInfoScreenAfterMonMovement(u8 taskId)
|
||
|
{
|
||
|
if (gSprites[sPokedexView->selectedMonSpriteId].x == MON_PAGE_X && gSprites[sPokedexView->selectedMonSpriteId].y == MON_PAGE_Y)
|
||
|
{
|
||
|
sPokedexView->currentPageBackup = sPokedexView->currentPage;
|
||
|
gTasks[taskId].tLoadScreenTaskId = LoadInfoScreen(&sPokedexView->pokedexList[sPokedexView->selectedPokemon], sPokedexView->selectedMonSpriteId);
|
||
|
sPokedexView->selectedMonSpriteId = -1;
|
||
|
gTasks[taskId].func = Task_WaitForExitSearchResultsInfoScreen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForExitSearchResultsInfoScreen(u8 taskId)
|
||
|
{
|
||
|
if (gTasks[gTasks[taskId].tLoadScreenTaskId].isActive)
|
||
|
{
|
||
|
// While active, handle scroll input
|
||
|
if (sPokedexView->currentPage == PAGE_INFO && !IsInfoScreenScrolling(gTasks[taskId].tLoadScreenTaskId) && TryDoInfoScreenScroll())
|
||
|
StartInfoScreenScroll(&sPokedexView->pokedexList[sPokedexView->selectedPokemon], gTasks[taskId].tLoadScreenTaskId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Exiting, back to search results
|
||
|
gTasks[taskId].func = Task_OpenSearchResults;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ReturnToPokedexFromSearchResults(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->pokeBallRotation = sPokedexView->pokeBallRotationBackup;
|
||
|
sPokedexView->selectedPokemon = sPokedexView->selectedPokemonBackup;
|
||
|
sPokedexView->dexMode = sPokedexView->dexModeBackup;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
sPokedexView->dexMode = DEX_MODE_HOENN;
|
||
|
sPokedexView->dexOrder = sPokedexView->dexOrderBackup;
|
||
|
gTasks[taskId].func = Task_OpenPokedexMainPage;
|
||
|
ClearMonSprites();
|
||
|
FreeWindowAndBgBuffers();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ClosePokedexFromSearchResultsStartMenu(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->pokeBallRotation = sPokedexView->pokeBallRotationBackup;
|
||
|
sPokedexView->selectedPokemon = sPokedexView->selectedPokemonBackup;
|
||
|
sPokedexView->dexMode = sPokedexView->dexModeBackup;
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
sPokedexView->dexMode = DEX_MODE_HOENN;
|
||
|
sPokedexView->dexOrder = sPokedexView->dexOrderBackup;
|
||
|
gTasks[taskId].func = Task_ClosePokedex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef tLoadScreenTaskId
|
||
|
|
||
|
// For loading main pokedex page or pokedex search results
|
||
|
static bool8 LoadPokedexListPage(u8 page)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
if (gPaletteFade.active)
|
||
|
return 0;
|
||
|
SetVBlankCallback(NULL);
|
||
|
sPokedexView->currentPage = page;
|
||
|
ResetOtherVideoRegisters(0);
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sPokedexView->initialVOffset);
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, sPokedex_BgTemplate, ARRAY_COUNT(sPokedex_BgTemplate));
|
||
|
SetBgTilemapBuffer(3, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(2, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(1, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(0, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, gPokedexMenu_Gfx, 0x2000, 0, 0);
|
||
|
CopyToBgTilemapBuffer(1, gPokedexList_Tilemap, 0, 0);
|
||
|
CopyToBgTilemapBuffer(3, gPokedexListUnderlay_Tilemap, 0, 0);
|
||
|
if (page == PAGE_MAIN)
|
||
|
CopyToBgTilemapBuffer(0, gPokedexStartMenuMain_Tilemap, 0, 0x280);
|
||
|
else
|
||
|
CopyToBgTilemapBuffer(0, gPokedexStartMenuSearchResults_Tilemap, 0, 0x280);
|
||
|
ResetPaletteFade();
|
||
|
if (page == PAGE_MAIN)
|
||
|
sPokedexView->isSearchResults = FALSE;
|
||
|
else
|
||
|
sPokedexView->isSearchResults = TRUE;
|
||
|
LoadPokedexBgPalette(sPokedexView->isSearchResults);
|
||
|
InitWindows(sPokemonList_WindowTemplate);
|
||
|
DeactivateAllTextPrinters();
|
||
|
PutWindowTilemap(0);
|
||
|
CopyWindowToVram(0, COPYWIN_FULL);
|
||
|
gMain.state = 1;
|
||
|
break;
|
||
|
case 1:
|
||
|
ResetSpriteData();
|
||
|
FreeAllSpritePalettes();
|
||
|
gReservedSpritePaletteCount = 8;
|
||
|
LoadCompressedSpriteSheet(&sInterfaceSpriteSheet[0]);
|
||
|
LoadSpritePalettes(sInterfaceSpritePalette);
|
||
|
CreateInterfaceSprites(page);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
if (page == PAGE_MAIN)
|
||
|
CreatePokedexList(sPokedexView->dexMode, sPokedexView->dexOrder);
|
||
|
CreateMonSpritesAtPos(sPokedexView->selectedPokemon, 0xE);
|
||
|
sPokedexView->menuIsOpen = FALSE;
|
||
|
sPokedexView->menuY = 0;
|
||
|
CopyBgTilemapBufferToVram(0);
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK);
|
||
|
SetVBlankCallback(VBlankCB_Pokedex);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_ALL | WININ_WIN1_ALL);
|
||
|
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_ALL | WINOUT_WINOBJ_BG0 | WINOUT_WINOBJ_BG2 | WINOUT_WINOBJ_BG3 | WINOUT_WINOBJ_OBJ);
|
||
|
SetGpuReg(REG_OFFSET_WIN0H, 0);
|
||
|
SetGpuReg(REG_OFFSET_WIN0V, 0);
|
||
|
SetGpuReg(REG_OFFSET_WIN1H, 0);
|
||
|
SetGpuReg(REG_OFFSET_WIN1V, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON | DISPCNT_OBJWIN_ON);
|
||
|
ShowBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
gMain.state = 0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static void LoadPokedexBgPalette(bool8 isSearchResults)
|
||
|
{
|
||
|
if (isSearchResults == TRUE)
|
||
|
LoadPalette(gPokedexSearchResults_Pal + 1, 1, 0xBE);
|
||
|
else if (!IsNationalPokedexEnabled())
|
||
|
LoadPalette(gPokedexBgHoenn_Pal + 1, 1, 0xBE);
|
||
|
else
|
||
|
LoadPalette(gPokedexBgNational_Pal + 1, 1, 0xBE);
|
||
|
LoadPalette(GetOverworldTextboxPalettePtr(), 0xF0, 32);
|
||
|
}
|
||
|
|
||
|
static void FreeWindowAndBgBuffers(void)
|
||
|
{
|
||
|
void* tilemapBuffer;
|
||
|
|
||
|
FreeAllWindowBuffers();
|
||
|
tilemapBuffer = GetBgTilemapBuffer(0);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(1);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(2);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(3);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
}
|
||
|
|
||
|
static void CreatePokedexList(u8 dexMode, u8 order)
|
||
|
{
|
||
|
u16 vars[3]; //I have no idea why three regular variables are stored in an array, but whatever.
|
||
|
#define temp_dexCount vars[0]
|
||
|
#define temp_isHoennDex vars[1]
|
||
|
#define temp_dexNum vars[2]
|
||
|
s16 i;
|
||
|
|
||
|
sPokedexView->pokemonListCount = 0;
|
||
|
|
||
|
switch (dexMode)
|
||
|
{
|
||
|
default:
|
||
|
case DEX_MODE_HOENN:
|
||
|
temp_dexCount = HOENN_DEX_COUNT;
|
||
|
temp_isHoennDex = TRUE;
|
||
|
break;
|
||
|
case DEX_MODE_NATIONAL:
|
||
|
if (IsNationalPokedexEnabled())
|
||
|
{
|
||
|
temp_dexCount = NATIONAL_DEX_COUNT;
|
||
|
temp_isHoennDex = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp_dexCount = HOENN_DEX_COUNT;
|
||
|
temp_isHoennDex = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (order)
|
||
|
{
|
||
|
case ORDER_NUMERICAL:
|
||
|
if (temp_isHoennDex)
|
||
|
{
|
||
|
for (i = 0; i < temp_dexCount; i++)
|
||
|
{
|
||
|
temp_dexNum = HoennToNationalOrder(i + 1);
|
||
|
sPokedexView->pokedexList[i].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[i].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
|
||
|
sPokedexView->pokedexList[i].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
|
||
|
if (sPokedexView->pokedexList[i].seen)
|
||
|
sPokedexView->pokemonListCount = i + 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s16 r5, r10;
|
||
|
for (i = 0, r5 = 0, r10 = 0; i < temp_dexCount; i++)
|
||
|
{
|
||
|
temp_dexNum = i + 1;
|
||
|
if (GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN))
|
||
|
r10 = 1;
|
||
|
if (r10)
|
||
|
{
|
||
|
sPokedexView->pokedexList[r5].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[r5].seen = GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN);
|
||
|
sPokedexView->pokedexList[r5].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
|
||
|
if (sPokedexView->pokedexList[r5].seen)
|
||
|
sPokedexView->pokemonListCount = r5 + 1;
|
||
|
r5++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ORDER_ALPHABETICAL:
|
||
|
for (i = 0; i < NUM_SPECIES - 1; i++)
|
||
|
{
|
||
|
temp_dexNum = gPokedexOrder_Alphabetical[i];
|
||
|
|
||
|
if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN))
|
||
|
{
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].owned = GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT);
|
||
|
sPokedexView->pokemonListCount++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ORDER_HEAVIEST:
|
||
|
for (i = NATIONAL_DEX_COUNT - 1; i >= 0; i--)
|
||
|
{
|
||
|
temp_dexNum = gPokedexOrder_Weight[i];
|
||
|
|
||
|
if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT))
|
||
|
{
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].owned = TRUE;
|
||
|
sPokedexView->pokemonListCount++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ORDER_LIGHTEST:
|
||
|
for (i = 0; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
temp_dexNum = gPokedexOrder_Weight[i];
|
||
|
|
||
|
if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT))
|
||
|
{
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].owned = TRUE;
|
||
|
sPokedexView->pokemonListCount++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ORDER_TALLEST:
|
||
|
for (i = NATIONAL_DEX_COUNT - 1; i >= 0; i--)
|
||
|
{
|
||
|
temp_dexNum = gPokedexOrder_Height[i];
|
||
|
|
||
|
if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT))
|
||
|
{
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].owned = TRUE;
|
||
|
sPokedexView->pokemonListCount++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ORDER_SMALLEST:
|
||
|
for (i = 0; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
temp_dexNum = gPokedexOrder_Height[i];
|
||
|
|
||
|
if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT))
|
||
|
{
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE;
|
||
|
sPokedexView->pokedexList[sPokedexView->pokemonListCount].owned = TRUE;
|
||
|
sPokedexView->pokemonListCount++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
for (i = sPokedexView->pokemonListCount; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
sPokedexView->pokedexList[i].dexNum = 0xFFFF;
|
||
|
sPokedexView->pokedexList[i].seen = FALSE;
|
||
|
sPokedexView->pokedexList[i].owned = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void PrintMonDexNumAndName(u8 windowId, u8 fontId, const u8* str, u8 left, u8 top)
|
||
|
{
|
||
|
u8 color[3];
|
||
|
|
||
|
color[0] = TEXT_COLOR_TRANSPARENT;
|
||
|
color[1] = TEXT_DYNAMIC_COLOR_6;
|
||
|
color[2] = TEXT_COLOR_LIGHT_GRAY;
|
||
|
AddTextPrinterParameterized4(windowId, fontId, left * 8, (top * 8) + 1, 0, 0, color, TEXT_SKIP_DRAW, str);
|
||
|
}
|
||
|
|
||
|
// u16 ignored is passed but never used
|
||
|
static void CreateMonListEntry(u8 position, u16 b, u16 ignored)
|
||
|
{
|
||
|
s16 entryNum;
|
||
|
u16 i;
|
||
|
u16 vOffset;
|
||
|
|
||
|
switch (position)
|
||
|
{
|
||
|
case 0: // Initial
|
||
|
default:
|
||
|
entryNum = b - 5;
|
||
|
for (i = 0; i <= 10; i++)
|
||
|
{
|
||
|
if (entryNum < 0 || entryNum >= NATIONAL_DEX_COUNT || sPokedexView->pokedexList[entryNum].dexNum == 0xFFFF)
|
||
|
{
|
||
|
ClearMonListEntry(17, i * 2, ignored);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ClearMonListEntry(17, i * 2, ignored);
|
||
|
if (sPokedexView->pokedexList[entryNum].seen)
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 0x12, i * 2, ignored);
|
||
|
CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, i * 2, ignored);
|
||
|
CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, i * 2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 0x12, i * 2, ignored);
|
||
|
CreateCaughtBall(FALSE, 0x11, i * 2, ignored);
|
||
|
CreateMonName(0, 0x16, i * 2);
|
||
|
}
|
||
|
}
|
||
|
entryNum++;
|
||
|
}
|
||
|
break;
|
||
|
case 1: // Up
|
||
|
entryNum = b - 5;
|
||
|
if (entryNum < 0 || entryNum >= NATIONAL_DEX_COUNT || sPokedexView->pokedexList[entryNum].dexNum == 0xFFFF)
|
||
|
{
|
||
|
ClearMonListEntry(17, sPokedexView->listVOffset * 2, ignored);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ClearMonListEntry(17, sPokedexView->listVOffset * 2, ignored);
|
||
|
if (sPokedexView->pokedexList[entryNum].seen)
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, ignored);
|
||
|
CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, sPokedexView->listVOffset * 2, ignored);
|
||
|
CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, sPokedexView->listVOffset * 2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 18, sPokedexView->listVOffset * 2, ignored);
|
||
|
CreateCaughtBall(FALSE, 17, sPokedexView->listVOffset * 2, ignored);
|
||
|
CreateMonName(0, 0x16, sPokedexView->listVOffset * 2);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 2: // Down
|
||
|
entryNum = b + 5;
|
||
|
vOffset = sPokedexView->listVOffset + 10;
|
||
|
if (vOffset >= LIST_SCROLL_STEP)
|
||
|
vOffset -= LIST_SCROLL_STEP;
|
||
|
if (entryNum < 0 || entryNum >= NATIONAL_DEX_COUNT || sPokedexView->pokedexList[entryNum].dexNum == 0xFFFF)
|
||
|
ClearMonListEntry(17, vOffset * 2, ignored);
|
||
|
else
|
||
|
{
|
||
|
ClearMonListEntry(17, vOffset * 2, ignored);
|
||
|
if (sPokedexView->pokedexList[entryNum].seen)
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 18, vOffset * 2, ignored);
|
||
|
CreateCaughtBall(sPokedexView->pokedexList[entryNum].owned, 0x11, vOffset * 2, ignored);
|
||
|
CreateMonName(sPokedexView->pokedexList[entryNum].dexNum, 0x16, vOffset * 2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CreateMonDexNum(entryNum, 18, vOffset * 2, ignored);
|
||
|
CreateCaughtBall(FALSE, 0x11, vOffset * 2, ignored);
|
||
|
CreateMonName(0, 0x16, vOffset * 2);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
}
|
||
|
|
||
|
static void CreateMonDexNum(u16 entryNum, u8 left, u8 top, u16 unused)
|
||
|
{
|
||
|
u8 text[6];
|
||
|
u16 dexNum;
|
||
|
|
||
|
memcpy(text, sText_No000, ARRAY_COUNT(text));
|
||
|
dexNum = sPokedexView->pokedexList[entryNum].dexNum;
|
||
|
if (sPokedexView->dexMode == DEX_MODE_HOENN)
|
||
|
dexNum = NationalToHoennOrder(dexNum);
|
||
|
text[2] = CHAR_0 + dexNum / 100;
|
||
|
text[3] = CHAR_0 + (dexNum % 100) / 10;
|
||
|
text[4] = CHAR_0 + (dexNum % 100) % 10;
|
||
|
PrintMonDexNumAndName(0, FONT_NARROW, text, left, top);
|
||
|
}
|
||
|
|
||
|
static void CreateCaughtBall(bool16 owned, u8 x, u8 y, u16 unused)
|
||
|
{
|
||
|
if (owned)
|
||
|
BlitBitmapToWindow(0, sCaughtBall_Gfx, x * 8, y * 8, 8, 16);
|
||
|
else
|
||
|
FillWindowPixelRect(0, PIXEL_FILL(0), x * 8, y * 8, 8, 16);
|
||
|
}
|
||
|
|
||
|
static u8 CreateMonName(u16 num, u8 left, u8 top)
|
||
|
{
|
||
|
const u8* str;
|
||
|
|
||
|
num = NationalPokedexNumToSpecies(num);
|
||
|
if (num)
|
||
|
str = gSpeciesNames[num];
|
||
|
else
|
||
|
str = sText_TenDashes;
|
||
|
PrintMonDexNumAndName(0, FONT_NARROW, str, left, top);
|
||
|
return StringLength(str);
|
||
|
}
|
||
|
|
||
|
static void ClearMonListEntry(u8 x, u8 y, u16 unused)
|
||
|
{
|
||
|
FillWindowPixelRect(0, PIXEL_FILL(0), x * 8, y * 8, 0x60, 16);
|
||
|
}
|
||
|
|
||
|
// u16 ignored is passed but never used
|
||
|
static void CreateMonSpritesAtPos(u16 selectedMon, u16 ignored)
|
||
|
{
|
||
|
u8 i;
|
||
|
u16 dexNum;
|
||
|
u8 spriteId;
|
||
|
|
||
|
gPaletteFade.bufferTransferDisabled = TRUE;
|
||
|
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
sPokedexView->monSpriteIds[i] = 0xFFFF;
|
||
|
sPokedexView->selectedMonSpriteId = 0xFFFF;
|
||
|
|
||
|
// Create top mon sprite
|
||
|
dexNum = GetPokemonSpriteToDisplay(selectedMon - 1);
|
||
|
if (dexNum != 0xFFFF)
|
||
|
{
|
||
|
spriteId = CreatePokedexMonSprite(dexNum, 0x60, 0x50);
|
||
|
gSprites[spriteId].callback = SpriteCB_PokedexListMonSprite;
|
||
|
gSprites[spriteId].data[5] = -32;
|
||
|
}
|
||
|
|
||
|
// Create mid mon sprite
|
||
|
dexNum = GetPokemonSpriteToDisplay(selectedMon);
|
||
|
if (dexNum != 0xFFFF)
|
||
|
{
|
||
|
spriteId = CreatePokedexMonSprite(dexNum, 0x60, 0x50);
|
||
|
gSprites[spriteId].callback = SpriteCB_PokedexListMonSprite;
|
||
|
gSprites[spriteId].data[5] = 0;
|
||
|
}
|
||
|
|
||
|
// Create bottom mon sprite
|
||
|
dexNum = GetPokemonSpriteToDisplay(selectedMon + 1);
|
||
|
if (dexNum != 0xFFFF)
|
||
|
{
|
||
|
spriteId = CreatePokedexMonSprite(dexNum, 0x60, 0x50);
|
||
|
gSprites[spriteId].callback = SpriteCB_PokedexListMonSprite;
|
||
|
gSprites[spriteId].data[5] = 32;
|
||
|
}
|
||
|
|
||
|
CreateMonListEntry(0, selectedMon, ignored);
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sPokedexView->initialVOffset);
|
||
|
|
||
|
sPokedexView->listVOffset = 0;
|
||
|
sPokedexView->listMovingVOffset = 0;
|
||
|
|
||
|
gPaletteFade.bufferTransferDisabled = FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 UpdateDexListScroll(u8 direction, u8 monMoveIncrement, u8 scrollTimerMax)
|
||
|
{
|
||
|
u16 i;
|
||
|
u8 step;
|
||
|
|
||
|
if (sPokedexView->scrollTimer)
|
||
|
{
|
||
|
sPokedexView->scrollTimer--;
|
||
|
switch (direction)
|
||
|
{
|
||
|
case 1: // Up
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
{
|
||
|
if (sPokedexView->monSpriteIds[i] != 0xFFFF)
|
||
|
gSprites[sPokedexView->monSpriteIds[i]].data[5] += monMoveIncrement;
|
||
|
}
|
||
|
step = LIST_SCROLL_STEP * (scrollTimerMax - sPokedexView->scrollTimer) / scrollTimerMax;
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sPokedexView->initialVOffset + sPokedexView->listMovingVOffset * LIST_SCROLL_STEP - step);
|
||
|
sPokedexView->pokeBallRotation -= sPokedexView->pokeBallRotationStep;
|
||
|
break;
|
||
|
case 2: // Down
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
{
|
||
|
if (sPokedexView->monSpriteIds[i] != 0xFFFF)
|
||
|
gSprites[sPokedexView->monSpriteIds[i]].data[5] -= monMoveIncrement;
|
||
|
}
|
||
|
step = LIST_SCROLL_STEP * (scrollTimerMax - sPokedexView->scrollTimer) / scrollTimerMax;
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sPokedexView->initialVOffset + sPokedexView->listMovingVOffset * LIST_SCROLL_STEP + step);
|
||
|
sPokedexView->pokeBallRotation += sPokedexView->pokeBallRotationStep;
|
||
|
break;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sPokedexView->initialVOffset + sPokedexView->listVOffset * LIST_SCROLL_STEP);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CreateScrollingPokemonSprite(u8 direction, u16 selectedMon)
|
||
|
{
|
||
|
u16 dexNum;
|
||
|
u8 spriteId;
|
||
|
|
||
|
sPokedexView->listMovingVOffset = sPokedexView->listVOffset;
|
||
|
switch (direction)
|
||
|
{
|
||
|
case 1: // up
|
||
|
dexNum = GetPokemonSpriteToDisplay(selectedMon - 1);
|
||
|
if (dexNum != 0xFFFF)
|
||
|
{
|
||
|
spriteId = CreatePokedexMonSprite(dexNum, 0x60, 0x50);
|
||
|
gSprites[spriteId].callback = SpriteCB_PokedexListMonSprite;
|
||
|
gSprites[spriteId].data[5] = -64;
|
||
|
}
|
||
|
if (sPokedexView->listVOffset > 0)
|
||
|
sPokedexView->listVOffset--;
|
||
|
else
|
||
|
sPokedexView->listVOffset = LIST_SCROLL_STEP - 1;
|
||
|
break;
|
||
|
case 2: // down
|
||
|
dexNum = GetPokemonSpriteToDisplay(selectedMon + 1);
|
||
|
if (dexNum != 0xFFFF)
|
||
|
{
|
||
|
spriteId = CreatePokedexMonSprite(dexNum, 0x60, 0x50);
|
||
|
gSprites[spriteId].callback = SpriteCB_PokedexListMonSprite;
|
||
|
gSprites[spriteId].data[5] = 64;
|
||
|
}
|
||
|
if (sPokedexView->listVOffset < LIST_SCROLL_STEP - 1)
|
||
|
sPokedexView->listVOffset++;
|
||
|
else
|
||
|
sPokedexView->listVOffset = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// u16 ignored is passed but never used
|
||
|
static u16 TryDoPokedexScroll(u16 selectedMon, u16 ignored)
|
||
|
{
|
||
|
u8 scrollTimer;
|
||
|
u8 scrollMonIncrement;
|
||
|
u8 i;
|
||
|
u16 startingPos;
|
||
|
u8 scrollDir = 0;
|
||
|
|
||
|
if (JOY_HELD(DPAD_UP) && (selectedMon > 0))
|
||
|
{
|
||
|
scrollDir = 1;
|
||
|
selectedMon = GetNextPosition(1, selectedMon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
CreateScrollingPokemonSprite(1, selectedMon);
|
||
|
CreateMonListEntry(1, selectedMon, ignored);
|
||
|
PlaySE(SE_DEX_SCROLL);
|
||
|
}
|
||
|
else if (JOY_HELD(DPAD_DOWN) && (selectedMon < sPokedexView->pokemonListCount - 1))
|
||
|
{
|
||
|
scrollDir = 2;
|
||
|
selectedMon = GetNextPosition(0, selectedMon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
CreateScrollingPokemonSprite(2, selectedMon);
|
||
|
CreateMonListEntry(2, selectedMon, ignored);
|
||
|
PlaySE(SE_DEX_SCROLL);
|
||
|
}
|
||
|
else if (JOY_NEW(DPAD_LEFT) && (selectedMon > 0))
|
||
|
{
|
||
|
startingPos = selectedMon;
|
||
|
|
||
|
for (i = 0; i < 7; i++)
|
||
|
selectedMon = GetNextPosition(1, selectedMon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
sPokedexView->pokeBallRotation += 16 * (selectedMon - startingPos);
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(selectedMon, 0xE);
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
}
|
||
|
else if (JOY_NEW(DPAD_RIGHT) && (selectedMon < sPokedexView->pokemonListCount - 1))
|
||
|
{
|
||
|
startingPos = selectedMon;
|
||
|
for (i = 0; i < 7; i++)
|
||
|
selectedMon = GetNextPosition(0, selectedMon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
sPokedexView->pokeBallRotation += 16 * (selectedMon - startingPos);
|
||
|
ClearMonSprites();
|
||
|
CreateMonSpritesAtPos(selectedMon, 0xE);
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
}
|
||
|
|
||
|
if (scrollDir == 0)
|
||
|
{
|
||
|
// Left/right input just snaps up/down, no scrolling
|
||
|
sPokedexView->scrollSpeed = 0;
|
||
|
return selectedMon;
|
||
|
}
|
||
|
|
||
|
scrollMonIncrement = sScrollMonIncrements[sPokedexView->scrollSpeed / 4];
|
||
|
scrollTimer = sScrollTimers[sPokedexView->scrollSpeed / 4];
|
||
|
sPokedexView->scrollTimer = scrollTimer;
|
||
|
sPokedexView->maxScrollTimer = scrollTimer;
|
||
|
sPokedexView->scrollMonIncrement = scrollMonIncrement;
|
||
|
sPokedexView->scrollDirection = scrollDir;
|
||
|
sPokedexView->pokeBallRotationStep = scrollMonIncrement / 2;
|
||
|
UpdateDexListScroll(sPokedexView->scrollDirection, sPokedexView->scrollMonIncrement, sPokedexView->maxScrollTimer);
|
||
|
if (sPokedexView->scrollSpeed < 12)
|
||
|
sPokedexView->scrollSpeed++;
|
||
|
return selectedMon;
|
||
|
}
|
||
|
|
||
|
static void UpdateSelectedMonSpriteId(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
{
|
||
|
u16 spriteId = sPokedexView->monSpriteIds[i];
|
||
|
|
||
|
if (gSprites[spriteId].x2 == 0 && gSprites[spriteId].y2 == 0 && spriteId != 0xFFFF)
|
||
|
sPokedexView->selectedMonSpriteId = spriteId;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool8 TryDoInfoScreenScroll(void)
|
||
|
{
|
||
|
u16 nextPokemon;
|
||
|
u16 selectedPokemon = sPokedexView->selectedPokemon;
|
||
|
|
||
|
if (JOY_NEW(DPAD_UP) && selectedPokemon)
|
||
|
{
|
||
|
nextPokemon = selectedPokemon;
|
||
|
while (nextPokemon != 0)
|
||
|
{
|
||
|
nextPokemon = GetNextPosition(1, nextPokemon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
|
||
|
if (sPokedexView->pokedexList[nextPokemon].seen)
|
||
|
{
|
||
|
selectedPokemon = nextPokemon;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sPokedexView->selectedPokemon == selectedPokemon)
|
||
|
return FALSE;
|
||
|
else
|
||
|
{
|
||
|
sPokedexView->selectedPokemon = selectedPokemon;
|
||
|
sPokedexView->pokeBallRotation -= 16;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
else if (JOY_NEW(DPAD_DOWN) && selectedPokemon < sPokedexView->pokemonListCount - 1)
|
||
|
{
|
||
|
nextPokemon = selectedPokemon;
|
||
|
while (nextPokemon < sPokedexView->pokemonListCount - 1)
|
||
|
{
|
||
|
nextPokemon = GetNextPosition(0, nextPokemon, 0, sPokedexView->pokemonListCount - 1);
|
||
|
|
||
|
if (sPokedexView->pokedexList[nextPokemon].seen)
|
||
|
{
|
||
|
selectedPokemon = nextPokemon;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sPokedexView->selectedPokemon == selectedPokemon)
|
||
|
return FALSE;
|
||
|
else
|
||
|
{
|
||
|
sPokedexView->selectedPokemon = selectedPokemon;
|
||
|
sPokedexView->pokeBallRotation += 16;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static u8 ClearMonSprites(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
{
|
||
|
if (sPokedexView->monSpriteIds[i] != 0xFFFF)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(sPokedexView->monSpriteIds[i]);
|
||
|
sPokedexView->monSpriteIds[i] = 0xFFFF;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static u16 GetPokemonSpriteToDisplay(u16 species)
|
||
|
{
|
||
|
if (species >= NATIONAL_DEX_COUNT || sPokedexView->pokedexList[species].dexNum == 0xFFFF)
|
||
|
return 0xFFFF;
|
||
|
else if (sPokedexView->pokedexList[species].seen)
|
||
|
return sPokedexView->pokedexList[species].dexNum;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static u32 CreatePokedexMonSprite(u16 num, s16 x, s16 y)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
for (i = 0; i < MAX_MONS_ON_SCREEN; i++)
|
||
|
{
|
||
|
if (sPokedexView->monSpriteIds[i] == 0xFFFF)
|
||
|
{
|
||
|
u8 spriteId = CreateMonSpriteFromNationalDexNumber(num, x, y, i);
|
||
|
|
||
|
gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
gSprites[spriteId].data[0] = 0;
|
||
|
gSprites[spriteId].data[1] = i;
|
||
|
gSprites[spriteId].data[2] = NationalPokedexNumToSpecies(num);
|
||
|
sPokedexView->monSpriteIds[i] = spriteId;
|
||
|
return spriteId;
|
||
|
}
|
||
|
}
|
||
|
return 0xFFFF;
|
||
|
}
|
||
|
|
||
|
#define sIsDownArrow data[1]
|
||
|
|
||
|
static void CreateInterfaceSprites(u8 page)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
u16 digitNum;
|
||
|
|
||
|
// Scroll arrows
|
||
|
spriteId = CreateSprite(&sScrollArrowSpriteTemplate, 184, 4, 0);
|
||
|
gSprites[spriteId].sIsDownArrow = FALSE;
|
||
|
spriteId = CreateSprite(&sScrollArrowSpriteTemplate, 184, DISPLAY_HEIGHT - 4, 0);
|
||
|
gSprites[spriteId].sIsDownArrow = TRUE;
|
||
|
gSprites[spriteId].vFlip = TRUE;
|
||
|
|
||
|
CreateSprite(&sScrollBarSpriteTemplate, 230, 20, 0);
|
||
|
// Start button
|
||
|
CreateSprite(&sInterfaceTextSpriteTemplate, 16, 120, 0);
|
||
|
// Menu text
|
||
|
spriteId = CreateSprite(&sInterfaceTextSpriteTemplate, 48, 120, 0);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 3);
|
||
|
// Select button
|
||
|
spriteId = CreateSprite(&sInterfaceTextSpriteTemplate, 16, DISPLAY_HEIGHT - 16, 0);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 2);
|
||
|
gSprites[spriteId].data[2] = 0x80;
|
||
|
// Search text
|
||
|
spriteId = CreateSprite(&sInterfaceTextSpriteTemplate, 48, DISPLAY_HEIGHT - 16, 0);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 1);
|
||
|
|
||
|
spriteId = CreateSprite(&sRotatingPokeBallSpriteTemplate, 0, DISPLAY_HEIGHT / 2, 2);
|
||
|
gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||
|
gSprites[spriteId].oam.matrixNum = 30;
|
||
|
gSprites[spriteId].data[0] = 30;
|
||
|
gSprites[spriteId].data[1] = 0;
|
||
|
|
||
|
spriteId = CreateSprite(&sRotatingPokeBallSpriteTemplate, 0, DISPLAY_HEIGHT / 2, 2);
|
||
|
gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||
|
gSprites[spriteId].oam.matrixNum = 31;
|
||
|
gSprites[spriteId].data[0] = 31;
|
||
|
gSprites[spriteId].data[1] = 128;
|
||
|
|
||
|
if (page == PAGE_MAIN)
|
||
|
{
|
||
|
bool32 drawNextDigit;
|
||
|
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
{
|
||
|
// Seen text
|
||
|
CreateSprite(&sSeenOwnTextSpriteTemplate, 32, 40, 1);
|
||
|
// Own text
|
||
|
spriteId = CreateSprite(&sSeenOwnTextSpriteTemplate, 32, 72, 1);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 1);
|
||
|
|
||
|
// Seen value - 100s
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 24, 48, 1);
|
||
|
digitNum = sPokedexView->seenCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Seen value - 10s
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 32, 48, 1);
|
||
|
digitNum = (sPokedexView->seenCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Seen value - 1s
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 40, 48, 1);
|
||
|
digitNum = (sPokedexView->seenCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
|
||
|
// Owned value - 100s
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 24, 80, 1);
|
||
|
digitNum = sPokedexView->ownCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Owned value - 10s
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 32, 80, 1);
|
||
|
digitNum = (sPokedexView->ownCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Owned value - 1s
|
||
|
spriteId = CreateSprite(&sHoennDexSeenOwnNumberSpriteTemplate, 40, 80, 1);
|
||
|
digitNum = (sPokedexView->ownCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u16 seenOwnedCount;
|
||
|
|
||
|
// Seen text
|
||
|
CreateSprite(&sSeenOwnTextSpriteTemplate, 32, 40, 1);
|
||
|
// Own text
|
||
|
spriteId = CreateSprite(&sSeenOwnTextSpriteTemplate, 32, 76, 1);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 1);
|
||
|
|
||
|
// Hoenn text (seen)
|
||
|
CreateSprite(&sHoennNationalTextSpriteTemplate, 17, 45, 1);
|
||
|
|
||
|
// National text (seen)
|
||
|
spriteId = CreateSprite(&sHoennNationalTextSpriteTemplate, 17, 55, 1);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 1);
|
||
|
|
||
|
// Hoenn text (own)
|
||
|
CreateSprite(&sHoennNationalTextSpriteTemplate, 17, 81, 1);
|
||
|
|
||
|
// National text (own)
|
||
|
spriteId = CreateSprite(&sHoennNationalTextSpriteTemplate, 17, 91, 1);
|
||
|
StartSpriteAnim(&gSprites[spriteId], 1);
|
||
|
|
||
|
// Hoenn seen value - 100s
|
||
|
seenOwnedCount = GetHoennPokedexCount(FLAG_GET_SEEN);
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 40, 45, 1);
|
||
|
digitNum = seenOwnedCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Hoenn seen value - 10s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 48, 45, 1);
|
||
|
digitNum = (seenOwnedCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Hoenn seen value - 1s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 56, 45, 1);
|
||
|
digitNum = (seenOwnedCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
|
||
|
// National seen value - 100s
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 40, 55, 1);
|
||
|
digitNum = sPokedexView->seenCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// National seen value - 10s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 48, 55, 1);
|
||
|
digitNum = (sPokedexView->seenCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// National seen value - 1s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 56, 55, 1);
|
||
|
digitNum = (sPokedexView->seenCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
|
||
|
seenOwnedCount = GetHoennPokedexCount(FLAG_GET_CAUGHT);
|
||
|
|
||
|
// Hoenn owned value - 100s
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 40, 81, 1);
|
||
|
digitNum = seenOwnedCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Hoenn owned value - 10s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 48, 81, 1);
|
||
|
digitNum = (seenOwnedCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// Hoenn owned value - 1s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 56, 81, 1);
|
||
|
digitNum = (seenOwnedCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
|
||
|
// National owned value - 100s
|
||
|
drawNextDigit = FALSE;
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 40, 91, 1);
|
||
|
digitNum = sPokedexView->ownCount / 100;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
if (digitNum != 0)
|
||
|
drawNextDigit = TRUE;
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// National owned value - 10s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 48, 91, 1);
|
||
|
digitNum = (sPokedexView->ownCount % 100) / 10;
|
||
|
if (digitNum != 0 || drawNextDigit)
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
else
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
// National owned value - 1s
|
||
|
spriteId = CreateSprite(&sNationalDexSeenOwnNumberSpriteTemplate, 56, 91, 1);
|
||
|
digitNum = (sPokedexView->ownCount % 100) % 10;
|
||
|
StartSpriteAnim(&gSprites[spriteId], digitNum);
|
||
|
}
|
||
|
spriteId = CreateSprite(&sDexListStartMenuCursorSpriteTemplate, 136, 96, 1);
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
}
|
||
|
else // PAGE_SEARCH_RESULTS
|
||
|
{
|
||
|
spriteId = CreateSprite(&sDexListStartMenuCursorSpriteTemplate, 136, 80, 1);
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_EndMoveMonForInfoScreen(struct Sprite *sprite)
|
||
|
{
|
||
|
// Once mon is done moving there's nothing left to do
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_SeenOwnInfo(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN)
|
||
|
DestroySprite(sprite);
|
||
|
}
|
||
|
|
||
|
void SpriteCB_MoveMonForInfoScreen(struct Sprite *sprite)
|
||
|
{
|
||
|
sprite->oam.priority = 0;
|
||
|
sprite->oam.affineMode = ST_OAM_AFFINE_OFF;
|
||
|
sprite->x2 = 0;
|
||
|
sprite->y2 = 0;
|
||
|
if (sprite->x != MON_PAGE_X || sprite->y != MON_PAGE_Y)
|
||
|
{
|
||
|
if (sprite->x > MON_PAGE_X)
|
||
|
sprite->x--;
|
||
|
if (sprite->x < MON_PAGE_X)
|
||
|
sprite->x++;
|
||
|
|
||
|
if (sprite->y > MON_PAGE_Y)
|
||
|
sprite->y--;
|
||
|
if (sprite->y < MON_PAGE_Y)
|
||
|
sprite->y++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprite->callback = SpriteCB_EndMoveMonForInfoScreen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_PokedexListMonSprite(struct Sprite *sprite)
|
||
|
{
|
||
|
u8 monId = sprite->data[1];
|
||
|
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(sPokedexView->monSpriteIds[monId]);
|
||
|
sPokedexView->monSpriteIds[monId] = 0xFFFF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u32 var;
|
||
|
sprite->y2 = gSineTable[(u8)sprite->data[5]] * 76 / 256;
|
||
|
var = SAFE_DIV(0x10000, gSineTable[sprite->data[5] + 64]);
|
||
|
if (var > 0xFFFF)
|
||
|
var = 0xFFFF;
|
||
|
SetOamMatrix(sprite->data[1] + 1, 0x100, 0, 0, var);
|
||
|
sprite->oam.matrixNum = monId + 1;
|
||
|
|
||
|
if (sprite->data[5] > -64 && sprite->data[5] < 64)
|
||
|
{
|
||
|
sprite->invisible = FALSE;
|
||
|
sprite->data[0] = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprite->invisible = TRUE;
|
||
|
}
|
||
|
|
||
|
if ((sprite->data[5] <= -64 || sprite->data[5] >= 64) && sprite->data[0] != 0)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(sPokedexView->monSpriteIds[monId]);
|
||
|
sPokedexView->monSpriteIds[monId] = 0xFFFF;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_Scrollbar(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
DestroySprite(sprite);
|
||
|
else
|
||
|
sprite->y2 = sPokedexView->selectedPokemon * 120 / (sPokedexView->pokemonListCount - 1);
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_ScrollArrow(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
{
|
||
|
DestroySprite(sprite);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u8 r0;
|
||
|
|
||
|
if (sprite->sIsDownArrow)
|
||
|
{
|
||
|
if (sPokedexView->selectedPokemon == sPokedexView->pokemonListCount - 1)
|
||
|
sprite->invisible = TRUE;
|
||
|
else
|
||
|
sprite->invisible = FALSE;
|
||
|
r0 = sprite->data[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (sPokedexView->selectedPokemon == 0)
|
||
|
sprite->invisible = TRUE;
|
||
|
else
|
||
|
sprite->invisible = FALSE;
|
||
|
r0 = sprite->data[2] - 128;
|
||
|
}
|
||
|
sprite->y2 = gSineTable[r0] / 64;
|
||
|
sprite->data[2] = sprite->data[2] + 8;
|
||
|
if (sPokedexView->menuIsOpen == FALSE && sPokedexView->menuY == 0 && sprite->invisible == FALSE)
|
||
|
sprite->invisible = FALSE;
|
||
|
else
|
||
|
sprite->invisible = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_DexListInterfaceText(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
DestroySprite(sprite);
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_RotatingPokeBall(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
{
|
||
|
DestroySprite(sprite);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u8 val;
|
||
|
s16 r3;
|
||
|
s16 r0;
|
||
|
|
||
|
val = sPokedexView->pokeBallRotation + sprite->data[1];
|
||
|
r3 = gSineTable[val];
|
||
|
r0 = gSineTable[val + 64];
|
||
|
SetOamMatrix(sprite->data[0], r0, r3, -r3, r0);
|
||
|
|
||
|
val = sPokedexView->pokeBallRotation + (sprite->data[1] + 64);
|
||
|
r3 = gSineTable[val];
|
||
|
r0 = gSineTable[val + 64];
|
||
|
sprite->x2 = r0 * 40 / 256;
|
||
|
sprite->y2 = r3 * 40 / 256;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_DexListStartMenuCursor(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sPokedexView->currentPage != PAGE_MAIN && sPokedexView->currentPage != PAGE_SEARCH_RESULTS)
|
||
|
{
|
||
|
DestroySprite(sprite);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u16 r1 = sPokedexView->currentPage == PAGE_MAIN ? 80 : 96;
|
||
|
|
||
|
if (sPokedexView->menuIsOpen && sPokedexView->menuY == r1)
|
||
|
{
|
||
|
sprite->invisible = FALSE;
|
||
|
sprite->y2 = sPokedexView->menuCursorPos * 16;
|
||
|
sprite->x2 = gSineTable[(u8)sprite->data[2]] / 64;
|
||
|
sprite->data[2] += 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprite->invisible = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void PrintInfoScreenText(const u8* str, u8 left, u8 top)
|
||
|
{
|
||
|
u8 color[3];
|
||
|
color[0] = TEXT_COLOR_TRANSPARENT;
|
||
|
color[1] = TEXT_DYNAMIC_COLOR_6;
|
||
|
color[2] = TEXT_COLOR_LIGHT_GRAY;
|
||
|
|
||
|
AddTextPrinterParameterized4(0, FONT_NORMAL, left, top, 0, 0, color, TEXT_SKIP_DRAW, str);
|
||
|
}
|
||
|
|
||
|
#define tScrolling data[0]
|
||
|
#define tMonSpriteDone data[1]
|
||
|
#define tBgLoaded data[2]
|
||
|
#define tSkipCry data[3]
|
||
|
#define tMonSpriteId data[4]
|
||
|
#define tTrainerSpriteId data[5]
|
||
|
|
||
|
static u8 LoadInfoScreen(struct PokedexListItem* item, u8 monSpriteId)
|
||
|
{
|
||
|
u8 taskId;
|
||
|
|
||
|
sPokedexListItem = item;
|
||
|
taskId = CreateTask(Task_LoadInfoScreen, 0);
|
||
|
gTasks[taskId].tScrolling = FALSE;
|
||
|
gTasks[taskId].tMonSpriteDone = TRUE; // Already has sprite from list view
|
||
|
gTasks[taskId].tBgLoaded = FALSE;
|
||
|
gTasks[taskId].tSkipCry = FALSE;
|
||
|
gTasks[taskId].tMonSpriteId = monSpriteId;
|
||
|
gTasks[taskId].tTrainerSpriteId = SPRITE_NONE;
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, sInfoScreen_BgTemplate, ARRAY_COUNT(sInfoScreen_BgTemplate));
|
||
|
SetBgTilemapBuffer(3, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(2, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(1, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(0, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
InitWindows(sInfoScreen_WindowTemplates);
|
||
|
DeactivateAllTextPrinters();
|
||
|
|
||
|
return taskId;
|
||
|
}
|
||
|
|
||
|
static bool8 IsInfoScreenScrolling(u8 taskId)
|
||
|
{
|
||
|
if (!gTasks[taskId].tScrolling && gTasks[taskId].func == Task_HandleInfoScreenInput)
|
||
|
return FALSE;
|
||
|
else
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static u8 StartInfoScreenScroll(struct PokedexListItem *item, u8 taskId)
|
||
|
{
|
||
|
sPokedexListItem = item;
|
||
|
gTasks[taskId].tScrolling = TRUE;
|
||
|
gTasks[taskId].tMonSpriteDone = FALSE;
|
||
|
gTasks[taskId].tBgLoaded = FALSE;
|
||
|
gTasks[taskId].tSkipCry = FALSE;
|
||
|
return taskId;
|
||
|
}
|
||
|
|
||
|
static void Task_LoadInfoScreen(u8 taskId)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
u16 r2;
|
||
|
|
||
|
sPokedexView->currentPage = PAGE_INFO;
|
||
|
gPokedexVBlankCB = gMain.vblankCallback;
|
||
|
SetVBlankCallback(NULL);
|
||
|
r2 = 0;
|
||
|
if (gTasks[taskId].tMonSpriteDone)
|
||
|
r2 += DISPCNT_OBJ_ON;
|
||
|
if (gTasks[taskId].tBgLoaded)
|
||
|
r2 |= DISPCNT_BG1_ON;
|
||
|
ResetOtherVideoRegisters(r2);
|
||
|
gMain.state = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, gPokedexMenu_Gfx, 0x2000, 0, 0);
|
||
|
CopyToBgTilemapBuffer(3, gPokedexInfoScreen_Tilemap, 0, 0);
|
||
|
FillWindowPixelBuffer(WIN_INFO, PIXEL_FILL(0));
|
||
|
PutWindowTilemap(WIN_INFO);
|
||
|
PutWindowTilemap(WIN_FOOTPRINT);
|
||
|
DrawFootprint(WIN_FOOTPRINT, sPokedexListItem->dexNum);
|
||
|
CopyWindowToVram(WIN_FOOTPRINT, COPYWIN_GFX);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
LoadScreenSelectBarMain(0xD);
|
||
|
HighlightScreenSelectBarItem(sPokedexView->selectedScreen, 0xD);
|
||
|
LoadPokedexBgPalette(sPokedexView->isSearchResults);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
PrintMonInfo(sPokedexListItem->dexNum, sPokedexView->dexMode == DEX_MODE_HOENN ? FALSE : TRUE, sPokedexListItem->owned, 0);
|
||
|
if (!sPokedexListItem->owned)
|
||
|
LoadPalette(gPlttBufferUnfaded + 1, 0x31, 0x1E);
|
||
|
CopyWindowToVram(WIN_INFO, COPYWIN_FULL);
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
if (!gTasks[taskId].tMonSpriteDone)
|
||
|
{
|
||
|
gTasks[taskId].tMonSpriteId = (u16)CreateMonSpriteFromNationalDexNumber(sPokedexListItem->dexNum, MON_PAGE_X, MON_PAGE_Y, 0);
|
||
|
gSprites[gTasks[taskId].tMonSpriteId].oam.priority = 0;
|
||
|
}
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
{
|
||
|
u32 preservedPalettes = 0;
|
||
|
|
||
|
if (gTasks[taskId].tBgLoaded)
|
||
|
preservedPalettes = 0x14; // each bit represents a palette index
|
||
|
if (gTasks[taskId].tMonSpriteDone)
|
||
|
preservedPalettes |= (1 << (gSprites[gTasks[taskId].tMonSpriteId].oam.paletteNum + 16));
|
||
|
BeginNormalPaletteFade(~preservedPalettes, 0, 16, 0, RGB_BLACK);
|
||
|
SetVBlankCallback(gPokedexVBlankCB);
|
||
|
gMain.state++;
|
||
|
}
|
||
|
break;
|
||
|
case 7:
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
HideBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 8:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
gMain.state++;
|
||
|
if (!gTasks[taskId].tSkipCry)
|
||
|
{
|
||
|
StopCryAndClearCrySongs();
|
||
|
PlayCry_NormalNoDucking(NationalPokedexNumToSpecies(sPokedexListItem->dexNum), 0, CRY_VOLUME_RS, CRY_PRIORITY_NORMAL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gMain.state++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 9:
|
||
|
if (!IsCryPlayingOrClearCrySongs())
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 10:
|
||
|
gTasks[taskId].tScrolling = FALSE;
|
||
|
gTasks[taskId].tMonSpriteDone = FALSE; // Reload next time screen comes up
|
||
|
gTasks[taskId].tBgLoaded = TRUE;
|
||
|
gTasks[taskId].tSkipCry = TRUE;
|
||
|
gTasks[taskId].func = Task_HandleInfoScreenInput;
|
||
|
gMain.state = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void FreeInfoScreenWindowAndBgBuffers(void)
|
||
|
{
|
||
|
void *tilemapBuffer;
|
||
|
|
||
|
FreeAllWindowBuffers();
|
||
|
tilemapBuffer = GetBgTilemapBuffer(0);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(1);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(2);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(3);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
}
|
||
|
|
||
|
static void Task_HandleInfoScreenInput(u8 taskId)
|
||
|
{
|
||
|
if (gTasks[taskId].tScrolling)
|
||
|
{
|
||
|
// Scroll up/down
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_LoadInfoScreenWaitForFade;
|
||
|
PlaySE(SE_DEX_SCROLL);
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ExitInfoScreen;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
switch (sPokedexView->selectedScreen)
|
||
|
{
|
||
|
case AREA_SCREEN:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 16, RGB_BLACK);
|
||
|
sPokedexView->screenSwitchState = 1;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromInfoScreen;
|
||
|
PlaySE(SE_PIN);
|
||
|
break;
|
||
|
case CRY_SCREEN:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
sPokedexView->screenSwitchState = 2;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromInfoScreen;
|
||
|
PlaySE(SE_PIN);
|
||
|
break;
|
||
|
case SIZE_SCREEN:
|
||
|
if (!sPokedexListItem->owned)
|
||
|
{
|
||
|
PlaySE(SE_FAILURE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
sPokedexView->screenSwitchState = 3;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromInfoScreen;
|
||
|
PlaySE(SE_PIN);
|
||
|
}
|
||
|
break;
|
||
|
case CANCEL_SCREEN:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ExitInfoScreen;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
break;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if ((JOY_NEW(DPAD_LEFT)
|
||
|
|| (JOY_NEW(L_BUTTON) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
|
||
|
&& sPokedexView->selectedScreen > 0)
|
||
|
{
|
||
|
sPokedexView->selectedScreen--;
|
||
|
HighlightScreenSelectBarItem(sPokedexView->selectedScreen, 0xD);
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
return;
|
||
|
}
|
||
|
if ((JOY_NEW(DPAD_RIGHT)
|
||
|
|| (JOY_NEW(R_BUTTON) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
|
||
|
&& sPokedexView->selectedScreen < CANCEL_SCREEN)
|
||
|
{
|
||
|
sPokedexView->selectedScreen++;
|
||
|
HighlightScreenSelectBarItem(sPokedexView->selectedScreen, 0xD);
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchScreensFromInfoScreen(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(gTasks[taskId].tMonSpriteId);
|
||
|
switch (sPokedexView->screenSwitchState)
|
||
|
{
|
||
|
case 1:
|
||
|
default:
|
||
|
gTasks[taskId].func = Task_LoadAreaScreen;
|
||
|
break;
|
||
|
case 2:
|
||
|
gTasks[taskId].func = Task_LoadCryScreen;
|
||
|
break;
|
||
|
case 3:
|
||
|
gTasks[taskId].func = Task_LoadSizeScreen;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_LoadInfoScreenWaitForFade(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(gTasks[taskId].tMonSpriteId);
|
||
|
gTasks[taskId].func = Task_LoadInfoScreen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ExitInfoScreen(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(gTasks[taskId].tMonSpriteId);
|
||
|
FreeInfoScreenWindowAndBgBuffers();
|
||
|
DestroyTask(taskId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_LoadAreaScreen(u8 taskId)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->currentPage = PAGE_AREA;
|
||
|
gPokedexVBlankCB = gMain.vblankCallback;
|
||
|
SetVBlankCallback(NULL);
|
||
|
ResetOtherVideoRegisters(DISPCNT_BG1_ON);
|
||
|
sPokedexView->selectedScreen = AREA_SCREEN;
|
||
|
gMain.state = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
LoadScreenSelectBarSubmenu(0xD);
|
||
|
HighlightSubmenuScreenSelectBarItem(0, 0xD);
|
||
|
LoadPokedexBgPalette(sPokedexView->isSearchResults);
|
||
|
SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
ShowPokedexAreaScreen(NationalPokedexNumToSpecies(sPokedexListItem->dexNum), &sPokedexView->screenSwitchState);
|
||
|
SetVBlankCallback(gPokedexVBlankCB);
|
||
|
sPokedexView->screenSwitchState = 0;
|
||
|
gMain.state = 0;
|
||
|
gTasks[taskId].func = Task_WaitForAreaScreenInput;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_WaitForAreaScreenInput(u8 taskId)
|
||
|
{
|
||
|
// See Task_HandlePokedexAreaScreenInput() in pokedex_area_screen.c
|
||
|
if (sPokedexView->screenSwitchState != 0)
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromAreaScreen;
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchScreensFromAreaScreen(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
switch (sPokedexView->screenSwitchState)
|
||
|
{
|
||
|
case 1:
|
||
|
default:
|
||
|
gTasks[taskId].func = Task_LoadInfoScreen;
|
||
|
break;
|
||
|
case 2:
|
||
|
gTasks[taskId].func = Task_LoadCryScreen;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_LoadCryScreen(u8 taskId)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
m4aMPlayStop(&gMPlayInfo_BGM);
|
||
|
sPokedexView->currentPage = PAGE_CRY;
|
||
|
gPokedexVBlankCB = gMain.vblankCallback;
|
||
|
SetVBlankCallback(NULL);
|
||
|
ResetOtherVideoRegisters(DISPCNT_BG1_ON);
|
||
|
sPokedexView->selectedScreen = CRY_SCREEN;
|
||
|
gMain.state = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, &gPokedexMenu_Gfx, 0x2000, 0, 0);
|
||
|
CopyToBgTilemapBuffer(3, &gPokedexCryScreen_Tilemap, 0, 0);
|
||
|
FillWindowPixelBuffer(WIN_INFO, PIXEL_FILL(0));
|
||
|
PutWindowTilemap(WIN_INFO);
|
||
|
PutWindowTilemap(WIN_VU_METER);
|
||
|
PutWindowTilemap(WIN_CRY_WAVE);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
LoadScreenSelectBarSubmenu(0xD);
|
||
|
HighlightSubmenuScreenSelectBarItem(1, 0xD);
|
||
|
LoadPokedexBgPalette(sPokedexView->isSearchResults);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
ResetPaletteFade();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
PrintInfoScreenText(gText_CryOf, 82, 33);
|
||
|
PrintCryScreenSpeciesName(0, sPokedexListItem->dexNum, 82, 49);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
gTasks[taskId].tMonSpriteId = CreateMonSpriteFromNationalDexNumber(sPokedexListItem->dexNum, MON_PAGE_X, MON_PAGE_Y, 0);
|
||
|
gSprites[gTasks[taskId].tMonSpriteId].oam.priority = 0;
|
||
|
gDexCryScreenState = 0;
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
{
|
||
|
struct CryScreenWindow waveformWindow;
|
||
|
|
||
|
waveformWindow.unk0 = 0x4020;
|
||
|
waveformWindow.unk2 = 31;
|
||
|
waveformWindow.paletteNo = 8;
|
||
|
waveformWindow.yPos = 30;
|
||
|
waveformWindow.xPos = 12;
|
||
|
if (LoadCryWaveformWindow(&waveformWindow, 2))
|
||
|
{
|
||
|
gMain.state++;
|
||
|
gDexCryScreenState = 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 7:
|
||
|
{
|
||
|
struct CryScreenWindow cryMeter;
|
||
|
|
||
|
cryMeter.paletteNo = 9;
|
||
|
cryMeter.xPos = 18;
|
||
|
cryMeter.yPos = 3;
|
||
|
if (LoadCryMeter(&cryMeter, 3))
|
||
|
gMain.state++;
|
||
|
CopyWindowToVram(WIN_VU_METER, COPYWIN_GFX);
|
||
|
CopyWindowToVram(WIN_INFO, COPYWIN_FULL);
|
||
|
CopyBgTilemapBufferToVram(0);
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
break;
|
||
|
case 8:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0x10, 0, RGB_BLACK);
|
||
|
SetVBlankCallback(gPokedexVBlankCB);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 9:
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
ShowBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 10:
|
||
|
sPokedexView->screenSwitchState = 0;
|
||
|
gMain.state = 0;
|
||
|
gTasks[taskId].func = Task_HandleCryScreenInput;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_HandleCryScreenInput(u8 taskId)
|
||
|
{
|
||
|
UpdateCryWaveformWindow(2);
|
||
|
|
||
|
if (IsCryPlaying())
|
||
|
LoadPlayArrowPalette(TRUE);
|
||
|
else
|
||
|
LoadPlayArrowPalette(FALSE);
|
||
|
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
LoadPlayArrowPalette(TRUE);
|
||
|
CryScreenPlayButton(NationalPokedexNumToSpecies(sPokedexListItem->dexNum));
|
||
|
return;
|
||
|
}
|
||
|
else if (!gPaletteFade.active)
|
||
|
{
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
m4aMPlayContinue(&gMPlayInfo_BGM);
|
||
|
sPokedexView->screenSwitchState = 1;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromCryScreen;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_LEFT)
|
||
|
|| (JOY_NEW(L_BUTTON) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
m4aMPlayContinue(&gMPlayInfo_BGM);
|
||
|
sPokedexView->screenSwitchState = 2;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromCryScreen;
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_RIGHT)
|
||
|
|| (JOY_NEW(R_BUTTON) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
|
||
|
{
|
||
|
if (!sPokedexListItem->owned)
|
||
|
{
|
||
|
PlaySE(SE_FAILURE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
m4aMPlayContinue(&gMPlayInfo_BGM);
|
||
|
sPokedexView->screenSwitchState = 3;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromCryScreen;
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchScreensFromCryScreen(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeCryScreen();
|
||
|
FreeAndDestroyMonPicSprite(gTasks[taskId].tMonSpriteId);
|
||
|
switch (sPokedexView->screenSwitchState)
|
||
|
{
|
||
|
default:
|
||
|
case 1:
|
||
|
gTasks[taskId].func = Task_LoadInfoScreen;
|
||
|
break;
|
||
|
case 2:
|
||
|
gTasks[taskId].func = Task_LoadAreaScreen;
|
||
|
break;
|
||
|
case 3:
|
||
|
gTasks[taskId].func = Task_LoadSizeScreen;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void LoadPlayArrowPalette(bool8 cryPlaying)
|
||
|
{
|
||
|
u16 color;
|
||
|
|
||
|
if (cryPlaying)
|
||
|
color = RGB(18, 28, 0);
|
||
|
else
|
||
|
color = RGB(15, 21, 0);
|
||
|
LoadPalette(&color, 0x5D, 2);
|
||
|
}
|
||
|
|
||
|
static void Task_LoadSizeScreen(u8 taskId)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
default:
|
||
|
case 0:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->currentPage = PAGE_SIZE;
|
||
|
gPokedexVBlankCB = gMain.vblankCallback;
|
||
|
SetVBlankCallback(NULL);
|
||
|
ResetOtherVideoRegisters(DISPCNT_BG1_ON);
|
||
|
sPokedexView->selectedScreen = SIZE_SCREEN;
|
||
|
gMain.state = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, gPokedexMenu_Gfx, 0x2000, 0, 0);
|
||
|
CopyToBgTilemapBuffer(3, gPokedexSizeScreen_Tilemap, 0, 0);
|
||
|
FillWindowPixelBuffer(WIN_INFO, PIXEL_FILL(0));
|
||
|
PutWindowTilemap(WIN_INFO);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
LoadScreenSelectBarSubmenu(0xD);
|
||
|
HighlightSubmenuScreenSelectBarItem(2, 0xD);
|
||
|
LoadPokedexBgPalette(sPokedexView->isSearchResults);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
{
|
||
|
u8 string[64];
|
||
|
|
||
|
StringCopy(string, gText_SizeComparedTo);
|
||
|
StringAppend(string, gSaveBlock2Ptr->playerName);
|
||
|
PrintInfoScreenText(string, GetStringCenterAlignXOffset(FONT_NORMAL, string, 0xF0), 0x79);
|
||
|
gMain.state++;
|
||
|
}
|
||
|
break;
|
||
|
case 4:
|
||
|
ResetPaletteFade();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
spriteId = CreateSizeScreenTrainerPic(PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender), 152, 56, 0);
|
||
|
gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||
|
gSprites[spriteId].oam.matrixNum = 1;
|
||
|
gSprites[spriteId].oam.priority = 0;
|
||
|
gSprites[spriteId].y2 = gPokedexEntries[sPokedexListItem->dexNum].trainerOffset;
|
||
|
SetOamMatrix(1, gPokedexEntries[sPokedexListItem->dexNum].trainerScale, 0, 0, gPokedexEntries[sPokedexListItem->dexNum].trainerScale);
|
||
|
LoadPalette(sSizeScreenSilhouette_Pal, (gSprites[spriteId].oam.paletteNum + 16) * 16, 0x20);
|
||
|
gTasks[taskId].tTrainerSpriteId = spriteId;
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
spriteId = CreateMonSpriteFromNationalDexNumber(sPokedexListItem->dexNum, 88, 56, 1);
|
||
|
gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||
|
gSprites[spriteId].oam.matrixNum = 2;
|
||
|
gSprites[spriteId].oam.priority = 0;
|
||
|
gSprites[spriteId].y2 = gPokedexEntries[sPokedexListItem->dexNum].pokemonOffset;
|
||
|
SetOamMatrix(2, gPokedexEntries[sPokedexListItem->dexNum].pokemonScale, 0, 0, gPokedexEntries[sPokedexListItem->dexNum].pokemonScale);
|
||
|
LoadPalette(sSizeScreenSilhouette_Pal, (gSprites[spriteId].oam.paletteNum + 16) * 16, 0x20);
|
||
|
gTasks[taskId].tMonSpriteId = spriteId;
|
||
|
CopyWindowToVram(WIN_INFO, COPYWIN_FULL);
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 7:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0x10, 0, RGB_BLACK);
|
||
|
SetVBlankCallback(gPokedexVBlankCB);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 8:
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
HideBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 9:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->screenSwitchState = 0;
|
||
|
gMain.state = 0;
|
||
|
gTasks[taskId].func = Task_HandleSizeScreenInput;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_HandleSizeScreenInput(u8 taskId)
|
||
|
{
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
sPokedexView->screenSwitchState = 1;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromSizeScreen;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
}
|
||
|
else if (JOY_NEW(DPAD_LEFT)
|
||
|
|| (JOY_NEW(L_BUTTON) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 0, 0x10, RGB_BLACK);
|
||
|
sPokedexView->screenSwitchState = 2;
|
||
|
gTasks[taskId].func = Task_SwitchScreensFromSizeScreen;
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchScreensFromSizeScreen(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeAndDestroyMonPicSprite(gTasks[taskId].tMonSpriteId);
|
||
|
FreeAndDestroyTrainerPicSprite(gTasks[taskId].tTrainerSpriteId);
|
||
|
switch (sPokedexView->screenSwitchState)
|
||
|
{
|
||
|
default:
|
||
|
case 1:
|
||
|
gTasks[taskId].func = Task_LoadInfoScreen;
|
||
|
break;
|
||
|
case 2:
|
||
|
gTasks[taskId].func = Task_LoadCryScreen;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef tScrolling
|
||
|
#undef tMonSpriteDone
|
||
|
#undef tBgLoaded
|
||
|
#undef tSkipCry
|
||
|
#undef tMonSpriteId
|
||
|
#undef tTrainerSpriteId
|
||
|
|
||
|
static void LoadScreenSelectBarMain(u16 unused)
|
||
|
{
|
||
|
CopyToBgTilemapBuffer(1, gPokedexScreenSelectBarMain_Tilemap, 0, 0);
|
||
|
}
|
||
|
|
||
|
static void LoadScreenSelectBarSubmenu(u16 unused)
|
||
|
{
|
||
|
CopyToBgTilemapBuffer(1, gPokedexScreenSelectBarSubmenu_Tilemap, 0, 0);
|
||
|
}
|
||
|
|
||
|
static void HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused)
|
||
|
{
|
||
|
u8 i;
|
||
|
u8 j;
|
||
|
u16* ptr = GetBgTilemapBuffer(1);
|
||
|
|
||
|
for (i = 0; i < SCREEN_COUNT; i++)
|
||
|
{
|
||
|
u8 row = (i * 7) + 1;
|
||
|
u16 newPalette;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
newPalette = 0x4000;
|
||
|
if (i == selectedScreen)
|
||
|
newPalette = 0x2000;
|
||
|
} while (0);
|
||
|
|
||
|
for (j = 0; j < 7; j++)
|
||
|
{
|
||
|
ptr[row + j] = (ptr[row + j] % 0x1000) | newPalette;
|
||
|
ptr[row + j + 0x20] = (ptr[row + j + 0x20] % 0x1000) | newPalette;
|
||
|
}
|
||
|
}
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
}
|
||
|
|
||
|
static void HighlightSubmenuScreenSelectBarItem(u8 a, u16 b)
|
||
|
{
|
||
|
u8 i;
|
||
|
u8 j;
|
||
|
u16* ptr = GetBgTilemapBuffer(1);
|
||
|
|
||
|
for (i = 0; i < 4; i++)
|
||
|
{
|
||
|
u8 row = i * 7 + 1;
|
||
|
u32 newPalette;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (i == a || i == 3)
|
||
|
newPalette = 0x2000;
|
||
|
else
|
||
|
newPalette = 0x4000;
|
||
|
} while (0);
|
||
|
|
||
|
for (j = 0; j < 7; j++)
|
||
|
{
|
||
|
ptr[row + j] = (ptr[row + j] % 0x1000) | newPalette;
|
||
|
ptr[row + j + 0x20] = (ptr[row + j + 0x20] % 0x1000) | newPalette;
|
||
|
}
|
||
|
}
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
}
|
||
|
|
||
|
#define tState data[0]
|
||
|
#define tDexNum data[1]
|
||
|
#define tPalTimer data[2]
|
||
|
#define tMonSpriteId data[3]
|
||
|
#define tOtIdLo data[12]
|
||
|
#define tOtIdHi data[13]
|
||
|
#define tPersonalityLo data[14]
|
||
|
#define tPersonalityHi data[15]
|
||
|
|
||
|
u8 DisplayCaughtMonDexPage(u16 dexNum, u32 otId, u32 personality)
|
||
|
{
|
||
|
u8 taskId = CreateTask(Task_DisplayCaughtMonDexPage, 0);
|
||
|
|
||
|
gTasks[taskId].tState = 0;
|
||
|
gTasks[taskId].tDexNum = dexNum;
|
||
|
gTasks[taskId].tOtIdLo = otId;
|
||
|
gTasks[taskId].tOtIdHi = otId >> 16;
|
||
|
gTasks[taskId].tPersonalityLo = personality;
|
||
|
gTasks[taskId].tPersonalityHi = personality >> 16;
|
||
|
return taskId;
|
||
|
}
|
||
|
|
||
|
static void Task_DisplayCaughtMonDexPage(u8 taskId)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
u16 dexNum = gTasks[taskId].tDexNum;
|
||
|
|
||
|
switch (gTasks[taskId].tState)
|
||
|
{
|
||
|
case 0:
|
||
|
default:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
gPokedexVBlankCB = gMain.vblankCallback;
|
||
|
SetVBlankCallback(NULL);
|
||
|
ResetOtherVideoRegisters(DISPCNT_BG0_ON);
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, sNewEntryInfoScreen_BgTemplate, ARRAY_COUNT(sNewEntryInfoScreen_BgTemplate));
|
||
|
SetBgTilemapBuffer(3, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(2, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
InitWindows(sNewEntryInfoScreen_WindowTemplates);
|
||
|
DeactivateAllTextPrinters();
|
||
|
gTasks[taskId].tState = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, gPokedexMenu_Gfx, 0x2000, 0, 0);
|
||
|
CopyToBgTilemapBuffer(3, gPokedexInfoScreen_Tilemap, 0, 0);
|
||
|
FillWindowPixelBuffer(WIN_INFO, PIXEL_FILL(0));
|
||
|
PutWindowTilemap(WIN_INFO);
|
||
|
PutWindowTilemap(WIN_FOOTPRINT);
|
||
|
DrawFootprint(WIN_FOOTPRINT, gTasks[taskId].tDexNum);
|
||
|
CopyWindowToVram(WIN_FOOTPRINT, COPYWIN_GFX);
|
||
|
ResetPaletteFade();
|
||
|
LoadPokedexBgPalette(FALSE);
|
||
|
gTasks[taskId].tState++;
|
||
|
break;
|
||
|
case 2:
|
||
|
gTasks[taskId].tState++;
|
||
|
break;
|
||
|
case 3:
|
||
|
PrintMonInfo(dexNum, IsNationalPokedexEnabled(), 1, 1);
|
||
|
CopyWindowToVram(WIN_INFO, COPYWIN_FULL);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gTasks[taskId].tState++;
|
||
|
break;
|
||
|
case 4:
|
||
|
spriteId = CreateMonSpriteFromNationalDexNumber(dexNum, MON_PAGE_X, MON_PAGE_Y, 0);
|
||
|
gSprites[spriteId].oam.priority = 0;
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK);
|
||
|
SetVBlankCallback(gPokedexVBlankCB);
|
||
|
gTasks[taskId].tMonSpriteId = spriteId;
|
||
|
gTasks[taskId].tState++;
|
||
|
break;
|
||
|
case 5:
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gTasks[taskId].tState++;
|
||
|
break;
|
||
|
case 6:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
PlayCry_Normal(NationalPokedexNumToSpecies(dexNum), 0);
|
||
|
gTasks[taskId].tPalTimer = 0;
|
||
|
gTasks[taskId].func = Task_HandleCaughtMonPageInput;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_HandleCaughtMonPageInput(u8 taskId)
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON | B_BUTTON))
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_BG, 0, 0, 16, RGB_BLACK);
|
||
|
gSprites[gTasks[taskId].tMonSpriteId].callback = SpriteCB_SlideCaughtMonToCenter;
|
||
|
gTasks[taskId].func = Task_ExitCaughtMonPage;
|
||
|
}
|
||
|
// Flicker caught screen color
|
||
|
else if (++gTasks[taskId].tPalTimer & 16)
|
||
|
{
|
||
|
LoadPalette(gPokedexBgHoenn_Pal + 1, 0x31, 14);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadPalette(gPokedexCaughtScreen_Pal + 1, 0x31, 14);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ExitCaughtMonPage(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
u16 species;
|
||
|
u32 otId;
|
||
|
u32 personality;
|
||
|
u8 paletteNum;
|
||
|
const u32 *lzPaletteData;
|
||
|
void *buffer;
|
||
|
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
FreeAllWindowBuffers();
|
||
|
buffer = GetBgTilemapBuffer(2);
|
||
|
if (buffer)
|
||
|
Free(buffer);
|
||
|
buffer = GetBgTilemapBuffer(3);
|
||
|
if (buffer)
|
||
|
Free(buffer);
|
||
|
|
||
|
species = NationalPokedexNumToSpecies(gTasks[taskId].tDexNum);
|
||
|
otId = ((u16)gTasks[taskId].tOtIdHi << 16) | (u16)gTasks[taskId].tOtIdLo;
|
||
|
personality = ((u16)gTasks[taskId].tPersonalityHi << 16) | (u16)gTasks[taskId].tPersonalityLo;
|
||
|
paletteNum = gSprites[gTasks[taskId].tMonSpriteId].oam.paletteNum;
|
||
|
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality);
|
||
|
LoadCompressedPalette(lzPaletteData, 0x100 | paletteNum * 16, 32);
|
||
|
DestroyTask(taskId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sprite->x < 0x78)
|
||
|
sprite->x += 2;
|
||
|
if (sprite->x > 0x78)
|
||
|
sprite->x -= 2;
|
||
|
|
||
|
if (sprite->y < 0x50)
|
||
|
sprite->y += 1;
|
||
|
if (sprite->y > 0x50)
|
||
|
sprite->y -= 1;
|
||
|
}
|
||
|
|
||
|
#undef tState
|
||
|
#undef tDexNum
|
||
|
#undef tPalTimer
|
||
|
#undef tMonSpriteId
|
||
|
#undef tOtIdLo
|
||
|
#undef tOtIdHi
|
||
|
#undef tPersonalityLo
|
||
|
#undef tPersonalityHi
|
||
|
|
||
|
// u32 value is re-used, but passed as a bool that's TRUE if national dex is enabled
|
||
|
static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
|
||
|
{
|
||
|
u8 str[16];
|
||
|
u8 str2[32];
|
||
|
u16 natNum;
|
||
|
const u8 *name;
|
||
|
const u8 *category;
|
||
|
const u8 *description;
|
||
|
|
||
|
if (newEntry)
|
||
|
PrintInfoScreenText(gText_PokedexRegistration, GetStringCenterAlignXOffset(FONT_NORMAL, gText_PokedexRegistration, 0xF0), 0);
|
||
|
if (value == 0)
|
||
|
value = NationalToHoennOrder(num);
|
||
|
else
|
||
|
value = num;
|
||
|
ConvertIntToDecimalStringN(StringCopy(str, gText_NumberClear01), value, STR_CONV_MODE_LEADING_ZEROS, 3);
|
||
|
PrintInfoScreenText(str, 0x60, 0x19);
|
||
|
natNum = NationalPokedexNumToSpecies(num);
|
||
|
if (natNum)
|
||
|
name = gSpeciesNames[natNum];
|
||
|
else
|
||
|
name = sText_TenDashes2;
|
||
|
PrintInfoScreenText(name, 0x84, 0x19);
|
||
|
if (owned)
|
||
|
{
|
||
|
CopyMonCategoryText(num, str2);
|
||
|
category = str2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
category = gText_5MarksPokemon;
|
||
|
}
|
||
|
PrintInfoScreenText(category, 0x64, 0x29);
|
||
|
PrintInfoScreenText(gText_HTHeight, 0x60, 0x39);
|
||
|
PrintInfoScreenText(gText_WTWeight, 0x60, 0x49);
|
||
|
if (owned)
|
||
|
{
|
||
|
PrintMonHeight(gPokedexEntries[num].height, 0x81, 0x39);
|
||
|
PrintMonWeight(gPokedexEntries[num].weight, 0x81, 0x49);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PrintInfoScreenText(gText_UnkHeight, 0x81, 0x39);
|
||
|
PrintInfoScreenText(gText_UnkWeight, 0x81, 0x49);
|
||
|
}
|
||
|
if (owned)
|
||
|
description = gPokedexEntries[num].description;
|
||
|
else
|
||
|
description = gExpandedPlaceholder_PokedexDescription;
|
||
|
PrintInfoScreenText(description, GetStringCenterAlignXOffset(FONT_NORMAL, description, 0xF0), 0x5F);
|
||
|
}
|
||
|
|
||
|
static void PrintMonHeight(u16 height, u8 left, u8 top)
|
||
|
{
|
||
|
u8 buffer[16];
|
||
|
u32 inches, feet;
|
||
|
u8 i = 0;
|
||
|
|
||
|
inches = (height * 10000) / 254;
|
||
|
if (inches % 10 >= 5)
|
||
|
inches += 10;
|
||
|
feet = inches / 120;
|
||
|
inches = (inches - (feet * 120)) / 10;
|
||
|
|
||
|
buffer[i++] = EXT_CTRL_CODE_BEGIN;
|
||
|
buffer[i++] = EXT_CTRL_CODE_CLEAR_TO;
|
||
|
if (feet / 10 == 0)
|
||
|
{
|
||
|
buffer[i++] = 18;
|
||
|
buffer[i++] = feet + CHAR_0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
buffer[i++] = 12;
|
||
|
buffer[i++] = feet / 10 + CHAR_0;
|
||
|
buffer[i++] = (feet % 10) + CHAR_0;
|
||
|
}
|
||
|
buffer[i++] = CHAR_SGL_QUOTE_RIGHT;
|
||
|
buffer[i++] = (inches / 10) + CHAR_0;
|
||
|
buffer[i++] = (inches % 10) + CHAR_0;
|
||
|
buffer[i++] = CHAR_DBL_QUOTE_RIGHT;
|
||
|
buffer[i++] = EOS;
|
||
|
PrintInfoScreenText(buffer, left, top);
|
||
|
}
|
||
|
|
||
|
static void PrintMonWeight(u16 weight, u8 left, u8 top)
|
||
|
{
|
||
|
u8 buffer[16];
|
||
|
bool8 output;
|
||
|
u8 i;
|
||
|
u32 lbs = (weight * 100000) / 4536;
|
||
|
|
||
|
if (lbs % 10u >= 5)
|
||
|
lbs += 10;
|
||
|
i = 0;
|
||
|
output = FALSE;
|
||
|
|
||
|
if ((buffer[i] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
|
||
|
{
|
||
|
buffer[i++] = CHAR_SPACER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
output = TRUE;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
lbs %= 100000;
|
||
|
if ((buffer[i] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
|
||
|
{
|
||
|
buffer[i++] = CHAR_SPACER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
output = TRUE;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
lbs %= 10000;
|
||
|
if ((buffer[i] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
|
||
|
{
|
||
|
buffer[i++] = CHAR_SPACER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
output = TRUE;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
lbs %= 1000;
|
||
|
buffer[i++] = (lbs / 100) + CHAR_0;
|
||
|
lbs %= 100;
|
||
|
buffer[i++] = CHAR_PERIOD;
|
||
|
buffer[i++] = (lbs / 10) + CHAR_0;
|
||
|
buffer[i++] = CHAR_SPACE;
|
||
|
buffer[i++] = CHAR_l;
|
||
|
buffer[i++] = CHAR_b;
|
||
|
buffer[i++] = CHAR_s;
|
||
|
buffer[i++] = CHAR_PERIOD;
|
||
|
buffer[i++] = EOS;
|
||
|
PrintInfoScreenText(buffer, left, top);
|
||
|
}
|
||
|
|
||
|
const u8 *GetPokedexCategoryName(u16 dexNum) // unused
|
||
|
{
|
||
|
return gPokedexEntries[dexNum].categoryName;
|
||
|
}
|
||
|
|
||
|
u16 GetPokedexHeightWeight(u16 dexNum, u8 data)
|
||
|
{
|
||
|
switch (data)
|
||
|
{
|
||
|
case 0: // height
|
||
|
return gPokedexEntries[dexNum].height;
|
||
|
case 1: // weight
|
||
|
return gPokedexEntries[dexNum].weight;
|
||
|
default:
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s8 GetSetPokedexFlag(u16 nationalDexNo, u8 caseID)
|
||
|
{
|
||
|
u8 index;
|
||
|
u8 bit;
|
||
|
u8 mask;
|
||
|
s8 retVal;
|
||
|
|
||
|
nationalDexNo--;
|
||
|
index = nationalDexNo / 8;
|
||
|
bit = nationalDexNo % 8;
|
||
|
mask = 1 << bit;
|
||
|
retVal = 0;
|
||
|
switch (caseID)
|
||
|
{
|
||
|
case FLAG_GET_SEEN:
|
||
|
if (gSaveBlock2Ptr->pokedex.seen[index] & mask)
|
||
|
{
|
||
|
if ((gSaveBlock2Ptr->pokedex.seen[index] & mask) == (gSaveBlock1Ptr->seen1[index] & mask)
|
||
|
&& (gSaveBlock2Ptr->pokedex.seen[index] & mask) == (gSaveBlock1Ptr->seen2[index] & mask))
|
||
|
retVal = 1;
|
||
|
else
|
||
|
{
|
||
|
gSaveBlock2Ptr->pokedex.seen[index] &= ~mask;
|
||
|
gSaveBlock1Ptr->seen1[index] &= ~mask;
|
||
|
gSaveBlock1Ptr->seen2[index] &= ~mask;
|
||
|
retVal = 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case FLAG_GET_CAUGHT:
|
||
|
if (gSaveBlock2Ptr->pokedex.owned[index] & mask)
|
||
|
{
|
||
|
if ((gSaveBlock2Ptr->pokedex.owned[index] & mask) == (gSaveBlock2Ptr->pokedex.seen[index] & mask)
|
||
|
&& (gSaveBlock2Ptr->pokedex.owned[index] & mask) == (gSaveBlock1Ptr->seen1[index] & mask)
|
||
|
&& (gSaveBlock2Ptr->pokedex.owned[index] & mask) == (gSaveBlock1Ptr->seen2[index] & mask))
|
||
|
retVal = 1;
|
||
|
else
|
||
|
{
|
||
|
gSaveBlock2Ptr->pokedex.owned[index] &= ~mask;
|
||
|
gSaveBlock2Ptr->pokedex.seen[index] &= ~mask;
|
||
|
gSaveBlock1Ptr->seen1[index] &= ~mask;
|
||
|
gSaveBlock1Ptr->seen2[index] &= ~mask;
|
||
|
retVal = 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case FLAG_SET_SEEN:
|
||
|
gSaveBlock2Ptr->pokedex.seen[index] |= mask;
|
||
|
gSaveBlock1Ptr->seen1[index] |= mask;
|
||
|
gSaveBlock1Ptr->seen2[index] |= mask;
|
||
|
break;
|
||
|
case FLAG_SET_CAUGHT:
|
||
|
gSaveBlock2Ptr->pokedex.owned[index] |= mask;
|
||
|
break;
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
u16 GetNationalPokedexCount(u8 caseID)
|
||
|
{
|
||
|
u16 count = 0;
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
switch (caseID)
|
||
|
{
|
||
|
case FLAG_GET_SEEN:
|
||
|
if (GetSetPokedexFlag(i + 1, FLAG_GET_SEEN))
|
||
|
count++;
|
||
|
break;
|
||
|
case FLAG_GET_CAUGHT:
|
||
|
if (GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
count++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
u16 GetHoennPokedexCount(u8 caseID)
|
||
|
{
|
||
|
u16 count = 0;
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < HOENN_DEX_COUNT; i++)
|
||
|
{
|
||
|
switch (caseID)
|
||
|
{
|
||
|
case FLAG_GET_SEEN:
|
||
|
if (GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_SEEN))
|
||
|
count++;
|
||
|
break;
|
||
|
case FLAG_GET_CAUGHT:
|
||
|
if (GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_CAUGHT))
|
||
|
count++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
u16 GetKantoPokedexCount(u8 caseID)
|
||
|
{
|
||
|
u16 count = 0;
|
||
|
u16 i;
|
||
|
|
||
|
for (i = 0; i < KANTO_DEX_COUNT; i++)
|
||
|
{
|
||
|
switch (caseID)
|
||
|
{
|
||
|
case FLAG_GET_SEEN:
|
||
|
if (GetSetPokedexFlag(i + 1, FLAG_GET_SEEN))
|
||
|
count++;
|
||
|
break;
|
||
|
case FLAG_GET_CAUGHT:
|
||
|
if (GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
count++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
bool16 HasAllHoennMons(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
// -2 excludes Jirachi and Deoxys
|
||
|
for (i = 0; i < HOENN_DEX_COUNT - 2; i++)
|
||
|
{
|
||
|
if (!GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_CAUGHT))
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
bool8 HasAllKantoMons(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
// -1 excludes Mew
|
||
|
for (i = 0; i < KANTO_DEX_COUNT - 1; i++)
|
||
|
{
|
||
|
if (!GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
bool16 HasAllMons(void)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
// -1 excludes Mew
|
||
|
for (i = 0; i < KANTO_DEX_COUNT - 1; i++)
|
||
|
{
|
||
|
if (!GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// -3 excludes Lugia, Ho-Oh, and Celebi
|
||
|
for (i = KANTO_DEX_COUNT; i < JOHTO_DEX_COUNT - 3; i++)
|
||
|
{
|
||
|
if (!GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// -2 excludes Jirachi and Deoxys
|
||
|
for (i = JOHTO_DEX_COUNT; i < NATIONAL_DEX_COUNT - 2; i++)
|
||
|
{
|
||
|
if (!GetSetPokedexFlag(i + 1, FLAG_GET_CAUGHT))
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void ResetOtherVideoRegisters(u16 a)
|
||
|
{
|
||
|
if (!(a & DISPCNT_BG0_ON))
|
||
|
{
|
||
|
ClearGpuRegBits(0, DISPCNT_BG0_ON);
|
||
|
SetGpuReg(REG_OFFSET_BG0CNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG0HOFS, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG0VOFS, 0);
|
||
|
}
|
||
|
if (!(a & DISPCNT_BG1_ON))
|
||
|
{
|
||
|
ClearGpuRegBits(0, DISPCNT_BG1_ON);
|
||
|
SetGpuReg(REG_OFFSET_BG1CNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG1HOFS, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG1VOFS, 0);
|
||
|
}
|
||
|
if (!(a & DISPCNT_BG2_ON))
|
||
|
{
|
||
|
ClearGpuRegBits(0, DISPCNT_BG2_ON);
|
||
|
SetGpuReg(REG_OFFSET_BG2CNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG2HOFS, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, 0);
|
||
|
}
|
||
|
if (!(a & DISPCNT_BG3_ON))
|
||
|
{
|
||
|
ClearGpuRegBits(0, DISPCNT_BG3_ON);
|
||
|
SetGpuReg(REG_OFFSET_BG3CNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG3HOFS, 0);
|
||
|
SetGpuReg(REG_OFFSET_BG3VOFS, 0);
|
||
|
}
|
||
|
if (!(a & DISPCNT_OBJ_ON))
|
||
|
{
|
||
|
ClearGpuRegBits(0, DISPCNT_OBJ_ON);
|
||
|
ResetSpriteData();
|
||
|
FreeAllSpritePalettes();
|
||
|
gReservedSpritePaletteCount = 8;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void PrintInfoSubMenuText(u8 windowId, const u8 *str, u8 left, u8 top)
|
||
|
{
|
||
|
u8 color[3];
|
||
|
color[0] = TEXT_COLOR_TRANSPARENT;
|
||
|
color[1] = TEXT_DYNAMIC_COLOR_6;
|
||
|
color[2] = TEXT_COLOR_LIGHT_GRAY;
|
||
|
|
||
|
AddTextPrinterParameterized4(windowId, FONT_NORMAL, left, top, 0, 0, color, TEXT_SKIP_DRAW, str);
|
||
|
}
|
||
|
|
||
|
static void UnusedPrintNum(u8 windowId, u16 num, u8 left, u8 top)
|
||
|
{
|
||
|
u8 str[4];
|
||
|
|
||
|
str[0] = CHAR_0 + num / 100;
|
||
|
str[1] = CHAR_0 + (num % 100) / 10;
|
||
|
str[2] = CHAR_0 + (num % 100) % 10;
|
||
|
str[3] = EOS;
|
||
|
PrintInfoSubMenuText(windowId, str, left, top);
|
||
|
}
|
||
|
|
||
|
static u8 PrintCryScreenSpeciesName(u8 windowId, u16 num, u8 left, u8 top)
|
||
|
{
|
||
|
u8 str[POKEMON_NAME_LENGTH + 1];
|
||
|
u8 i;
|
||
|
|
||
|
for (i = 0; i < ARRAY_COUNT(str); i++)
|
||
|
str[i] = EOS;
|
||
|
num = NationalPokedexNumToSpecies(num);
|
||
|
switch (num)
|
||
|
{
|
||
|
default:
|
||
|
for (i = 0; gSpeciesNames[num][i] != EOS && i < POKEMON_NAME_LENGTH; i++)
|
||
|
str[i] = gSpeciesNames[num][i];
|
||
|
break;
|
||
|
case 0:
|
||
|
for (i = 0; i < 5; i++)
|
||
|
str[i] = CHAR_HYPHEN;
|
||
|
break;
|
||
|
}
|
||
|
PrintInfoSubMenuText(windowId, str, left, top);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static void UnusedPrintMonName(u8 windowId, const u8* name, u8 left, u8 top)
|
||
|
{
|
||
|
u8 str[POKEMON_NAME_LENGTH + 1];
|
||
|
u8 i;
|
||
|
u8 nameLength;
|
||
|
|
||
|
for (i = 0; i < ARRAY_COUNT(str); i++)
|
||
|
str[i] = CHAR_SPACE;
|
||
|
for (nameLength = 0; name[nameLength] != CHAR_SPACE && nameLength < ARRAY_COUNT(str); nameLength++)
|
||
|
;
|
||
|
for (i = 0; i < nameLength; i++)
|
||
|
str[ARRAY_COUNT(str) - nameLength + i] = name[i];
|
||
|
#ifdef UBFIX
|
||
|
str[ARRAY_COUNT(str) - 1] = EOS;
|
||
|
#else
|
||
|
str[ARRAY_COUNT(str)] = EOS;
|
||
|
#endif
|
||
|
PrintInfoSubMenuText(windowId, str, left, top);
|
||
|
}
|
||
|
|
||
|
static void UnusedPrintDecimalNum(u8 windowId, u16 b, u8 left, u8 top)
|
||
|
{
|
||
|
u8 str[6];
|
||
|
bool8 outputted = FALSE;
|
||
|
u8 result;
|
||
|
|
||
|
result = b / 1000;
|
||
|
if (result == 0)
|
||
|
{
|
||
|
str[0] = CHAR_SPACER;
|
||
|
outputted = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
str[0] = CHAR_0 + result;
|
||
|
outputted = TRUE;
|
||
|
}
|
||
|
|
||
|
result = (b % 1000) / 100;
|
||
|
if (result == 0 && !outputted)
|
||
|
{
|
||
|
str[1] = CHAR_SPACER;
|
||
|
outputted = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
str[1] = CHAR_0 + result;
|
||
|
outputted = TRUE;
|
||
|
}
|
||
|
|
||
|
str[2] = CHAR_0 + ((b % 1000) % 100) / 10;
|
||
|
str[3] = CHAR_PERIOD;
|
||
|
str[4] = CHAR_0 + ((b % 1000) % 100) % 10;
|
||
|
str[5] = EOS;
|
||
|
PrintInfoSubMenuText(windowId, str, left, top);
|
||
|
}
|
||
|
|
||
|
static void DrawFootprint(u8 windowId, u16 dexNum)
|
||
|
{
|
||
|
u8 footprint[32 * 4];
|
||
|
const u8 * footprintGfx = gMonFootprintTable[NationalPokedexNumToSpecies(dexNum)];
|
||
|
u16 tileIdx = 0;
|
||
|
u16 i, j;
|
||
|
|
||
|
for (i = 0; i < 32; i++)
|
||
|
{
|
||
|
u8 tile = footprintGfx[i];
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
u8 value = ((tile >> (2 * j)) & 1 ? 2 : 0);
|
||
|
if (tile & (2 << (2 * j)))
|
||
|
value |= 0x20;
|
||
|
footprint[tileIdx] = value;
|
||
|
tileIdx++;
|
||
|
}
|
||
|
}
|
||
|
CopyToWindowPixelBuffer(windowId, footprint, sizeof(footprint), 0);
|
||
|
}
|
||
|
|
||
|
// Unused Ruby/Sapphire function.
|
||
|
static void RS_DrawFootprint(u16 offset, u16 tileNum)
|
||
|
{
|
||
|
*(u16 *)(VRAM + offset * 0x800 + 0x232) = 0xF000 + tileNum + 0;
|
||
|
*(u16 *)(VRAM + offset * 0x800 + 0x234) = 0xF000 + tileNum + 1;
|
||
|
*(u16 *)(VRAM + offset * 0x800 + 0x272) = 0xF000 + tileNum + 2;
|
||
|
*(u16 *)(VRAM + offset * 0x800 + 0x274) = 0xF000 + tileNum + 3;
|
||
|
}
|
||
|
|
||
|
static u16 GetNextPosition(u8 direction, u16 position, u16 min, u16 max)
|
||
|
{
|
||
|
switch (direction)
|
||
|
{
|
||
|
case 1: // Up/Left
|
||
|
if (position > min)
|
||
|
position--;
|
||
|
break;
|
||
|
case 0: // Down/Right
|
||
|
if (position < max)
|
||
|
position++;
|
||
|
break;
|
||
|
case 3: // Up/Left with loop (unused)
|
||
|
if (position > min)
|
||
|
position--;
|
||
|
else
|
||
|
position = max;
|
||
|
break;
|
||
|
case 2: // Down/Right with loop (unused)
|
||
|
if (position < max)
|
||
|
position++;
|
||
|
else
|
||
|
position = min;
|
||
|
break;
|
||
|
}
|
||
|
return position;
|
||
|
}
|
||
|
|
||
|
// Unown and Spinda use the personality of the first seen individual of that species
|
||
|
// All others use personality 0
|
||
|
static u32 GetPokedexMonPersonality(u16 species)
|
||
|
{
|
||
|
if (species == SPECIES_UNOWN || species == SPECIES_SPINDA)
|
||
|
{
|
||
|
if (species == SPECIES_UNOWN)
|
||
|
return gSaveBlock2Ptr->pokedex.unownPersonality;
|
||
|
else
|
||
|
return gSaveBlock2Ptr->pokedex.spindaPersonality;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
u16 CreateMonSpriteFromNationalDexNumber(u16 nationalNum, s16 x, s16 y, u16 paletteSlot)
|
||
|
{
|
||
|
nationalNum = NationalPokedexNumToSpecies(nationalNum);
|
||
|
return CreateMonPicSprite_HandleDeoxys(nationalNum, SHINY_ODDS, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE);
|
||
|
}
|
||
|
|
||
|
static u16 CreateSizeScreenTrainerPic(u16 species, s16 x, s16 y, s8 paletteSlot)
|
||
|
{
|
||
|
return CreateTrainerPicSprite(species, TRUE, x, y, paletteSlot, TAG_NONE);
|
||
|
}
|
||
|
|
||
|
static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, u8 bodyColor, u8 type1, u8 type2)
|
||
|
{
|
||
|
u16 species;
|
||
|
u16 i;
|
||
|
u16 resultsCount;
|
||
|
u8 types[2];
|
||
|
|
||
|
CreatePokedexList(dexMode, order);
|
||
|
|
||
|
for (i = 0, resultsCount = 0; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
if (sPokedexView->pokedexList[i].seen)
|
||
|
{
|
||
|
sPokedexView->pokedexList[resultsCount] = sPokedexView->pokedexList[i];
|
||
|
resultsCount++;
|
||
|
}
|
||
|
}
|
||
|
sPokedexView->pokemonListCount = resultsCount;
|
||
|
|
||
|
// Search by name
|
||
|
if (abcGroup != 0xFF)
|
||
|
{
|
||
|
for (i = 0, resultsCount = 0; i < sPokedexView->pokemonListCount; i++)
|
||
|
{
|
||
|
u8 firstLetter;
|
||
|
|
||
|
species = NationalPokedexNumToSpecies(sPokedexView->pokedexList[i].dexNum);
|
||
|
firstLetter = gSpeciesNames[species][0];
|
||
|
if (LETTER_IN_RANGE_UPPER(firstLetter, abcGroup) || LETTER_IN_RANGE_LOWER(firstLetter, abcGroup))
|
||
|
{
|
||
|
sPokedexView->pokedexList[resultsCount] = sPokedexView->pokedexList[i];
|
||
|
resultsCount++;
|
||
|
}
|
||
|
}
|
||
|
sPokedexView->pokemonListCount = resultsCount;
|
||
|
}
|
||
|
|
||
|
// Search by body color
|
||
|
if (bodyColor != 0xFF)
|
||
|
{
|
||
|
for (i = 0, resultsCount = 0; i < sPokedexView->pokemonListCount; i++)
|
||
|
{
|
||
|
species = NationalPokedexNumToSpecies(sPokedexView->pokedexList[i].dexNum);
|
||
|
|
||
|
if (bodyColor == gBaseStats[species].bodyColor)
|
||
|
{
|
||
|
sPokedexView->pokedexList[resultsCount] = sPokedexView->pokedexList[i];
|
||
|
resultsCount++;
|
||
|
}
|
||
|
}
|
||
|
sPokedexView->pokemonListCount = resultsCount;
|
||
|
}
|
||
|
|
||
|
// Search by type
|
||
|
if (type1 != TYPE_NONE || type2 != TYPE_NONE)
|
||
|
{
|
||
|
if (type1 == TYPE_NONE)
|
||
|
{
|
||
|
type1 = type2;
|
||
|
type2 = TYPE_NONE;
|
||
|
}
|
||
|
|
||
|
if (type2 == TYPE_NONE)
|
||
|
{
|
||
|
for (i = 0, resultsCount = 0; i < sPokedexView->pokemonListCount; i++)
|
||
|
{
|
||
|
if (sPokedexView->pokedexList[i].owned)
|
||
|
{
|
||
|
species = NationalPokedexNumToSpecies(sPokedexView->pokedexList[i].dexNum);
|
||
|
|
||
|
types[0] = gBaseStats[species].type1;
|
||
|
types[1] = gBaseStats[species].type2;
|
||
|
if (types[0] == type1 || types[1] == type1)
|
||
|
{
|
||
|
sPokedexView->pokedexList[resultsCount] = sPokedexView->pokedexList[i];
|
||
|
resultsCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0, resultsCount = 0; i < sPokedexView->pokemonListCount; i++)
|
||
|
{
|
||
|
if (sPokedexView->pokedexList[i].owned)
|
||
|
{
|
||
|
species = NationalPokedexNumToSpecies(sPokedexView->pokedexList[i].dexNum);
|
||
|
|
||
|
types[0] = gBaseStats[species].type1;
|
||
|
types[1] = gBaseStats[species].type2;
|
||
|
if ((types[0] == type1 && types[1] == type2) || (types[0] == type2 && types[1] == type1))
|
||
|
{
|
||
|
sPokedexView->pokedexList[resultsCount] = sPokedexView->pokedexList[i];
|
||
|
resultsCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
sPokedexView->pokemonListCount = resultsCount;
|
||
|
}
|
||
|
|
||
|
if (sPokedexView->pokemonListCount != 0)
|
||
|
{
|
||
|
for (i = sPokedexView->pokemonListCount; i < NATIONAL_DEX_COUNT; i++)
|
||
|
{
|
||
|
sPokedexView->pokedexList[i].dexNum = 0xFFFF;
|
||
|
sPokedexView->pokedexList[i].seen = FALSE;
|
||
|
sPokedexView->pokedexList[i].owned = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return resultsCount;
|
||
|
}
|
||
|
|
||
|
static u8 LoadSearchMenu(void)
|
||
|
{
|
||
|
return CreateTask(Task_LoadSearchMenu, 0);
|
||
|
}
|
||
|
|
||
|
static void PrintSearchText(const u8 *str, u32 x, u32 y)
|
||
|
{
|
||
|
u8 color[3];
|
||
|
|
||
|
color[0] = TEXT_COLOR_TRANSPARENT;
|
||
|
color[1] = TEXT_DYNAMIC_COLOR_6;
|
||
|
color[2] = TEXT_COLOR_DARK_GRAY;
|
||
|
AddTextPrinterParameterized4(0, FONT_NORMAL, x, y, 0, 0, color, TEXT_SKIP_DRAW, str);
|
||
|
}
|
||
|
|
||
|
static void ClearSearchMenuRect(u32 x, u32 y, u32 width, u32 height)
|
||
|
{
|
||
|
FillWindowPixelRect(0, PIXEL_FILL(0), x, y, width, height);
|
||
|
}
|
||
|
|
||
|
// Search task data
|
||
|
#define tTopBarItem data[0]
|
||
|
#define tMenuItem data[1]
|
||
|
#define tCursorPos_Mode data[2]
|
||
|
#define tScrollOffset_Mode data[3]
|
||
|
#define tCursorPos_Order data[4]
|
||
|
#define tScrollOffset_Order data[5]
|
||
|
#define tCursorPos_Name data[6]
|
||
|
#define tScrollOffset_Name data[7]
|
||
|
#define tCursorPos_Color data[8]
|
||
|
#define tScrollOffset_Color data[9]
|
||
|
#define tCursorPos_TypeLeft data[10]
|
||
|
#define tScrollOffset_TypeLeft data[11]
|
||
|
#define tCursorPos_TypeRight data[12]
|
||
|
#define tScrollOffset_TypeRight data[13]
|
||
|
#define tCursorPos data[14]
|
||
|
#define tScrollOffset data[15]
|
||
|
|
||
|
static void Task_LoadSearchMenu(u8 taskId)
|
||
|
{
|
||
|
u16 i;
|
||
|
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
default:
|
||
|
case 0:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
sPokedexView->currentPage = PAGE_SEARCH;
|
||
|
ResetOtherVideoRegisters(0);
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, sSearchMenu_BgTemplate, ARRAY_COUNT(sSearchMenu_BgTemplate));
|
||
|
SetBgTilemapBuffer(3, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(2, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(1, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
SetBgTilemapBuffer(0, AllocZeroed(BG_SCREEN_SIZE));
|
||
|
InitWindows(sSearchMenu_WindowTemplate);
|
||
|
DeactivateAllTextPrinters();
|
||
|
PutWindowTilemap(0);
|
||
|
DecompressAndLoadBgGfxUsingHeap(3, gPokedexSearchMenu_Gfx, 0x2000, 0, 0);
|
||
|
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
CopyToBgTilemapBuffer(3, gPokedexSearchMenuHoenn_Tilemap, 0, 0);
|
||
|
else
|
||
|
CopyToBgTilemapBuffer(3, gPokedexSearchMenuNational_Tilemap, 0, 0);
|
||
|
LoadPalette(gPokedexSearchMenu_Pal + 1, 1, 0x7E);
|
||
|
gMain.state = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
LoadCompressedSpriteSheet(sInterfaceSpriteSheet);
|
||
|
LoadSpritePalettes(sInterfaceSpritePalette);
|
||
|
CreateSearchParameterScrollArrows(taskId);
|
||
|
for (i = 0; i < NUM_TASK_DATA; i++)
|
||
|
gTasks[taskId].data[i] = 0;
|
||
|
SetDefaultSearchModeAndOrder(taskId);
|
||
|
HighlightSelectedSearchTopBarItem(SEARCH_TOPBAR_SEARCH);
|
||
|
PrintSelectedSearchParameters(taskId);
|
||
|
CopyWindowToVram(0, COPYWIN_FULL);
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||
|
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
HideBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenuTopBar;
|
||
|
gMain.state = 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void FreeSearchWindowAndBgBuffers(void)
|
||
|
{
|
||
|
void* tilemapBuffer;
|
||
|
|
||
|
FreeAllWindowBuffers();
|
||
|
tilemapBuffer = GetBgTilemapBuffer(0);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(1);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(2);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
tilemapBuffer = GetBgTilemapBuffer(3);
|
||
|
if (tilemapBuffer)
|
||
|
Free(tilemapBuffer);
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchToSearchMenuTopBar(u8 taskId)
|
||
|
{
|
||
|
HighlightSelectedSearchTopBarItem(gTasks[taskId].tTopBarItem);
|
||
|
PrintSelectedSearchParameters(taskId);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gTasks[taskId].func = Task_HandleSearchTopBarInput;
|
||
|
}
|
||
|
|
||
|
static void Task_HandleSearchTopBarInput(u8 taskId)
|
||
|
{
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
gTasks[taskId].func = Task_ExitSearch;
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
switch (gTasks[taskId].tTopBarItem)
|
||
|
{
|
||
|
case SEARCH_TOPBAR_SEARCH:
|
||
|
PlaySE(SE_PIN);
|
||
|
gTasks[taskId].tMenuItem = SEARCH_NAME;
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenu;
|
||
|
break;
|
||
|
case SEARCH_TOPBAR_SHIFT:
|
||
|
PlaySE(SE_PIN);
|
||
|
gTasks[taskId].tMenuItem = SEARCH_ORDER;
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenu;
|
||
|
break;
|
||
|
case SEARCH_TOPBAR_CANCEL:
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
gTasks[taskId].func = Task_ExitSearch;
|
||
|
break;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_LEFT) && gTasks[taskId].tTopBarItem > SEARCH_TOPBAR_SEARCH)
|
||
|
{
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
gTasks[taskId].tTopBarItem--;
|
||
|
HighlightSelectedSearchTopBarItem(gTasks[taskId].tTopBarItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_RIGHT) && gTasks[taskId].tTopBarItem < SEARCH_TOPBAR_CANCEL)
|
||
|
{
|
||
|
PlaySE(SE_DEX_PAGE);
|
||
|
gTasks[taskId].tTopBarItem++;
|
||
|
HighlightSelectedSearchTopBarItem(gTasks[taskId].tTopBarItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SwitchToSearchMenu(u8 taskId)
|
||
|
{
|
||
|
HighlightSelectedSearchMenuItem(gTasks[taskId].tTopBarItem, gTasks[taskId].tMenuItem);
|
||
|
PrintSelectedSearchParameters(taskId);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
gTasks[taskId].func = Task_HandleSearchMenuInput;
|
||
|
}
|
||
|
|
||
|
// Input for main search menu
|
||
|
static void Task_HandleSearchMenuInput(u8 taskId)
|
||
|
{
|
||
|
const u8 (*movementMap)[4];
|
||
|
|
||
|
if (gTasks[taskId].tTopBarItem != SEARCH_TOPBAR_SEARCH)
|
||
|
{
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
movementMap = sSearchMovementMap_ShiftHoennDex;
|
||
|
else
|
||
|
movementMap = sSearchMovementMap_ShiftNatDex;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
movementMap = sSearchMovementMap_SearchHoennDex;
|
||
|
else
|
||
|
movementMap = sSearchMovementMap_SearchNatDex;
|
||
|
}
|
||
|
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
PlaySE(SE_BALL);
|
||
|
SetDefaultSearchModeAndOrder(taskId);
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenuTopBar;
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
if (gTasks[taskId].tMenuItem == SEARCH_OK)
|
||
|
{
|
||
|
if (gTasks[taskId].tTopBarItem != SEARCH_TOPBAR_SEARCH)
|
||
|
{
|
||
|
sPokeBallRotation = POKEBALL_ROTATION_TOP;
|
||
|
sPokedexView->pokeBallRotationBackup = POKEBALL_ROTATION_TOP;
|
||
|
sLastSelectedPokemon = 0;
|
||
|
sPokedexView->selectedPokemonBackup = 0;
|
||
|
gSaveBlock2Ptr->pokedex.mode = GetSearchModeSelection(taskId, SEARCH_MODE);
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
gSaveBlock2Ptr->pokedex.mode = DEX_MODE_HOENN;
|
||
|
sPokedexView->dexModeBackup = gSaveBlock2Ptr->pokedex.mode;
|
||
|
gSaveBlock2Ptr->pokedex.order = GetSearchModeSelection(taskId, SEARCH_ORDER);
|
||
|
sPokedexView->dexOrderBackup = gSaveBlock2Ptr->pokedex.order;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
gTasks[taskId].func = Task_ExitSearch;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EraseAndPrintSearchTextBox(gText_SearchingPleaseWait);
|
||
|
gTasks[taskId].func = Task_StartPokedexSearch;
|
||
|
PlaySE(SE_DEX_SEARCH);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PlaySE(SE_PIN);
|
||
|
gTasks[taskId].func = Task_SelectSearchMenuItem;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (JOY_NEW(DPAD_LEFT) && movementMap[gTasks[taskId].tMenuItem][0] != 0xFF)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
gTasks[taskId].tMenuItem = movementMap[gTasks[taskId].tMenuItem][0];
|
||
|
HighlightSelectedSearchMenuItem(gTasks[taskId].tTopBarItem, gTasks[taskId].tMenuItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_RIGHT) && movementMap[gTasks[taskId].tMenuItem][1] != 0xFF)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
gTasks[taskId].tMenuItem = movementMap[gTasks[taskId].tMenuItem][1];
|
||
|
HighlightSelectedSearchMenuItem(gTasks[taskId].tTopBarItem, gTasks[taskId].tMenuItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_UP) && movementMap[gTasks[taskId].tMenuItem][2] != 0xFF)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
gTasks[taskId].tMenuItem = movementMap[gTasks[taskId].tMenuItem][2];
|
||
|
HighlightSelectedSearchMenuItem(gTasks[taskId].tTopBarItem, gTasks[taskId].tMenuItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
if (JOY_NEW(DPAD_DOWN) && movementMap[gTasks[taskId].tMenuItem][3] != 0xFF)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
gTasks[taskId].tMenuItem = movementMap[gTasks[taskId].tMenuItem][3];
|
||
|
HighlightSelectedSearchMenuItem(gTasks[taskId].tTopBarItem, gTasks[taskId].tMenuItem);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_StartPokedexSearch(u8 taskId)
|
||
|
{
|
||
|
u8 dexMode = GetSearchModeSelection(taskId, SEARCH_MODE);
|
||
|
u8 order = GetSearchModeSelection(taskId, SEARCH_ORDER);
|
||
|
u8 abcGroup = GetSearchModeSelection(taskId, SEARCH_NAME);
|
||
|
u8 bodyColor = GetSearchModeSelection(taskId, SEARCH_COLOR);
|
||
|
u8 type1 = GetSearchModeSelection(taskId, SEARCH_TYPE_LEFT);
|
||
|
u8 type2 = GetSearchModeSelection(taskId, SEARCH_TYPE_RIGHT);
|
||
|
|
||
|
DoPokedexSearch(dexMode, order, abcGroup, bodyColor, type1, type2);
|
||
|
gTasks[taskId].func = Task_WaitAndCompleteSearch;
|
||
|
}
|
||
|
|
||
|
static void Task_WaitAndCompleteSearch(u8 taskId)
|
||
|
{
|
||
|
if (!IsSEPlaying())
|
||
|
{
|
||
|
if (sPokedexView->pokemonListCount != 0)
|
||
|
{
|
||
|
PlaySE(SE_SUCCESS);
|
||
|
EraseAndPrintSearchTextBox(gText_SearchCompleted);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PlaySE(SE_FAILURE);
|
||
|
EraseAndPrintSearchTextBox(gText_NoMatchingPkmnWereFound);
|
||
|
}
|
||
|
gTasks[taskId].func = Task_SearchCompleteWaitForInput;
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SearchCompleteWaitForInput(u8 taskId)
|
||
|
{
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
if (sPokedexView->pokemonListCount != 0)
|
||
|
{
|
||
|
// Return to dex list and show search results
|
||
|
sPokedexView->screenSwitchState = 1;
|
||
|
sPokedexView->dexMode = GetSearchModeSelection(taskId, SEARCH_MODE);
|
||
|
sPokedexView->dexOrder = GetSearchModeSelection(taskId, SEARCH_ORDER);
|
||
|
gTasks[taskId].func = Task_ExitSearch;
|
||
|
PlaySE(SE_PC_OFF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenu;
|
||
|
PlaySE(SE_BALL);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_SelectSearchMenuItem(u8 taskId)
|
||
|
{
|
||
|
u8 menuItem;
|
||
|
u16 *cursorPos;
|
||
|
u16 *scrollOffset;
|
||
|
|
||
|
DrawOrEraseSearchParameterBox(FALSE);
|
||
|
menuItem = gTasks[taskId].tMenuItem;
|
||
|
cursorPos = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataCursorPos];
|
||
|
scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset];
|
||
|
gTasks[taskId].tCursorPos = *cursorPos;
|
||
|
gTasks[taskId].tScrollOffset = *scrollOffset;
|
||
|
PrintSearchParameterText(taskId);
|
||
|
PrintSelectorArrow(*cursorPos);
|
||
|
gTasks[taskId].func = Task_HandleSearchParameterInput;
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
}
|
||
|
|
||
|
// Input for scrolling parameter box in right column
|
||
|
static void Task_HandleSearchParameterInput(u8 taskId)
|
||
|
{
|
||
|
u8 menuItem;
|
||
|
const struct SearchOptionText *texts;
|
||
|
u16 *cursorPos;
|
||
|
u16 *scrollOffset;
|
||
|
u16 maxOption;
|
||
|
bool8 moved;
|
||
|
|
||
|
menuItem = gTasks[taskId].tMenuItem;
|
||
|
texts = sSearchOptions[menuItem].texts;
|
||
|
cursorPos = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataCursorPos];
|
||
|
scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset];
|
||
|
maxOption = sSearchOptions[menuItem].numOptions - 1;
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
{
|
||
|
PlaySE(SE_PIN);
|
||
|
ClearSearchParameterBoxText();
|
||
|
DrawOrEraseSearchParameterBox(TRUE);
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenu;
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_NEW(B_BUTTON))
|
||
|
{
|
||
|
PlaySE(SE_BALL);
|
||
|
ClearSearchParameterBoxText();
|
||
|
DrawOrEraseSearchParameterBox(TRUE);
|
||
|
*cursorPos = gTasks[taskId].tCursorPos;
|
||
|
*scrollOffset = gTasks[taskId].tScrollOffset;
|
||
|
gTasks[taskId].func = Task_SwitchToSearchMenu;
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
return;
|
||
|
}
|
||
|
moved = FALSE;
|
||
|
if (JOY_REPEAT(DPAD_UP))
|
||
|
{
|
||
|
if (*cursorPos != 0)
|
||
|
{
|
||
|
// Move cursor up
|
||
|
EraseSelectorArrow(*cursorPos);
|
||
|
(*cursorPos)--;
|
||
|
PrintSelectorArrow(*cursorPos);
|
||
|
moved = TRUE;
|
||
|
}
|
||
|
else if (*scrollOffset != 0)
|
||
|
{
|
||
|
// Scroll up
|
||
|
(*scrollOffset)--;
|
||
|
PrintSearchParameterText(taskId);
|
||
|
PrintSelectorArrow(*cursorPos);
|
||
|
moved = TRUE;
|
||
|
}
|
||
|
if (moved)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
EraseAndPrintSearchTextBox(texts[*cursorPos + *scrollOffset].description);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if (JOY_REPEAT(DPAD_DOWN))
|
||
|
{
|
||
|
if (*cursorPos < MAX_SEARCH_PARAM_CURSOR_POS && *cursorPos < maxOption)
|
||
|
{
|
||
|
// Move cursor down
|
||
|
EraseSelectorArrow(*cursorPos);
|
||
|
(*cursorPos)++;
|
||
|
PrintSelectorArrow(*cursorPos);
|
||
|
moved = TRUE;
|
||
|
}
|
||
|
else if (maxOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset < maxOption - MAX_SEARCH_PARAM_CURSOR_POS)
|
||
|
{
|
||
|
// Scroll down
|
||
|
(*scrollOffset)++;
|
||
|
PrintSearchParameterText(taskId);
|
||
|
PrintSelectorArrow(5);
|
||
|
moved = TRUE;
|
||
|
}
|
||
|
if (moved)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
EraseAndPrintSearchTextBox(texts[*cursorPos + *scrollOffset].description);
|
||
|
CopyWindowToVram(0, COPYWIN_GFX);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Task_ExitSearch(u8 taskId)
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
||
|
gTasks[taskId].func = Task_ExitSearchWaitForFade;
|
||
|
}
|
||
|
|
||
|
static void Task_ExitSearchWaitForFade(u8 taskId)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
FreeSearchWindowAndBgBuffers();
|
||
|
DestroyTask(taskId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SetSearchRectHighlight(u8 flags, u8 x, u8 y, u8 width)
|
||
|
{
|
||
|
u16 i;
|
||
|
u16 temp; //should be a pointer, but does not match as one
|
||
|
u32 ptr = (u32)GetBgTilemapBuffer(3); //same as above
|
||
|
|
||
|
for (i = 0; i < width; i++)
|
||
|
{
|
||
|
temp = *(u16 *)(ptr + (y + 0) * 64 + (x + i) * 2);
|
||
|
temp &= 0x0fff;
|
||
|
temp |= (flags << 12);
|
||
|
*(u16 *)(ptr + (y + 0) * 64 + (x + i) * 2) = temp;
|
||
|
|
||
|
temp = *(u16 *)(ptr + (y + 1) * 64 + (x + i) * 2);
|
||
|
temp &= 0x0fff;
|
||
|
temp |= (flags << 12);
|
||
|
*(u16 *)(ptr + (y + 1) * 64 + (x + i) * 2) = temp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define SEARCH_BG_SEARCH SEARCH_TOPBAR_SEARCH
|
||
|
#define SEARCH_BG_SHIFT SEARCH_TOPBAR_SHIFT
|
||
|
#define SEARCH_BG_CANCEL SEARCH_TOPBAR_CANCEL
|
||
|
#define SEARCH_BG_NAME (SEARCH_NAME + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_COLOR (SEARCH_COLOR + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_TYPE_SELECTION_LEFT (SEARCH_TYPE_LEFT + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_TYPE_SELECTION_RIGHT (SEARCH_TYPE_RIGHT + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_ORDER (SEARCH_ORDER + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_MODE (SEARCH_MODE + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_OK (SEARCH_OK + SEARCH_TOPBAR_COUNT)
|
||
|
#define SEARCH_BG_TYPE_TITLE (SEARCH_COUNT + SEARCH_TOPBAR_COUNT)
|
||
|
|
||
|
static void DrawSearchMenuItemBgHighlight(u8 searchBg, bool8 unselected, bool8 disabled)
|
||
|
{
|
||
|
u8 highlightFlags = (unselected & 1) | ((disabled & 1) << 1);
|
||
|
|
||
|
switch (searchBg)
|
||
|
{
|
||
|
case SEARCH_BG_SEARCH:
|
||
|
case SEARCH_BG_SHIFT:
|
||
|
case SEARCH_BG_CANCEL:
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuTopBarItems[searchBg].highlightX, sSearchMenuTopBarItems[searchBg].highlightY, sSearchMenuTopBarItems[searchBg].highlightWidth);
|
||
|
break;
|
||
|
case SEARCH_BG_NAME:
|
||
|
case SEARCH_BG_COLOR:
|
||
|
case SEARCH_BG_ORDER:
|
||
|
case SEARCH_BG_MODE:
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgX, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgY, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgWidth);
|
||
|
// fall through, draw selectionBg for above
|
||
|
case SEARCH_BG_TYPE_SELECTION_LEFT:
|
||
|
case SEARCH_BG_TYPE_SELECTION_RIGHT:
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].selectionBgX, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].selectionBgY, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].selectionBgWidth);
|
||
|
break;
|
||
|
case SEARCH_BG_TYPE_TITLE:
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuItems[SEARCH_TYPE_LEFT].titleBgX, sSearchMenuItems[SEARCH_TYPE_LEFT].titleBgY, sSearchMenuItems[SEARCH_TYPE_LEFT].titleBgWidth);
|
||
|
break;
|
||
|
case SEARCH_BG_OK:
|
||
|
if (!IsNationalPokedexEnabled())
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgX, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgY - 2, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgWidth);
|
||
|
else
|
||
|
SetSearchRectHighlight(highlightFlags, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgX, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgY, sSearchMenuItems[searchBg - SEARCH_TOPBAR_COUNT].titleBgWidth);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SetInitialSearchMenuBgHighlights(u8 topBarItem)
|
||
|
{
|
||
|
switch (topBarItem)
|
||
|
{
|
||
|
case SEARCH_TOPBAR_SEARCH:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SEARCH, FALSE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SHIFT, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_CANCEL, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_NAME, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_COLOR, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_TITLE, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_LEFT, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_RIGHT, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_ORDER, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_MODE, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_OK, TRUE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_TOPBAR_SHIFT:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SEARCH, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SHIFT, FALSE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_CANCEL, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_NAME, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_COLOR, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_TITLE, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_LEFT, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_RIGHT, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_ORDER, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_MODE, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_OK, TRUE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_TOPBAR_CANCEL:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SEARCH, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_SHIFT, TRUE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_CANCEL, FALSE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_NAME, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_COLOR, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_TITLE, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_LEFT, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_RIGHT, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_ORDER, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_MODE, TRUE, TRUE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_OK, TRUE, TRUE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void HighlightSelectedSearchTopBarItem(u8 topBarItem)
|
||
|
{
|
||
|
SetInitialSearchMenuBgHighlights(topBarItem);
|
||
|
EraseAndPrintSearchTextBox(sSearchMenuTopBarItems[topBarItem].description);
|
||
|
}
|
||
|
|
||
|
static void HighlightSelectedSearchMenuItem(u8 topBarItem, u8 menuItem)
|
||
|
{
|
||
|
SetInitialSearchMenuBgHighlights(topBarItem);
|
||
|
switch (menuItem)
|
||
|
{
|
||
|
case SEARCH_NAME:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_NAME, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_COLOR:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_COLOR, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_TYPE_LEFT:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_TITLE, FALSE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_LEFT, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_TYPE_RIGHT:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_TITLE, FALSE, FALSE);
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_TYPE_SELECTION_RIGHT, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_ORDER:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_ORDER, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_MODE:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_MODE, FALSE, FALSE);
|
||
|
break;
|
||
|
case SEARCH_OK:
|
||
|
DrawSearchMenuItemBgHighlight(SEARCH_BG_OK, FALSE, FALSE);
|
||
|
break;
|
||
|
}
|
||
|
EraseAndPrintSearchTextBox(sSearchMenuItems[menuItem].description);
|
||
|
}
|
||
|
|
||
|
// Prints the currently selected search parameters in the search menu selection boxes
|
||
|
static void PrintSelectedSearchParameters(u8 taskId)
|
||
|
{
|
||
|
u16 searchParamId;
|
||
|
|
||
|
ClearSearchMenuRect(40, 16, 96, 80);
|
||
|
|
||
|
searchParamId = gTasks[taskId].tCursorPos_Name + gTasks[taskId].tScrollOffset_Name;
|
||
|
PrintSearchText(sDexSearchNameOptions[searchParamId].title, 0x2D, 0x11);
|
||
|
|
||
|
searchParamId = gTasks[taskId].tCursorPos_Color + gTasks[taskId].tScrollOffset_Color;
|
||
|
PrintSearchText(sDexSearchColorOptions[searchParamId].title, 0x2D, 0x21);
|
||
|
|
||
|
searchParamId = gTasks[taskId].tCursorPos_TypeLeft + gTasks[taskId].tScrollOffset_TypeLeft;
|
||
|
PrintSearchText(sDexSearchTypeOptions[searchParamId].title, 0x2D, 0x31);
|
||
|
|
||
|
searchParamId = gTasks[taskId].tCursorPos_TypeRight + gTasks[taskId].tScrollOffset_TypeRight;
|
||
|
PrintSearchText(sDexSearchTypeOptions[searchParamId].title, 0x5D, 0x31);
|
||
|
|
||
|
searchParamId = gTasks[taskId].tCursorPos_Order + gTasks[taskId].tScrollOffset_Order;
|
||
|
PrintSearchText(sDexOrderOptions[searchParamId].title, 0x2D, 0x41);
|
||
|
|
||
|
if (IsNationalPokedexEnabled())
|
||
|
{
|
||
|
searchParamId = gTasks[taskId].tCursorPos_Mode + gTasks[taskId].tScrollOffset_Mode;
|
||
|
PrintSearchText(sDexModeOptions[searchParamId].title, 0x2D, 0x51);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void DrawOrEraseSearchParameterBox(bool8 erase)
|
||
|
{
|
||
|
u16 i;
|
||
|
u16 j;
|
||
|
u16* ptr = GetBgTilemapBuffer(3);
|
||
|
|
||
|
if (!erase)
|
||
|
{
|
||
|
*(ptr + 0x11) = 0xC0B;
|
||
|
for (i = 0x12; i < 0x1F; i++)
|
||
|
*(ptr + i) = 0x80D;
|
||
|
for (j = 1; j < 13; j++)
|
||
|
{
|
||
|
*(ptr + 0x11 + j * 32) = 0x40A;
|
||
|
for (i = 0x12; i < 0x1F; i++)
|
||
|
*(ptr + j * 32 + i) = 2;
|
||
|
}
|
||
|
*(ptr + 0x1B1) = 0x40B;
|
||
|
for (i = 0x12; i < 0x1F; i++)
|
||
|
*(ptr + 0x1A0 + i) = 0xD;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (j = 0; j < 14; j++)
|
||
|
{
|
||
|
for (i = 0x11; i < 0x1E; i++)
|
||
|
{
|
||
|
*(ptr + j * 32 + i) = 0x4F;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Prints the currently viewable search parameter titles in the right-hand text box
|
||
|
// and the currently selected search parameter description in the bottom text box
|
||
|
static void PrintSearchParameterText(u8 taskId)
|
||
|
{
|
||
|
const struct SearchOptionText *texts = sSearchOptions[gTasks[taskId].tMenuItem].texts;
|
||
|
const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataCursorPos];
|
||
|
const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataScrollOffset];
|
||
|
u16 i;
|
||
|
u16 j;
|
||
|
|
||
|
ClearSearchParameterBoxText();
|
||
|
|
||
|
for (i = 0, j = *scrollOffset; i < MAX_SEARCH_PARAM_ON_SCREEN && texts[j].title != NULL; i++, j++)
|
||
|
PrintSearchParameterTitle(i, texts[j].title);
|
||
|
|
||
|
EraseAndPrintSearchTextBox(texts[*cursorPos + *scrollOffset].description);
|
||
|
}
|
||
|
|
||
|
static u8 GetSearchModeSelection(u8 taskId, u8 option)
|
||
|
{
|
||
|
const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[option].taskDataCursorPos];
|
||
|
const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[option].taskDataScrollOffset];
|
||
|
u16 id = *cursorPos + *scrollOffset;
|
||
|
|
||
|
switch (option)
|
||
|
{
|
||
|
default:
|
||
|
return 0;
|
||
|
case SEARCH_MODE:
|
||
|
return sPokedexModes[id];
|
||
|
case SEARCH_ORDER:
|
||
|
return sOrderOptions[id];
|
||
|
case SEARCH_NAME:
|
||
|
if (id == 0)
|
||
|
return 0xFF;
|
||
|
else
|
||
|
return id;
|
||
|
case SEARCH_COLOR:
|
||
|
if (id == 0)
|
||
|
return 0xFF;
|
||
|
else
|
||
|
return id - 1;
|
||
|
case SEARCH_TYPE_LEFT:
|
||
|
case SEARCH_TYPE_RIGHT:
|
||
|
return sDexSearchTypeIds[id];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void SetDefaultSearchModeAndOrder(u8 taskId)
|
||
|
{
|
||
|
u16 selected;
|
||
|
|
||
|
switch (sPokedexView->dexModeBackup)
|
||
|
{
|
||
|
default:
|
||
|
case DEX_MODE_HOENN:
|
||
|
selected = DEX_MODE_HOENN;
|
||
|
break;
|
||
|
case DEX_MODE_NATIONAL:
|
||
|
selected = DEX_MODE_NATIONAL;
|
||
|
break;
|
||
|
}
|
||
|
gTasks[taskId].tCursorPos_Mode = selected;
|
||
|
|
||
|
switch (sPokedexView->dexOrderBackup)
|
||
|
{
|
||
|
default:
|
||
|
case ORDER_NUMERICAL:
|
||
|
selected = ORDER_NUMERICAL;
|
||
|
break;
|
||
|
case ORDER_ALPHABETICAL:
|
||
|
selected = ORDER_ALPHABETICAL;
|
||
|
break;
|
||
|
case ORDER_HEAVIEST:
|
||
|
selected = ORDER_HEAVIEST;
|
||
|
break;
|
||
|
case ORDER_LIGHTEST:
|
||
|
selected = ORDER_LIGHTEST;
|
||
|
break;
|
||
|
case ORDER_TALLEST:
|
||
|
selected = ORDER_TALLEST;
|
||
|
break;
|
||
|
case ORDER_SMALLEST:
|
||
|
selected = ORDER_SMALLEST;
|
||
|
break;
|
||
|
}
|
||
|
gTasks[taskId].tCursorPos_Order = selected;
|
||
|
}
|
||
|
|
||
|
static bool8 SearchParamCantScrollUp(u8 taskId)
|
||
|
{
|
||
|
u8 menuItem = gTasks[taskId].tMenuItem;
|
||
|
const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset];
|
||
|
u16 lastOption = sSearchOptions[menuItem].numOptions - 1;
|
||
|
|
||
|
if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset != 0)
|
||
|
return FALSE;
|
||
|
else
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static bool8 SearchParamCantScrollDown(u8 taskId)
|
||
|
{
|
||
|
u8 menuItem = gTasks[taskId].tMenuItem;
|
||
|
const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset];
|
||
|
u16 lastOption = sSearchOptions[menuItem].numOptions - 1;
|
||
|
|
||
|
if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset < lastOption - MAX_SEARCH_PARAM_CURSOR_POS)
|
||
|
return FALSE;
|
||
|
else
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#define sTaskId data[0]
|
||
|
|
||
|
static void SpriteCB_SearchParameterScrollArrow(struct Sprite *sprite)
|
||
|
{
|
||
|
if (gTasks[sprite->sTaskId].func == Task_HandleSearchParameterInput)
|
||
|
{
|
||
|
u8 val;
|
||
|
|
||
|
if (sprite->sIsDownArrow)
|
||
|
{
|
||
|
if (SearchParamCantScrollDown(sprite->sTaskId))
|
||
|
sprite->invisible = TRUE;
|
||
|
else
|
||
|
sprite->invisible = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (SearchParamCantScrollUp(sprite->sTaskId))
|
||
|
sprite->invisible = TRUE;
|
||
|
else
|
||
|
sprite->invisible = FALSE;
|
||
|
}
|
||
|
val = sprite->data[2] + sprite->sIsDownArrow * 128;
|
||
|
sprite->y2 = gSineTable[val] / 128;
|
||
|
sprite->data[2] += 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprite->invisible = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CreateSearchParameterScrollArrows(u8 taskId)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
spriteId = CreateSprite(&sScrollArrowSpriteTemplate, 184, 4, 0);
|
||
|
gSprites[spriteId].sTaskId = taskId;
|
||
|
gSprites[spriteId].sIsDownArrow = FALSE;
|
||
|
gSprites[spriteId].callback = SpriteCB_SearchParameterScrollArrow;
|
||
|
|
||
|
spriteId = CreateSprite(&sScrollArrowSpriteTemplate, 184, 108, 0);
|
||
|
gSprites[spriteId].sTaskId = taskId;
|
||
|
gSprites[spriteId].sIsDownArrow = TRUE;
|
||
|
gSprites[spriteId].vFlip = TRUE;
|
||
|
gSprites[spriteId].callback = SpriteCB_SearchParameterScrollArrow;
|
||
|
}
|
||
|
|
||
|
#undef sTaskId
|
||
|
#undef sIsDownArrow
|
||
|
|
||
|
static void EraseAndPrintSearchTextBox(const u8* str)
|
||
|
{
|
||
|
ClearSearchMenuRect(8, 120, 224, 32);
|
||
|
PrintSearchText(str, 8, 121);
|
||
|
}
|
||
|
|
||
|
static void EraseSelectorArrow(u32 y)
|
||
|
{
|
||
|
ClearSearchMenuRect(144, y * 16 + 8, 8, 16);
|
||
|
}
|
||
|
|
||
|
static void PrintSelectorArrow(u32 y)
|
||
|
{
|
||
|
PrintSearchText(gText_SelectorArrow, 144, y * 16 + 9);
|
||
|
}
|
||
|
|
||
|
static void PrintSearchParameterTitle(u32 y, const u8* str)
|
||
|
{
|
||
|
PrintSearchText(str, 152, y * 16 + 9);
|
||
|
}
|
||
|
|
||
|
static void ClearSearchParameterBoxText(void)
|
||
|
{
|
||
|
ClearSearchMenuRect(144, 8, 96, 96);
|
||
|
}
|