2582 lines
67 KiB
C
2582 lines
67 KiB
C
|
#include "global.h"
|
||
|
#include "naming_screen.h"
|
||
|
#include "malloc.h"
|
||
|
#include "palette.h"
|
||
|
#include "task.h"
|
||
|
#include "sprite.h"
|
||
|
#include "string_util.h"
|
||
|
#include "window.h"
|
||
|
#include "bg.h"
|
||
|
#include "gpu_regs.h"
|
||
|
#include "pokemon.h"
|
||
|
#include "field_specials.h"
|
||
|
#include "field_player_avatar.h"
|
||
|
#include "event_object_movement.h"
|
||
|
#include "event_data.h"
|
||
|
#include "constants/songs.h"
|
||
|
#include "pokemon_storage_system.h"
|
||
|
#include "graphics.h"
|
||
|
#include "sound.h"
|
||
|
#include "trig.h"
|
||
|
#include "field_effect.h"
|
||
|
#include "pokemon_icon.h"
|
||
|
#include "data.h"
|
||
|
#include "strings.h"
|
||
|
#include "menu.h"
|
||
|
#include "text_window.h"
|
||
|
#include "overworld.h"
|
||
|
#include "walda_phrase.h"
|
||
|
#include "constants/event_objects.h"
|
||
|
#include "constants/rgb.h"
|
||
|
|
||
|
enum {
|
||
|
INPUT_NONE,
|
||
|
INPUT_DPAD_UP,
|
||
|
INPUT_DPAD_DOWN,
|
||
|
INPUT_DPAD_LEFT,
|
||
|
INPUT_DPAD_RIGHT,
|
||
|
INPUT_A_BUTTON,
|
||
|
INPUT_B_BUTTON,
|
||
|
INPUT_LR_BUTTON,
|
||
|
INPUT_SELECT,
|
||
|
INPUT_START,
|
||
|
};
|
||
|
|
||
|
#define KBROW_COUNT 4
|
||
|
#define KBCOL_COUNT 8
|
||
|
|
||
|
enum {
|
||
|
GFXTAG_BACK_BUTTON,
|
||
|
GFXTAG_OK_BUTTON,
|
||
|
GFXTAG_PAGE_SWAP_FRAME,
|
||
|
GFXTAG_PAGE_SWAP_BUTTON,
|
||
|
GFXTAG_PAGE_SWAP_UPPER,
|
||
|
GFXTAG_PAGE_SWAP_LOWER,
|
||
|
GFXTAG_PAGE_SWAP_OTHERS,
|
||
|
GFXTAG_CURSOR,
|
||
|
GFXTAG_CURSOR_SQUISHED,
|
||
|
GFXTAG_CURSOR_FILLED,
|
||
|
GFXTAG_INPUT_ARROW,
|
||
|
GFXTAG_UNDERSCORE,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
PALTAG_PC_ICON,
|
||
|
PALTAG_PAGE_SWAP_UPPER,
|
||
|
PALTAG_PAGE_SWAP_LOWER,
|
||
|
PALTAG_PAGE_SWAP_OTHERS,
|
||
|
PALTAG_PAGE_SWAP,
|
||
|
PALTAG_CURSOR,
|
||
|
PALTAG_BACK_BUTTON,
|
||
|
PALTAG_OK_BUTTON,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
WIN_KB_PAGE_1, // Which of these two windows is in front is cycled as the player swaps
|
||
|
WIN_KB_PAGE_2, // Initially WIN_KB_PAGE_1 is in front, with WIN_KB_PAGE_2 on deck
|
||
|
WIN_TEXT_ENTRY,
|
||
|
WIN_TEXT_ENTRY_BOX,
|
||
|
WIN_BANNER,
|
||
|
WIN_COUNT,
|
||
|
};
|
||
|
|
||
|
// The constants for the pages are needlessly complicated because GF didn't keep the indexing order consistent
|
||
|
// This set is used for sNamingScreen->currentPage. It uses the order that the pages are cycled in
|
||
|
enum {
|
||
|
KBPAGE_SYMBOLS,
|
||
|
KBPAGE_LETTERS_UPPER,
|
||
|
KBPAGE_LETTERS_LOWER,
|
||
|
KBPAGE_COUNT,
|
||
|
};
|
||
|
|
||
|
// This set is used for initializing a page's keyboard text and getting its number of columns
|
||
|
enum {
|
||
|
KEYBOARD_LETTERS_LOWER,
|
||
|
KEYBOARD_LETTERS_UPPER,
|
||
|
KEYBOARD_SYMBOLS,
|
||
|
};
|
||
|
|
||
|
// This set is used for getting the gfx/pal tags of the page's swap button
|
||
|
enum {
|
||
|
PAGE_SWAP_UPPER,
|
||
|
PAGE_SWAP_OTHERS,
|
||
|
PAGE_SWAP_LOWER,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
KEY_ROLE_CHAR,
|
||
|
KEY_ROLE_PAGE,
|
||
|
KEY_ROLE_BACKSPACE,
|
||
|
KEY_ROLE_OK,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
BUTTON_PAGE,
|
||
|
BUTTON_BACK,
|
||
|
BUTTON_OK,
|
||
|
BUTTON_COUNT,
|
||
|
};
|
||
|
|
||
|
// states for Task_NamingScreen
|
||
|
enum {
|
||
|
STATE_FADE_IN,
|
||
|
STATE_WAIT_FADE_IN,
|
||
|
STATE_HANDLE_INPUT,
|
||
|
STATE_MOVE_TO_OK_BUTTON,
|
||
|
STATE_START_PAGE_SWAP,
|
||
|
STATE_WAIT_PAGE_SWAP,
|
||
|
STATE_PRESSED_OK,
|
||
|
STATE_WAIT_SENT_TO_PC_MESSAGE,
|
||
|
STATE_FADE_OUT,
|
||
|
STATE_EXIT,
|
||
|
};
|
||
|
|
||
|
// sates for Task_HandleInput
|
||
|
enum
|
||
|
{
|
||
|
INPUT_STATE_DISABLED,
|
||
|
INPUT_STATE_ENABLED,
|
||
|
INPUT_STATE_OVERRIDE,
|
||
|
};
|
||
|
|
||
|
struct NamingScreenTemplate
|
||
|
{
|
||
|
u8 copyExistingString;
|
||
|
u8 maxChars;
|
||
|
u8 iconFunction;
|
||
|
u8 addGenderIcon;
|
||
|
u8 initialPage;
|
||
|
u8 unused;
|
||
|
const u8 *title;
|
||
|
};
|
||
|
|
||
|
struct NamingScreenData
|
||
|
{
|
||
|
u8 tilemapBuffer1[0x800];
|
||
|
u8 tilemapBuffer2[0x800];
|
||
|
u8 tilemapBuffer3[0x800];
|
||
|
u8 textBuffer[16];
|
||
|
u8 tileBuffer[0x600];
|
||
|
u8 state;
|
||
|
u8 windows[WIN_COUNT];
|
||
|
u16 inputCharBaseXPos;
|
||
|
u16 bg1vOffset;
|
||
|
u16 bg2vOffset;
|
||
|
u16 bg1Priority;
|
||
|
u16 bg2Priority;
|
||
|
u8 bgToReveal;
|
||
|
u8 bgToHide;
|
||
|
u8 currentPage;
|
||
|
u8 cursorSpriteId;
|
||
|
u8 swapBtnFrameSpriteId;
|
||
|
u8 keyRepeatStartDelayCopy;
|
||
|
const struct NamingScreenTemplate *template;
|
||
|
u8 templateNum;
|
||
|
u8 *destBuffer;
|
||
|
u16 monSpecies;
|
||
|
u16 monGender;
|
||
|
u32 monPersonality;
|
||
|
MainCallback returnCallback;
|
||
|
};
|
||
|
|
||
|
EWRAM_DATA static struct NamingScreenData *sNamingScreen = NULL;
|
||
|
extern u16 gKeyRepeatStartDelay;
|
||
|
|
||
|
// extern text
|
||
|
extern const u8 gText_MoveOkBack[];
|
||
|
extern const u8 gText_YourName[];
|
||
|
extern const u8 gText_BoxName[];
|
||
|
extern const u8 gText_PkmnsNickname[];
|
||
|
extern const u8 gText_TellHimTheWords[];
|
||
|
|
||
|
|
||
|
// start of .rodata
|
||
|
static const u8 sPCIconOff_Gfx[] = INCBIN_U8("graphics/naming_screen/pc_icon/off.4bpp");
|
||
|
static const u8 sPCIconOn_Gfx[] = INCBIN_U8("graphics/naming_screen/pc_icon/on.4bpp");
|
||
|
static const u16 sKeyboard_Pal[] = INCBIN_U16("graphics/naming_screen/keyboard.gbapal");
|
||
|
static const u16 sUnused_Pal[] = INCBIN_U16("graphics/naming_screen/unused.gbapal");
|
||
|
|
||
|
static const u8 *const sTransferredToPCMessages[] =
|
||
|
{
|
||
|
gText_PkmnTransferredSomeonesPC,
|
||
|
gText_PkmnTransferredLanettesPC,
|
||
|
gText_PkmnTransferredSomeonesPCBoxFull,
|
||
|
gText_PkmnTransferredLanettesPCBoxFull
|
||
|
};
|
||
|
|
||
|
static const u8 sText_AlphabetUpperLower[] = _("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!");
|
||
|
|
||
|
static const struct BgTemplate sBgTemplates[] =
|
||
|
{
|
||
|
{
|
||
|
.bg = 0,
|
||
|
.charBaseIndex = 0,
|
||
|
.mapBaseIndex = 30,
|
||
|
.priority = 0
|
||
|
},
|
||
|
{
|
||
|
.bg = 1,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 29,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.bg = 2,
|
||
|
.charBaseIndex = 2,
|
||
|
.mapBaseIndex = 28,
|
||
|
.priority = 2
|
||
|
},
|
||
|
{
|
||
|
.bg = 3,
|
||
|
.charBaseIndex = 3,
|
||
|
.mapBaseIndex = 31,
|
||
|
.priority = 3
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct WindowTemplate sWindowTemplates[WIN_COUNT + 1] =
|
||
|
{
|
||
|
[WIN_KB_PAGE_1] = {
|
||
|
.bg = 1,
|
||
|
.tilemapLeft = 3,
|
||
|
.tilemapTop = 10,
|
||
|
.width = 19,
|
||
|
.height = 8,
|
||
|
.paletteNum = 10,
|
||
|
.baseBlock = 0x030
|
||
|
},
|
||
|
[WIN_KB_PAGE_2] = {
|
||
|
.bg = 2,
|
||
|
.tilemapLeft = 3,
|
||
|
.tilemapTop = 10,
|
||
|
.width = 19,
|
||
|
.height = 8,
|
||
|
.paletteNum = 10,
|
||
|
.baseBlock = 0x0C8
|
||
|
},
|
||
|
[WIN_TEXT_ENTRY] = {
|
||
|
.bg = 3,
|
||
|
.tilemapLeft = 8,
|
||
|
.tilemapTop = 6,
|
||
|
.width = 17,
|
||
|
.height = 2,
|
||
|
.paletteNum = 10,
|
||
|
.baseBlock = 0x030
|
||
|
},
|
||
|
[WIN_TEXT_ENTRY_BOX] = {
|
||
|
.bg = 3,
|
||
|
.tilemapLeft = 8,
|
||
|
.tilemapTop = 4,
|
||
|
.width = 17,
|
||
|
.height = 2,
|
||
|
.paletteNum = 10,
|
||
|
.baseBlock = 0x052
|
||
|
},
|
||
|
[WIN_BANNER] = {
|
||
|
.bg = 0,
|
||
|
.tilemapLeft = 0,
|
||
|
.tilemapTop = 0,
|
||
|
.width = 30,
|
||
|
.height = 2,
|
||
|
.paletteNum = 11,
|
||
|
.baseBlock = 0x074
|
||
|
},
|
||
|
DUMMY_WIN_TEMPLATE
|
||
|
};
|
||
|
|
||
|
// This handles what characters get inserted when a key is pressed
|
||
|
// The keys shown on the keyboard are handled separately by sNamingScreenKeyboardText
|
||
|
static const u8 sKeyboardChars[KBPAGE_COUNT][KBROW_COUNT][KBCOL_COUNT] = {
|
||
|
[KEYBOARD_LETTERS_LOWER] = {
|
||
|
__("abcdef ."),
|
||
|
__("ghijkl ,"),
|
||
|
__("mnopqrs "),
|
||
|
__("tuvwxyz "),
|
||
|
},
|
||
|
[KEYBOARD_LETTERS_UPPER] = {
|
||
|
__("ABCDEF ."),
|
||
|
__("GHIJKL ,"),
|
||
|
__("MNOPQRS "),
|
||
|
__("TUVWXYZ "),
|
||
|
},
|
||
|
[KEYBOARD_SYMBOLS] = {
|
||
|
__("01234 "),
|
||
|
__("56789 "),
|
||
|
__("!?♂♀/- "),
|
||
|
__("…“”‘' "),
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const u8 sPageColumnCounts[KBPAGE_COUNT] = {
|
||
|
[KEYBOARD_LETTERS_LOWER] = KBCOL_COUNT,
|
||
|
[KEYBOARD_LETTERS_UPPER] = KBCOL_COUNT,
|
||
|
[KEYBOARD_SYMBOLS] = 6
|
||
|
};
|
||
|
static const u8 sPageColumnXPos[KBPAGE_COUNT * KBCOL_COUNT] = {
|
||
|
0, 12, 24, 56, 68, 80, 92, 123, // KEYBOARD_LETTERS_LOWER
|
||
|
0, 12, 24, 56, 68, 80, 92, 123, // KEYBOARD_LETTERS_UPPER
|
||
|
0, 22, 44, 66, 88, 110 // KEYBOARD_SYMBOLS
|
||
|
};
|
||
|
|
||
|
// forward declarations
|
||
|
static const struct NamingScreenTemplate *const sNamingScreenTemplates[];
|
||
|
static const struct SubspriteTable sSubspriteTable_PageSwapFrame[];
|
||
|
static const struct SubspriteTable sSubspriteTable_PageSwapText[];
|
||
|
static const struct SubspriteTable sSubspriteTable_Button[];
|
||
|
static const struct SubspriteTable sSubspriteTable_PCIcon[];
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapFrame;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapButton;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapText;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_BackButton;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_OkButton;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_Cursor;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_InputArrow;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_Underscore;
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PCIcon;
|
||
|
static const u8* const sNamingScreenKeyboardText[KBPAGE_COUNT][KBROW_COUNT];
|
||
|
static const struct SpriteSheet sSpriteSheets[];
|
||
|
static const struct SpritePalette sSpritePalettes[];
|
||
|
|
||
|
static void CB2_LoadNamingScreen(void);
|
||
|
static void NamingScreen_Init(void);
|
||
|
static void NamingScreen_InitBGs(void);
|
||
|
static void CreateNamingScreenTask(void);
|
||
|
static void Task_NamingScreen(u8 taskId);
|
||
|
static bool8 MainState_FadeIn(void);
|
||
|
static bool8 MainState_WaitFadeIn(void);
|
||
|
static bool8 MainState_HandleInput(void);
|
||
|
static bool8 MainState_MoveToOKButton(void);
|
||
|
static bool8 MainState_PressedOKButton(void);
|
||
|
static bool8 MainState_FadeOut(void);
|
||
|
static bool8 MainState_Exit(void);
|
||
|
static void DisplaySentToPCMessage(void);
|
||
|
static bool8 MainState_WaitSentToPCMessage(void);
|
||
|
static bool8 MainState_StartPageSwap(void);
|
||
|
static bool8 MainState_WaitPageSwap(void);
|
||
|
static void StartPageSwapAnim(void);
|
||
|
static void Task_HandlePageSwapAnim(u8);
|
||
|
static bool8 IsPageSwapAnimNotInProgress(void);
|
||
|
static void TryStartButtonFlash(u8, bool8, bool8);
|
||
|
static void Task_UpdateButtonFlash(u8);
|
||
|
static u16 GetButtonPalOffset(u8);
|
||
|
static void RestoreButtonColor(u8);
|
||
|
static void StartButtonFlash(struct Task *, u8, bool8);
|
||
|
static void CreateSprites(void);
|
||
|
static void CreateCursorSprite(void);
|
||
|
static void SetCursorPos(s16, s16);
|
||
|
static void GetCursorPos(s16 *x, s16 *y);
|
||
|
static void MoveCursorToOKButton(void);
|
||
|
static void SetCursorInvisibility(u8);
|
||
|
static void SetCursorFlashing(bool8);
|
||
|
static u8 IsCursorAnimFinished(void);
|
||
|
static u8 GetCurrentPageColumnCount(void);
|
||
|
static void CreatePageSwapButtonSprites(void);
|
||
|
static void StartPageSwapButtonAnim(void);
|
||
|
static void SetPageSwapButtonGfx(u8, struct Sprite *, struct Sprite *);
|
||
|
static void CreateBackOkSprites(void);
|
||
|
static void CreateTextEntrySprites(void);
|
||
|
static void CreateInputTargetIcon(void);
|
||
|
static u8 HandleKeyboardEvent(void);
|
||
|
static u8 SwapKeyboardPage(void);
|
||
|
static u8 GetInputEvent(void);
|
||
|
static void SetInputState(u8);
|
||
|
static void DrawTextEntryBox(void);
|
||
|
static u8 GetTextEntryPosition(void);
|
||
|
static void DeleteTextCharacter(void);
|
||
|
static bool8 AddTextCharacter(void);
|
||
|
static void BufferCharacter(u8);
|
||
|
static void SaveInputText(void);
|
||
|
static void LoadGfx(void);
|
||
|
static void CreateHelperTasks(void);
|
||
|
static void LoadPalettes(void);
|
||
|
static void DrawBgTilemap(u8, const void *);
|
||
|
static void NamingScreen_Dummy(u8, u8);
|
||
|
static void DrawTextEntry(void);
|
||
|
static void PrintKeyboardKeys(u8, u8);
|
||
|
static void DrawKeyboardPageOnDeck(void);
|
||
|
static void PrintControls(void);
|
||
|
static void CB2_NamingScreen(void);
|
||
|
static void ResetVHBlank(void);
|
||
|
static void SetVBlank(void);
|
||
|
static void VBlankCB_NamingScreen(void);
|
||
|
static void NamingScreen_ShowBgs(void);
|
||
|
static bool8 IsWideLetter(u8);
|
||
|
|
||
|
void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGender, u32 monPersonality, MainCallback returnCallback)
|
||
|
{
|
||
|
sNamingScreen = Alloc(sizeof(struct NamingScreenData));
|
||
|
if (!sNamingScreen)
|
||
|
{
|
||
|
SetMainCallback2(returnCallback);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sNamingScreen->templateNum = templateNum;
|
||
|
sNamingScreen->monSpecies = monSpecies;
|
||
|
sNamingScreen->monGender = monGender;
|
||
|
sNamingScreen->monPersonality = monPersonality;
|
||
|
sNamingScreen->destBuffer = destBuffer;
|
||
|
sNamingScreen->returnCallback = returnCallback;
|
||
|
|
||
|
if (templateNum == NAMING_SCREEN_PLAYER)
|
||
|
StartTimer1();
|
||
|
|
||
|
SetMainCallback2(CB2_LoadNamingScreen);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CB2_LoadNamingScreen(void)
|
||
|
{
|
||
|
switch (gMain.state)
|
||
|
{
|
||
|
case 0:
|
||
|
ResetVHBlank();
|
||
|
NamingScreen_Init();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 1:
|
||
|
NamingScreen_InitBGs();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 2:
|
||
|
ResetPaletteFade();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 3:
|
||
|
ResetSpriteData();
|
||
|
FreeAllSpritePalettes();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 4:
|
||
|
ResetTasks();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 5:
|
||
|
LoadPalettes();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 6:
|
||
|
LoadGfx();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
case 7:
|
||
|
CreateSprites();
|
||
|
UpdatePaletteFade();
|
||
|
NamingScreen_ShowBgs();
|
||
|
gMain.state++;
|
||
|
break;
|
||
|
default:
|
||
|
CreateHelperTasks();
|
||
|
CreateNamingScreenTask();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_Init(void)
|
||
|
{
|
||
|
sNamingScreen->state = STATE_FADE_IN;
|
||
|
sNamingScreen->bg1vOffset = 0;
|
||
|
sNamingScreen->bg2vOffset = 0;
|
||
|
sNamingScreen->bg1Priority = BGCNT_PRIORITY(1);
|
||
|
sNamingScreen->bg2Priority = BGCNT_PRIORITY(2);
|
||
|
sNamingScreen->bgToReveal = 0;
|
||
|
sNamingScreen->bgToHide = 1;
|
||
|
sNamingScreen->template = sNamingScreenTemplates[sNamingScreen->templateNum];
|
||
|
sNamingScreen->currentPage = sNamingScreen->template->initialPage;
|
||
|
sNamingScreen->inputCharBaseXPos = (DISPLAY_WIDTH - sNamingScreen->template->maxChars * 8) / 2 + 6;
|
||
|
if (sNamingScreen->templateNum == NAMING_SCREEN_WALDA)
|
||
|
sNamingScreen->inputCharBaseXPos += 11;
|
||
|
sNamingScreen->keyRepeatStartDelayCopy = gKeyRepeatStartDelay;
|
||
|
memset(sNamingScreen->textBuffer, EOS, sizeof(sNamingScreen->textBuffer));
|
||
|
if (sNamingScreen->template->copyExistingString)
|
||
|
StringCopy(sNamingScreen->textBuffer, sNamingScreen->destBuffer);
|
||
|
gKeyRepeatStartDelay = 16;
|
||
|
}
|
||
|
|
||
|
static void SetSpritesVisible(void)
|
||
|
{
|
||
|
u8 i;
|
||
|
for (i = 0; i < MAX_SPRITES; i++)
|
||
|
{
|
||
|
if (gSprites[i].inUse)
|
||
|
gSprites[i].invisible = FALSE;
|
||
|
}
|
||
|
SetCursorInvisibility(FALSE);
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_InitBGs(void)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
DmaClearLarge16(3, (void *)VRAM, VRAM_SIZE, 0x1000);
|
||
|
DmaClear32(3, (void *)OAM, OAM_SIZE);
|
||
|
DmaClear16(3, (void *)PLTT, PLTT_SIZE);
|
||
|
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0);
|
||
|
ResetBgsAndClearDma3BusyFlags(0);
|
||
|
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
|
||
|
|
||
|
ChangeBgX(0, 0, BG_COORD_SET);
|
||
|
ChangeBgY(0, 0, BG_COORD_SET);
|
||
|
ChangeBgX(1, 0, BG_COORD_SET);
|
||
|
ChangeBgY(1, 0, BG_COORD_SET);
|
||
|
ChangeBgX(2, 0, BG_COORD_SET);
|
||
|
ChangeBgY(2, 0, BG_COORD_SET);
|
||
|
ChangeBgX(3, 0, BG_COORD_SET);
|
||
|
ChangeBgY(3, 0, BG_COORD_SET);
|
||
|
|
||
|
InitStandardTextBoxWindows();
|
||
|
InitTextBoxGfxAndPrinters();
|
||
|
|
||
|
for (i = 0; i < WIN_COUNT; i++)
|
||
|
sNamingScreen->windows[i] = AddWindow(&sWindowTemplates[i]);
|
||
|
|
||
|
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||
|
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2);
|
||
|
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 8));
|
||
|
|
||
|
SetBgTilemapBuffer(1, sNamingScreen->tilemapBuffer1);
|
||
|
SetBgTilemapBuffer(2, sNamingScreen->tilemapBuffer2);
|
||
|
SetBgTilemapBuffer(3, sNamingScreen->tilemapBuffer3);
|
||
|
|
||
|
FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 0x20, 0x20);
|
||
|
FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 0x20, 0x20);
|
||
|
FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20);
|
||
|
}
|
||
|
|
||
|
static void CreateNamingScreenTask(void)
|
||
|
{
|
||
|
CreateTask(Task_NamingScreen, 2);
|
||
|
SetMainCallback2(CB2_NamingScreen);
|
||
|
}
|
||
|
|
||
|
static void Task_NamingScreen(u8 taskId)
|
||
|
{
|
||
|
switch (sNamingScreen->state)
|
||
|
{
|
||
|
case STATE_FADE_IN:
|
||
|
MainState_FadeIn();
|
||
|
SetSpritesVisible();
|
||
|
SetVBlank();
|
||
|
break;
|
||
|
case STATE_WAIT_FADE_IN:
|
||
|
MainState_WaitFadeIn();
|
||
|
break;
|
||
|
case STATE_HANDLE_INPUT:
|
||
|
MainState_HandleInput();
|
||
|
break;
|
||
|
case STATE_MOVE_TO_OK_BUTTON:
|
||
|
MainState_MoveToOKButton();
|
||
|
MainState_HandleInput();
|
||
|
break;
|
||
|
case STATE_START_PAGE_SWAP:
|
||
|
MainState_StartPageSwap();
|
||
|
break;
|
||
|
case STATE_WAIT_PAGE_SWAP:
|
||
|
MainState_WaitPageSwap();
|
||
|
break;
|
||
|
case STATE_PRESSED_OK:
|
||
|
MainState_PressedOKButton();
|
||
|
break;
|
||
|
case STATE_WAIT_SENT_TO_PC_MESSAGE:
|
||
|
MainState_WaitSentToPCMessage();
|
||
|
break;
|
||
|
case STATE_FADE_OUT:
|
||
|
MainState_FadeOut();
|
||
|
break;
|
||
|
case STATE_EXIT:
|
||
|
MainState_Exit();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Which gfx/pal to load for the swap page button
|
||
|
static const u8 sPageToNextGfxId[KBPAGE_COUNT] =
|
||
|
{
|
||
|
[KBPAGE_SYMBOLS] = PAGE_SWAP_UPPER,
|
||
|
[KBPAGE_LETTERS_UPPER] = PAGE_SWAP_LOWER,
|
||
|
[KBPAGE_LETTERS_LOWER] = PAGE_SWAP_OTHERS
|
||
|
};
|
||
|
|
||
|
static const u8 sPageToNextKeyboardId[KBPAGE_COUNT] =
|
||
|
{
|
||
|
[KBPAGE_SYMBOLS] = KEYBOARD_LETTERS_UPPER,
|
||
|
[KBPAGE_LETTERS_UPPER] = KEYBOARD_LETTERS_LOWER,
|
||
|
[KBPAGE_LETTERS_LOWER] = KEYBOARD_SYMBOLS
|
||
|
};
|
||
|
|
||
|
static const u8 sPageToKeyboardId[KBPAGE_COUNT] =
|
||
|
{
|
||
|
[KBPAGE_SYMBOLS] = KEYBOARD_SYMBOLS,
|
||
|
[KBPAGE_LETTERS_UPPER] = KEYBOARD_LETTERS_UPPER,
|
||
|
[KBPAGE_LETTERS_LOWER] = KEYBOARD_LETTERS_LOWER
|
||
|
};
|
||
|
|
||
|
static u8 PageToNextGfxId(u8 page)
|
||
|
{
|
||
|
return sPageToNextGfxId[page];
|
||
|
}
|
||
|
|
||
|
static u8 CurrentPageToNextKeyboardId(void)
|
||
|
{
|
||
|
return sPageToNextKeyboardId[sNamingScreen->currentPage];
|
||
|
}
|
||
|
|
||
|
static u8 CurrentPageToKeyboardId(void)
|
||
|
{
|
||
|
return sPageToKeyboardId[sNamingScreen->currentPage];
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_FadeIn(void)
|
||
|
{
|
||
|
DrawBgTilemap(3, gNamingScreenBackground_Tilemap);
|
||
|
sNamingScreen->currentPage = KBPAGE_LETTERS_UPPER;
|
||
|
DrawBgTilemap(2, gNamingScreenKeyboardLower_Tilemap);
|
||
|
DrawBgTilemap(1, gNamingScreenKeyboardUpper_Tilemap);
|
||
|
PrintKeyboardKeys(sNamingScreen->windows[WIN_KB_PAGE_2], KEYBOARD_LETTERS_LOWER);
|
||
|
PrintKeyboardKeys(sNamingScreen->windows[WIN_KB_PAGE_1], KEYBOARD_LETTERS_UPPER);
|
||
|
NamingScreen_Dummy(2, KEYBOARD_LETTERS_LOWER);
|
||
|
NamingScreen_Dummy(1, KEYBOARD_LETTERS_UPPER);
|
||
|
DrawTextEntry();
|
||
|
DrawTextEntryBox();
|
||
|
PrintControls();
|
||
|
CopyBgTilemapBufferToVram(1);
|
||
|
CopyBgTilemapBufferToVram(2);
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
BlendPalettes(PALETTES_ALL, 16, 0);
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
||
|
sNamingScreen->state++;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_WaitFadeIn(void)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
SetInputState(INPUT_STATE_ENABLED);
|
||
|
SetCursorFlashing(TRUE);
|
||
|
sNamingScreen->state++;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_HandleInput(void)
|
||
|
{
|
||
|
return HandleKeyboardEvent();
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_MoveToOKButton(void)
|
||
|
{
|
||
|
if (IsCursorAnimFinished())
|
||
|
{
|
||
|
SetInputState(INPUT_STATE_ENABLED);
|
||
|
MoveCursorToOKButton();
|
||
|
sNamingScreen->state = STATE_HANDLE_INPUT;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_PressedOKButton(void)
|
||
|
{
|
||
|
SaveInputText();
|
||
|
SetInputState(INPUT_STATE_DISABLED);
|
||
|
SetCursorFlashing(FALSE);
|
||
|
TryStartButtonFlash(BUTTON_COUNT, FALSE, TRUE);
|
||
|
if (sNamingScreen->templateNum == NAMING_SCREEN_CAUGHT_MON
|
||
|
&& CalculatePlayerPartyCount() >= PARTY_SIZE)
|
||
|
{
|
||
|
DisplaySentToPCMessage();
|
||
|
sNamingScreen->state = STATE_WAIT_SENT_TO_PC_MESSAGE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sNamingScreen->state = STATE_FADE_OUT;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_FadeOut(void)
|
||
|
{
|
||
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
||
|
sNamingScreen->state++;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_Exit(void)
|
||
|
{
|
||
|
if (!gPaletteFade.active)
|
||
|
{
|
||
|
if (sNamingScreen->templateNum == NAMING_SCREEN_PLAYER)
|
||
|
SeedRngAndSetTrainerId();
|
||
|
SetMainCallback2(sNamingScreen->returnCallback);
|
||
|
DestroyTask(FindTaskIdByFunc(Task_NamingScreen));
|
||
|
FreeAllWindowBuffers();
|
||
|
FREE_AND_SET_NULL(sNamingScreen);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static void DisplaySentToPCMessage(void)
|
||
|
{
|
||
|
u8 stringToDisplay = 0;
|
||
|
|
||
|
if (!IsDestinationBoxFull())
|
||
|
{
|
||
|
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON)));
|
||
|
StringCopy(gStringVar2, sNamingScreen->destBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON)));
|
||
|
StringCopy(gStringVar2, sNamingScreen->destBuffer);
|
||
|
StringCopy(gStringVar3, GetBoxNamePtr(GetPCBoxToSendMon()));
|
||
|
stringToDisplay = 2;
|
||
|
}
|
||
|
|
||
|
if (FlagGet(FLAG_SYS_PC_LANETTE))
|
||
|
stringToDisplay++;
|
||
|
|
||
|
StringExpandPlaceholders(gStringVar4, sTransferredToPCMessages[stringToDisplay]);
|
||
|
DrawDialogueFrame(0, 0);
|
||
|
gTextFlags.canABSpeedUpPrint = TRUE;
|
||
|
AddTextPrinterParameterized2(0, FONT_NORMAL, gStringVar4, GetPlayerTextSpeedDelay(), 0, 2, 1, 3);
|
||
|
CopyWindowToVram(0, COPYWIN_FULL);
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_WaitSentToPCMessage(void)
|
||
|
{
|
||
|
RunTextPrinters();
|
||
|
if (!IsTextPrinterActive(0) && JOY_NEW(A_BUTTON))
|
||
|
sNamingScreen->state = STATE_FADE_OUT;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_StartPageSwap(void)
|
||
|
{
|
||
|
SetInputState(INPUT_STATE_DISABLED);
|
||
|
StartPageSwapButtonAnim();
|
||
|
StartPageSwapAnim();
|
||
|
SetCursorInvisibility(TRUE);
|
||
|
TryStartButtonFlash(BUTTON_PAGE, FALSE, TRUE);
|
||
|
PlaySE(SE_WIN_OPEN);
|
||
|
sNamingScreen->state = STATE_WAIT_PAGE_SWAP;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 MainState_WaitPageSwap(void)
|
||
|
{
|
||
|
s16 cursorX;
|
||
|
s16 cursorY;
|
||
|
bool32 onLastColumn;
|
||
|
|
||
|
if (IsPageSwapAnimNotInProgress())
|
||
|
{
|
||
|
|
||
|
GetCursorPos(&cursorX, &cursorY);
|
||
|
onLastColumn = (cursorX == GetCurrentPageColumnCount());
|
||
|
|
||
|
sNamingScreen->state = STATE_HANDLE_INPUT;
|
||
|
sNamingScreen->currentPage++;
|
||
|
sNamingScreen->currentPage %= KBPAGE_COUNT;
|
||
|
|
||
|
if (onLastColumn)
|
||
|
{
|
||
|
cursorX = GetCurrentPageColumnCount();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (cursorX >= GetCurrentPageColumnCount())
|
||
|
cursorX = GetCurrentPageColumnCount() - 1;
|
||
|
}
|
||
|
|
||
|
SetCursorPos(cursorX, cursorY);
|
||
|
DrawKeyboardPageOnDeck();
|
||
|
SetInputState(INPUT_STATE_ENABLED);
|
||
|
SetCursorInvisibility(FALSE);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
// Page Swap
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
#define tState data[0]
|
||
|
#define tFrameCount data[1]
|
||
|
|
||
|
static bool8 PageSwapAnimState_Init(struct Task *);
|
||
|
static bool8 PageSwapAnimState_1(struct Task *);
|
||
|
static bool8 PageSwapAnimState_2(struct Task *);
|
||
|
static bool8 PageSwapAnimState_Done(struct Task *);
|
||
|
|
||
|
static bool8 (*const sPageSwapAnimStateFuncs[])(struct Task *) =
|
||
|
{
|
||
|
PageSwapAnimState_Init,
|
||
|
PageSwapAnimState_1,
|
||
|
PageSwapAnimState_2,
|
||
|
PageSwapAnimState_Done,
|
||
|
};
|
||
|
|
||
|
static void StartPageSwapAnim(void)
|
||
|
{
|
||
|
u8 taskId;
|
||
|
|
||
|
taskId = CreateTask(Task_HandlePageSwapAnim, 0);
|
||
|
Task_HandlePageSwapAnim(taskId);
|
||
|
}
|
||
|
|
||
|
static void Task_HandlePageSwapAnim(u8 taskId)
|
||
|
{
|
||
|
while (sPageSwapAnimStateFuncs[gTasks[taskId].tState](&gTasks[taskId]) != 0);
|
||
|
}
|
||
|
|
||
|
static bool8 IsPageSwapAnimNotInProgress(void)
|
||
|
{
|
||
|
if (FindTaskIdByFunc(Task_HandlePageSwapAnim) == TASK_NONE)
|
||
|
return TRUE;
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapAnimState_Init(struct Task *task)
|
||
|
{
|
||
|
sNamingScreen->bg1vOffset = 0;
|
||
|
sNamingScreen->bg2vOffset = 0;
|
||
|
task->tState++;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapAnimState_1(struct Task *task)
|
||
|
{
|
||
|
u16 *const vOffsets[] =
|
||
|
{
|
||
|
&sNamingScreen->bg2vOffset,
|
||
|
&sNamingScreen->bg1vOffset
|
||
|
};
|
||
|
|
||
|
task->tFrameCount += 4;
|
||
|
*vOffsets[sNamingScreen->bgToReveal] = Sin(task->tFrameCount, 40);
|
||
|
*vOffsets[sNamingScreen->bgToHide] = Sin((task->tFrameCount + 128) & 0xFF, 40);
|
||
|
if (task->tFrameCount >= 64)
|
||
|
{
|
||
|
u8 temp = sNamingScreen->bg1Priority; //Why u8 and not u16?
|
||
|
|
||
|
sNamingScreen->bg1Priority = sNamingScreen->bg2Priority;
|
||
|
sNamingScreen->bg2Priority = temp;
|
||
|
task->tState++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapAnimState_2(struct Task *task)
|
||
|
{
|
||
|
u16 *const vOffsets[] =
|
||
|
{
|
||
|
&sNamingScreen->bg2vOffset,
|
||
|
&sNamingScreen->bg1vOffset
|
||
|
};
|
||
|
|
||
|
task->tFrameCount += 4;
|
||
|
*vOffsets[sNamingScreen->bgToReveal] = Sin(task->tFrameCount, 40);
|
||
|
*vOffsets[sNamingScreen->bgToHide] = Sin((task->tFrameCount + 128) & 0xFF, 40);
|
||
|
if (task->tFrameCount >= 128)
|
||
|
{
|
||
|
u8 temp = sNamingScreen->bgToReveal;
|
||
|
|
||
|
sNamingScreen->bgToReveal = sNamingScreen->bgToHide;
|
||
|
sNamingScreen->bgToHide = temp;
|
||
|
task->tState++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapAnimState_Done(struct Task *task)
|
||
|
{
|
||
|
DestroyTask(FindTaskIdByFunc(Task_HandlePageSwapAnim));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#undef tState
|
||
|
#undef tFrameCount
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
//
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
#define tButtonId data[0]
|
||
|
#define tKeepFlashing data[1]
|
||
|
#define tAllowFlash data[2]
|
||
|
#define tColor data[3]
|
||
|
#define tColorIncr data[4]
|
||
|
#define tColorDelay data[5]
|
||
|
#define tColorDelta data[6]
|
||
|
|
||
|
static void CreateButtonFlashTask(void)
|
||
|
{
|
||
|
u8 taskId;
|
||
|
|
||
|
taskId = CreateTask(Task_UpdateButtonFlash, 3);
|
||
|
gTasks[taskId].tButtonId = BUTTON_COUNT;
|
||
|
}
|
||
|
|
||
|
static void TryStartButtonFlash(u8 button, bool8 keepFlashing, bool8 interruptCurFlash)
|
||
|
{
|
||
|
struct Task *task = &gTasks[FindTaskIdByFunc(Task_UpdateButtonFlash)];
|
||
|
|
||
|
if (button == task->tButtonId && !interruptCurFlash)
|
||
|
{
|
||
|
task->tKeepFlashing = keepFlashing;
|
||
|
task->tAllowFlash = TRUE;
|
||
|
return;
|
||
|
}
|
||
|
if (button == BUTTON_COUNT && !task->tKeepFlashing && !interruptCurFlash)
|
||
|
return;
|
||
|
|
||
|
if (task->tButtonId != BUTTON_COUNT)
|
||
|
RestoreButtonColor(task->tButtonId);
|
||
|
|
||
|
StartButtonFlash(task, button, keepFlashing);
|
||
|
}
|
||
|
|
||
|
static void Task_UpdateButtonFlash(u8 taskId)
|
||
|
{
|
||
|
struct Task *task = &gTasks[taskId];
|
||
|
|
||
|
if (task->tButtonId == BUTTON_COUNT || !task->tAllowFlash)
|
||
|
return;
|
||
|
|
||
|
MultiplyInvertedPaletteRGBComponents(GetButtonPalOffset(task->tButtonId), task->tColor, task->tColor, task->tColor);
|
||
|
|
||
|
if (task->tColorDelay && --task->tColorDelay)
|
||
|
return;
|
||
|
|
||
|
task->tColorDelay = 2;
|
||
|
if (task->tColorIncr >= 0)
|
||
|
{
|
||
|
if (task->tColor < 14)
|
||
|
{
|
||
|
task->tColor += task->tColorIncr;
|
||
|
task->tColorDelta += task->tColorIncr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
task->tColor = 16;
|
||
|
task->tColorDelta++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
task->tColor += task->tColorIncr;
|
||
|
task->tColorDelta += task->tColorIncr;
|
||
|
}
|
||
|
|
||
|
if (task->tColor == 16 && task->tColorDelta == 22)
|
||
|
{
|
||
|
task->tColorIncr = -4;
|
||
|
}
|
||
|
else if (task->tColor == 0)
|
||
|
{
|
||
|
task->tAllowFlash = task->tKeepFlashing;
|
||
|
task->tColorIncr = 2;
|
||
|
task->tColorDelta = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static u16 GetButtonPalOffset(u8 button)
|
||
|
{
|
||
|
const u16 palOffsets[BUTTON_COUNT + 1] =
|
||
|
{
|
||
|
[BUTTON_PAGE] = IndexOfSpritePaletteTag(PALTAG_PAGE_SWAP) * 16 + 0x10E,
|
||
|
[BUTTON_BACK] = IndexOfSpritePaletteTag(PALTAG_BACK_BUTTON) * 16 + 0x10E,
|
||
|
[BUTTON_OK] = IndexOfSpritePaletteTag(PALTAG_OK_BUTTON) * 16 + 0x10E,
|
||
|
[BUTTON_COUNT] = IndexOfSpritePaletteTag(PALTAG_OK_BUTTON) * 16 + 0x101,
|
||
|
};
|
||
|
|
||
|
return palOffsets[button];
|
||
|
}
|
||
|
|
||
|
static void RestoreButtonColor(u8 button)
|
||
|
{
|
||
|
u16 index = GetButtonPalOffset(button);
|
||
|
gPlttBufferFaded[index] = gPlttBufferUnfaded[index];
|
||
|
}
|
||
|
|
||
|
static void StartButtonFlash(struct Task *task, u8 button, bool8 keepFlashing)
|
||
|
{
|
||
|
task->tButtonId = button;
|
||
|
task->tKeepFlashing = keepFlashing;
|
||
|
task->tAllowFlash = TRUE;
|
||
|
task->tColor = 4;
|
||
|
task->tColorIncr = 2;
|
||
|
task->tColorDelay = 0;
|
||
|
task->tColorDelta = 4;
|
||
|
}
|
||
|
|
||
|
#undef tButtonId
|
||
|
#undef tColor
|
||
|
|
||
|
// Sprite data for the the cursor
|
||
|
#define sX data[0]
|
||
|
#define sY data[1]
|
||
|
#define sPrevX data[2]
|
||
|
#define sPrevY data[3]
|
||
|
#define sInvisible data[4] & 0x00FF
|
||
|
#define sFlashing data[4] & 0xFF00
|
||
|
#define sColor data[5]
|
||
|
#define sColorIncr data[6]
|
||
|
#define sColorDelay data[7]
|
||
|
|
||
|
static void SpriteCB_Cursor(struct Sprite *sprite)
|
||
|
{
|
||
|
if (sprite->animEnded)
|
||
|
StartSpriteAnim(sprite, 0);
|
||
|
|
||
|
// Hide cursor when on button column
|
||
|
sprite->invisible = sprite->sInvisible;
|
||
|
if (sprite->sX == GetCurrentPageColumnCount())
|
||
|
sprite->invisible = TRUE;
|
||
|
|
||
|
if (sprite->invisible
|
||
|
|| !(sprite->sFlashing)
|
||
|
|| sprite->sX != sprite->sPrevX
|
||
|
|| sprite->sY != sprite->sPrevY)
|
||
|
{
|
||
|
sprite->sColor = 0;
|
||
|
sprite->sColorIncr = 2;
|
||
|
sprite->sColorDelay = 2;
|
||
|
}
|
||
|
|
||
|
sprite->sColorDelay--;
|
||
|
if (sprite->sColorDelay == 0)
|
||
|
{
|
||
|
sprite->sColor += sprite->sColorIncr;
|
||
|
if (sprite->sColor == 16 || sprite->sColor == 0)
|
||
|
sprite->sColorIncr = -sprite->sColorIncr;
|
||
|
sprite->sColorDelay = 2;
|
||
|
}
|
||
|
|
||
|
if (sprite->sFlashing)
|
||
|
{
|
||
|
s8 gb = sprite->sColor;
|
||
|
s8 r = sprite->sColor >> 1;
|
||
|
u16 index = IndexOfSpritePaletteTag(PALTAG_CURSOR) * 16 + 0x0101;
|
||
|
|
||
|
MultiplyInvertedPaletteRGBComponents(index, r, gb, gb);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define sDelay data[0]
|
||
|
#define sXPosId data[1]
|
||
|
|
||
|
static void SpriteCB_InputArrow(struct Sprite *sprite)
|
||
|
{
|
||
|
const s16 x[] = {0, -4, -2, -1};
|
||
|
|
||
|
if (sprite->sDelay == 0 || --sprite->sDelay == 0)
|
||
|
{
|
||
|
sprite->sDelay = 8;
|
||
|
sprite->sXPosId = (sprite->sXPosId + 1) & (ARRAY_COUNT(x) - 1);
|
||
|
}
|
||
|
sprite->x2 = x[sprite->sXPosId];
|
||
|
}
|
||
|
|
||
|
#undef sDelay
|
||
|
#undef sXPosId
|
||
|
|
||
|
#define sId data[0] // set in CreateTextEntrySprites
|
||
|
#define sYPosId data[1]
|
||
|
#define sDelay data[2]
|
||
|
|
||
|
static void SpriteCB_Underscore(struct Sprite *sprite)
|
||
|
{
|
||
|
const s16 y[] = {2, 3, 2, 1};
|
||
|
u8 pos;
|
||
|
|
||
|
pos = GetTextEntryPosition();
|
||
|
if (pos != (u8)sprite->sId)
|
||
|
{
|
||
|
sprite->y2 = 0;
|
||
|
sprite->sYPosId = 0;
|
||
|
sprite->sDelay = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprite->y2 = y[sprite->sYPosId];
|
||
|
sprite->sDelay++;
|
||
|
if (sprite->sDelay > 8)
|
||
|
{
|
||
|
sprite->sYPosId = (sprite->sYPosId + 1) & (ARRAY_COUNT(y) - 1);
|
||
|
sprite->sDelay = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef sId
|
||
|
#undef sYPosId
|
||
|
#undef sDelay
|
||
|
|
||
|
static void CreateSprites(void)
|
||
|
{
|
||
|
CreateCursorSprite();
|
||
|
CreatePageSwapButtonSprites();
|
||
|
CreateBackOkSprites();
|
||
|
CreateTextEntrySprites();
|
||
|
CreateInputTargetIcon();
|
||
|
}
|
||
|
|
||
|
static void CreateCursorSprite(void)
|
||
|
{
|
||
|
sNamingScreen->cursorSpriteId = CreateSprite(&sSpriteTemplate_Cursor, 38, 88, 1);
|
||
|
SetCursorInvisibility(TRUE);
|
||
|
gSprites[sNamingScreen->cursorSpriteId].oam.priority = 1;
|
||
|
gSprites[sNamingScreen->cursorSpriteId].oam.objMode = ST_OAM_OBJ_BLEND;
|
||
|
gSprites[sNamingScreen->cursorSpriteId].sColorIncr = 1; // ? immediately overwritten
|
||
|
gSprites[sNamingScreen->cursorSpriteId].sColorIncr = 2;
|
||
|
SetCursorPos(0, 0);
|
||
|
}
|
||
|
|
||
|
static void SetCursorPos(s16 x, s16 y)
|
||
|
{
|
||
|
struct Sprite *cursorSprite = &gSprites[sNamingScreen->cursorSpriteId];
|
||
|
|
||
|
if (x < sPageColumnCounts[CurrentPageToKeyboardId()])
|
||
|
cursorSprite->x = sPageColumnXPos[x + CurrentPageToKeyboardId() * KBCOL_COUNT] + 38;
|
||
|
else
|
||
|
cursorSprite->x = 0;
|
||
|
|
||
|
cursorSprite->y = y * 16 + 88;
|
||
|
cursorSprite->sPrevX = cursorSprite->sX;
|
||
|
cursorSprite->sPrevY = cursorSprite->sY;
|
||
|
cursorSprite->sX = x;
|
||
|
cursorSprite->sY = y;
|
||
|
}
|
||
|
|
||
|
static void GetCursorPos(s16 *x, s16 *y)
|
||
|
{
|
||
|
struct Sprite *cursorSprite = &gSprites[sNamingScreen->cursorSpriteId];
|
||
|
|
||
|
*x = cursorSprite->sX;
|
||
|
*y = cursorSprite->sY;
|
||
|
}
|
||
|
|
||
|
static void MoveCursorToOKButton(void)
|
||
|
{
|
||
|
SetCursorPos(GetCurrentPageColumnCount(), 2);
|
||
|
}
|
||
|
|
||
|
static void SetCursorInvisibility(bool8 invisible)
|
||
|
{
|
||
|
gSprites[sNamingScreen->cursorSpriteId].data[4] &= 0xFF00;
|
||
|
gSprites[sNamingScreen->cursorSpriteId].data[4] |= invisible; // sInvisible
|
||
|
StartSpriteAnim(&gSprites[sNamingScreen->cursorSpriteId], 0);
|
||
|
}
|
||
|
|
||
|
static void SetCursorFlashing(bool8 flashing)
|
||
|
{
|
||
|
gSprites[sNamingScreen->cursorSpriteId].data[4] &= 0xFF;
|
||
|
gSprites[sNamingScreen->cursorSpriteId].data[4] |= flashing << 8; // sFlashing
|
||
|
}
|
||
|
|
||
|
static void SquishCursor(void)
|
||
|
{
|
||
|
StartSpriteAnim(&gSprites[sNamingScreen->cursorSpriteId], 1);
|
||
|
}
|
||
|
|
||
|
static bool8 IsCursorAnimFinished(void)
|
||
|
{
|
||
|
return gSprites[sNamingScreen->cursorSpriteId].animEnded;
|
||
|
}
|
||
|
|
||
|
static const u8 sButtonKeyRoles[] = {KEY_ROLE_PAGE, KEY_ROLE_BACKSPACE, KEY_ROLE_OK};
|
||
|
|
||
|
static u8 GetKeyRoleAtCursorPos(void)
|
||
|
{
|
||
|
s16 cursorX;
|
||
|
s16 cursorY;
|
||
|
|
||
|
GetCursorPos(&cursorX, &cursorY);
|
||
|
if (cursorX < GetCurrentPageColumnCount())
|
||
|
return KEY_ROLE_CHAR;
|
||
|
else
|
||
|
return sButtonKeyRoles[cursorY];
|
||
|
}
|
||
|
|
||
|
// If the cursor's x is equal to the column count, cursor is in the button column
|
||
|
static u8 GetCurrentPageColumnCount(void)
|
||
|
{
|
||
|
return sPageColumnCounts[CurrentPageToKeyboardId()];
|
||
|
}
|
||
|
|
||
|
#undef sX
|
||
|
#undef sY
|
||
|
#undef sPrevX
|
||
|
#undef sPrevY
|
||
|
#undef sInvisible
|
||
|
#undef sFlashing
|
||
|
#undef sColor
|
||
|
#undef sColorIncr
|
||
|
#undef sColorDelay
|
||
|
|
||
|
static bool8 PageSwapSprite_Init(struct Sprite *);
|
||
|
static bool8 PageSwapSprite_Idle(struct Sprite *);
|
||
|
static bool8 PageSwapSprite_SlideOff(struct Sprite *);
|
||
|
static bool8 PageSwapSprite_SlideOn(struct Sprite *);
|
||
|
|
||
|
#define sState data[0]
|
||
|
#define sPage data[1]
|
||
|
#define sTextSpriteId data[6]
|
||
|
#define sButtonSpriteId data[7]
|
||
|
|
||
|
static void CreatePageSwapButtonSprites(void)
|
||
|
{
|
||
|
u8 frameSpriteId;
|
||
|
u8 textSpriteId;
|
||
|
u8 buttonSpriteId;
|
||
|
|
||
|
frameSpriteId = CreateSprite(&sSpriteTemplate_PageSwapFrame, 204, 88, 0);
|
||
|
sNamingScreen->swapBtnFrameSpriteId = frameSpriteId;
|
||
|
SetSubspriteTables(&gSprites[frameSpriteId], sSubspriteTable_PageSwapFrame);
|
||
|
gSprites[frameSpriteId].invisible = TRUE;
|
||
|
|
||
|
textSpriteId = CreateSprite(&sSpriteTemplate_PageSwapText, 204, 84, 1);
|
||
|
gSprites[frameSpriteId].sTextSpriteId = textSpriteId;
|
||
|
SetSubspriteTables(&gSprites[textSpriteId], sSubspriteTable_PageSwapText);
|
||
|
gSprites[textSpriteId].invisible = TRUE;
|
||
|
|
||
|
buttonSpriteId = CreateSprite(&sSpriteTemplate_PageSwapButton, 204, 83, 2);
|
||
|
gSprites[buttonSpriteId].oam.priority = 1;
|
||
|
gSprites[frameSpriteId].sButtonSpriteId = buttonSpriteId;
|
||
|
gSprites[buttonSpriteId].invisible = TRUE;
|
||
|
}
|
||
|
|
||
|
static void StartPageSwapButtonAnim(void)
|
||
|
{
|
||
|
struct Sprite *sprite = &gSprites[sNamingScreen->swapBtnFrameSpriteId];
|
||
|
|
||
|
sprite->sState = 2; // go to PageSwapSprite_SlideOff
|
||
|
sprite->sPage = sNamingScreen->currentPage;
|
||
|
}
|
||
|
|
||
|
static u8 (*const sPageSwapSpriteFuncs[])(struct Sprite *) =
|
||
|
{
|
||
|
PageSwapSprite_Init,
|
||
|
PageSwapSprite_Idle,
|
||
|
PageSwapSprite_SlideOff,
|
||
|
PageSwapSprite_SlideOn,
|
||
|
};
|
||
|
|
||
|
static void SpriteCB_PageSwap(struct Sprite *sprite)
|
||
|
{
|
||
|
while (sPageSwapSpriteFuncs[sprite->sState](sprite));
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapSprite_Init(struct Sprite *sprite)
|
||
|
{
|
||
|
struct Sprite *text = &gSprites[sprite->sTextSpriteId];
|
||
|
struct Sprite *button = &gSprites[sprite->sButtonSpriteId];
|
||
|
|
||
|
SetPageSwapButtonGfx(PageToNextGfxId(sNamingScreen->currentPage), text, button);
|
||
|
sprite->sState++;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapSprite_Idle(struct Sprite *sprite)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapSprite_SlideOff(struct Sprite *sprite)
|
||
|
{
|
||
|
struct Sprite *text = &gSprites[sprite->sTextSpriteId];
|
||
|
struct Sprite *button = &gSprites[sprite->sButtonSpriteId];
|
||
|
|
||
|
text->y2++;
|
||
|
if (text->y2 > 7)
|
||
|
{
|
||
|
sprite->sState++;
|
||
|
text->y2 = -4;
|
||
|
text->invisible = TRUE;
|
||
|
SetPageSwapButtonGfx(PageToNextGfxId(((u8)sprite->sPage + 1) % KBPAGE_COUNT), text, button);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 PageSwapSprite_SlideOn(struct Sprite *sprite)
|
||
|
{
|
||
|
struct Sprite *text = &gSprites[sprite->sTextSpriteId];
|
||
|
|
||
|
text->invisible = FALSE;
|
||
|
text->y2++;
|
||
|
if (text->y2 >= 0)
|
||
|
{
|
||
|
text->y2 = 0;
|
||
|
sprite->sState = 1; // go to PageSwapSprite_Idle
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static const u16 sPageSwapPalTags[] = {
|
||
|
[PAGE_SWAP_UPPER] = PALTAG_PAGE_SWAP_UPPER,
|
||
|
[PAGE_SWAP_OTHERS] = PALTAG_PAGE_SWAP_OTHERS,
|
||
|
[PAGE_SWAP_LOWER] = PALTAG_PAGE_SWAP_LOWER
|
||
|
};
|
||
|
|
||
|
static const u16 sPageSwapGfxTags[] = {
|
||
|
[PAGE_SWAP_UPPER] = GFXTAG_PAGE_SWAP_UPPER,
|
||
|
[PAGE_SWAP_OTHERS] = GFXTAG_PAGE_SWAP_OTHERS,
|
||
|
[PAGE_SWAP_LOWER] = GFXTAG_PAGE_SWAP_LOWER
|
||
|
};
|
||
|
|
||
|
static void SetPageSwapButtonGfx(u8 page, struct Sprite *text, struct Sprite *button)
|
||
|
{
|
||
|
button->oam.paletteNum = IndexOfSpritePaletteTag(sPageSwapPalTags[page]);
|
||
|
text->sheetTileStart = GetSpriteTileStartByTag(sPageSwapGfxTags[page]);
|
||
|
text->subspriteTableNum = page;
|
||
|
}
|
||
|
|
||
|
#undef sState
|
||
|
#undef sPage
|
||
|
#undef sTextSpriteId
|
||
|
#undef sButtonSpriteId
|
||
|
|
||
|
static void CreateBackOkSprites(void)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
spriteId = CreateSprite(&sSpriteTemplate_BackButton, 204, 116, 0);
|
||
|
SetSubspriteTables(&gSprites[spriteId], sSubspriteTable_Button);
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
|
||
|
spriteId = CreateSprite(&sSpriteTemplate_OkButton, 204, 140, 0);
|
||
|
SetSubspriteTables(&gSprites[spriteId], sSubspriteTable_Button);
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
}
|
||
|
|
||
|
static void CreateTextEntrySprites(void)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
s16 xPos;
|
||
|
u8 i;
|
||
|
|
||
|
xPos = sNamingScreen->inputCharBaseXPos - 5;
|
||
|
spriteId = CreateSprite(&sSpriteTemplate_InputArrow, xPos, 56, 0);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
xPos = sNamingScreen->inputCharBaseXPos;
|
||
|
for (i = 0; i < sNamingScreen->template->maxChars; i++, xPos += 8)
|
||
|
{
|
||
|
spriteId = CreateSprite(&sSpriteTemplate_Underscore, xPos + 3, 60, 0);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
gSprites[spriteId].data[0] = i;
|
||
|
gSprites[spriteId].invisible = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
// Icon creation (the thing you're naming or giving input to)
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
static void NamingScreen_NoIcon(void);
|
||
|
static void NamingScreen_CreatePlayerIcon(void);
|
||
|
static void NamingScreen_CreatePCIcon(void);
|
||
|
static void NamingScreen_CreateMonIcon(void);
|
||
|
static void NamingScreen_CreateWaldaDadIcon(void);
|
||
|
|
||
|
static void (*const sIconFunctions[])(void) =
|
||
|
{
|
||
|
NamingScreen_NoIcon,
|
||
|
NamingScreen_CreatePlayerIcon,
|
||
|
NamingScreen_CreatePCIcon,
|
||
|
NamingScreen_CreateMonIcon,
|
||
|
NamingScreen_CreateWaldaDadIcon,
|
||
|
};
|
||
|
|
||
|
static void CreateInputTargetIcon(void)
|
||
|
{
|
||
|
sIconFunctions[sNamingScreen->template->iconFunction]();
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_NoIcon(void)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_CreatePlayerIcon(void)
|
||
|
{
|
||
|
u8 rivalGfxId;
|
||
|
u8 spriteId;
|
||
|
|
||
|
rivalGfxId = GetRivalAvatarGraphicsIdByStateIdAndGender(0, sNamingScreen->monSpecies);
|
||
|
spriteId = CreateObjectGraphicsSprite(rivalGfxId, SpriteCallbackDummy, 56, 37, 0);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
StartSpriteAnim(&gSprites[spriteId], 4);
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_CreatePCIcon(void)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
spriteId = CreateSprite(&sSpriteTemplate_PCIcon, 56, 41, 0);
|
||
|
SetSubspriteTables(&gSprites[spriteId], sSubspriteTable_PCIcon);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_CreateMonIcon(void)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
LoadMonIconPalettes();
|
||
|
spriteId = CreateMonIcon(sNamingScreen->monSpecies, SpriteCallbackDummy, 56, 40, 0, sNamingScreen->monPersonality, 1);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_CreateWaldaDadIcon(void)
|
||
|
{
|
||
|
u8 spriteId;
|
||
|
|
||
|
spriteId = CreateObjectGraphicsSprite(OBJ_EVENT_GFX_MAN_1, SpriteCallbackDummy, 56, 37, 0);
|
||
|
gSprites[spriteId].oam.priority = 3;
|
||
|
StartSpriteAnim(&gSprites[spriteId], 4);
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
// Keyboard handling
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
static bool8 KeyboardKeyHandler_Character(u8);
|
||
|
static bool8 KeyboardKeyHandler_Page(u8);
|
||
|
static bool8 KeyboardKeyHandler_Backspace(u8);
|
||
|
static bool8 KeyboardKeyHandler_OK(u8);
|
||
|
|
||
|
static bool8 (*const sKeyboardKeyHandlers[])(u8) =
|
||
|
{
|
||
|
[KEY_ROLE_CHAR] = KeyboardKeyHandler_Character,
|
||
|
[KEY_ROLE_PAGE] = KeyboardKeyHandler_Page,
|
||
|
[KEY_ROLE_BACKSPACE] = KeyboardKeyHandler_Backspace,
|
||
|
[KEY_ROLE_OK] = KeyboardKeyHandler_OK,
|
||
|
};
|
||
|
|
||
|
static bool8 HandleKeyboardEvent(void)
|
||
|
{
|
||
|
u8 input = GetInputEvent();
|
||
|
u8 keyRole = GetKeyRoleAtCursorPos();
|
||
|
|
||
|
if (input == INPUT_SELECT)
|
||
|
{
|
||
|
return SwapKeyboardPage();
|
||
|
}
|
||
|
else if (input == INPUT_B_BUTTON)
|
||
|
{
|
||
|
DeleteTextCharacter();
|
||
|
return FALSE;
|
||
|
}
|
||
|
else if (input == INPUT_START)
|
||
|
{
|
||
|
MoveCursorToOKButton();
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return sKeyboardKeyHandlers[keyRole](input);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool8 KeyboardKeyHandler_Character(u8 input)
|
||
|
{
|
||
|
TryStartButtonFlash(BUTTON_COUNT, FALSE, FALSE);
|
||
|
if (input == INPUT_A_BUTTON)
|
||
|
{
|
||
|
bool8 textFull = AddTextCharacter();
|
||
|
|
||
|
if (sNamingScreen ->currentPage == KBPAGE_LETTERS_UPPER && GetTextEntryPosition() == 1)
|
||
|
MainState_StartPageSwap();
|
||
|
|
||
|
SquishCursor();
|
||
|
if (textFull)
|
||
|
{
|
||
|
SetInputState(INPUT_STATE_OVERRIDE);
|
||
|
sNamingScreen->state = STATE_MOVE_TO_OK_BUTTON;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 KeyboardKeyHandler_Page(u8 input)
|
||
|
{
|
||
|
TryStartButtonFlash(BUTTON_PAGE, TRUE, FALSE);
|
||
|
if (input == INPUT_A_BUTTON)
|
||
|
return SwapKeyboardPage();
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 KeyboardKeyHandler_Backspace(u8 input)
|
||
|
{
|
||
|
TryStartButtonFlash(BUTTON_BACK, TRUE, FALSE);
|
||
|
if (input == INPUT_A_BUTTON)
|
||
|
DeleteTextCharacter();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 KeyboardKeyHandler_OK(u8 input)
|
||
|
{
|
||
|
TryStartButtonFlash(BUTTON_OK, TRUE, FALSE);
|
||
|
if (input == INPUT_A_BUTTON)
|
||
|
{
|
||
|
PlaySE(SE_SELECT);
|
||
|
sNamingScreen->state = STATE_PRESSED_OK;
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool8 SwapKeyboardPage(void)
|
||
|
{
|
||
|
sNamingScreen->state = STATE_START_PAGE_SWAP;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
// Input handling
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
#define tState data[0]
|
||
|
#define tKeyboardEvent data[1]
|
||
|
#define tButtonId data[2]
|
||
|
|
||
|
|
||
|
static void Input_Disabled(struct Task *);
|
||
|
static void Input_Enabled(struct Task *);
|
||
|
static void Input_Override(struct Task *);
|
||
|
|
||
|
static void (*const sInputFuncs[])(struct Task *) =
|
||
|
{
|
||
|
[INPUT_STATE_DISABLED] = Input_Disabled,
|
||
|
[INPUT_STATE_ENABLED] = Input_Enabled,
|
||
|
[INPUT_STATE_OVERRIDE] = Input_Override,
|
||
|
};
|
||
|
|
||
|
static void Task_HandleInput(u8);
|
||
|
static void HandleDpadMovement(struct Task *);
|
||
|
|
||
|
static void CreateInputHandlerTask(void)
|
||
|
{
|
||
|
CreateTask(Task_HandleInput, 1);
|
||
|
}
|
||
|
|
||
|
static u8 GetInputEvent(void)
|
||
|
{
|
||
|
u8 taskId = FindTaskIdByFunc(Task_HandleInput);
|
||
|
|
||
|
return gTasks[taskId].tKeyboardEvent;
|
||
|
}
|
||
|
|
||
|
static void SetInputState(u8 state)
|
||
|
{
|
||
|
u8 taskId = FindTaskIdByFunc(Task_HandleInput);
|
||
|
|
||
|
gTasks[taskId].tState = state;
|
||
|
}
|
||
|
|
||
|
static void Task_HandleInput(u8 taskId)
|
||
|
{
|
||
|
sInputFuncs[gTasks[taskId].tState](&gTasks[taskId]);
|
||
|
}
|
||
|
|
||
|
static void Input_Disabled(struct Task *task)
|
||
|
{
|
||
|
task->tKeyboardEvent = INPUT_NONE;
|
||
|
}
|
||
|
|
||
|
static void Input_Enabled(struct Task *task)
|
||
|
{
|
||
|
task->tKeyboardEvent = INPUT_NONE;
|
||
|
|
||
|
if (JOY_NEW(A_BUTTON))
|
||
|
task->tKeyboardEvent = INPUT_A_BUTTON;
|
||
|
else if (JOY_NEW(B_BUTTON))
|
||
|
task->tKeyboardEvent = INPUT_B_BUTTON;
|
||
|
else if (JOY_NEW(SELECT_BUTTON))
|
||
|
task->tKeyboardEvent = INPUT_SELECT;
|
||
|
else if (JOY_NEW(START_BUTTON))
|
||
|
task->tKeyboardEvent = INPUT_START;
|
||
|
else
|
||
|
HandleDpadMovement(task);
|
||
|
}
|
||
|
|
||
|
static void Input_Override(struct Task *task)
|
||
|
{
|
||
|
task->tKeyboardEvent = INPUT_NONE;
|
||
|
}
|
||
|
|
||
|
static void HandleDpadMovement(struct Task *task)
|
||
|
{
|
||
|
const s16 sDpadDeltaX[] =
|
||
|
{
|
||
|
[INPUT_NONE] = 0,
|
||
|
[INPUT_DPAD_UP] = 0,
|
||
|
[INPUT_DPAD_DOWN] = 0,
|
||
|
[INPUT_DPAD_LEFT] = -1,
|
||
|
[INPUT_DPAD_RIGHT] = 1
|
||
|
};
|
||
|
|
||
|
const s16 sDpadDeltaY[] =
|
||
|
{
|
||
|
[INPUT_NONE] = 0,
|
||
|
[INPUT_DPAD_UP] = -1,
|
||
|
[INPUT_DPAD_DOWN] = 1,
|
||
|
[INPUT_DPAD_LEFT] = 0,
|
||
|
[INPUT_DPAD_RIGHT] = 0
|
||
|
};
|
||
|
|
||
|
const s16 sKeyRowToButtonRow[KBROW_COUNT] = {0, 1, 1, 2};
|
||
|
const s16 sButtonRowToKeyRow[BUTTON_COUNT] = {0, 0, 3};
|
||
|
|
||
|
s16 cursorX;
|
||
|
s16 cursorY;
|
||
|
u16 input;
|
||
|
s16 prevCursorX;
|
||
|
|
||
|
GetCursorPos(&cursorX, &cursorY);
|
||
|
input = INPUT_NONE;
|
||
|
if (JOY_REPEAT(DPAD_UP))
|
||
|
input = INPUT_DPAD_UP;
|
||
|
if (JOY_REPEAT(DPAD_DOWN))
|
||
|
input = INPUT_DPAD_DOWN;
|
||
|
if (JOY_REPEAT(DPAD_LEFT))
|
||
|
input = INPUT_DPAD_LEFT;
|
||
|
if (JOY_REPEAT(DPAD_RIGHT))
|
||
|
input = INPUT_DPAD_RIGHT;
|
||
|
|
||
|
// Get new cursor position
|
||
|
prevCursorX = cursorX;
|
||
|
cursorX += sDpadDeltaX[input];
|
||
|
cursorY += sDpadDeltaY[input];
|
||
|
|
||
|
// Wrap cursor position in the X direction
|
||
|
if (cursorX < 0)
|
||
|
cursorX = GetCurrentPageColumnCount();
|
||
|
if (cursorX > GetCurrentPageColumnCount())
|
||
|
cursorX = 0;
|
||
|
|
||
|
|
||
|
// Handle moving on/off the button column
|
||
|
if (sDpadDeltaX[input] != 0)
|
||
|
{
|
||
|
if (cursorX == GetCurrentPageColumnCount())
|
||
|
{
|
||
|
// Moved onto button column
|
||
|
// Save cursor pos in tButtonId for moving back onto keys
|
||
|
task->tButtonId = cursorY;
|
||
|
cursorY = sKeyRowToButtonRow[cursorY];
|
||
|
}
|
||
|
else if (prevCursorX == GetCurrentPageColumnCount())
|
||
|
{
|
||
|
// Moved off button column
|
||
|
// If you're on the middle button, go to the row that
|
||
|
// the cursor was on previously (saved in tButtonId above)
|
||
|
if (cursorY == BUTTON_COUNT / 2)
|
||
|
cursorY = task->tButtonId;
|
||
|
else
|
||
|
cursorY = sButtonRowToKeyRow[cursorY];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Wrap cursor position in the y direction
|
||
|
if (cursorX == GetCurrentPageColumnCount())
|
||
|
{
|
||
|
// There are only 3 keys in the button column
|
||
|
// so wrap Y accordingly
|
||
|
if (cursorY < 0)
|
||
|
cursorY = BUTTON_COUNT - 1;
|
||
|
if (cursorY >= BUTTON_COUNT)
|
||
|
cursorY = 0;
|
||
|
|
||
|
if (cursorY == 0)
|
||
|
task->tButtonId = BUTTON_BACK;
|
||
|
else if (cursorY == BUTTON_COUNT - 1)
|
||
|
task->tButtonId = BUTTON_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (cursorY < 0)
|
||
|
cursorY = KBROW_COUNT - 1;
|
||
|
if (cursorY > KBROW_COUNT - 1)
|
||
|
cursorY = 0;
|
||
|
}
|
||
|
SetCursorPos(cursorX, cursorY);
|
||
|
}
|
||
|
|
||
|
#undef tState
|
||
|
#undef tKeyboardEvent
|
||
|
#undef tButtonId
|
||
|
|
||
|
static void DrawNormalTextEntryBox(void)
|
||
|
{
|
||
|
FillWindowPixelBuffer(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX], PIXEL_FILL(1));
|
||
|
AddTextPrinterParameterized(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX], FONT_NORMAL, sNamingScreen->template->title, 8, 1, 0, 0);
|
||
|
PutWindowTilemap(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX]);
|
||
|
}
|
||
|
|
||
|
static void DrawMonTextEntryBox(void)
|
||
|
{
|
||
|
u8 buffer[32];
|
||
|
|
||
|
StringCopy(buffer, gSpeciesNames[sNamingScreen->monSpecies]);
|
||
|
StringAppendN(buffer, sNamingScreen->template->title, 15);
|
||
|
FillWindowPixelBuffer(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX], PIXEL_FILL(1));
|
||
|
AddTextPrinterParameterized(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX], FONT_NORMAL, buffer, 8, 1, 0, 0);
|
||
|
PutWindowTilemap(sNamingScreen->windows[WIN_TEXT_ENTRY_BOX]);
|
||
|
}
|
||
|
|
||
|
static void (*const sDrawTextEntryBoxFuncs[])(void) =
|
||
|
{
|
||
|
[NAMING_SCREEN_PLAYER] = DrawNormalTextEntryBox,
|
||
|
[NAMING_SCREEN_BOX] = DrawNormalTextEntryBox,
|
||
|
[NAMING_SCREEN_CAUGHT_MON] = DrawMonTextEntryBox,
|
||
|
[NAMING_SCREEN_NICKNAME] = DrawMonTextEntryBox,
|
||
|
[NAMING_SCREEN_WALDA] = DrawNormalTextEntryBox,
|
||
|
};
|
||
|
|
||
|
static void DrawTextEntryBox(void)
|
||
|
{
|
||
|
sDrawTextEntryBoxFuncs[sNamingScreen->templateNum]();
|
||
|
}
|
||
|
|
||
|
static void DummyGenderIcon(void);
|
||
|
static void DrawGenderIcon(void);
|
||
|
|
||
|
static void (*const sDrawGenderIconFuncs[])(void) =
|
||
|
{
|
||
|
[FALSE] = DummyGenderIcon,
|
||
|
[TRUE] = DrawGenderIcon,
|
||
|
};
|
||
|
|
||
|
static void TryDrawGenderIcon(void)
|
||
|
{
|
||
|
sDrawGenderIconFuncs[sNamingScreen->template->addGenderIcon]();
|
||
|
}
|
||
|
|
||
|
static void DummyGenderIcon(void)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
static const u8 sGenderColors[2][3] =
|
||
|
{
|
||
|
{TEXT_COLOR_TRANSPARENT, TEXT_COLOR_LIGHT_BLUE, TEXT_COLOR_BLUE},
|
||
|
{TEXT_COLOR_TRANSPARENT, TEXT_COLOR_LIGHT_RED, TEXT_COLOR_RED}
|
||
|
};
|
||
|
|
||
|
static void DrawGenderIcon(void)
|
||
|
{
|
||
|
u8 text[2];
|
||
|
bool8 isFemale = FALSE;
|
||
|
|
||
|
StringCopy(text, gText_MaleSymbol);
|
||
|
if (sNamingScreen->monGender != MON_GENDERLESS)
|
||
|
{
|
||
|
if (sNamingScreen->monGender == MON_FEMALE)
|
||
|
{
|
||
|
StringCopy(text, gText_FemaleSymbol);
|
||
|
isFemale = TRUE;
|
||
|
}
|
||
|
AddTextPrinterParameterized3(sNamingScreen->windows[WIN_TEXT_ENTRY], FONT_NORMAL, 0x68, 1, sGenderColors[isFemale], TEXT_SKIP_DRAW, text);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static u8 GetCharAtKeyboardPos(s16 x, s16 y)
|
||
|
{
|
||
|
return sKeyboardChars[CurrentPageToKeyboardId()][y][x];
|
||
|
}
|
||
|
|
||
|
|
||
|
static u8 GetTextEntryPosition(void)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
for (i = 0; i < sNamingScreen->template->maxChars; i++)
|
||
|
{
|
||
|
if (sNamingScreen->textBuffer[i] == EOS)
|
||
|
return i;
|
||
|
}
|
||
|
return sNamingScreen->template->maxChars - 1;
|
||
|
}
|
||
|
|
||
|
static u8 GetPreviousTextCaretPosition(void)
|
||
|
{
|
||
|
s8 i;
|
||
|
|
||
|
for (i = sNamingScreen->template->maxChars - 1; i > 0; i--)
|
||
|
{
|
||
|
if (sNamingScreen->textBuffer[i] != EOS)
|
||
|
return i;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void DeleteTextCharacter(void)
|
||
|
{
|
||
|
u8 index;
|
||
|
u8 keyRole;
|
||
|
|
||
|
index = GetPreviousTextCaretPosition();
|
||
|
sNamingScreen->textBuffer[index] = 0;
|
||
|
DrawTextEntry();
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
sNamingScreen->textBuffer[index] = EOS;
|
||
|
keyRole = GetKeyRoleAtCursorPos();
|
||
|
|
||
|
// The below flashes the Back key once on delete
|
||
|
// It incorrectly leaves the Back key 1 shade lighter than its default
|
||
|
if (keyRole == KEY_ROLE_CHAR || keyRole == KEY_ROLE_BACKSPACE)
|
||
|
TryStartButtonFlash(BUTTON_BACK, FALSE, TRUE);
|
||
|
PlaySE(SE_BALL);
|
||
|
}
|
||
|
|
||
|
// Returns TRUE if the text entry is now full
|
||
|
static bool8 AddTextCharacter(void)
|
||
|
{
|
||
|
s16 x;
|
||
|
s16 y;
|
||
|
|
||
|
GetCursorPos(&x, &y);
|
||
|
BufferCharacter(GetCharAtKeyboardPos(x, y));
|
||
|
DrawTextEntry();
|
||
|
CopyBgTilemapBufferToVram(3);
|
||
|
PlaySE(SE_SELECT);
|
||
|
|
||
|
if (GetPreviousTextCaretPosition() != sNamingScreen->template->maxChars - 1)
|
||
|
return FALSE;
|
||
|
else
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void BufferCharacter(u8 ch)
|
||
|
{
|
||
|
u8 index = GetTextEntryPosition();
|
||
|
sNamingScreen->textBuffer[index] = ch;
|
||
|
}
|
||
|
|
||
|
static void SaveInputText(void)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
for (i = 0; i < sNamingScreen->template->maxChars; i++)
|
||
|
{
|
||
|
if (sNamingScreen->textBuffer[i] != CHAR_SPACE && sNamingScreen->textBuffer[i] != EOS)
|
||
|
{
|
||
|
StringCopyN(sNamingScreen->destBuffer, sNamingScreen->textBuffer, sNamingScreen->template->maxChars + 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void LoadGfx(void)
|
||
|
{
|
||
|
LZ77UnCompWram(gNamingScreenMenu_Gfx, sNamingScreen->tileBuffer);
|
||
|
LoadBgTiles(1, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0);
|
||
|
LoadBgTiles(2, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0);
|
||
|
LoadBgTiles(3, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0);
|
||
|
LoadSpriteSheets(sSpriteSheets);
|
||
|
LoadSpritePalettes(sSpritePalettes);
|
||
|
}
|
||
|
|
||
|
static void CreateHelperTasks(void)
|
||
|
{
|
||
|
CreateInputHandlerTask();
|
||
|
CreateButtonFlashTask();
|
||
|
}
|
||
|
|
||
|
static void LoadPalettes(void)
|
||
|
{
|
||
|
LoadPalette(gNamingScreenMenu_Pal, 0, 0xC0);
|
||
|
LoadPalette(sKeyboard_Pal, 0xA0, sizeof(sKeyboard_Pal));
|
||
|
LoadPalette(GetTextWindowPalette(2), 0xB0, 0x20);
|
||
|
}
|
||
|
|
||
|
static void DrawBgTilemap(u8 bg, const void *src)
|
||
|
{
|
||
|
CopyToBgTilemapBuffer(bg, src, 0, 0);
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_Dummy(u8 bg, u8 page)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
static void DrawTextEntry(void)
|
||
|
{
|
||
|
u8 i;
|
||
|
u8 temp[2];
|
||
|
u16 extraWidth;
|
||
|
u8 maxChars = sNamingScreen->template->maxChars;
|
||
|
u16 x = sNamingScreen->inputCharBaseXPos - 0x40;
|
||
|
|
||
|
FillWindowPixelBuffer(sNamingScreen->windows[WIN_TEXT_ENTRY], PIXEL_FILL(1));
|
||
|
|
||
|
for (i = 0; i < maxChars; i++)
|
||
|
{
|
||
|
temp[0] = sNamingScreen->textBuffer[i];
|
||
|
temp[1] = gText_ExpandedPlaceholder_Empty[0];
|
||
|
extraWidth = (IsWideLetter(temp[0]) == TRUE) ? 2 : 0;
|
||
|
|
||
|
AddTextPrinterParameterized(sNamingScreen->windows[WIN_TEXT_ENTRY], FONT_NORMAL, temp, i * 8 + x + extraWidth, 1, TEXT_SKIP_DRAW, NULL);
|
||
|
}
|
||
|
|
||
|
TryDrawGenderIcon();
|
||
|
CopyWindowToVram(sNamingScreen->windows[WIN_TEXT_ENTRY], COPYWIN_GFX);
|
||
|
PutWindowTilemap(sNamingScreen->windows[WIN_TEXT_ENTRY]);
|
||
|
}
|
||
|
|
||
|
struct TextColor // Needed because of alignment
|
||
|
{
|
||
|
u8 colors[3][4];
|
||
|
};
|
||
|
|
||
|
static const struct TextColor sTextColorStruct =
|
||
|
{
|
||
|
{
|
||
|
{TEXT_DYNAMIC_COLOR_4, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY},
|
||
|
{TEXT_DYNAMIC_COLOR_5, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY},
|
||
|
{TEXT_DYNAMIC_COLOR_6, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const u8 sFillValues[KBPAGE_COUNT] =
|
||
|
{
|
||
|
[KEYBOARD_LETTERS_LOWER] = PIXEL_FILL(14),
|
||
|
[KEYBOARD_LETTERS_UPPER] = PIXEL_FILL(13),
|
||
|
[KEYBOARD_SYMBOLS] = PIXEL_FILL(15)
|
||
|
};
|
||
|
|
||
|
static const u8 *const sKeyboardTextColors[KBPAGE_COUNT] =
|
||
|
{
|
||
|
[KEYBOARD_LETTERS_LOWER] = sTextColorStruct.colors[1],
|
||
|
[KEYBOARD_LETTERS_UPPER] = sTextColorStruct.colors[0],
|
||
|
[KEYBOARD_SYMBOLS] = sTextColorStruct.colors[2]
|
||
|
};
|
||
|
|
||
|
static void PrintKeyboardKeys(u8 window, u8 page)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
FillWindowPixelBuffer(window, sFillValues[page]);
|
||
|
|
||
|
for (i = 0; i < KBROW_COUNT; i++)
|
||
|
AddTextPrinterParameterized3(window, FONT_NORMAL, 0, i * 16 + 1, sKeyboardTextColors[page], 0, sNamingScreenKeyboardText[page][i]);
|
||
|
|
||
|
PutWindowTilemap(window);
|
||
|
}
|
||
|
|
||
|
static const u8 *const sNextKeyboardPageTilemaps[] =
|
||
|
{
|
||
|
[KBPAGE_SYMBOLS] = gNamingScreenKeyboardUpper_Tilemap,
|
||
|
[KBPAGE_LETTERS_UPPER] = gNamingScreenKeyboardLower_Tilemap, // lower
|
||
|
[KBPAGE_LETTERS_LOWER] = gNamingScreenKeyboardSymbols_Tilemap // symbols
|
||
|
};
|
||
|
|
||
|
// There are always 2 keyboard pages drawn, the current page and the one that will shown next if the player swaps
|
||
|
// When the page swap is complete this function invisibly replaces the old page with the new next one
|
||
|
static void DrawKeyboardPageOnDeck(void)
|
||
|
{
|
||
|
u8 bg;
|
||
|
u8 bg_;
|
||
|
u8 windowId;
|
||
|
u8 bg1Priority = GetGpuReg(REG_OFFSET_BG1CNT) & 3;
|
||
|
u8 bg2Priority = GetGpuReg(REG_OFFSET_BG2CNT) & 3;
|
||
|
|
||
|
if (bg1Priority > bg2Priority)
|
||
|
{
|
||
|
bg = 1;
|
||
|
bg_ = 1;
|
||
|
windowId = sNamingScreen->windows[WIN_KB_PAGE_1];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bg = 2;
|
||
|
bg_ = 2;
|
||
|
windowId = sNamingScreen->windows[WIN_KB_PAGE_2];
|
||
|
}
|
||
|
|
||
|
DrawBgTilemap(bg, sNextKeyboardPageTilemaps[sNamingScreen->currentPage]);
|
||
|
PrintKeyboardKeys(windowId, CurrentPageToNextKeyboardId());
|
||
|
NamingScreen_Dummy(bg, CurrentPageToNextKeyboardId());
|
||
|
CopyBgTilemapBufferToVram(bg_);
|
||
|
}
|
||
|
|
||
|
static void PrintControls(void)
|
||
|
{
|
||
|
const u8 color[3] = { TEXT_DYNAMIC_COLOR_6, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY };
|
||
|
|
||
|
FillWindowPixelBuffer(sNamingScreen->windows[WIN_BANNER], PIXEL_FILL(15));
|
||
|
AddTextPrinterParameterized3(sNamingScreen->windows[WIN_BANNER], FONT_SMALL, 2, 1, color, 0, gText_MoveOkBack);
|
||
|
PutWindowTilemap(sNamingScreen->windows[WIN_BANNER]);
|
||
|
CopyWindowToVram(sNamingScreen->windows[WIN_BANNER], COPYWIN_FULL);
|
||
|
}
|
||
|
|
||
|
static void CB2_NamingScreen(void)
|
||
|
{
|
||
|
RunTasks();
|
||
|
AnimateSprites();
|
||
|
BuildOamBuffer();
|
||
|
UpdatePaletteFade();
|
||
|
}
|
||
|
|
||
|
static void ResetVHBlank(void)
|
||
|
{
|
||
|
SetVBlankCallback(NULL);
|
||
|
SetHBlankCallback(NULL);
|
||
|
}
|
||
|
|
||
|
static void SetVBlank(void)
|
||
|
{
|
||
|
SetVBlankCallback(VBlankCB_NamingScreen);
|
||
|
}
|
||
|
|
||
|
static void VBlankCB_NamingScreen(void)
|
||
|
{
|
||
|
LoadOam();
|
||
|
ProcessSpriteCopyRequests();
|
||
|
TransferPlttBuffer();
|
||
|
SetGpuReg(REG_OFFSET_BG1VOFS, sNamingScreen->bg1vOffset);
|
||
|
SetGpuReg(REG_OFFSET_BG2VOFS, sNamingScreen->bg2vOffset);
|
||
|
SetGpuReg(REG_OFFSET_BG1CNT, GetGpuReg(REG_OFFSET_BG1CNT) & 0xFFFC);
|
||
|
SetGpuRegBits(REG_OFFSET_BG1CNT, sNamingScreen->bg1Priority);
|
||
|
SetGpuReg(REG_OFFSET_BG2CNT, GetGpuReg(REG_OFFSET_BG2CNT) & 0xFFFC);
|
||
|
SetGpuRegBits(REG_OFFSET_BG2CNT, sNamingScreen->bg2Priority);
|
||
|
}
|
||
|
|
||
|
static void NamingScreen_ShowBgs(void)
|
||
|
{
|
||
|
ShowBg(0);
|
||
|
ShowBg(1);
|
||
|
ShowBg(2);
|
||
|
ShowBg(3);
|
||
|
}
|
||
|
|
||
|
// Always false (presumably for non-latin languages)
|
||
|
static bool8 IsWideLetter(u8 character)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
for (i = 0; sText_AlphabetUpperLower[i] != EOS; i++)
|
||
|
{
|
||
|
if (character == sText_AlphabetUpperLower[i])
|
||
|
return FALSE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Debug? Unused, and arguments aren't sensible for non-player screens.
|
||
|
static void Debug_NamingScreenPlayer(void)
|
||
|
{
|
||
|
DoNamingScreen(NAMING_SCREEN_PLAYER, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu);
|
||
|
}
|
||
|
|
||
|
static void Debug_NamingScreenBox(void)
|
||
|
{
|
||
|
DoNamingScreen(NAMING_SCREEN_BOX, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu);
|
||
|
}
|
||
|
|
||
|
static void Debug_NamingScreenCaughtMon(void)
|
||
|
{
|
||
|
DoNamingScreen(NAMING_SCREEN_CAUGHT_MON, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu);
|
||
|
}
|
||
|
|
||
|
static void Debug_NamingScreenNickname(void)
|
||
|
{
|
||
|
DoNamingScreen(NAMING_SCREEN_NICKNAME, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu);
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------
|
||
|
// Forward-declared variables
|
||
|
//--------------------------------------------------
|
||
|
|
||
|
// Initial pages below are pointless, they're overwritten with KBPAGE_LETTERS_UPPER in MainState_FadeIn()
|
||
|
static const struct NamingScreenTemplate sPlayerNamingScreenTemplate =
|
||
|
{
|
||
|
.copyExistingString = FALSE,
|
||
|
.maxChars = PLAYER_NAME_LENGTH,
|
||
|
.iconFunction = 1,
|
||
|
.addGenderIcon = FALSE,
|
||
|
.initialPage = KBPAGE_LETTERS_UPPER,
|
||
|
.unused = 35,
|
||
|
.title = gText_YourName,
|
||
|
};
|
||
|
|
||
|
static const struct NamingScreenTemplate sPCBoxNamingTemplate =
|
||
|
{
|
||
|
.copyExistingString = FALSE,
|
||
|
.maxChars = BOX_NAME_LENGTH,
|
||
|
.iconFunction = 2,
|
||
|
.addGenderIcon = FALSE,
|
||
|
.initialPage = KBPAGE_LETTERS_UPPER,
|
||
|
.unused = 19,
|
||
|
.title = gText_BoxName,
|
||
|
};
|
||
|
|
||
|
static const struct NamingScreenTemplate sMonNamingScreenTemplate =
|
||
|
{
|
||
|
.copyExistingString = FALSE,
|
||
|
.maxChars = POKEMON_NAME_LENGTH,
|
||
|
.iconFunction = 3,
|
||
|
.addGenderIcon = TRUE,
|
||
|
.initialPage = KBPAGE_LETTERS_UPPER,
|
||
|
.unused = 35,
|
||
|
.title = gText_PkmnsNickname,
|
||
|
};
|
||
|
|
||
|
static const struct NamingScreenTemplate sWaldaWordsScreenTemplate =
|
||
|
{
|
||
|
.copyExistingString = TRUE,
|
||
|
.maxChars = WALDA_PHRASE_LENGTH,
|
||
|
.iconFunction = 4,
|
||
|
.addGenderIcon = FALSE,
|
||
|
.initialPage = KBPAGE_LETTERS_UPPER,
|
||
|
.unused = 11,
|
||
|
.title = gText_TellHimTheWords,
|
||
|
};
|
||
|
|
||
|
static const struct NamingScreenTemplate *const sNamingScreenTemplates[] =
|
||
|
{
|
||
|
[NAMING_SCREEN_PLAYER] = &sPlayerNamingScreenTemplate,
|
||
|
[NAMING_SCREEN_BOX] = &sPCBoxNamingTemplate,
|
||
|
[NAMING_SCREEN_CAUGHT_MON] = &sMonNamingScreenTemplate,
|
||
|
[NAMING_SCREEN_NICKNAME] = &sMonNamingScreenTemplate,
|
||
|
[NAMING_SCREEN_WALDA] = &sWaldaWordsScreenTemplate,
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOam_8x8 =
|
||
|
{
|
||
|
.y = 0,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.x = 0,
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOam_16x16 =
|
||
|
{
|
||
|
.y = 0,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(16x16),
|
||
|
.x = 0,
|
||
|
.size = SPRITE_SIZE(16x16),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
};
|
||
|
|
||
|
static const struct OamData sOam_32x16 =
|
||
|
{
|
||
|
.y = 0,
|
||
|
.affineMode = ST_OAM_AFFINE_OFF,
|
||
|
.objMode = ST_OAM_OBJ_NORMAL,
|
||
|
.bpp = ST_OAM_4BPP,
|
||
|
.shape = SPRITE_SHAPE(32x16),
|
||
|
.x = 0,
|
||
|
.size = SPRITE_SIZE(32x16),
|
||
|
.tileNum = 0,
|
||
|
.priority = 0,
|
||
|
.paletteNum = 0,
|
||
|
};
|
||
|
|
||
|
static const struct Subsprite sSubsprites_PageSwapFrame[] =
|
||
|
{
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = -16,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 0,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = -16,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 4,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = -8,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 5,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = -8,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 9,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = 0,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 10,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = 0,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 14,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = 8,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 15,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = 8,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 19,
|
||
|
.priority = 1
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct Subsprite sSubsprites_PageSwapText[] =
|
||
|
{
|
||
|
{
|
||
|
.x = -12,
|
||
|
.y = -4,
|
||
|
.shape = SPRITE_SHAPE(16x8),
|
||
|
.size = SPRITE_SIZE(16x8),
|
||
|
.tileOffset = 0,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 4,
|
||
|
.y = -4,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 2,
|
||
|
.priority = 1
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct Subsprite sSubsprites_Button[] =
|
||
|
{
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = -12,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 0,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = -12,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 4,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = -4,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 5,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = -4,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 9,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = -20,
|
||
|
.y = 4,
|
||
|
.shape = SPRITE_SHAPE(32x8),
|
||
|
.size = SPRITE_SIZE(32x8),
|
||
|
.tileOffset = 10,
|
||
|
.priority = 1
|
||
|
},
|
||
|
{
|
||
|
.x = 12,
|
||
|
.y = 4,
|
||
|
.shape = SPRITE_SHAPE(8x8),
|
||
|
.size = SPRITE_SIZE(8x8),
|
||
|
.tileOffset = 14,
|
||
|
.priority = 1
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct Subsprite sSubsprites_PCIcon[] =
|
||
|
{
|
||
|
{
|
||
|
.x = -8,
|
||
|
.y = -12,
|
||
|
.shape = SPRITE_SHAPE(16x8),
|
||
|
.size = SPRITE_SIZE(16x8),
|
||
|
.tileOffset = 0,
|
||
|
.priority = 3
|
||
|
},
|
||
|
{
|
||
|
.x = -8,
|
||
|
.y = -4,
|
||
|
.shape = SPRITE_SHAPE(16x8),
|
||
|
.size = SPRITE_SIZE(16x8),
|
||
|
.tileOffset = 2,
|
||
|
.priority = 3
|
||
|
},
|
||
|
{
|
||
|
.x = -8,
|
||
|
.y = 4,
|
||
|
.shape = SPRITE_SHAPE(16x8),
|
||
|
.size = SPRITE_SIZE(16x8),
|
||
|
.tileOffset = 4,
|
||
|
.priority = 3
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const struct SubspriteTable sSubspriteTable_PageSwapFrame[] =
|
||
|
{
|
||
|
{ARRAY_COUNT(sSubsprites_PageSwapFrame), sSubsprites_PageSwapFrame}
|
||
|
};
|
||
|
|
||
|
static const struct SubspriteTable sSubspriteTable_PageSwapText[] =
|
||
|
{
|
||
|
{ARRAY_COUNT(sSubsprites_PageSwapText), sSubsprites_PageSwapText},
|
||
|
{ARRAY_COUNT(sSubsprites_PageSwapText), sSubsprites_PageSwapText},
|
||
|
{ARRAY_COUNT(sSubsprites_PageSwapText), sSubsprites_PageSwapText}
|
||
|
};
|
||
|
|
||
|
static const struct SubspriteTable sSubspriteTable_Button[] =
|
||
|
{
|
||
|
{ARRAY_COUNT(sSubsprites_Button), sSubsprites_Button}
|
||
|
};
|
||
|
|
||
|
static const struct SubspriteTable sSubspriteTable_PCIcon[] =
|
||
|
{
|
||
|
{ARRAY_COUNT(sSubsprites_PCIcon), sSubsprites_PCIcon}
|
||
|
};
|
||
|
|
||
|
static const struct SpriteFrameImage sImageTable_PCIcon[] =
|
||
|
{
|
||
|
{sPCIconOff_Gfx, sizeof(sPCIconOff_Gfx)},
|
||
|
{sPCIconOn_Gfx, sizeof(sPCIconOn_Gfx)},
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sAnim_Loop[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(0, 1),
|
||
|
ANIMCMD_JUMP(0)
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sAnim_CursorSquish[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(4, 8),
|
||
|
ANIMCMD_FRAME(8, 8),
|
||
|
ANIMCMD_END
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd sAnim_PCIcon[] =
|
||
|
{
|
||
|
ANIMCMD_FRAME(0, 2),
|
||
|
ANIMCMD_FRAME(1, 2),
|
||
|
ANIMCMD_JUMP(0)
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sAnims_Loop[] =
|
||
|
{
|
||
|
sAnim_Loop
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sAnims_Cursor[] =
|
||
|
{
|
||
|
sAnim_Loop,
|
||
|
sAnim_CursorSquish
|
||
|
};
|
||
|
|
||
|
static const union AnimCmd *const sAnims_PCIcon[] =
|
||
|
{
|
||
|
sAnim_PCIcon
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapFrame =
|
||
|
{
|
||
|
.tileTag = GFXTAG_PAGE_SWAP_FRAME,
|
||
|
.paletteTag = PALTAG_PAGE_SWAP,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_PageSwap
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapButton =
|
||
|
{
|
||
|
.tileTag = GFXTAG_PAGE_SWAP_BUTTON,
|
||
|
.paletteTag = PALTAG_PAGE_SWAP_UPPER,
|
||
|
.oam = &sOam_32x16,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCallbackDummy
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PageSwapText =
|
||
|
{
|
||
|
.tileTag = GFXTAG_PAGE_SWAP_UPPER,
|
||
|
.paletteTag = PALTAG_PAGE_SWAP,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCallbackDummy
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_BackButton =
|
||
|
{
|
||
|
.tileTag = GFXTAG_BACK_BUTTON,
|
||
|
.paletteTag = PALTAG_BACK_BUTTON,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCallbackDummy
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_OkButton =
|
||
|
{
|
||
|
.tileTag = GFXTAG_OK_BUTTON,
|
||
|
.paletteTag = PALTAG_OK_BUTTON,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCallbackDummy
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_Cursor =
|
||
|
{
|
||
|
.tileTag = GFXTAG_CURSOR,
|
||
|
.paletteTag = PALTAG_CURSOR,
|
||
|
.oam = &sOam_16x16,
|
||
|
.anims = sAnims_Cursor,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_Cursor
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_InputArrow =
|
||
|
{
|
||
|
.tileTag = GFXTAG_INPUT_ARROW,
|
||
|
.paletteTag = PALTAG_PAGE_SWAP_OTHERS,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_InputArrow
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_Underscore =
|
||
|
{
|
||
|
.tileTag = GFXTAG_UNDERSCORE,
|
||
|
.paletteTag = PALTAG_PAGE_SWAP_OTHERS,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_Loop,
|
||
|
.images = NULL,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCB_Underscore
|
||
|
};
|
||
|
|
||
|
static const struct SpriteTemplate sSpriteTemplate_PCIcon =
|
||
|
{
|
||
|
.tileTag = TAG_NONE,
|
||
|
.paletteTag = PALTAG_PC_ICON,
|
||
|
.oam = &sOam_8x8,
|
||
|
.anims = sAnims_PCIcon,
|
||
|
.images = sImageTable_PCIcon,
|
||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||
|
.callback = SpriteCallbackDummy
|
||
|
};
|
||
|
|
||
|
static const u8* const sNamingScreenKeyboardText[KBPAGE_COUNT][KBROW_COUNT] =
|
||
|
{
|
||
|
[KEYBOARD_LETTERS_LOWER] =
|
||
|
{
|
||
|
gText_NamingScreenKeyboard_abcdef,
|
||
|
gText_NamingScreenKeyboard_ghijkl,
|
||
|
gText_NamingScreenKeyboard_mnopqrs,
|
||
|
gText_NamingScreenKeyboard_tuvwxyz
|
||
|
},
|
||
|
[KEYBOARD_LETTERS_UPPER] =
|
||
|
{
|
||
|
gText_NamingScreenKeyboard_ABCDEF,
|
||
|
gText_NamingScreenKeyboard_GHIJKL,
|
||
|
gText_NamingScreenKeyboard_MNOPQRS,
|
||
|
gText_NamingScreenKeyboard_TUVWXYZ
|
||
|
},
|
||
|
[KEYBOARD_SYMBOLS] =
|
||
|
{
|
||
|
gText_NamingScreenKeyboard_01234,
|
||
|
gText_NamingScreenKeyboard_56789,
|
||
|
gText_NamingScreenKeyboard_Symbols1,
|
||
|
gText_NamingScreenKeyboard_Symbols2
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static const struct SpriteSheet sSpriteSheets[] =
|
||
|
{
|
||
|
{gNamingScreenRWindow_Gfx + 0x280, 0x1E0, GFXTAG_BACK_BUTTON},
|
||
|
{gNamingScreenRWindow_Gfx + 0x460, 0x1E0, GFXTAG_OK_BUTTON},
|
||
|
{gNamingScreenRWindow_Gfx, 0x280, GFXTAG_PAGE_SWAP_FRAME},
|
||
|
{gNamingScreenPageButton_Gfx + 0x20, 0x100, GFXTAG_PAGE_SWAP_BUTTON},
|
||
|
{gNamingScreenROptions_Gfx, 0x060, GFXTAG_PAGE_SWAP_UPPER},
|
||
|
{gNamingScreenROptions_Gfx + 0xA0, 0x060, GFXTAG_PAGE_SWAP_LOWER},
|
||
|
{gNamingScreenROptions_Gfx + 0x140, 0x060, GFXTAG_PAGE_SWAP_OTHERS},
|
||
|
{gNamingScreenCursor_Gfx, 0x080, GFXTAG_CURSOR},
|
||
|
{gNamingScreenCursor_Gfx + 0xA0, 0x080, GFXTAG_CURSOR_SQUISHED},
|
||
|
{gNamingScreenCursor_Gfx + 0x140, 0x080, GFXTAG_CURSOR_FILLED},
|
||
|
{gNamingScreenInputArrow_Gfx, 0x020, GFXTAG_INPUT_ARROW},
|
||
|
{gNamingScreenUnderscore_Gfx, 0x020, GFXTAG_UNDERSCORE},
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
static const struct SpritePalette sSpritePalettes[] =
|
||
|
{
|
||
|
{gNamingScreenMenu_Pal, PALTAG_PC_ICON},
|
||
|
{gNamingScreenMenu_Pal + 0x10, PALTAG_PAGE_SWAP_UPPER},
|
||
|
{gNamingScreenMenu_Pal + 0x20, PALTAG_PAGE_SWAP_LOWER},
|
||
|
{gNamingScreenMenu_Pal + 0x30, PALTAG_PAGE_SWAP_OTHERS},
|
||
|
{gNamingScreenMenu_Pal + 0x40, PALTAG_PAGE_SWAP},
|
||
|
{gNamingScreenMenu_Pal + 0x50, PALTAG_CURSOR},
|
||
|
{gNamingScreenMenu_Pal + 0x40, PALTAG_BACK_BUTTON},
|
||
|
{gNamingScreenMenu_Pal + 0x40, PALTAG_OK_BUTTON},
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
|