summaryrefslogtreecommitdiff
path: root/src/pokemon
diff options
context:
space:
mode:
Diffstat (limited to 'src/pokemon')
-rw-r--r--src/pokemon/learn_move.c1081
-rw-r--r--src/pokemon/mail.c437
-rw-r--r--src/pokemon/mail_data.c208
-rw-r--r--src/pokemon/mon_markings.c383
-rw-r--r--src/pokemon/pokeblock_feed.c1015
-rw-r--r--src/pokemon/pokedex.c5527
-rw-r--r--src/pokemon/pokedex_cry_screen.c85
-rw-r--r--src/pokemon/pokemon_1.c671
-rw-r--r--src/pokemon/pokemon_2.c1218
-rw-r--r--src/pokemon/pokemon_3.c1380
-rw-r--r--src/pokemon/pokemon_data.c128
-rw-r--r--src/pokemon/pokemon_icon.c1273
-rw-r--r--src/pokemon/pokemon_menu.c1200
-rw-r--r--src/pokemon/pokemon_size_record.c217
-rw-r--r--src/pokemon/pokemon_storage_system.c99
-rw-r--r--src/pokemon/pokemon_summary_screen.c180
16 files changed, 15102 insertions, 0 deletions
diff --git a/src/pokemon/learn_move.c b/src/pokemon/learn_move.c
new file mode 100644
index 000000000..33252c66b
--- /dev/null
+++ b/src/pokemon/learn_move.c
@@ -0,0 +1,1081 @@
+#include "global.h"
+#include "data2.h"
+#include "field_fadetransition.h"
+#include "main.h"
+#include "menu.h"
+#include "menu_cursor.h"
+#include "palette.h"
+#include "pokemon.h"
+#include "overworld.h"
+#include "script.h"
+#include "songs.h"
+#include "sound.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "strings.h"
+#include "strings2.h"
+#include "task.h"
+#include "trig.h"
+
+extern u8 ewram[];
+extern u16 gSpecialVar_0x8004;
+extern u16 gSpecialVar_0x8005;
+extern u8 gTileBuffer[];
+
+struct ContestMove
+{
+ u8 effect;
+ u8 contestCategory:3;
+ u8 comboStarterId;
+ u8 comboMoves[4];
+};
+
+struct ContestEffect
+{
+ u8 effectType;
+ u8 appeal;
+ u8 jam;
+};
+
+extern const struct ContestMove gContestMoves[];
+extern const struct ContestEffect gContestEffects[];
+extern const struct WindowConfig gWindowConfig_81E6CE4;
+extern const struct WindowConfig gWindowConfig_81E7240;
+extern const u8 *const gUnknown_083CADD4[];
+extern const u8 *const gMoveDescriptions[];
+extern const u8 gTypeNames[][7];
+extern const u8 *const gUnknown_083CAF70[];
+
+#ifdef GERMAN
+extern const u8 deuOtherText_ForgotAndLearned[];
+#endif
+
+extern void sub_809D9F0(struct Pokemon *, u8, u8, void *, u32);
+
+struct LearnMoveStruct
+{
+ u8 state;
+ u8 filler1;
+ u8 unk2;
+ u8 spriteIDs[20];
+ u8 filler17[1];
+ u8 unk18;
+ u8 unk19;
+ u8 numMenuChoices;
+ u8 menuSelection;
+ u8 unk1C;
+ bool8 unk1D;
+ u8 unk1E;
+ u8 filler1F;
+ /*0x020*/ u16 movesToLearn[20];
+ u8 filler48[0x52-0x48];
+ u8 moveNames[6][0x19];
+ u8 fillerE8[0x2C3-0xE8];
+ bool8 unk2C3;
+ bool8 showContestInfo;
+ /*0x2C5*/ u8 partyMon;
+ u8 unk2C6;
+};
+
+static struct LearnMoveStruct *sLearnMoveStruct;
+
+const u16 gDexArrows_Pal[] = INCBIN_U16("graphics/pokedex/arrows.gbapal");
+
+const u8 gDexArrows_Gfx[] = INCBIN_U8("graphics/pokedex/arrows.4bpp");
+
+const u8 gUnknown_08402CF8[][4] =
+{
+ { 0, 0, 9, 13},
+ {10, 0, 29, 7},
+ { 2, 14, 27, 19},
+ {10, 8, 29, 13},
+};
+
+struct UnknownStruct1
+{
+ const u8 *unk0;
+ u8 unk4;
+ u8 unk5;
+ u8 unk6;
+};
+
+const struct UnknownStruct1 gUnknown_08402D08[][4] =
+{
+ {
+ {OtherText_Battle, 1, 1, 0},
+ {OtherText_Power, 1, 4, 1},
+ {OtherText_Accuracy, 1, 9, 2},
+ {NULL, 0, 0, 0},
+ },
+ {
+ {OtherText_Contest, 1, 1, 0},
+ {OtherText_Appeal, 1, 4, 1},
+ {OtherText_Jam, 1, 9, 2},
+ {NULL, 0, 0, 0},
+ },
+};
+
+// XXX: What are these for?
+const u32 unkDataFF00FFEF = 0xFF00FFEF;
+const u8 *const gTileBuffer_ = gTileBuffer;
+
+const struct OamData gOamData_8402D50 = {.shape = 0};
+const struct OamData gOamData_8402D58 = {.shape = 2};
+const struct OamData gOamData_8402D60 = {.shape = 1};
+
+const union AnimCmd gSpriteAnim_8402D68[] =
+{
+ ANIMCMD_FRAME(2, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_8402D70[] =
+{
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_8402D78[] =
+{
+ gSpriteAnim_8402D68,
+ gSpriteAnim_8402D70,
+};
+
+const struct SpriteSheet gUnknown_08402D80 = {gDexArrows_Gfx, sizeof(gDexArrows_Gfx), 5525};
+const struct SpritePalette gUnknown_08402D88 = {gDexArrows_Pal, 5526};
+
+void sub_8133300(struct Sprite *);
+const struct SpriteTemplate gSpriteTemplate_8402D90 =
+{
+ .tileTag = 5525,
+ .paletteTag = 5526,
+ .oam = &gOamData_8402D58,
+ .anims = gSpriteAnimTable_8402D78,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_8133300,
+};
+
+const union AnimCmd gSpriteAnim_8402DA8[] =
+{
+ ANIMCMD_FRAME(4, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_8402DB0[] =
+{
+ ANIMCMD_FRAME(6, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_8402DB8[] =
+{
+ gSpriteAnim_8402DA8,
+ gSpriteAnim_8402DB0,
+};
+
+const struct SpriteTemplate gSpriteTemplate_8402DC0 =
+{
+ .tileTag = 5525,
+ .paletteTag = 5526,
+ .oam = &gOamData_8402D60,
+ .anims = gSpriteAnimTable_8402DB8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_8133300,
+};
+
+const union AnimCmd gSpriteAnim_8402DD8[] =
+{
+ ANIMCMD_FRAME(8, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_8402DE0[] =
+{
+ ANIMCMD_FRAME(9, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_8402DE8[] =
+{
+ ANIMCMD_FRAME(10, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_8402DF0[] =
+{
+ ANIMCMD_FRAME(11, 5),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_8402DF8[] =
+{
+ gSpriteAnim_8402DD8,
+ gSpriteAnim_8402DE0,
+ gSpriteAnim_8402DE8,
+ gSpriteAnim_8402DF0,
+};
+
+const struct SpriteTemplate gSpriteTemplate_8402E08 =
+{
+ .tileTag = 5525,
+ .paletteTag = 5526,
+ .oam = &gOamData_8402D50,
+ .anims = gSpriteAnimTable_8402DF8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_8133300,
+};
+
+const u8 gString_AkitoMori[] = _("あきと"); // programmer Akito Mori?
+
+void sub_813269C(u8);
+void CB2_InitLearnMove(void);
+void CB2_LearnMove(void);
+void LearnMoveMain(void);
+void DrawLearnMoveMenuWindow(void);
+void sub_8133030(bool8);
+u8 sub_81330E8(void);
+void sub_8133140(u8);
+u8 sub_8133248(void);
+void ClearLearnMoveVars(void);
+void sub_8133358(void);
+void sub_8133558(void);
+void sub_813362C(void);
+void sub_8133800(void);
+void sub_8133AEC(bool8, int);
+void sub_8133CA4(void);
+
+void VBlankCB_LearnMove(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void sub_8132670(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(sub_813269C, 10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+}
+
+void sub_813269C(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(CB2_InitLearnMove);
+ gFieldCallback = sub_8080990;
+ DestroyTask(taskId);
+ }
+}
+
+void CB2_InitLearnMove(void)
+{
+ REG_DISPCNT = 0;
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ sLearnMoveStruct = (struct LearnMoveStruct *)(ewram + 0x17000);
+ ClearLearnMoveVars();
+ sLearnMoveStruct->partyMon = gSpecialVar_0x8004;
+ sub_8133558();
+ SetVBlankCallback(VBlankCB_LearnMove);
+
+ SetUpWindowConfig(&gWindowConfig_81E7240);
+ InitMenuWindow(&gWindowConfig_81E7240);
+ MenuZeroFillScreen();
+
+ SetUpWindowConfig(&gWindowConfig_81E6CE4);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+ MenuZeroFillScreen();
+
+ REG_BG0VOFS = 0;
+ REG_BG0VOFS = 0; // huh?
+ REG_BG1HOFS = 0;
+ REG_BG1HOFS = 0; // huh?
+
+ LoadSpriteSheet(&gUnknown_08402D80);
+ LoadSpritePalette(&gUnknown_08402D88);
+ sub_8133358();
+ FillPalette(0, 0, 2);
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ SetMainCallback2(CB2_LearnMove);
+}
+
+void sub_81327A4(void)
+{
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ sLearnMoveStruct = (struct LearnMoveStruct *)(ewram + 0x17000);
+ sub_8133558();
+ sLearnMoveStruct->unk2C6 = gSpecialVar_0x8005;
+ SetVBlankCallback(VBlankCB_LearnMove);
+
+ SetUpWindowConfig(&gWindowConfig_81E7240);
+ InitMenuWindow(&gWindowConfig_81E7240);
+ MenuZeroFillScreen();
+
+ SetUpWindowConfig(&gWindowConfig_81E6CE4);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+ MenuZeroFillScreen();
+
+ REG_DISPCNT = 0x1340;
+ REG_BG0VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1HOFS = 0; // huh?
+
+ LoadSpriteSheet(&gUnknown_08402D80);
+ LoadSpritePalette(&gUnknown_08402D88);
+ sub_8133358();
+ FillPalette(0, 0, 2);
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ SetMainCallback2(CB2_LearnMove);
+}
+
+void CB2_LearnMove(void)
+{
+ LearnMoveMain();
+ if (sLearnMoveStruct->unk1D)
+ {
+ sLearnMoveStruct->unk1D = FALSE;
+ sub_814AD7C(0x58, (sLearnMoveStruct->unk18 * 2 + 1) * 8);
+ }
+ if (sLearnMoveStruct->unk1E != 0)
+ {
+ sLearnMoveStruct->unk1E = 0;
+ sub_8133800();
+ }
+ if (sLearnMoveStruct->unk2C3)
+ {
+ sub_8133AEC(sLearnMoveStruct->showContestInfo, 1);
+ sLearnMoveStruct->unk2C3 = FALSE;
+ }
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+void sub_81328E8(const u8 *a)
+{
+ StringExpandPlaceholders(gStringVar4, a);
+ MenuPrintMessage(gStringVar4, 3, 15);
+}
+
+void LearnMoveMain(void)
+{
+ switch (sLearnMoveStruct->state)
+ {
+ case 0:
+ sLearnMoveStruct->state++;
+ DrawLearnMoveMenuWindow();
+ sub_8133030(FALSE);
+ sub_8133800();
+ gSprites[1].pos1.x = 0x48;
+ sLearnMoveStruct->unk2C3 = TRUE;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ REG_DISPCNT = 0x1340;
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ sLearnMoveStruct->state = 4;
+ break;
+ case 2:
+ sLearnMoveStruct->state++;
+ break;
+ case 3:
+ sub_8133030(FALSE);
+ sub_8133800();
+ sLearnMoveStruct->unk2C3 = TRUE;
+ sLearnMoveStruct->state++;
+ gSprites[1].pos1.x = 0x48;
+ break;
+ case 4:
+ if (sub_81330E8() == 0)
+ sub_813362C();
+ return;
+ case 5:
+ sub_8133140(0);
+ sub_8133800();
+ sLearnMoveStruct->unk2C3 = TRUE;
+ gSprites[1].pos1.x = 0x48;
+ sLearnMoveStruct->state++;
+ break;
+ case 6:
+ if (sub_8133248() == 0)
+ sub_813362C();
+ break;
+ case 8:
+ if (MenuUpdateWindowText())
+ {
+ DisplayYesNoMenu(21, 7, 1);
+ sLearnMoveStruct->state++;
+ }
+ break;
+ case 9:
+ {
+ s8 selection = ProcessMenuInputNoWrap_();
+
+ if (selection == 0)
+ {
+ sub_8133CA4();
+ if (GiveMoveToMon(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->movesToLearn[sLearnMoveStruct->menuSelection]) != 0xFFFF)
+ {
+ sub_81328E8(gOtherText_PokeLearnedMove);
+ gSpecialVar_0x8004 = 1;
+ sLearnMoveStruct->state = 31;
+ }
+ else
+ {
+ sLearnMoveStruct->state = 16;
+ }
+ }
+ else if (selection == -1 || selection == 1)
+ {
+ sub_8133CA4();
+ if (sLearnMoveStruct->showContestInfo == FALSE)
+ sLearnMoveStruct->state = 3;
+ if (sLearnMoveStruct->showContestInfo == TRUE)
+ sLearnMoveStruct->state = 5;
+ }
+ }
+ break;
+ case 12:
+ if (MenuUpdateWindowText())
+ {
+ DisplayYesNoMenu(21, 7, 1);
+ sLearnMoveStruct->state++;
+ }
+ break;
+ case 13:
+ {
+ s8 selection = ProcessMenuInputNoWrap_();
+
+ if (selection == 0)
+ {
+ sub_8133CA4();
+ gSpecialVar_0x8004 = selection;
+ sLearnMoveStruct->state = 14;
+ }
+ else if (selection == -1 || selection == 1)
+ {
+ sub_8133CA4();
+ if (sLearnMoveStruct->showContestInfo == FALSE)
+ sLearnMoveStruct->state = 3;
+ if (sLearnMoveStruct->showContestInfo == TRUE)
+ sLearnMoveStruct->state = 5;
+ }
+ }
+ break;
+ case 16:
+ sub_81328E8(gOtherText_DeleteOlderMove);
+ sLearnMoveStruct->state++;
+ break;
+ case 17:
+ if (MenuUpdateWindowText())
+ {
+ DisplayYesNoMenu(21, 7, 1);
+ sLearnMoveStruct->state = 18;
+ }
+ break;
+ case 18:
+ {
+ s8 var = ProcessMenuInputNoWrap_();
+
+ if (var == 0)
+ {
+ sub_8133CA4();
+ sub_81328E8(gOtherText_WhichMoveToForget);
+ sLearnMoveStruct->state = 19;
+ }
+ else if (var == -1 || var == 1)
+ {
+ sub_8133CA4();
+ sLearnMoveStruct->state = 24;
+ }
+ }
+ break;
+ case 24:
+ sub_81328E8(gOtherText_StopLearningMove);
+ sLearnMoveStruct->state++;
+ break;
+ case 25:
+ if (MenuUpdateWindowText())
+ {
+ sLearnMoveStruct->state = 26;
+ DisplayYesNoMenu(21, 7, 1);
+ }
+ break;
+ case 26:
+ {
+ s8 var = ProcessMenuInputNoWrap_();
+
+ if (var == 0)
+ {
+ sub_8133CA4();
+ sLearnMoveStruct->state = 27;
+ }
+ else if (var == -1 || var == 1)
+ {
+ sub_8133CA4();
+
+ // What's the point? It gets set to 16, anyway.
+ if (sLearnMoveStruct->showContestInfo == FALSE)
+ sLearnMoveStruct->state = 3;
+ if (sLearnMoveStruct->showContestInfo == TRUE)
+ sLearnMoveStruct->state = 5;
+ sLearnMoveStruct->state = 16;
+ }
+ }
+ break;
+ case 27:
+ if (MenuUpdateWindowText())
+ {
+ if (sLearnMoveStruct->showContestInfo == FALSE)
+ sLearnMoveStruct->state = 3;
+ if (sLearnMoveStruct->showContestInfo == TRUE)
+ sLearnMoveStruct->state = 5;
+ }
+ break;
+ case 19:
+ if (MenuUpdateWindowText())
+ {
+ sLearnMoveStruct->state = 20;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ }
+ break;
+ case 20:
+ if (!gPaletteFade.active)
+ {
+ sub_809D9F0(gPlayerParty, sLearnMoveStruct->partyMon, gPlayerPartyCount - 1, sub_81327A4, sLearnMoveStruct->movesToLearn[sLearnMoveStruct->menuSelection]);
+ sLearnMoveStruct->state = 28;
+ }
+ break;
+ case 21:
+ if (MenuUpdateWindowText())
+ sLearnMoveStruct->state = 14;
+ break;
+ case 22:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ break;
+ case 14:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ sLearnMoveStruct->state++;
+ break;
+ case 15:
+ if (!gPaletteFade.active)
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ break;
+ case 28:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ sLearnMoveStruct->state++;
+ DrawLearnMoveMenuWindow();
+ sub_8133800();
+ if (sLearnMoveStruct->showContestInfo == FALSE)
+ sub_8133030(TRUE);
+ if (sLearnMoveStruct->showContestInfo == TRUE)
+ {
+ gSprites[1].pos1.x = 0x48;
+ sub_8133140(1);
+ }
+ sub_8133AEC(sLearnMoveStruct->showContestInfo, 1);
+ break;
+ case 29:
+ if (!gPaletteFade.active)
+ {
+ if (sLearnMoveStruct->unk2C6 == 4)
+ {
+ sLearnMoveStruct->state = 24;
+ }
+ else
+ {
+ u16 moveId = GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_MOVE1 + sLearnMoveStruct->unk2C6);
+
+ StringCopy(gStringVar3, gMoveNames[moveId]);
+ RemoveMonPPBonus(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->unk2C6);
+ SetMonMoveSlot(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->movesToLearn[sLearnMoveStruct->menuSelection], sLearnMoveStruct->unk2C6);
+ StringCopy(gStringVar2, gMoveNames[sLearnMoveStruct->movesToLearn[sLearnMoveStruct->menuSelection]]);
+ sub_81328E8(gOtherText_ForgotMove123);
+ sLearnMoveStruct->state = 30;
+ gSpecialVar_0x8004 = 1;
+ }
+ }
+ break;
+ case 30:
+ if (MenuUpdateWindowText())
+ {
+#ifdef ENGLISH
+ sub_81328E8(gOtherText_ForgotOrDidNotLearnMove);
+#else
+ sub_81328E8(deuOtherText_ForgotAndLearned);
+#endif
+ sLearnMoveStruct->state = 31;
+ PlayFanfare(BGM_FANFA1);
+ }
+ break;
+ case 31:
+ if (MenuUpdateWindowText())
+ {
+ PlayFanfare(BGM_FANFA1);
+ sLearnMoveStruct->state = 32;
+ }
+ break;
+ case 32:
+ if (IsFanfareTaskInactive())
+ sLearnMoveStruct->state = 33;
+ break;
+ case 33:
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->state = 14;
+ }
+ break;
+ }
+}
+
+void DrawLearnMoveMenuWindow(void)
+{
+ u32 i;
+
+ BasicInitMenuWindow(&gWindowConfig_81E7240);
+ for (i = 0; i < 4; i++)
+ {
+ MenuDrawTextWindow(
+ gUnknown_08402CF8[i][0],
+ gUnknown_08402CF8[i][1],
+ gUnknown_08402CF8[i][2],
+ gUnknown_08402CF8[i][3]);
+ }
+ BasicInitMenuWindow(&gWindowConfig_81E6CE4);
+}
+
+void sub_8133030(bool8 a)
+{
+ s32 i;
+
+ gSprites[sLearnMoveStruct->spriteIDs[0]].invisible = FALSE;
+ gSprites[sLearnMoveStruct->spriteIDs[1]].invisible = FALSE;
+
+ for (i = 0; i < 16; i++)
+ gSprites[sLearnMoveStruct->spriteIDs[i + 4]].invisible = TRUE;
+
+ for (i = 0; gUnknown_08402D08[0][i].unk0 != NULL; i++)
+ {
+ sub_8072C74(gTileBuffer, gUnknown_08402D08[0][i].unk0, 64, 2);
+ MenuPrint(gTileBuffer, gUnknown_08402D08[0][i].unk4, gUnknown_08402D08[0][i].unk5);
+ }
+
+ if (!a)
+ sub_8072AB0(gOtherText_TeachWhichMove, 24, 120, 192, 32, 1);
+}
+
+u8 sub_81330E8(void)
+{
+ u32 result = (gMain.newKeys & DPAD_LEFT) || (gMain.newKeys & DPAD_RIGHT);
+
+ if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR
+ && ((gMain.newKeys & L_BUTTON) || (gMain.newKeys & R_BUTTON)))
+ result++;
+
+ if (result != 0)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->state = 5;
+ sLearnMoveStruct->showContestInfo = TRUE;
+ }
+
+ return result;
+}
+
+void sub_8133140(bool8 a)
+{
+ s32 i;
+
+ gSprites[sLearnMoveStruct->spriteIDs[0]].invisible = FALSE;
+ gSprites[sLearnMoveStruct->spriteIDs[1]].invisible = FALSE;
+
+ for (i = 0; i < 16; i++)
+ gSprites[sLearnMoveStruct->spriteIDs[i + 4]].invisible = FALSE;
+
+ for (i = 0; gUnknown_08402D08[0][i].unk0 != NULL; i++)
+ {
+ sub_8072C74(gTileBuffer, gUnknown_08402D08[1][i].unk0, 64, 2);
+ MenuPrint(gTileBuffer, gUnknown_08402D08[1][i].unk4, gUnknown_08402D08[1][i].unk5);
+ if (i != 0)
+ {
+ MenuZeroFillWindowRect(
+ gUnknown_08402D08[1][i].unk4,
+ gUnknown_08402D08[1][i].unk5 + 2,
+ gUnknown_08402D08[1][i].unk4 + 7,
+ gUnknown_08402D08[1][i].unk5 + 3);
+ }
+ }
+
+ if (!a)
+ sub_8072AB0(gOtherText_TeachWhichMove, 24, 120, 192, 32, 1);
+}
+
+u8 sub_8133248(void)
+{
+ u32 result = (gMain.newKeys & DPAD_LEFT) || (gMain.newKeys & DPAD_RIGHT);
+
+ if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR
+ && ((gMain.newKeys & L_BUTTON) || (gMain.newKeys & R_BUTTON)))
+ result++;
+
+ if (result != 0)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->state = 3;
+ sLearnMoveStruct->showContestInfo = FALSE;
+ }
+
+ return result;
+}
+
+void ClearLearnMoveVars(void)
+{
+ s32 i;
+
+ sLearnMoveStruct->state = 0;
+ sLearnMoveStruct->unk2 = 0;
+ sLearnMoveStruct->unk19 = 0;
+ sLearnMoveStruct->unk18 = 0;
+ sLearnMoveStruct->unk1C = 0;
+ sLearnMoveStruct->numMenuChoices = 0;
+ sLearnMoveStruct->menuSelection = 0;
+ sLearnMoveStruct->unk1D = FALSE;
+ sLearnMoveStruct->unk1E = 0;
+ sLearnMoveStruct->unk2C3 = FALSE;
+ sLearnMoveStruct->showContestInfo = FALSE;
+ for (i = 0; i < 20; i++)
+ sLearnMoveStruct->movesToLearn[i] = 0;
+}
+
+void sub_8133300(struct Sprite *sprite)
+{
+ s16 var = (sprite->data1 * 10) & 0xFF;
+
+ switch (sprite->data0)
+ {
+ case 0:
+ break;
+ case 1:
+ sprite->pos2.x = Sin(var, 3) * sprite->data2;
+ break;
+ case 2:
+ sprite->pos2.y = Sin(var, 1) * sprite->data2;
+ break;
+ }
+ sprite->data1++;
+}
+
+void sub_8133358(void)
+{
+ s32 i;
+
+ sLearnMoveStruct->spriteIDs[0] = CreateSprite(&gSpriteTemplate_8402D90, 8, 16, 0);
+ gSprites[sLearnMoveStruct->spriteIDs[0]].data0 = 1;
+ gSprites[sLearnMoveStruct->spriteIDs[0]].data2 = -1;
+
+ sLearnMoveStruct->spriteIDs[1] = CreateSprite(&gSpriteTemplate_8402D90, 72, 16, 0);
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[1]], 1);
+ gSprites[sLearnMoveStruct->spriteIDs[1]].data0 = 1;
+ gSprites[sLearnMoveStruct->spriteIDs[1]].data2 = 1;
+
+ sLearnMoveStruct->spriteIDs[2] = CreateSprite(&gSpriteTemplate_8402DC0, 160, 4, 0);
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[2]], 1);
+ gSprites[sLearnMoveStruct->spriteIDs[2]].data0 = 2;
+ gSprites[sLearnMoveStruct->spriteIDs[2]].data2 = -1;
+
+ sLearnMoveStruct->spriteIDs[3] = CreateSprite(&gSpriteTemplate_8402DC0, 160, 60, 0);
+ gSprites[sLearnMoveStruct->spriteIDs[3]].data0 = 2;
+ gSprites[sLearnMoveStruct->spriteIDs[3]].data2 = 1;
+
+ for (i = 0; i < 8; i++)
+ {
+ sLearnMoveStruct->spriteIDs[i + 4] = CreateSprite(&gSpriteTemplate_8402E08, (i - (i / 4) * 4) * 8 + 0x1C, (i / 4) * 8 + 0x34, 0);
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 4]], 2);
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ sLearnMoveStruct->spriteIDs[i + 12] = CreateSprite(&gSpriteTemplate_8402E08, (i - (i / 4) * 4) * 8 + 0x1C, (i / 4) * 8 + 0x5C, 0);
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 12]], 2);
+ }
+
+ for (i = 0; i < 20; i++)
+ gSprites[sLearnMoveStruct->spriteIDs[i]].invisible = TRUE;
+
+ CreateBlendedOutlineCursor(16, 0xFFFF, 12, 0x2D9F, 18);
+}
+
+void sub_8133558(void)
+{
+ s32 i;
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+
+ sLearnMoveStruct->numMenuChoices = GetMoveRelearnerMoves(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->movesToLearn);
+ for (i = 0; i < sLearnMoveStruct->numMenuChoices; i++)
+ StringCopy(sLearnMoveStruct->moveNames[i], gMoveNames[sLearnMoveStruct->movesToLearn[i]]);
+ GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_NICKNAME, nickname);
+ StringCopy10(gStringVar1, nickname);
+ StringCopy(sLearnMoveStruct->moveNames[sLearnMoveStruct->numMenuChoices], gUnknownText_Exit);
+ sLearnMoveStruct->numMenuChoices++;
+}
+
+void sub_813360C(s8 delta)
+{
+ sLearnMoveStruct->unk1C = sLearnMoveStruct->unk18;
+ sLearnMoveStruct->unk18 += delta;
+ sLearnMoveStruct->unk1D = TRUE;
+}
+
+void sub_813362C(void)
+{
+ if (gMain.newAndRepeatedKeys & DPAD_UP)
+ {
+ if (sLearnMoveStruct->menuSelection != 0)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->menuSelection--;
+ sLearnMoveStruct->unk2C3 = TRUE;
+ if (sLearnMoveStruct->unk18 != 0)
+ {
+ sub_813360C(-1);
+ }
+ else if (sLearnMoveStruct->unk19 != 0)
+ {
+ sLearnMoveStruct->unk19--;
+ sLearnMoveStruct->unk1E++;
+ }
+ }
+ }
+ else if (gMain.newAndRepeatedKeys & DPAD_DOWN)
+ {
+ if (sLearnMoveStruct->menuSelection < sLearnMoveStruct->numMenuChoices - 1)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->menuSelection++;
+ sLearnMoveStruct->unk2C3 = TRUE;
+ if (sLearnMoveStruct->unk18 != 2)
+ {
+ sub_813360C(1);
+ }
+ else if (sLearnMoveStruct->unk19 != sLearnMoveStruct->numMenuChoices - 3)
+ {
+ sLearnMoveStruct->unk19++;
+ sLearnMoveStruct->unk1E++;
+ }
+ }
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ if (sLearnMoveStruct->menuSelection != sLearnMoveStruct->numMenuChoices - 1)
+ {
+ sLearnMoveStruct->state = 8;
+ StringCopy(gStringVar2, sLearnMoveStruct->moveNames[sLearnMoveStruct->menuSelection]);
+ StringExpandPlaceholders(gStringVar4, gOtherText_TeachSpecificMove);
+ MenuPrintMessage(gStringVar4, 3, 15);
+ }
+ else
+ {
+ StringExpandPlaceholders(gStringVar4, gOtherText_GiveUpTeachingMove);
+ MenuPrintMessage(gStringVar4, 3, 15);
+ sLearnMoveStruct->state = 12;
+ }
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ sLearnMoveStruct->state = 12;
+ StringExpandPlaceholders(gStringVar4, gOtherText_GiveUpTeachingMove);
+ MenuPrintMessage(gStringVar4, 3, 15);
+ }
+ if (sLearnMoveStruct->numMenuChoices > 3)
+ {
+ gSprites[2].invisible = FALSE;
+ gSprites[3].invisible = FALSE;
+ if (sLearnMoveStruct->unk19 == 0)
+ gSprites[2].invisible = TRUE;
+ else if (sLearnMoveStruct->unk19 == sLearnMoveStruct->numMenuChoices - 3)
+ gSprites[3].invisible = TRUE;
+ }
+}
+
+void sub_8133800(void)
+{
+ u8 r6 = sLearnMoveStruct->unk19;
+ u8 *str = gTileBuffer;
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (r6 >= sLearnMoveStruct->numMenuChoices)
+ {
+ str = sub_8072C74(str, gEmptyString_81E72B0, 0x90, 0);
+ }
+ else if (r6 == sLearnMoveStruct->numMenuChoices - 1)
+ {
+ str = sub_8072C74(str, gUnknownText_Exit, 0x90, 0);
+ }
+ else
+ {
+ u16 moveId = sLearnMoveStruct->movesToLearn[r6];
+
+ if (sLearnMoveStruct->showContestInfo)
+ str = sub_8072C74(str, gUnknown_083CAF70[gContestMoves[moveId].contestCategory], 0x27, 0);
+ else
+ str = sub_8072C74(str, gTypeNames[gBattleMoves[moveId].type], 0x27, 0);
+
+ str = sub_8072C74(str, sLearnMoveStruct->moveNames[r6], 0x72, 0);
+
+ str[0] = CHAR_P;
+ str[1] = CHAR_P;
+ str[2] = CHAR_SLASH;
+ str += 3;
+
+ str = sub_8072C14(str, gBattleMoves[moveId].pp, 0x90, 0);
+ }
+ *str++ = CHAR_NEWLINE;
+ r6++;
+ }
+ *str = EOS;
+ MenuPrint(gTileBuffer, 11, 1);
+ sub_813360C(0);
+}
+
+const u8 gUnknown_08402E24[7][3] =
+{
+ {11, 1, 1},
+ { 3, 6, 2},
+ {24, 1, 3},
+ { 3, 11, 4},
+ { 5, 4, 5},
+ { 3, 6, 6},
+ { 3, 11, 7},
+};
+
+const u8 gUnknown_08402E39[] = {0, 1, 2, 3};
+const u8 gUnknown_08402E3D[] = {4, 5, 6};
+
+void PrintMoveInfo(u16 moveId, const u8 *b)
+{
+ u8 str[0x34];
+ u8 numHearts;
+ u8 i;
+
+ StringCopy(str, gExpandedPlaceholder_Empty);
+ switch (b[2])
+ {
+ case 1:
+ break;
+ case 2:
+ if (gBattleMoves[moveId].power < 2)
+ sub_8072C74(str, gOtherText_ThreeDashes2, 32, 2);
+ else
+ sub_8072C14(str, gBattleMoves[moveId].power, 32, 2);
+ MenuPrint(str, b[0], b[1]);
+ break;
+ case 4:
+ if (gBattleMoves[moveId].accuracy == 0)
+ sub_8072C74(str, gOtherText_ThreeDashes2, 32, 2);
+ else
+ sub_8072C14(str, gBattleMoves[moveId].accuracy, 32, 2);
+ MenuPrint(str, b[0], b[1]);
+ break;
+ case 6:
+ MenuZeroFillWindowRect(b[0], b[1], b[0], b[1] + 1);
+ numHearts = gContestEffects[gContestMoves[moveId].effect].appeal / 10;
+ if (numHearts == 255)
+ numHearts = 0;
+ for (i = 0; i < 8; i++)
+ {
+ if (i < numHearts)
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 4]], 1);
+ else
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 4]], 0);
+ }
+ break;
+ case 7:
+ MenuZeroFillWindowRect(b[0], b[1], b[0], b[1] + 1);
+ numHearts = gContestEffects[gContestMoves[moveId].effect].jam / 10;
+ if (numHearts == 255)
+ numHearts = 0;
+ for (i = 0; i < 8; i++)
+ {
+ if (i < numHearts)
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 12]], 3);
+ else
+ StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIDs[i + 12]], 2);
+ }
+ break;
+ }
+}
+
+void sub_8133AEC(bool8 contestInfo, int unused)
+{
+ u16 i;
+
+ if (sLearnMoveStruct->menuSelection != sLearnMoveStruct->numMenuChoices - 1)
+ {
+ u16 moveId = sLearnMoveStruct->movesToLearn[sLearnMoveStruct->menuSelection];
+
+ if (contestInfo)
+ {
+ for (i = 0; i < 16; i++)
+ gSprites[sLearnMoveStruct->spriteIDs[i + 4]].invisible = FALSE;
+ for (i = 0; i < 3; i++)
+ PrintMoveInfo(moveId, gUnknown_08402E24[gUnknown_08402E3D[i]]);
+ sub_8072AB0(gUnknown_083CADD4[gContestMoves[moveId].effect], 0x58, 0x48, 0x90, 32, 1);
+ }
+ else
+ {
+ u8 var;
+
+ for (i = 0; i < 4; i++)
+ PrintMoveInfo(moveId, gUnknown_08402E24[gUnknown_08402E39[i]]);
+ var = sub_8072A18(gMoveDescriptions[moveId - 1], 0x58, 0x48, 0x90, 1);
+ if (var < 2)
+ {
+ u8 r1 = var * 2 + 9;
+
+ MenuFillWindowRectWithBlankTile(11, r1, 28, 12);
+ }
+ }
+ }
+ else
+ {
+ if (contestInfo)
+ {
+ MenuZeroFillWindowRect(gUnknown_08402E24[5][0], gUnknown_08402E24[5][1], gUnknown_08402E24[5][0], gUnknown_08402E24[5][1] + 1);
+ MenuZeroFillWindowRect(gUnknown_08402E24[6][0], gUnknown_08402E24[6][1], gUnknown_08402E24[6][0], gUnknown_08402E24[6][1] + 1);
+ for (i = 0; i < 16; i++)
+ gSprites[sLearnMoveStruct->spriteIDs[i + 4]].invisible = TRUE;
+ }
+ else
+ {
+ MenuZeroFillWindowRect(gUnknown_08402E24[1][0], gUnknown_08402E24[1][1], gUnknown_08402E24[1][0] + 3, gUnknown_08402E24[1][1] + 1);
+ MenuZeroFillWindowRect(gUnknown_08402E24[3][0], gUnknown_08402E24[3][1], gUnknown_08402E24[3][0] + 3, gUnknown_08402E24[3][1] + 1);
+ }
+ MenuZeroFillWindowRect(11, 9, 28, 12);
+ }
+}
+
+void sub_8133CA4(void)
+{
+ MenuZeroFillWindowRect(21, 7, 27, 12);
+ sub_8133AEC(sLearnMoveStruct->showContestInfo, 0);
+}
diff --git a/src/pokemon/mail.c b/src/pokemon/mail.c
new file mode 100644
index 000000000..c5dd119e3
--- /dev/null
+++ b/src/pokemon/mail.c
@@ -0,0 +1,437 @@
+#include "global.h"
+#include "mail.h"
+#include "easy_chat.h"
+#include "items.h"
+#include "mail_data.h"
+#include "menu.h"
+#include "menu_helpers.h"
+#include "name_string_util.h"
+#include "palette.h"
+#include "pokemon_icon.h"
+#include "overworld.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "strings2.h"
+#include "task.h"
+#include "text.h"
+#include "unknown_task.h"
+
+struct UnkMailStruct
+{
+ u8 unk_0_0:2;
+ u8 unk_0_2:2;
+ u8 unk_0_4:4;
+};
+
+struct MailLayout
+{
+ u8 var0;
+ u8 var1;
+ u8 var2;
+ u8 var3_0:4;
+ u8 var3_4:4;
+ struct UnkMailStruct *var4;
+};
+
+struct Unk2000000
+{
+ /* 0x00*/ u8 words[8][27];
+ /* 0xD8*/ u8 varD8[20];
+ /* 0xEC*/ MainCallback varEC;
+ /* 0xF0*/ MainCallback varF0;
+ /* 0xF4*/ struct MailStruct *varF4;
+ /* 0xF8*/ u8 varF8;
+ /* 0xF9*/ u8 varF9;
+ /* 0xFA*/ u8 varFA;
+ /* 0xFB*/ u8 varFB;
+ /* 0xFC*/ u8 varFC;
+ u8 padFD[1];
+ /* 0xFE*/ u8 varFE;
+ /* 0xFF*/ u8 varFF;
+ /*0x100*/ u8 var100;
+ u8 pad101[3];
+ /*0x104*/ MainCallback var104;
+ /*0x108*/ MainCallback var108;
+ /*0x10C*/ struct MailLayout *var10C;
+};
+
+struct MailGraphics
+{
+ u16 (*palette)[];
+ u8 (*tiles)[];
+ u8 (*tileMap)[];
+ u16 var0C;
+ u16 var0E;
+ u16 color10;
+ u16 color12;
+};
+
+extern u8 ewram[];
+#define ewram0 (*(struct Unk2000000 *)(ewram))
+
+extern struct MailGraphics gMailGraphicsTable[];
+extern u16 gUnknown_083E562C[][2];
+
+extern struct MailLayout gUnknown_083E5730[];
+extern struct MailLayout gUnknown_083E57A4[];
+
+static u8 sub_80F8A28(void);
+static void sub_80F8D50(void);
+static void sub_80F8DA0(void);
+static void sub_80F8E80(void);
+static void sub_80F8F18(void);
+static void sub_80F8F2C(void);
+static void sub_80F8F58(void);
+static void sub_80F8F78(void);
+static void sub_80F8FB4(void);
+
+void HandleReadMail(struct MailStruct *arg0, MainCallback arg1, bool8 arg2)
+{
+ u16 mailDesign;
+ u16 buffer[2];
+
+ ewram0.varFF = GAME_LANGUAGE;
+ ewram0.var100 = 1;
+ ewram0.var104 = (MainCallback)EasyChat_GetWordText;
+ ewram0.var108 = (MainCallback)ConvertEasyChatWordsToString;
+
+ mailDesign = arg0->itemId - ITEM_ORANGE_MAIL;
+
+ if (mailDesign <= 11)
+ {
+ ewram0.varFA = arg0->itemId - ITEM_ORANGE_MAIL;
+ }
+ else
+ {
+ ewram0.varFA = 0;
+ arg2 = FALSE;
+ }
+
+ switch (ewram0.var100)
+ {
+ case 0:
+ default:
+ ewram0.var10C = &gUnknown_083E5730[ewram0.varFA];
+ break;
+
+ case 1:
+ ewram0.var10C = &gUnknown_083E57A4[ewram0.varFA];
+ break;
+ }
+
+ if (((MailSpeciesToSpecies(arg0->species, buffer) << 16) + 0xFFFF0000) <= (410 << 16))
+ {
+ switch (ewram0.varFA)
+ {
+ case 6:
+ ewram0.varFB = 1;
+ break;
+
+ case 9:
+ ewram0.varFB = 2;
+ break;
+
+ default:
+ ewram0.varFB = 0;
+ break;
+ }
+ }
+ else
+ {
+ ewram0.varFB = 0;
+ }
+
+
+ ewram0.varF4 = arg0;
+ ewram0.varEC = arg1;
+ ewram0.varF8 = arg2;
+
+ SetMainCallback2(sub_80F8D50);
+}
+
+#define RETURN_UP_STATE break
+#define RETURN_SKIP_STATE return FALSE
+
+static u8 sub_80F8A28(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ remove_some_task();
+ REG_DISPCNT = 0;
+ RETURN_UP_STATE;
+
+ case 1: CpuFill16(0, (void *)OAM, OAM_SIZE);
+ RETURN_UP_STATE;
+
+ case 2:
+ ResetPaletteFade();
+ RETURN_UP_STATE;
+
+ case 3:
+ ResetTasks();
+ RETURN_UP_STATE;
+
+ case 4:
+ ResetSpriteData();
+ RETURN_UP_STATE;
+
+ case 5:
+ FreeAllSpritePalettes();
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG2HOFS = 0;
+ REG_BG3HOFS = 0;
+ REG_BG3VOFS = 0;
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ RETURN_UP_STATE;
+
+ case 6:
+ SetUpWindowConfig(&gWindowConfig_81E6DFC);
+ RETURN_UP_STATE;
+
+ case 7:
+ MultistepInitMenuWindowBegin(&gWindowConfig_81E6DFC);
+ RETURN_UP_STATE;
+
+ case 8:
+ if (MultistepInitMenuWindowContinue() == 0)
+ {
+ return FALSE;
+ }
+ RETURN_UP_STATE;
+
+ case 9:
+ MenuZeroFillScreen();
+ RETURN_UP_STATE;
+
+ case 10: CpuFill16(1, (void *)(VRAM + 0x4800), 0x800);
+ RETURN_UP_STATE;
+
+ case 11:
+ LoadPalette(gMailGraphicsTable[ewram0.varFA].palette, 0, 16 * 2);
+ RETURN_UP_STATE;
+
+ case 12:
+ LZ77UnCompVram(gMailGraphicsTable[ewram0.varFA].tileMap, (void *)(VRAM + 0x4000));
+ RETURN_UP_STATE;
+
+ case 13:
+ LZ77UnCompVram(gMailGraphicsTable[ewram0.varFA].tiles, (void *)(VRAM));
+
+ gPlttBufferUnfaded[241] = gMailGraphicsTable[ewram0.varFA].color10;
+ gPlttBufferUnfaded[248] = gMailGraphicsTable[ewram0.varFA].color12;
+ gPlttBufferUnfaded[10] = gUnknown_083E562C[gSaveBlock2.playerGender][0];
+ gPlttBufferUnfaded[11] = gUnknown_083E562C[gSaveBlock2.playerGender][1];
+ RETURN_UP_STATE;
+
+ case 14:
+ if (ewram0.varF8 != 0)
+ {
+ sub_80F8DA0();
+ }
+ RETURN_UP_STATE;
+
+ case 15:
+ if (ewram0.varF8 != 0)
+ {
+ sub_80F8E80();
+ }
+
+ SetVBlankCallback(sub_80F8F18);
+ gPaletteFade.bufferTransferDisabled = 1;
+ RETURN_UP_STATE;
+
+ case 16:
+ {
+ u16 local1;
+
+ local1 = sub_809D4A8(ewram0.varF4->species);
+
+ switch (ewram0.varFB)
+ {
+ case 1:
+ sub_809D580(local1);
+ ewram0.varFC = sub_809D3A4(local1, SpriteCallbackDummy, 96, 128, 0);
+ break;
+
+ case 2:
+ sub_809D580(local1);
+ ewram0.varFC = sub_809D3A4(local1, SpriteCallbackDummy, 40, 128, 0);
+ break;
+ }
+ RETURN_UP_STATE;
+ }
+
+ case 17:
+ if (sub_8055870() != TRUE)
+ {
+ RETURN_UP_STATE;
+ }
+ RETURN_SKIP_STATE;
+
+ case 18:
+ REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(31) | BGCNT_16COLOR | BGCNT_TXT256x512;
+ REG_BG1CNT = BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(8) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG2CNT = BGCNT_PRIORITY(2) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(9) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BLDCNT = 0;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON;
+ BeginNormalPaletteFade(-1, 0, 16, 0, 0);
+ gPaletteFade.bufferTransferDisabled = 0;
+ ewram0.varF0 = sub_80F8F58;
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+
+ gMain.state += 1;
+ return FALSE;
+}
+
+static void sub_80F8D50(void)
+{
+ do
+ {
+ if (sub_80F8A28() == 1)
+ {
+ SetMainCallback2(sub_80F8F2C);
+ return;
+ }
+ } while (sub_80F9344() != 1);
+}
+
+static u8 *sub_80F8D7C(u8 *dest, u8 *src)
+{
+ u16 length;
+
+ StringCopy(dest, src);
+ SanitizeNameString(dest);
+
+ length = StringLength(dest);
+
+ return dest + length;
+}
+
+static void sub_80F8DA0(void)
+{
+ u16 i;
+ u8 r6;
+ u8 *ptr;
+
+ r6 = 0;
+ for (i = 0; i < ewram0.var10C->var0; i++)
+ {
+ ConvertEasyChatWordsToString(ewram0.words[i], &ewram0.varF4->words[r6], ewram0.var10C->var4[i].unk_0_2, 1);
+ r6 += ewram0.var10C->var4[i].unk_0_2;
+ }
+ ptr = ewram0.varD8;
+ if (ewram0.var100 == 0)
+ {
+ ptr = sub_80F8D7C(ptr, ewram0.varF4->playerName);
+ StringCopy(ptr, gOtherText_From);
+ ewram0.varF9 = ewram0.var10C->var2 - StringLength(ewram0.varD8);
+
+ }
+ else
+ {
+ ptr = StringCopy(ptr, gOtherText_From);
+ sub_80F8D7C(ptr, ewram0.varF4->playerName);
+ ewram0.varF9 = ewram0.var10C->var2;
+ }
+}
+
+static void sub_80F8E80(void)
+{
+ u16 pos;
+ u8 x;
+ u8 y = 0;
+
+ for (pos = 0; pos < ewram0.var10C->var0; pos++)
+ {
+ if (ewram0.words[pos][0] == 0xFF)
+ {
+ continue;
+ }
+
+ if (ewram0.words[pos][0] == 0x00)
+ {
+ continue;
+ }
+
+ x = ewram0.var10C->var4[pos].unk_0_4;
+ y += ewram0.var10C->var4[pos].unk_0_0;
+ MenuPrint(ewram0.words[pos], ewram0.var10C->var3_4 + x, ewram0.var10C->var3_0 + y);
+ y += 2;
+ }
+
+ MenuPrint(ewram0.varD8, ewram0.varF9, ewram0.var10C->var1);
+}
+
+static void sub_80F8F18(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void sub_80F8F2C(void)
+{
+ if (ewram0.varFB != 0)
+ {
+ AnimateSprites();
+ BuildOamBuffer();
+ }
+
+ ewram0.varF0();
+}
+
+static void sub_80F8F58(void)
+{
+ u8 local0;
+
+ local0 = UpdatePaletteFade();
+ if (local0 == 0)
+ {
+ ewram0.varF0 = sub_80F8F78;
+ }
+}
+
+static void sub_80F8F78(void)
+{
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ ewram0.varF0 = sub_80F8FB4;
+ }
+}
+
+static void sub_80F8FB4(void)
+{
+ u16 local1;
+
+ if (UpdatePaletteFade())
+ {
+ return;
+ }
+
+ SetMainCallback2(ewram0.varEC);
+ switch (ewram0.varFB)
+ {
+ case 2:
+ case 1:
+ local1 = sub_809D4A8(ewram0.varF4->species);
+ sub_809D608(local1);
+
+ sub_809D510(&gSprites[ewram0.varFC]);
+ break;
+ }
+
+ memset(&ewram0, 0, 0x110);
+ ResetPaletteFade();
+}
diff --git a/src/pokemon/mail_data.c b/src/pokemon/mail_data.c
new file mode 100644
index 000000000..ae3f4b3e8
--- /dev/null
+++ b/src/pokemon/mail_data.c
@@ -0,0 +1,208 @@
+#include "global.h"
+#include "mail_data.h"
+#include "items.h"
+#include "name_string_util.h"
+#include "pokemon.h"
+#include "pokemon_icon.h"
+#include "species.h"
+#include "text.h"
+
+void ClearMailData(void)
+{
+ u8 i;
+
+ for (i = 0; i < 16; i++)
+ ClearMailStruct(&gSaveBlock1.mail[i]);
+}
+
+void ClearMailStruct(struct MailStruct *mail)
+{
+ int i;
+
+ for (i = 0; i < 9; i++)
+ mail->words[i] = -1;
+
+ for (i = 0; i < 8; i++)
+ mail->playerName[i] = -1;
+
+ for (i = 0; i < 4; i++)
+ mail->trainerId[i] = 0;
+
+ mail->species = 1;
+ mail->itemId = 0;
+}
+
+bool8 MonHasMail(struct Pokemon *mon)
+{
+ u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM);
+ if (ItemIsMail(heldItem) && GetMonData(mon, MON_DATA_MAIL) != 0xFF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+u8 GiveMailToMon(struct Pokemon *mon, u16 itemId)
+{
+ u16 _itemId;
+ u8 heldItem[2];
+ u8 id;
+ u8 i;
+ u16 species;
+ u32 personality;
+
+ _itemId = itemId;
+ heldItem[0] = _itemId;
+ heldItem[1] = _itemId >> 8;
+ id = 0;
+
+ while (id < 6)
+ {
+ if (gSaveBlock1.mail[id].itemId == 0)
+ {
+ for (i = 0; i < 9; i++)
+ gSaveBlock1.mail[id].words[i] = -1;
+
+ for (i = 0; i < 7; i++)
+ gSaveBlock1.mail[id].playerName[i] = gSaveBlock2.playerName[i];
+ gSaveBlock1.mail[id].playerName[i] = EOS;
+ PadNameString(gSaveBlock1.mail[id].playerName, 0);
+
+ for (i = 0; i < 4; i++)
+ gSaveBlock1.mail[id].trainerId[i] = gSaveBlock2.playerTrainerId[i];
+
+ species = GetBoxMonData(&mon->box, MON_DATA_SPECIES);
+ personality = GetBoxMonData(&mon->box, MON_DATA_PERSONALITY);
+ gSaveBlock1.mail[id].species = SpeciesToMailSpecies(species, personality);
+ gSaveBlock1.mail[id].itemId = _itemId;
+ SetMonData(mon, MON_DATA_MAIL, &id);
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+ return id;
+ }
+ id++;
+ }
+
+ return -1;
+}
+
+u16 SpeciesToMailSpecies(u16 species, u32 personality)
+{
+ if (species == SPECIES_UNOWN)
+ {
+ int mailSpecies = GetUnownLetterByPersonality(personality) + 30000;
+ return mailSpecies;
+ }
+
+ return species;
+}
+
+u16 MailSpeciesToSpecies(u16 a1, u16 *a2)
+{
+ u16 result;
+
+ if (a1 >= 30000 && a1 < (30000 + UNOWN_FORM_COUNT))
+ {
+ result = SPECIES_UNOWN;
+ *a2 = a1 - 30000;
+ }
+ else
+ {
+ result = a1;
+ }
+
+ return result;
+}
+
+u8 GiveMailToMon2(struct Pokemon *mon, struct MailStruct *mail)
+{
+ u8 heldItem[2];
+ u16 itemId = mail->itemId;
+ u8 mailId = GiveMailToMon(mon, itemId);
+
+ if (mailId == 0xFF)
+ return 0xFF;
+
+ gSaveBlock1.mail[mailId] = *mail;
+
+ SetMonData(mon, MON_DATA_MAIL, &mailId);
+
+ heldItem[0] = itemId;
+ heldItem[1] = itemId >> 8;
+
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+
+ return mailId;
+}
+
+int unref_sub_80A2DF4(void)
+{
+ return 0;
+}
+
+void TakeMailFromMon(struct Pokemon *mon)
+{
+ u8 heldItem[2];
+ u8 mailId;
+
+ if (MonHasMail(mon))
+ {
+ mailId = GetMonData(mon, MON_DATA_MAIL);
+ gSaveBlock1.mail[mailId].itemId = 0;
+ mailId = 0xFF;
+ heldItem[0] = 0;
+ heldItem[1] = 0;
+ SetMonData(mon, MON_DATA_MAIL, &mailId);
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+ }
+}
+
+void DeleteMail(u8 mailId)
+{
+ gSaveBlock1.mail[mailId].itemId = 0;
+}
+
+u8 TakeMailFromMon2(struct Pokemon *mon)
+{
+ u8 i;
+ u8 newHeldItem[2];
+ u8 newMailId;
+
+ newHeldItem[0] = 0;
+ newHeldItem[1] = 0;
+ newMailId = 0xFF;
+
+ for (i = 6; i < 16; i++)
+ {
+ if (gSaveBlock1.mail[i].itemId == 0)
+ {
+ memcpy(&gSaveBlock1.mail[i], &gSaveBlock1.mail[GetMonData(mon, MON_DATA_MAIL)], sizeof(struct MailStruct));
+ gSaveBlock1.mail[GetMonData(mon, MON_DATA_MAIL)].itemId = 0;
+ SetMonData(mon, MON_DATA_MAIL, &newMailId);
+ SetMonData(mon, MON_DATA_HELD_ITEM, newHeldItem);
+ return i;
+ }
+ }
+
+ return 0xFF;
+}
+
+bool8 ItemIsMail(u16 itemId)
+{
+ switch (itemId)
+ {
+ case ITEM_ORANGE_MAIL:
+ case ITEM_HARBOR_MAIL:
+ case ITEM_GLITTER_MAIL:
+ case ITEM_MECH_MAIL:
+ case ITEM_WOOD_MAIL:
+ case ITEM_WAVE_MAIL:
+ case ITEM_BEAD_MAIL:
+ case ITEM_SHADOW_MAIL:
+ case ITEM_TROPIC_MAIL:
+ case ITEM_DREAM_MAIL:
+ case ITEM_FAB_MAIL:
+ case ITEM_RETRO_MAIL:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
diff --git a/src/pokemon/mon_markings.c b/src/pokemon/mon_markings.c
new file mode 100644
index 000000000..0cad8db59
--- /dev/null
+++ b/src/pokemon/mon_markings.c
@@ -0,0 +1,383 @@
+#include "global.h"
+#include "main.h"
+#include "menu_cursor.h"
+#include "text_window.h"
+#include "songs.h"
+#include "sound.h"
+#include "sprite.h"
+
+#ifdef GERMAN
+#define MENU_TEXT_SPRITE_X_OFFSET 24
+#else
+#define MENU_TEXT_SPRITE_X_OFFSET 32
+#endif
+
+struct PokemonMarkMenu
+{
+ /*0x0000*/ u16 baseTileTag;
+ /*0x0002*/ u16 basePaletteTag;
+ /*0x0004*/ u8 markings; // bit flags
+ /*0x0005*/ s8 cursorPos;
+ /*0x0006*/ bool8 markingsArray[4];
+ /*0x000A*/ u8 cursorBaseY;
+ /*0x000B*/ bool8 spriteSheetLoadRequired;
+ /*0x000C*/ struct Sprite *menuWindowSprites[2]; // upper and lower halves of menu window
+ /*0x0014*/ struct Sprite *menuMarkingSprites[4];
+ /*0x0024*/ struct Sprite *menuTextSprite;
+ /*0x0028*/ u8 *frameTiles;
+ /*0x002C*/ u16 *framePalette;
+ /*0x0030*/ u8 menuWindowSpriteTiles[0x1000];
+ /*0x1030*/ u8 filler1030[0x80];
+ /*0x10B0*/ u8 tileLoadState;
+};
+
+extern u8 gPokenavConditionMenuMisc_Gfx[];
+extern u16 gUnknown_08E966B8[];
+
+extern u16 gUnknown_083E49F4[];
+extern u8 gUnknown_083E4A14[];
+extern struct OamData gOamData_83E5214;
+extern struct OamData gOamData_83E521C;
+extern const union AnimCmd *const gSpriteAnimTable_83E5274[];
+extern const union AnimCmd *const gSpriteAnimTable_83E52AC[];
+extern struct OamData gOamData_83E52B4;
+extern const union AnimCmd *const gSpriteAnimTable_83E533C[];
+
+static EWRAM_DATA struct PokemonMarkMenu *sMenu = NULL;
+
+void sub_80F761C(s16, s16, u16, u16);
+void nullsub_65(struct Sprite *);
+void sub_80F78CC(struct Sprite *);
+void sub_80F7908(struct Sprite *);
+struct Sprite *sub_80F7960(u16, u16, u16 *, u16);
+
+void sub_80F727C(struct PokemonMarkMenu *ptr)
+{
+ sMenu = ptr;
+ sMenu->spriteSheetLoadRequired = FALSE;
+}
+
+void sub_80F728C(void)
+{
+ const struct FrameGraphics *frame = GetTextWindowFrameGraphics(gSaveBlock2.optionsWindowFrameType);
+ sMenu->frameTiles = frame->tiles;
+ sMenu->framePalette = frame->palette;
+ sMenu->tileLoadState = 0;
+ CpuFill16(0, sMenu->menuWindowSpriteTiles, sizeof(sMenu->menuWindowSpriteTiles));
+}
+
+bool8 sub_80F72D4(void)
+{
+ u16 i;
+ u8 *dest = sMenu->menuWindowSpriteTiles + sMenu->tileLoadState * 0x100;
+
+ switch (sMenu->tileLoadState)
+ {
+ case 0:
+ CpuFastCopy(sMenu->frameTiles, dest, TILE_SIZE_4BPP);
+ for (i = 0; i < 6; i++)
+ {
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP);
+ }
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 2, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP);
+ sMenu->tileLoadState++;
+ break;
+ default:
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 3, dest, TILE_SIZE_4BPP);
+ for (i = 0; i < 6; i++)
+ {
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 4, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP);
+ }
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 5, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP);
+ sMenu->tileLoadState++;
+ break;
+ case 13:
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 6, dest, TILE_SIZE_4BPP);
+ for (i = 0; i < 6; i++)
+ {
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 7, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP);
+ }
+ CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 8, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP);
+ sMenu->tileLoadState++;
+ return FALSE;
+ case 14:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void sub_80F7404(void)
+{
+ sub_80F728C();
+ while (sub_80F72D4())
+ ;
+}
+
+void sub_80F7418(u8 markings, s16 x, s16 y)
+{
+ u16 i;
+ sMenu->cursorPos = 0;
+ sMenu->markings = markings;
+ for (i = 0; i < 4; i++)
+ sMenu->markingsArray[i] = (sMenu->markings >> i) & 1;
+ DestroyMenuCursor();
+ sub_80F761C(x, y, sMenu->baseTileTag, sMenu->basePaletteTag);
+}
+
+void sub_80F7470(void)
+{
+ u16 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ FreeSpriteTilesByTag(sMenu->baseTileTag + i);
+ }
+
+ FreeSpritePaletteByTag(sMenu->basePaletteTag);
+ FreeSpritePaletteByTag(sMenu->basePaletteTag + 1);
+
+ for (i = 0; i < 2; i++)
+ {
+ if (!sMenu->menuWindowSprites[i])
+ return;
+ DestroySprite(sMenu->menuWindowSprites[i]);
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!sMenu->menuMarkingSprites[i])
+ return;
+ DestroySprite(sMenu->menuMarkingSprites[i]);
+ }
+
+ DestroyMenuCursor();
+
+ if (sMenu->menuTextSprite)
+ DestroySprite(sMenu->menuTextSprite);
+}
+
+bool8 sub_80F7500(void)
+{
+ u16 i;
+ struct SpriteSheet sheets[3] =
+ {
+ { sMenu->menuWindowSpriteTiles, 0x1000, sMenu->baseTileTag },
+ { gPokenavConditionMenuMisc_Gfx, 0x520, sMenu->baseTileTag + 1 },
+ { NULL, 0, 0 }
+ };
+
+ if (sMenu->spriteSheetLoadRequired)
+ {
+ LoadTilesForSpriteSheets(sheets);
+ sMenu->spriteSheetLoadRequired = FALSE;
+ }
+
+ if (gMain.newKeys & DPAD_UP)
+ {
+ s8 pos;
+ PlaySE(SE_SELECT);
+ pos = --sMenu->cursorPos;
+ if (pos < 0)
+ sMenu->cursorPos = 5;
+ return TRUE;
+ }
+
+ if (gMain.newKeys & DPAD_DOWN)
+ {
+ s8 pos;
+ PlaySE(SE_SELECT);
+ pos = ++sMenu->cursorPos;
+ if (pos > 5)
+ sMenu->cursorPos = 0;
+ return TRUE;
+ }
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+
+ switch (sMenu->cursorPos)
+ {
+ case 4:
+ sMenu->markings = 0;
+ for (i = 0; i < 4; i++)
+ sMenu->markings |= sMenu->markingsArray[i] << i;
+ return FALSE;
+ case 5:
+ return FALSE;
+ }
+
+ sMenu->markingsArray[sMenu->cursorPos] = !sMenu->markingsArray[sMenu->cursorPos];
+ return TRUE;
+ }
+
+ if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void sub_80F761C(s16 x, s16 y, u16 baseTileTag, u16 basePaletteTag)
+{
+ u16 i;
+ u8 spriteId;
+
+ struct SpriteSheet sheets[] =
+ {
+ { sMenu->menuWindowSpriteTiles, 0x1000, baseTileTag },
+ { gPokenavConditionMenuMisc_Gfx, 0x520, baseTileTag + 1 },
+ { NULL, 0 }
+ };
+
+ struct SpritePalette palettes[] =
+ {
+ { sMenu->framePalette, basePaletteTag },
+ { gUnknown_08E966B8, basePaletteTag + 1},
+ { NULL, 0 }
+ };
+
+ struct SpriteTemplate sprTemplate =
+ {
+ baseTileTag,
+ basePaletteTag,
+ &gOamData_83E5214,
+ gSpriteAnimTable_83E52AC,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ nullsub_65,
+ };
+
+ sMenu->spriteSheetLoadRequired = TRUE;
+ AllocTilesForSpriteSheets(sheets);
+ LoadSpritePalettes(palettes);
+
+ for (i = 0; i < 2; i++)
+ {
+ spriteId = CreateSprite(&sprTemplate, x + 32, y + 32, 2);
+ if (spriteId != 64)
+ {
+ sMenu->menuWindowSprites[i] = &gSprites[spriteId];
+ StartSpriteAnim(&gSprites[spriteId], i);
+ }
+ else
+ {
+ sMenu->menuWindowSprites[i] = NULL;
+ return;
+ }
+ }
+
+ sMenu->menuWindowSprites[1]->pos1.y = y + 96;
+
+ sprTemplate.tileTag++;
+ sprTemplate.paletteTag++;
+ sprTemplate.anims = gSpriteAnimTable_83E5274;
+ sprTemplate.callback = sub_80F78CC;
+ sprTemplate.oam = &gOamData_83E521C;
+
+ for (i = 0; i < 4; i++)
+ {
+ spriteId = CreateSprite(&sprTemplate, x + 32, y + 16 + 16 * i, 1);
+ if (spriteId != 64)
+ {
+ sMenu->menuMarkingSprites[i] = &gSprites[spriteId];
+ gSprites[spriteId].data0 = i;
+ }
+ else
+ {
+ sMenu->menuMarkingSprites[i] = NULL;
+ return;
+ }
+ }
+
+ sprTemplate.callback = SpriteCallbackDummy;
+
+ spriteId = CreateSprite(&sprTemplate, 0, 0, 1);
+
+ if (spriteId != 64)
+ {
+ sMenu->menuTextSprite = &gSprites[spriteId];
+ sMenu->menuTextSprite->oam.shape = ST_OAM_H_RECTANGLE;
+ sMenu->menuTextSprite->oam.size = 3;
+ StartSpriteAnim(sMenu->menuTextSprite, 9);
+ sMenu->menuTextSprite->pos1.x = x + MENU_TEXT_SPRITE_X_OFFSET;
+ sMenu->menuTextSprite->pos1.y = y + 80;
+ CalcCenterToCornerVec(sMenu->menuTextSprite, 1, 2, 0);
+ }
+ else
+ {
+ sMenu->menuTextSprite = NULL;
+ }
+
+ sMenu->cursorBaseY = y + 8;
+ sub_814A5C0(0, basePaletteTag + 1, 15, 0, 0x30);
+ sub_814A880(x + 8, sMenu->cursorBaseY);
+ sub_814AABC(sub_80F7908);
+}
+
+void nullsub_65(struct Sprite *sprite)
+{
+}
+
+void sub_80F78CC(struct Sprite *sprite)
+{
+ if (sMenu->markingsArray[sprite->data0])
+ StartSpriteAnim(sprite, 2 * sprite->data0 + 1);
+ else
+ StartSpriteAnim(sprite, 2 * sprite->data0);
+}
+
+void sub_80F7908(struct Sprite *sprite)
+{
+ sprite->pos1.y = 16 * sMenu->cursorPos + sMenu->cursorBaseY;
+}
+
+struct Sprite *sub_80F7920(u16 tileTag, u16 paletteTag, u16 *palette)
+{
+ if (!palette)
+ palette = gUnknown_083E49F4;
+ return sub_80F7960(tileTag, paletteTag, palette, 16);
+}
+
+struct Sprite *sub_80F7940(u16 tileTag, u16 paletteTag, u16 *palette)
+{
+ if (!palette)
+ palette = gUnknown_083E49F4;
+ return sub_80F7960(tileTag, paletteTag, palette, 1);
+}
+
+struct Sprite *sub_80F7960(u16 tileTag, u16 paletteTag, u16 *palette, u16 size)
+{
+ u8 spriteId;
+ struct SpriteTemplate sprTemplate;
+ struct SpriteSheet sheet = { gUnknown_083E4A14, 0x80, tileTag };
+ struct SpritePalette sprPalette = { palette, paletteTag };
+
+ sprTemplate.tileTag = tileTag;
+ sprTemplate.paletteTag = paletteTag;
+ sprTemplate.oam = &gOamData_83E52B4;
+ sprTemplate.anims = gSpriteAnimTable_83E533C;
+ sprTemplate.images = NULL;
+ sprTemplate.affineAnims = gDummySpriteAffineAnimTable;
+ sprTemplate.callback = nullsub_65;
+
+ sheet.size = size * 0x80;
+
+ LoadSpriteSheet(&sheet);
+ LoadSpritePalette(&sprPalette);
+
+ spriteId = CreateSprite(&sprTemplate, 0, 0, 0);
+ if (spriteId != 64)
+ return &gSprites[spriteId];
+ else
+ return NULL;
+}
+
+void sub_80F7A10(u8 markings, void *dest)
+{
+ void *src = gUnknown_083E4A14 + markings * 0x80;
+ DmaCopy16(3, src, dest, 0x80);
+}
diff --git a/src/pokemon/pokeblock_feed.c b/src/pokemon/pokeblock_feed.c
new file mode 100644
index 000000000..5d6b215cd
--- /dev/null
+++ b/src/pokemon/pokeblock_feed.c
@@ -0,0 +1,1015 @@
+#include "global.h"
+#include "task.h"
+#include "palette.h"
+#include "main.h"
+#include "menu_helpers.h"
+#include "text.h"
+#include "text_window.h"
+#include "menu.h"
+#include "overworld.h"
+#include "decompress.h"
+#include "data2.h"
+#include "sprite.h"
+#include "item_use.h"
+#include "pokeblock.h"
+#include "party_menu.h"
+#include "strings.h"
+#include "string_util.h"
+#include "m4a.h"
+#include "field_effect.h"
+#include "sound.h"
+#include "trig.h"
+
+extern u8 ewram[];
+extern struct MusicPlayerInfo gMPlay_BGM;
+extern u8 gPokeblockMonID;
+extern s16 gPokeblockGain;
+
+extern const u8 gPokeblockRed_Pal[];
+extern const u8 gPokeblockBlue_Pal[];
+extern const u8 gPokeblockPink_Pal[];
+extern const u8 gPokeblockGreen_Pal[];
+extern const u8 gPokeblockYellow_Pal[];
+extern const u8 gPokeblockPurple_Pal[];
+extern const u8 gPokeblockIndigo_Pal[];
+extern const u8 gPokeblockBrown_Pal[];
+extern const u8 gPokeblockLiteBlue_Pal[];
+extern const u8 gPokeblockOlive_Pal[];
+extern const u8 gPokeblockGray_Pal[];
+extern const u8 gPokeblockBlack_Pal[];
+extern const u8 gPokeblockWhite_Pal[];
+extern const u8 gPokeblockGold_Pal[];
+extern const u8 gPokeblock_Gfx[];
+extern const u8 gBattleTerrainTiles_Building[];
+extern const u8 gUnknown_08E782FC[];
+extern const u8 gBattleTerrainPalette_BattleTower[];
+extern const struct CompressedSpriteSheet gUnknown_083F7F74;
+extern const struct CompressedSpritePalette gUnknown_083F7F7C;
+
+bool8 IsPokeSpriteNotFlipped(u16 species);
+
+// this file's functions
+static void sub_8147B04(void);
+static void sub_81481DC(void);
+static void sub_814825C(void);
+static u8 sub_81480B4(void);
+static u8 CreatePokeblockSprite(void);
+static u8 PokeblockFeed_CreatePokeSprite(struct Pokemon* mon);
+static bool8 sub_8147B20(struct Pokemon* mon);
+static void LaunchPokeblockFeedTask(u8);
+static void sub_8148044(u8);
+static void sub_8148078(struct Sprite* sprite);
+static void Task_PrintAtePokeblockText(u8 taskID);
+static void Task_PaletteFadeToReturn(u8 taskID);
+static void SetPokeblockFeedSpritePal(u8);
+static void sub_8148108(u8, bool8);
+static bool8 sub_8148540(void);
+static bool8 sub_81485CC(void);
+static bool8 FreePokeSpriteMatrix(void);
+void sub_8148710(void);
+static void SpriteCB_ThrownPokeblock(struct Sprite* sprite);
+static void sub_814862C(void);
+
+// EWRAM
+EWRAM_DATA static struct CompressedSpritePalette sPokeblockFeedSpritePal = {0};
+
+// IWRAM common
+struct Sprite* gPokeblockFeedPokeSprite;
+u16 gPokeblockFeedMonSpecies;
+bool8 gPokeblockMonNotFlipped;
+u8 gPokeblockFeedMonSpriteID;
+u8 gPokeblockFeedMonNature;
+u16 gUnknown_03005F34;
+u8 gPokeblockFeedUnused0;
+u8 gUnknown_03005F3C;
+u8 gUnknown_03005F40;
+struct Sprite gPokeblockFeedPokeSpriteCopy;
+u16 gUnknown_03005F94;
+s16 gUnknown_03005FA0[24];
+
+// rodata
+
+static const u8 sNatureToMonPokeblockAnim[][2] =
+{
+ { 0, 0 }, // HARDY
+ { 3, 0 }, // LONELY
+ { 4, 1 }, // BRAVE
+ { 5, 0 }, // ADAMANT
+ { 10, 0 }, // NAUGHTY
+ { 13, 0 }, // BOLD
+ { 15, 0 }, // DOCILE
+ { 16, 2 }, // RELAXED
+ { 18, 0 }, // IMPISH
+ { 19, 0 }, // LAX
+ { 20, 0 }, // TIMID
+ { 25, 0 }, // HASTY
+ { 27, 3 }, // SERIOUS
+ { 28, 0 }, // JOLLY
+ { 29, 0 }, // NAIVE
+ { 33, 4 }, // MODEST
+ { 36, 0 }, // MILD
+ { 37, 0 }, // QUIET
+ { 39, 0 }, // BASHFUL
+ { 42, 0 }, // RASH
+ { 45, 0 }, // CALM
+ { 46, 5 }, // GENTLE
+ { 47, 6 }, // SASSY
+ { 48, 0 }, // CAREFUL
+ { 53, 0 }, // QUIRKY
+};
+
+static const s16 sMonPokeblockAnims[][10] =
+{
+ // HARDY
+ { 0, 4, 0, 8, 24, 0, 0, 0, 12, 0},
+ { 0, 4, 0, 16, 24, 0, 0, 0, 12, 0},
+ { 0, 4, 0, 32, 32, 0, 0, 0, 16, 1},
+
+ // LONELY
+ { 0, 3, 6, 0, 48, 0, 0, 0, 24, 1},
+
+ // BRAVE
+ { 64, 16, -24, 0, 32, 0, 0, 0, 0, 1},
+
+ // ADAMANT
+ { 0, 4, 8, 0, 16, 0, -8, 0, 0, 0},
+ { 0, 0, 0, 0, 16, 0, 0, 0, 0, 0},
+ { 0, 4, 8, 0, 16, 0, -8, 0, 0, 0},
+ { 0, 0, 0, 0, 16, 0, 0, 0, 0, 0},
+ { 0, 4, -16, 0, 4, 0, 16, 0, 0, 1},
+
+ // NAUGHTY
+ { 0, 3, 6, 0, 12, 0, 0, 0, 6, 0},
+ { 0, 3, -6, 0, 12, 0, 0, 0, 6, 0},
+ { 0, 16, 16, 0, 45, 1, 0, 0, 0, 1},
+
+ // BOLD
+ { 0, 16, 0, 24, 32, 0, 0, 0, 16, 0},
+ { 0, 16, 0, 23, 32, 0, 0, 0, 16, 1},
+
+ // DOCILE
+ { 0, 0, 0, 0, 80, 0, 0, 0, 0, 1},
+
+ // RELAXED
+ { 0, 2, 8, 0, 32, 0, 0, 0, 0, 0},
+ { 0, 2, -8, 0, 32, 0, 0, 0, 0, 1},
+
+ // IMPISH
+ { 0, 32, 2, 1, 48, 1, 0, 0, 24, 1},
+
+ // LAX
+ { 0, 2, 16, 16, 128, 0, 0, 0, 0, 1},
+
+ // TIMID
+ { 0, 2, -8, 0, 48, 0, -24, 0, 0, 0},
+ { 0, 0, 0, 0, 8, 0, 0, 0, 0, 0},
+ { 64, 32, 2, 0, 36, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 8, 0, 0, 0, 0, 0},
+ { 0, 2, 8, 0, 48, 0, 24, 0, 0, 1},
+
+ // HASTY
+ { 64, 24, 16, 0, 32, 0, 0, 0, 0, 0},
+ { 0, 28, 2, 1, 32, 1, 0, 0, 16, 1},
+
+ // SERIOUS
+ { 0, 0, 0, 0, 32, 0, 0, 0, 0, 1},
+
+ // JOLLY
+ { 64, 16, -16, 2, 48, 0, 0, 0, 32, 1},
+
+ // NAIVE
+ { 0, 12, -8, 4, 24, 0, 8, 0, 12, 0},
+ { 0, 12, 8, 8, 24, 0, -16, 0, 12, 0},
+ { 0, 12, -8, 16, 24, 0, 16, 0, 12, 0},
+ { 0, 12, 8, 28, 24, 0, -8, 0, 12, 1},
+
+ // MODEST
+ { 0, 0, 0, 0, 8, 0, 0, 0, 0, 0},
+ { 64, 16, -4, 0, 32, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 8, 0, 0, 0, 0, 1},
+
+ // MILD
+ { 128, 4, 0, 8, 64, 0, 0, 0, 0, 1},
+
+ // QUIET
+ { 0, 2, 16, 0, 48, 0, 0, 0, 0, 0},
+ { 128, 2, 16, 0, 48, 0, 0, 0, 0, 1},
+
+ // BASHFUL
+ { 0, 2, -4, 0, 48, 0, -48, 0, 0, 0},
+ { 0, 0, 0, 0, 80, 0, 0, 0, 0, 0},
+ { 0, 2, 8, 0, 24, 0, 48, 0, 0, 1},
+
+ // RASH
+ { 64, 4, 64, 58, 52, 0, -88, 0, 0, 0},
+ { 0, 0, 0, 0, 80, 0, 0, 0, 0, 0},
+ { 0, 24, 80, 0, 32, 0, 88, 0, 0, 1},
+
+ // CALM
+ { 0, 2, 16, 4, 64, 0, 0, 0, 0, 1},
+
+ // GENTLE
+ { 0, 0, 0, 0, 32, 0, 0, 0, 0, 1},
+
+ // SASSY
+ { 0, 0, 0, 0, 42, 0, 0, 0, 0, 1},
+
+ // CAREFUL
+ { 0, 4, 0, 8, 24, 0, 0, 0, 12, 0},
+ { 0, 0, 0, 0, 12, 0, 0, 0, 0, 0},
+ { 0, 4, 0, 12, 24, 0, 0, 0, 12, 0},
+ { 0, 0, 0, 0, 12, 0, 0, 0, 0, 0},
+ { 0, 4, 0, 4, 24, 0, 0, 0, 12, 1},
+
+ // QUIRKY
+ { 0, 4, 16, 12, 64, 0, 0, 0, 0, 0},
+ { 0, -4, 16, 12, 64, 0, 0, 0, 0, 1},
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411E90[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411EA0[] =
+{
+ AFFINEANIMCMD_FRAME(0, 0, 12, 1),
+ AFFINEANIMCMD_FRAME(0, 0, 0, 30),
+ AFFINEANIMCMD_FRAME(0, 0, -12, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411EC0[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0, 0, 12, 1),
+ AFFINEANIMCMD_FRAME(0, 0, 0, 28),
+ AFFINEANIMCMD_FRAME(0, 0, -4, 3),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411EE8[] =
+{
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 32),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 16),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411F08[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 32),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 16),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411F30[] =
+{
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411F50[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411F78[] =
+{
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 32),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411F98[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 32),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411FC0[] =
+{
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 4),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 24),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 4),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8411FE0[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -1, 4),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 24),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 4),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8412008[] =
+{
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 24),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -12, 2),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8412028[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 1, 24),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 16),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -12, 2),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_8412050[] =
+{
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411EA0,
+ sSpriteAffineAnim_8411EE8,
+ sSpriteAffineAnim_8411F30,
+ sSpriteAffineAnim_8411F78,
+ sSpriteAffineAnim_8411FC0,
+ sSpriteAffineAnim_8412008,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411EC0,
+ sSpriteAffineAnim_8411F08,
+ sSpriteAffineAnim_8411F50,
+ sSpriteAffineAnim_8411F98,
+ sSpriteAffineAnim_8411FE0,
+ sSpriteAffineAnim_8412028,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+ sSpriteAffineAnim_8411E90,
+};
+
+static const u8* const sPokeblocksPals[] =
+{
+ gPokeblockRed_Pal,
+ gPokeblockBlue_Pal,
+ gPokeblockPink_Pal,
+ gPokeblockGreen_Pal,
+ gPokeblockYellow_Pal,
+ gPokeblockPurple_Pal,
+ gPokeblockIndigo_Pal,
+ gPokeblockBrown_Pal,
+ gPokeblockLiteBlue_Pal,
+ gPokeblockOlive_Pal,
+ gPokeblockGray_Pal,
+ gPokeblockBlack_Pal,
+ gPokeblockWhite_Pal,
+ gPokeblockGold_Pal
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_84120DC[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_84120EC[] =
+{
+ sSpriteAffineAnim_84120DC
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_84120F0[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 16, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 16, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 16, 1),
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_8412148[] =
+{
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 1),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 1),
+ AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_84121A0[] =
+{
+ sSpriteAffineAnim_84120DC
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_84121A4[] =
+{
+ sSpriteAffineAnim_84120F0
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_84121A8[] =
+{
+ sSpriteAffineAnim_8412148
+};
+
+static const struct OamData sThrownPokeblockOamData =
+{
+ .y = 0,
+ .affineMode = 3,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sThrownPokeblockSpriteAnim[] =
+{
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sThrownPokeblockAnimTable[] =
+{
+ sThrownPokeblockSpriteAnim,
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_84121C0[] =
+{
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(-8, -8, 0, 1),
+ AFFINEANIMCMD_JUMP(1)
+};
+
+static const union AffineAnimCmd *const sThrownPokeblockAffineAnimTable[] =
+{
+ sSpriteAffineAnim_84121C0
+};
+
+static const struct CompressedSpriteSheet sUnknown_084121DC =
+{
+ gPokeblock_Gfx, 0x20, 14818
+};
+
+static const struct SpriteTemplate sThrownPokeblockSpriteTemplate =
+{
+ .tileTag = 14818,
+ .paletteTag = 14818,
+ .oam = &sThrownPokeblockOamData,
+ .anims = sThrownPokeblockAnimTable,
+ .images = NULL,
+ .affineAnims = sThrownPokeblockAffineAnimTable,
+ .callback = SpriteCB_ThrownPokeblock
+};
+
+// code
+
+static void CB2_PokeblockFeed(void)
+{
+ AnimateSprites();
+ BuildOamBuffer();
+ RunTasks();
+ UpdatePaletteFade();
+}
+
+static void VBlankCB_PokeblockFeed(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static bool8 TransitionToPokeblockFeedScene(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ sub_80F9438();
+ sub_80F9368();
+ sub_8147B04();
+ gMain.state++;
+ break;
+ case 1:
+ ResetPaletteFade();
+ gPaletteFade.bufferTransferDisabled = 1;
+ gMain.state++;
+ break;
+ case 2:
+ ResetSpriteData();
+ gMain.state++;
+ break;
+ case 3:
+ FreeAllSpritePalettes();
+ gMain.state++;
+ break;
+ case 4:
+ SetUpWindowConfig(&gWindowConfig_81E6E50);
+ gMain.state++;
+ break;
+ case 5:
+ MultistepInitMenuWindowBegin(&gWindowConfig_81E6E50);
+ gMain.state++;
+ break;
+ case 6:
+ if (MultistepInitMenuWindowContinue())
+ {
+ ewram[0x1FFFF] = 0;
+ gMain.state++;
+ }
+ break;
+ case 7:
+ if (sub_8147B20(&gPlayerParty[gPokeblockMonID]))
+ {
+ gMain.state++;
+ }
+ break;
+ case 8:
+ ewram[0x1FFFD] = sub_81480B4();
+ gMain.state++;
+ break;
+ case 9:
+ ewram[0x1FFFE] = PokeblockFeed_CreatePokeSprite(&gPlayerParty[gPokeblockMonID]);
+ gMain.state++;
+ break;
+ case 10:
+ MenuDrawTextWindow(0, 14, 29, 19);
+ gMain.state++;
+ break;
+ case 11:
+ if (sub_8055870() != 1)
+ {
+ gMain.state++;
+ }
+ break;
+ case 12:
+ {
+ u16 savedIME = REG_IME;
+ REG_IME = 0;
+ REG_IE |= 1;
+ REG_IME = savedIME;
+ REG_DISPSTAT |= 8;
+ SetVBlankCallback(VBlankCB_PokeblockFeed);
+ gMain.state++;
+ }
+ case 13:
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ gPaletteFade.bufferTransferDisabled = 0;
+ SetMainCallback2(CB2_PokeblockFeed);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CB2_PreparePokeblockFeedScene(void)
+{
+ while (1)
+ {
+ if (TransitionToPokeblockFeedScene() == 1)
+ {
+ LaunchPokeblockFeedTask(1);
+ break;
+ }
+ if (sub_80F9344() == 1)
+ break;
+ }
+}
+
+static void sub_8147B04(void)
+{
+ REG_BG1CNT = 0x1D02l;
+ REG_DISPCNT = 0x1340;
+}
+
+static bool8 sub_8147B20(struct Pokemon* mon)
+{
+ u16 species;
+ u32 PiD, TiD;
+ switch (ewram[0x1FFFF])
+ {
+ case 0:
+ species = GetMonData(mon, MON_DATA_SPECIES2);
+ PiD = GetMonData(mon, MON_DATA_PERSONALITY);
+ HandleLoadSpecialPokePic(&gMonFrontPicTable[species], gMonFrontPicCoords[species].coords, gMonFrontPicCoords[species].y_offset, 0x2000000, gUnknown_081FAF4C[1], species, PiD);
+ ewram[0x1FFFF]++;
+ break;
+ case 1:
+ {
+ const struct CompressedSpritePalette* palette;
+
+ species = GetMonData(mon, MON_DATA_SPECIES2);
+ PiD = GetMonData(mon, MON_DATA_PERSONALITY);
+ TiD = GetMonData(mon, MON_DATA_OT_ID);
+ palette = GetMonSpritePalStructFromOtIdPersonality(species, TiD, PiD);
+ LoadCompressedObjectPalette(palette);
+ GetMonSpriteTemplate_803C56C(palette->tag, 1);
+ ewram[0x1FFFF]++;
+ }
+ break;
+ case 2:
+ LoadCompressedObjectPic(&gUnknown_083F7F74);
+ ewram[0x1FFFF]++;
+ break;
+ case 3:
+ LoadCompressedObjectPalette(&gUnknown_083F7F7C);
+ ewram[0x1FFFF]++;
+ break;
+ case 4:
+ LoadCompressedObjectPic(&sUnknown_084121DC);
+ ewram[0x1FFFF]++;
+ break;
+ case 5:
+ SetPokeblockFeedSpritePal(gScriptItemId);
+ LoadCompressedObjectPalette(&sPokeblockFeedSpritePal);
+ ewram[0x1FFFF]++;
+ break;
+ case 6:
+ LZDecompressVram(gBattleTerrainTiles_Building, (void*)(VRAM));
+ ewram[0x1FFFF]++;
+ break;
+ case 7:
+ LZDecompressVram(gUnknown_08E782FC, (void*)(VRAM + 0xE800));
+ ewram[0x1FFFF]++;
+ break;
+ case 8:
+ LoadCompressedPalette(gBattleTerrainPalette_BattleTower, 0x20, 0x60);
+ ewram[0x1FFFF] = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void SetPokeblockFeedSpritePal(u8 pkbID)
+{
+ u8 color = GetPokeblockData(&gSaveBlock1.pokeblocks[pkbID], PBLOCK_COLOR);
+ sPokeblockFeedSpritePal.data = sPokeblocksPals[color - 1];
+ sPokeblockFeedSpritePal.tag = 0x39E2;
+}
+
+static void sub_8147CC8(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (gTasks[taskID].data[0])
+ {
+ case 0:
+ gUnknown_03005F3C = 0;
+ gUnknown_03005F94 = 0;
+ sub_81481DC();
+ break;
+ case 255:
+ sub_8148108(ewram[0x1FFFD], gTasks[taskID].data[1]);
+ break;
+ case 269:
+ ewram[0x1FFFC] = CreatePokeblockSprite();
+ break;
+ case 281:
+ sub_8148044(ewram[0x1FFFE]);
+ break;
+ case 297:
+ gTasks[taskID].func = Task_PrintAtePokeblockText;
+ return;
+ }
+ if (gUnknown_03005F94 < gUnknown_03005F34)
+ sub_814825C();
+ else if (gUnknown_03005F94 == gUnknown_03005F34)
+ gTasks[taskID].data[0] = 254;
+
+ gUnknown_03005F94++;
+ gTasks[taskID].data[0]++;
+ }
+}
+
+static void LaunchPokeblockFeedTask(u8 a0)
+{
+ u8 taskID = CreateTask(sub_8147CC8, 0);
+ gTasks[taskID].data[0] = 0;
+ gTasks[taskID].data[1] = a0;
+}
+
+static void Task_WaitForAtePokeblockText(u8 taskID)
+{
+ if (MenuUpdateWindowText() == 1)
+ gTasks[taskID].func = Task_PaletteFadeToReturn;
+}
+
+static void Task_PrintAtePokeblockText(u8 taskID)
+{
+ struct Pokemon* mon = &gPlayerParty[gPokeblockMonID];
+ struct Pokeblock* pokeblock = &gSaveBlock1.pokeblocks[gScriptItemId];
+
+ gPokeblockGain = PokeblockGetGain(GetNature(mon), pokeblock);
+ GetMonNickname(mon, gStringVar1);
+ PokeblockCopyName(pokeblock, gStringVar2);
+
+ if (gPokeblockGain == 0)
+ StringExpandPlaceholders(gStringVar4, gContestStatsText_NormallyAte);
+ else if (gPokeblockGain > 0)
+ StringExpandPlaceholders(gStringVar4, gContestStatsText_HappilyAte);
+ else
+ StringExpandPlaceholders(gStringVar4, gContestStatsText_DisdainfullyAte);
+
+ MenuPrintMessage(gStringVar4, 1, 15);
+ gTasks[taskID].func = Task_WaitForAtePokeblockText;
+}
+
+static void Task_ReturnAfterPaletteFade(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ m4aMPlayVolumeControl(&gMPlay_BGM, -1, 256);
+ SetMainCallback2(gMain.savedCallback);
+ DestroyTask(taskID);
+ }
+}
+
+static void Task_PaletteFadeToReturn(u8 taskID)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = Task_ReturnAfterPaletteFade;
+}
+
+static u8 PokeblockFeed_CreatePokeSprite(struct Pokemon* mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2);
+ u8 spriteID = CreateSprite(&gUnknown_02024E8C, 48, 80, 2);
+
+ gPokeblockFeedMonSpecies = species;
+ gPokeblockFeedMonSpriteID = spriteID;
+ gPokeblockFeedMonNature = GetNature(mon);
+ gSprites[spriteID].data2 = species;
+ gSprites[spriteID].callback = SpriteCallbackDummy;
+ gPokeblockMonNotFlipped = 1;
+ if (!IsPokeSpriteNotFlipped(species))
+ {
+ gSprites[spriteID].affineAnims = sSpriteAffineAnimTable_84120EC;
+ gSprites[spriteID].oam.affineMode = 3;
+ CalcCenterToCornerVec(&gSprites[spriteID], gSprites[spriteID].oam.shape, gSprites[spriteID].oam.size, gSprites[spriteID].oam.affineMode);
+ gPokeblockMonNotFlipped = 0;
+ }
+ return spriteID;
+}
+
+static void sub_8148044(u8 spriteID)
+{
+ gSprites[spriteID].pos1.x = 48;
+ gSprites[spriteID].pos1.y = 80;
+ gSprites[spriteID].data0 = -8;
+ gSprites[spriteID].data1 = 1;
+ gSprites[spriteID].callback = sub_8148078;
+}
+
+static void sub_8148078(struct Sprite* sprite)
+{
+ sprite->pos1.x += 4;
+ sprite->pos1.y += sprite->data0;
+ sprite->data0 += sprite->data1;
+ if (sprite->data0 == 0)
+ PlayCry1(sprite->data2, 0);
+ if (sprite->data0 == 9)
+ sprite->callback = SpriteCallbackDummy;
+}
+
+static u8 sub_81480B4(void)
+{
+ u8 spriteID = sub_810BA50(188, 100, 2);
+ gSprites[spriteID].oam.affineMode = 1;
+ gSprites[spriteID].affineAnims = sSpriteAffineAnimTable_84121A0;
+ gSprites[spriteID].callback = SpriteCallbackDummy;
+ InitSpriteAffineAnim(&gSprites[spriteID]);
+ return spriteID;
+}
+
+static void sub_8148108(u8 spriteID, bool8 a1)
+{
+ FreeOamMatrix(gSprites[spriteID].oam.matrixNum);
+ gSprites[spriteID].oam.affineMode = 3;
+ if (!a1)
+ gSprites[spriteID].affineAnims = sSpriteAffineAnimTable_84121A4;
+ else
+ gSprites[spriteID].affineAnims = sSpriteAffineAnimTable_84121A8;
+ InitSpriteAffineAnim(&gSprites[spriteID]);
+}
+
+static u8 CreatePokeblockSprite(void)
+{
+ u8 spriteID = CreateSprite(&sThrownPokeblockSpriteTemplate, 174, 84, 1);
+ gSprites[spriteID].data0 = -12;
+ gSprites[spriteID].data1 = 1;
+ return spriteID;
+}
+
+static void SpriteCB_ThrownPokeblock(struct Sprite* sprite)
+{
+ sprite->pos1.x -= 4;
+ sprite->pos1.y += sprite->data0;
+ sprite->data0 += sprite->data1;
+ if (sprite->data0 == 10)
+ DestroySprite(sprite);
+}
+
+static void sub_81481DC(void)
+{
+ u8 animID, i;
+
+ gUnknown_03005F34 = 1;
+ animID = sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][0];
+ for (i = 0; i < 8; i++, animID++)
+ {
+ gUnknown_03005F34 += sMonPokeblockAnims[animID][4];
+ if (sMonPokeblockAnims[animID][9] == 1)
+ break;
+ }
+}
+
+static void sub_814825C(void)
+{
+ switch (gUnknown_03005F3C)
+ {
+ case 0:
+ gUnknown_03005F40 = sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][0];
+ gPokeblockFeedPokeSprite = &gSprites[gPokeblockFeedMonSpriteID];
+ gPokeblockFeedPokeSpriteCopy = *gPokeblockFeedPokeSprite;
+ gUnknown_03005F3C = 10;
+ break;
+ case 1 ... 9:
+ break;
+ case 10:
+ sub_8148540();
+ if (sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][1] != 0)
+ {
+ gPokeblockFeedPokeSprite->oam.affineMode = 3;
+ gPokeblockFeedPokeSprite->oam.matrixNum = 0;
+ gPokeblockFeedPokeSprite->affineAnims = sSpriteAffineAnimTable_8412050;
+ InitSpriteAffineAnim(gPokeblockFeedPokeSprite);
+ }
+ gUnknown_03005F3C = 50;
+ case 50:
+ if (sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][1] != 0)
+ {
+ if (gPokeblockMonNotFlipped == 0)
+ StartSpriteAffineAnim(gPokeblockFeedPokeSprite, sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][1] + 10);
+ else
+ StartSpriteAffineAnim(gPokeblockFeedPokeSprite, sNatureToMonPokeblockAnim[gPokeblockFeedMonNature][1]);
+ }
+ gUnknown_03005F3C = 60;
+ break;
+ case 60:
+ if (sub_81485CC() == 1)
+ {
+ if (gUnknown_03005FA0[9] == 0)
+ {
+ gUnknown_03005F40++;
+ sub_8148540();
+ gUnknown_03005F3C = 60;
+ }
+ else
+ {
+ FreeOamMatrix(gPokeblockFeedPokeSprite->oam.matrixNum);
+ gUnknown_03005F3C = 70;
+ }
+ }
+ break;
+ case 70:
+ FreePokeSpriteMatrix();
+ gUnknown_03005F40 = 0;
+ gUnknown_03005F3C = 0;
+ break;
+ case 71 ... 90:
+ break;
+ }
+}
+
+static bool8 sub_8148540(void)
+{
+ u8 i;
+ for (i = 0; i < 10; i++)
+ gUnknown_03005FA0[i] = sMonPokeblockAnims[gUnknown_03005F40][i];
+ if (gUnknown_03005FA0[4] == 0)
+ return TRUE;
+ else
+ {
+ gUnknown_03005FA0[10] = Sin(gUnknown_03005FA0[0], gUnknown_03005FA0[2]);
+ gUnknown_03005FA0[11] = Cos(gUnknown_03005FA0[0], gUnknown_03005FA0[3]);
+ gUnknown_03005FA0[12] = gUnknown_03005FA0[4];
+ gUnknown_03005FA0[13] = gPokeblockFeedPokeSprite->pos2.x;
+ gUnknown_03005FA0[14] = gPokeblockFeedPokeSprite->pos2.y;
+ sub_8148710();
+ gUnknown_03005FA0[4] = gUnknown_03005FA0[12];
+ sub_814862C();
+ gUnknown_03005FA0[4] = gUnknown_03005FA0[12];
+ return FALSE;
+ }
+}
+
+#define ewram1D000 ((u16 *)(ewram + 0x1D000))
+#define ewram1D400 ((u16 *)(ewram + 0x1D400))
+
+static bool8 sub_81485CC(void)
+{
+ u16 var = gUnknown_03005FA0[12] - gUnknown_03005FA0[4];
+
+ gPokeblockFeedPokeSprite->pos2.x = ewram1D000[var];
+ gPokeblockFeedPokeSprite->pos2.y = ewram1D400[var];
+
+ if (--gUnknown_03005FA0[4] == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static bool8 FreePokeSpriteMatrix(void)
+{
+ FreeSpriteOamMatrix(gPokeblockFeedPokeSprite);
+ return FALSE;
+}
+
+static void sub_814862C(void)
+{
+ u16 i;
+ u16 r8 = gUnknown_03005FA0[8];
+ u16 r7 = gUnknown_03005FA0[12] - r8;
+ s16 var3 = gUnknown_03005FA0[13] + gUnknown_03005FA0[6];
+ s16 r9 = gUnknown_03005FA0[14] + gUnknown_03005FA0[7];
+
+ for (i = 0; i < r7 - 1; i++)
+ {
+ s16* r3 = &ewram1D000[r8 + i];
+ s16 r1 = *r3 - (var3);
+
+ s16* r5 = &ewram1D400[r8 + i];
+ s16 r4 = *r5 - r9;
+
+ *r3 -= r1 * (i + 1) / r7;
+ *r5 -= r4 * (i + 1) / r7;
+ }
+
+ ewram1D000[(r8 + r7) - 1] = var3;
+ ewram1D400[(r8 + r7) - 1] = r9;
+}
+
+void sub_8148710(void)
+{
+ bool8 var_24 = FALSE;
+ s16 r8 = gUnknown_03005FA0[13] - gUnknown_03005FA0[10];
+ s16 r7 = gUnknown_03005FA0[14] - gUnknown_03005FA0[11];
+ while (1)
+ {
+ u16 r5;
+ u16 r4;
+ u16 var;
+
+ var = abs(gUnknown_03005FA0[5]);
+ r5 = var + gUnknown_03005FA0[3];
+ gUnknown_03005FA0[3] = r5;
+
+ if (gUnknown_03005FA0[2] < 0)
+ var_24 = TRUE;
+
+ r4 = gUnknown_03005FA0[12] - gUnknown_03005FA0[4];
+
+ if (gUnknown_03005FA0[4] == 0)
+ break;
+
+ if (!var_24)
+ {
+ ewram1D000[r4] = Sin(gUnknown_03005FA0[0], gUnknown_03005FA0[2] + r5 / 256) + r8;
+ ewram1D400[r4] = Cos(gUnknown_03005FA0[0], gUnknown_03005FA0[3] + r5 / 256) + r7;
+ }
+ else
+ {
+ ewram1D000[r4] = Sin(gUnknown_03005FA0[0], gUnknown_03005FA0[2] - r5 / 256) + r8;
+ ewram1D400[r4] = Cos(gUnknown_03005FA0[0], gUnknown_03005FA0[3] - r5 / 256) + r7;
+ }
+
+ gUnknown_03005FA0[0] += gUnknown_03005FA0[1];
+ gUnknown_03005FA0[0] &= 0xFF;
+ gUnknown_03005FA0[4]--;
+ }
+}
diff --git a/src/pokemon/pokedex.c b/src/pokemon/pokedex.c
new file mode 100644
index 000000000..e27ec1e05
--- /dev/null
+++ b/src/pokemon/pokedex.c
@@ -0,0 +1,5527 @@
+#include "global.h"
+#include "gba/m4a_internal.h"
+#include "pokedex.h"
+#include "battle.h"
+#include "data2.h"
+#include "decompress.h"
+#include "event_data.h"
+#include "graphics.h"
+#include "m4a.h"
+#include "main.h"
+#include "menu.h"
+#include "menu_cursor.h"
+#include "palette.h"
+#include "pokedex_area_screen.h"
+#include "pokedex_cry_screen.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "overworld.h"
+#include "songs.h"
+#include "sound.h"
+#include "species.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "trig.h"
+#include "unknown_task.h"
+
+#define NATIONAL_DEX_COUNT 386
+
+struct PokedexListItem
+{
+ u16 dexNum;
+ u16 seen:1;
+ u16 owned:1;
+};
+
+struct PokedexView
+{
+ struct PokedexListItem unk0[NATIONAL_DEX_COUNT];
+ u16 unk608;
+ u8 unk60A_1:1;
+ u8 unk60A_2:1;
+ u8 unk60B;
+ u16 pokemonListCount;
+ u16 selectedPokemon;
+ u16 unk610;
+ u16 dexMode;
+ u16 unk614;
+ u16 dexOrder;
+ u16 unk618;
+ u16 unk61A;
+ u16 unk61C;
+ u16 unk61E[4];
+ u16 selectedMonSpriteId;
+ u16 unk628;
+ u16 unk62A;
+ u8 unk62C;
+ u8 unk62D;
+ u8 unk62E;
+ u8 unk62F;
+ s16 unk630;
+ s16 unk632;
+ u16 unk634;
+ u16 unk636;
+ u16 unk638;
+ u16 unk63A[4];
+ u8 filler642[8];
+ u8 unk64A;
+ u8 unk64B;
+ u8 unk64C_1:1;
+ u8 selectedScreen;
+ u8 descriptionPageNum;
+ u8 unk64F;
+ u8 menuIsOpen; //menuIsOpen
+ u8 unk651;
+ u16 menuCursorPos; //Menu cursor position
+ s16 menuY; //Menu Y position (inverted because we use REG_BG0VOFS for this)
+ u8 unk656[8];
+ u8 unk65E[8];
+};
+
+enum
+{
+ DEX_MODE_HOENN,
+ DEX_MODE_NATIONAL
+};
+
+enum
+{
+ PAGE_SCREEN,
+ AREA_SCREEN,
+ CRY_SCREEN,
+ SIZE_SCREEN
+};
+
+struct PokedexEntry
+{
+ /*0x00*/ u8 categoryName[12];
+ /*0x0C*/ u16 height; //in decimeters
+ /*0x0E*/ u16 weight; //in hectograms
+ /*0x10*/ const u8 *descriptionPage1;
+ /*0x14*/ const u8 *descriptionPage2;
+ /*0x18*/ u16 unused;
+ /*0x1A*/ u16 pokemonScale;
+ /*0x1C*/ u16 pokemonOffset;
+ /*0x1E*/ u16 trainerScale;
+ /*0x20*/ u16 trainerOffset;
+}; /*size = 0x24*/
+
+struct UnknownStruct2
+{
+ const u8 *text1;
+ const u8 *text2;
+};
+
+struct UnknownStruct1
+{
+ const struct UnknownStruct2 *unk0;
+ u8 unk4;
+ u8 unk5;
+ u16 unk6;
+};
+
+struct UnknownStruct3
+{
+ const u8 *text;
+ u8 unk4;
+ u8 unk5;
+ u8 unk6;
+};
+
+struct UnknownStruct4
+{
+ const u8 *text;
+ u8 unk4;
+ u8 unk5;
+ u8 unk6;
+ u8 unk7;
+ u8 unk8;
+ u8 unk9;
+};
+
+extern struct MusicPlayerInfo gMPlay_BGM;
+extern u8 gReservedSpritePaletteCount;
+extern struct SpriteTemplate gUnknown_02024E8C;
+extern u8 gUnknown_03005E98;
+extern const u8 gPokedexMenu_Gfx[];
+extern const u8 gUnknown_08E96738[];
+extern const u8 gUnknown_08E96888[];
+extern const u8 gUnknown_08E96994[];
+extern const u8 gUnknown_08E9C6DC[];
+extern const u8 gUnknown_08D00524[];
+extern const u8 gUnknown_08E96BD4[];
+extern const u8 gUnknown_08E96ACC[];
+extern const u8 gUnknown_08E96B58[];
+extern const u16 gPokedexMenu_Pal[];
+extern const u16 gPokedexMenu2_Pal[];
+extern const struct CompressedSpriteSheet gTrainerFrontPicTable[];
+extern const struct MonCoords gTrainerFrontPicCoords[];
+extern const struct PokedexEntry gPokedexEntries[];
+extern const u8 gPokedexMenuSearch_Gfx[];
+extern const u8 gUnknown_08E96D2C[];
+extern const u16 gPokedexMenuSearch_Pal[];
+extern const u8 gTypeNames[][7];
+extern const u8 gPokedexMenu2_Gfx[];
+
+static EWRAM_DATA struct PokedexView *gPokedexView = NULL;
+static EWRAM_DATA u16 gUnknown_0202FFB8 = 0;
+static EWRAM_DATA u8 gUnknown_0202FFBA = 0;
+static EWRAM_DATA struct PokedexListItem *gUnknown_0202FFBC = NULL;
+
+u8 gUnknown_03005CE8;
+IntrCallback gUnknown_03005CEC;
+
+static u8 sub_8091E3C(void);
+
+static const u16 sPokedexSearchPalette[] = INCBIN_U16("graphics/pokedex/search.gbapal");
+static const u16 sNationalPokedexPalette[] = INCBIN_U16("graphics/pokedex/national.gbapal");
+const u8 gEmptySpacce_839F7FC[0xA4] = {0};
+static const u8 gUnknown_0839F8A0[] = INCBIN_U8("graphics/pokedex/pokedex_cry_layout.bin.lz");
+static const u8 gUnknown_0839F988[] = INCBIN_U8("graphics/pokedex/pokedex_size_layout.bin.lz");
+#if ENGLISH
+static const u8 gUnknown_0839FA7C[] = INCBIN_U8("graphics/pokedex/noball.4bpp.lz");
+#elif GERMAN
+extern const u8 gUnknown_0839FA7C[];
+#endif
+
+#include "../data/pokedex_orders.h"
+static const struct OamData gOamData_83A0404 =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const struct OamData gOamData_83A040C =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const struct OamData gOamData_83A0414 =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const struct OamData gOamData_83A041C =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 2,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 2,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const struct OamData gOamData_83A0424 =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const struct OamData gOamData_83A042C =
+{
+ .y = 160,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 2,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static const union AnimCmd gSpriteAnim_83A0434[] =
+{
+ ANIMCMD_FRAME(3, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A043C[] =
+{
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0444[] =
+{
+ ANIMCMD_FRAME(16, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A044C[] =
+{
+ ANIMCMD_FRAME(32, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0454[] =
+{
+ ANIMCMD_FRAME(64, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A045C[] =
+{
+ ANIMCMD_FRAME(96, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0464[] =
+{
+ ANIMCMD_FRAME(128, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A046C[] =
+{
+ ANIMCMD_FRAME(160, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0474[] =
+{
+ ANIMCMD_FRAME(192, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A047C[] =
+{
+ ANIMCMD_FRAME(224, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0484[] =
+{
+ ANIMCMD_FRAME(226, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A048C[] =
+{
+ ANIMCMD_FRAME(228, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A0494[] =
+{
+ ANIMCMD_FRAME(230, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A049C[] =
+{
+ ANIMCMD_FRAME(232, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04A4[] =
+{
+ ANIMCMD_FRAME(234, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04AC[] =
+{
+ ANIMCMD_FRAME(236, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04B4[] =
+{
+ ANIMCMD_FRAME(238, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04BC[] =
+{
+ ANIMCMD_FRAME(240, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04C4[] =
+{
+ ANIMCMD_FRAME(242, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd gSpriteAnim_83A04CC[] =
+{
+ ANIMCMD_FRAME(4, 30),
+ ANIMCMD_END,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04D4[] =
+{
+ gSpriteAnim_83A0434,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04D8[] =
+{
+ gSpriteAnim_83A043C,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04DC[] =
+{
+ gSpriteAnim_83A0444,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04E0[] =
+{
+ gSpriteAnim_83A044C,
+ gSpriteAnim_83A0454,
+ gSpriteAnim_83A045C,
+ gSpriteAnim_83A0464,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04F0[] =
+{
+ gSpriteAnim_83A046C,
+ gSpriteAnim_83A0474,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A04F8[] =
+{
+ gSpriteAnim_83A047C,
+ gSpriteAnim_83A0484,
+ gSpriteAnim_83A048C,
+ gSpriteAnim_83A0494,
+ gSpriteAnim_83A049C,
+ gSpriteAnim_83A04A4,
+ gSpriteAnim_83A04AC,
+ gSpriteAnim_83A04B4,
+ gSpriteAnim_83A04BC,
+ gSpriteAnim_83A04C4,
+};
+static const union AnimCmd *const gSpriteAnimTable_83A0520[] =
+{
+ gSpriteAnim_83A04CC,
+};
+static void sub_808EF38(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A0524 =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A0404,
+ .anims = gSpriteAnimTable_83A04D4,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808EF38,
+};
+static void sub_808EF8C(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A053C =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A040C,
+ .anims = gSpriteAnimTable_83A04D8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808EF8C,
+};
+static void sub_808F08C(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A0554 =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A0414,
+ .anims = gSpriteAnimTable_83A04E0,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808F08C,
+};
+static void sub_808F0B4(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A056C =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A041C,
+ .anims = gSpriteAnimTable_83A04DC,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808F0B4,
+};
+static void sub_808ED94(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A0584 =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A0424,
+ .anims = gSpriteAnimTable_83A04F0,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808ED94,
+};
+static const struct SpriteTemplate gSpriteTemplate_83A059C =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A042C,
+ .anims = gSpriteAnimTable_83A04F8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808ED94,
+};
+static void sub_808F168(struct Sprite *);
+static const struct SpriteTemplate gSpriteTemplate_83A05B4 =
+{
+ .tileTag = 4096,
+ .paletteTag = 4096,
+ .oam = &gOamData_83A042C,
+ .anims = gSpriteAnimTable_83A0520,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_808F168,
+};
+static const struct CompressedSpriteSheet gUnknown_083A05CC[] =
+{
+ {gPokedexMenu2_Gfx, 0x1F00, 0x1000},
+ {NULL, 0, 0},
+};
+static const struct SpritePalette gUnknown_083A05DC[] =
+{
+ {gPokedexMenu_Pal, 0x1000},
+ {NULL, 0},
+};
+static const u8 gUnknown_083A05EC[] = {2, 4, 8, 16, 32};
+static const u8 gUnknown_083A05F1[] = {16, 8, 4, 2, 1};
+const u8 gEmptySpacce_83A05F6[] = {0, 0}; // Padding, maybe?
+static const u8 gUnknown_083A05F8[] = _("");
+#if ENGLISH
+#include "../data/pokedex_entries_en.h"
+#elif GERMAN
+#include "../data/pokedex_entries_de.h"
+#endif
+static const u16 gUnknown_083B4EC4[16] = {0};
+static const u8 *const sMonFootprintTable[] =
+{
+ gMonFootprint_Bulbasaur,
+ gMonFootprint_Bulbasaur,
+ gMonFootprint_Ivysaur,
+ gMonFootprint_Venusaur,
+ gMonFootprint_Charmander,
+ gMonFootprint_Charmeleon,
+ gMonFootprint_Charizard,
+ gMonFootprint_Squirtle,
+ gMonFootprint_Wartortle,
+ gMonFootprint_Blastoise,
+ gMonFootprint_Caterpie,
+ gMonFootprint_Metapod,
+ gMonFootprint_Butterfree,
+ gMonFootprint_Weedle,
+ gMonFootprint_Kakuna,
+ gMonFootprint_Beedrill,
+ gMonFootprint_Pidgey,
+ gMonFootprint_Pidgeotto,
+ gMonFootprint_Pidgeot,
+ gMonFootprint_Rattata,
+ gMonFootprint_Raticate,
+ gMonFootprint_Spearow,
+ gMonFootprint_Fearow,
+ gMonFootprint_Ekans,
+ gMonFootprint_Arbok,
+ gMonFootprint_Pikachu,
+ gMonFootprint_Raichu,
+ gMonFootprint_Sandshrew,
+ gMonFootprint_Sandslash,
+ gMonFootprint_NidoranF,
+ gMonFootprint_Nidorina,
+ gMonFootprint_Nidoqueen,
+ gMonFootprint_NidoranM,
+ gMonFootprint_Nidorino,
+ gMonFootprint_Nidoking,
+ gMonFootprint_Clefairy,
+ gMonFootprint_Clefable,
+ gMonFootprint_Vulpix,
+ gMonFootprint_Ninetales,
+ gMonFootprint_Jigglypuff,
+ gMonFootprint_Wigglytuff,
+ gMonFootprint_Zubat,
+ gMonFootprint_Golbat,
+ gMonFootprint_Oddish,
+ gMonFootprint_Gloom,
+ gMonFootprint_Vileplume,
+ gMonFootprint_Paras,
+ gMonFootprint_Parasect,
+ gMonFootprint_Venonat,
+ gMonFootprint_Venomoth,
+ gMonFootprint_Diglett,
+ gMonFootprint_Dugtrio,
+ gMonFootprint_Meowth,
+ gMonFootprint_Persian,
+ gMonFootprint_Psyduck,
+ gMonFootprint_Golduck,
+ gMonFootprint_Mankey,
+ gMonFootprint_Primeape,
+ gMonFootprint_Growlithe,
+ gMonFootprint_Arcanine,
+ gMonFootprint_Poliwag,
+ gMonFootprint_Poliwhirl,
+ gMonFootprint_Poliwrath,
+ gMonFootprint_Abra,
+ gMonFootprint_Kadabra,
+ gMonFootprint_Alakazam,
+ gMonFootprint_Machop,
+ gMonFootprint_Machoke,
+ gMonFootprint_Machamp,
+ gMonFootprint_Bellsprout,
+ gMonFootprint_Weepinbell,
+ gMonFootprint_Victreebel,
+ gMonFootprint_Tentacool,
+ gMonFootprint_Tentacruel,
+ gMonFootprint_Geodude,
+ gMonFootprint_Graveler,
+ gMonFootprint_Golem,
+ gMonFootprint_Ponyta,
+ gMonFootprint_Rapidash,
+ gMonFootprint_Slowpoke,
+ gMonFootprint_Slowbro,
+ gMonFootprint_Magnemite,
+ gMonFootprint_Magneton,
+ gMonFootprint_Farfetchd,
+ gMonFootprint_Doduo,
+ gMonFootprint_Dodrio,
+ gMonFootprint_Seel,
+ gMonFootprint_Dewgong,
+ gMonFootprint_Grimer,
+ gMonFootprint_Muk,
+ gMonFootprint_Shellder,
+ gMonFootprint_Cloyster,
+ gMonFootprint_Gastly,
+ gMonFootprint_Haunter,
+ gMonFootprint_Gengar,
+ gMonFootprint_Onix,
+ gMonFootprint_Drowzee,
+ gMonFootprint_Hypno,
+ gMonFootprint_Krabby,
+ gMonFootprint_Kingler,
+ gMonFootprint_Voltorb,
+ gMonFootprint_Electrode,
+ gMonFootprint_Exeggcute,
+ gMonFootprint_Exeggutor,
+ gMonFootprint_Cubone,
+ gMonFootprint_Marowak,
+ gMonFootprint_Hitmonlee,
+ gMonFootprint_Hitmonchan,
+ gMonFootprint_Lickitung,
+ gMonFootprint_Koffing,
+ gMonFootprint_Weezing,
+ gMonFootprint_Rhyhorn,
+ gMonFootprint_Rhydon,
+ gMonFootprint_Chansey,
+ gMonFootprint_Tangela,
+ gMonFootprint_Kangaskhan,
+ gMonFootprint_Horsea,
+ gMonFootprint_Seadra,
+ gMonFootprint_Goldeen,
+ gMonFootprint_Seaking,
+ gMonFootprint_Staryu,
+ gMonFootprint_Starmie,
+ gMonFootprint_Mrmime,
+ gMonFootprint_Scyther,
+ gMonFootprint_Jynx,
+ gMonFootprint_Electabuzz,
+ gMonFootprint_Magmar,
+ gMonFootprint_Pinsir,
+ gMonFootprint_Tauros,
+ gMonFootprint_Magikarp,
+ gMonFootprint_Gyarados,
+ gMonFootprint_Lapras,
+ gMonFootprint_Ditto,
+ gMonFootprint_Eevee,
+ gMonFootprint_Vaporeon,
+ gMonFootprint_Jolteon,
+ gMonFootprint_Flareon,
+ gMonFootprint_Porygon,
+ gMonFootprint_Omanyte,
+ gMonFootprint_Omastar,
+ gMonFootprint_Kabuto,
+ gMonFootprint_Kabutops,
+ gMonFootprint_Aerodactyl,
+ gMonFootprint_Snorlax,
+ gMonFootprint_Articuno,
+ gMonFootprint_Zapdos,
+ gMonFootprint_Moltres,
+ gMonFootprint_Dratini,
+ gMonFootprint_Dragonair,
+ gMonFootprint_Dragonite,
+ gMonFootprint_Mewtwo,
+ gMonFootprint_Mew,
+ gMonFootprint_Chikorita,
+ gMonFootprint_Bayleef,
+ gMonFootprint_Meganium,
+ gMonFootprint_Cyndaquil,
+ gMonFootprint_Quilava,
+ gMonFootprint_Typhlosion,
+ gMonFootprint_Totodile,
+ gMonFootprint_Croconaw,
+ gMonFootprint_Feraligatr,
+ gMonFootprint_Sentret,
+ gMonFootprint_Furret,
+ gMonFootprint_Hoothoot,
+ gMonFootprint_Noctowl,
+ gMonFootprint_Ledyba,
+ gMonFootprint_Ledian,
+ gMonFootprint_Spinarak,
+ gMonFootprint_Ariados,
+ gMonFootprint_Crobat,
+ gMonFootprint_Chinchou,
+ gMonFootprint_Lanturn,
+ gMonFootprint_Pichu,
+ gMonFootprint_Cleffa,
+ gMonFootprint_Igglybuff,
+ gMonFootprint_Togepi,
+ gMonFootprint_Togetic,
+ gMonFootprint_Natu,
+ gMonFootprint_Xatu,
+ gMonFootprint_Mareep,
+ gMonFootprint_Flaaffy,
+ gMonFootprint_Ampharos,
+ gMonFootprint_Bellossom,
+ gMonFootprint_Marill,
+ gMonFootprint_Azumarill,
+ gMonFootprint_Sudowoodo,
+ gMonFootprint_Politoed,
+ gMonFootprint_Hoppip,
+ gMonFootprint_Skiploom,
+ gMonFootprint_Jumpluff,
+ gMonFootprint_Aipom,
+ gMonFootprint_Sunkern,
+ gMonFootprint_Sunflora,
+ gMonFootprint_Yanma,
+ gMonFootprint_Wooper,
+ gMonFootprint_Quagsire,
+ gMonFootprint_Espeon,
+ gMonFootprint_Umbreon,
+ gMonFootprint_Murkrow,
+ gMonFootprint_Slowking,
+ gMonFootprint_Misdreavus,
+ gMonFootprint_Unown,
+ gMonFootprint_Wobbuffet,
+ gMonFootprint_Girafarig,
+ gMonFootprint_Pineco,
+ gMonFootprint_Forretress,
+ gMonFootprint_Dunsparce,
+ gMonFootprint_Gligar,
+ gMonFootprint_Steelix,
+ gMonFootprint_Snubbull,
+ gMonFootprint_Granbull,
+ gMonFootprint_Qwilfish,
+ gMonFootprint_Scizor,
+ gMonFootprint_Shuckle,
+ gMonFootprint_Heracross,
+ gMonFootprint_Sneasel,
+ gMonFootprint_Teddiursa,
+ gMonFootprint_Ursaring,
+ gMonFootprint_Slugma,
+ gMonFootprint_Magcargo,
+ gMonFootprint_Swinub,
+ gMonFootprint_Piloswine,
+ gMonFootprint_Corsola,
+ gMonFootprint_Remoraid,
+ gMonFootprint_Octillery,
+ gMonFootprint_Delibird,
+ gMonFootprint_Mantine,
+ gMonFootprint_Skarmory,
+ gMonFootprint_Houndour,
+ gMonFootprint_Houndoom,
+ gMonFootprint_Kingdra,
+ gMonFootprint_Phanpy,
+ gMonFootprint_Donphan,
+ gMonFootprint_Porygon2,
+ gMonFootprint_Stantler,
+ gMonFootprint_Smeargle,
+ gMonFootprint_Tyrogue,
+ gMonFootprint_Hitmontop,
+ gMonFootprint_Smoochum,
+ gMonFootprint_Elekid,
+ gMonFootprint_Magby,
+ gMonFootprint_Miltank,
+ gMonFootprint_Blissey,
+ gMonFootprint_Raikou,
+ gMonFootprint_Entei,
+ gMonFootprint_Suicune,
+ gMonFootprint_Larvitar,
+ gMonFootprint_Pupitar,
+ gMonFootprint_Tyranitar,
+ gMonFootprint_Lugia,
+ gMonFootprint_HoOh,
+ gMonFootprint_Celebi,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_QuestionMark,
+ gMonFootprint_Treecko,
+ gMonFootprint_Grovyle,
+ gMonFootprint_Sceptile,
+ gMonFootprint_Torchic,
+ gMonFootprint_Combusken,
+ gMonFootprint_Blaziken,
+ gMonFootprint_Mudkip,
+ gMonFootprint_Marshtomp,
+ gMonFootprint_Swampert,
+ gMonFootprint_Poochyena,
+ gMonFootprint_Mightyena,
+ gMonFootprint_Zigzagoon,
+ gMonFootprint_Linoone,
+ gMonFootprint_Wurmple,
+ gMonFootprint_Silcoon,
+ gMonFootprint_Beautifly,
+ gMonFootprint_Cascoon,
+ gMonFootprint_Dustox,
+ gMonFootprint_Lotad,
+ gMonFootprint_Lombre,
+ gMonFootprint_Ludicolo,
+ gMonFootprint_Seedot,
+ gMonFootprint_Nuzleaf,
+ gMonFootprint_Shiftry,
+ gMonFootprint_Nincada,
+ gMonFootprint_Ninjask,
+ gMonFootprint_Shedinja,
+ gMonFootprint_Taillow,
+ gMonFootprint_Swellow,
+ gMonFootprint_Shroomish,
+ gMonFootprint_Breloom,
+ gMonFootprint_Spinda,
+ gMonFootprint_Wingull,
+ gMonFootprint_Pelipper,
+ gMonFootprint_Surskit,
+ gMonFootprint_Masquerain,
+ gMonFootprint_Wailmer,
+ gMonFootprint_Wailord,
+ gMonFootprint_Skitty,
+ gMonFootprint_Delcatty,
+ gMonFootprint_Kecleon,
+ gMonFootprint_Baltoy,
+ gMonFootprint_Claydol,
+ gMonFootprint_Nosepass,
+ gMonFootprint_Torkoal,
+ gMonFootprint_Sableye,
+ gMonFootprint_Barboach,
+ gMonFootprint_Whiscash,
+ gMonFootprint_Luvdisc,
+ gMonFootprint_Corphish,
+ gMonFootprint_Crawdaunt,
+ gMonFootprint_Feebas,
+ gMonFootprint_Milotic,
+ gMonFootprint_Carvanha,
+ gMonFootprint_Sharpedo,
+ gMonFootprint_Trapinch,
+ gMonFootprint_Vibrava,
+ gMonFootprint_Flygon,
+ gMonFootprint_Makuhita,
+ gMonFootprint_Hariyama,
+ gMonFootprint_Electrike,
+ gMonFootprint_Manectric,
+ gMonFootprint_Numel,
+ gMonFootprint_Camerupt,
+ gMonFootprint_Spheal,
+ gMonFootprint_Sealeo,
+ gMonFootprint_Walrein,
+ gMonFootprint_Cacnea,
+ gMonFootprint_Cacturne,
+ gMonFootprint_Snorunt,
+ gMonFootprint_Glalie,
+ gMonFootprint_Lunatone,
+ gMonFootprint_Solrock,
+ gMonFootprint_Azurill,
+ gMonFootprint_Spoink,
+ gMonFootprint_Grumpig,
+ gMonFootprint_Plusle,
+ gMonFootprint_Minun,
+ gMonFootprint_Mawile,
+ gMonFootprint_Meditite,
+ gMonFootprint_Medicham,
+ gMonFootprint_Swablu,
+ gMonFootprint_Altaria,
+ gMonFootprint_Wynaut,
+ gMonFootprint_Duskull,
+ gMonFootprint_Dusclops,
+ gMonFootprint_Roselia,
+ gMonFootprint_Slakoth,
+ gMonFootprint_Vigoroth,
+ gMonFootprint_Slaking,
+ gMonFootprint_Gulpin,
+ gMonFootprint_Swalot,
+ gMonFootprint_Tropius,
+ gMonFootprint_Whismur,
+ gMonFootprint_Loudred,
+ gMonFootprint_Exploud,
+ gMonFootprint_Clamperl,
+ gMonFootprint_Huntail,
+ gMonFootprint_Gorebyss,
+ gMonFootprint_Absol,
+ gMonFootprint_Shuppet,
+ gMonFootprint_Banette,
+ gMonFootprint_Seviper,
+ gMonFootprint_Zangoose,
+ gMonFootprint_Relicanth,
+ gMonFootprint_Aron,
+ gMonFootprint_Lairon,
+ gMonFootprint_Aggron,
+ gMonFootprint_Castform,
+ gMonFootprint_Volbeat,
+ gMonFootprint_Illumise,
+ gMonFootprint_Lileep,
+ gMonFootprint_Cradily,
+ gMonFootprint_Anorith,
+ gMonFootprint_Armaldo,
+ gMonFootprint_Ralts,
+ gMonFootprint_Kirlia,
+ gMonFootprint_Gardevoir,
+ gMonFootprint_Bagon,
+ gMonFootprint_Shelgon,
+ gMonFootprint_Salamence,
+ gMonFootprint_Beldum,
+ gMonFootprint_Metang,
+ gMonFootprint_Metagross,
+ gMonFootprint_Regirock,
+ gMonFootprint_Regice,
+ gMonFootprint_Registeel,
+ gMonFootprint_Kyogre,
+ gMonFootprint_Groudon,
+ gMonFootprint_Rayquaza,
+ gMonFootprint_Latias,
+ gMonFootprint_Latios,
+ gMonFootprint_Jirachi,
+ gMonFootprint_Deoxys,
+ gMonFootprint_Chimecho,
+ gMonFootprint_Bulbasaur,
+};
+static const u8 gUnknown_083B5558[] = _("{CLEAR_TO 0}");
+const u8 gUnknown_083B555C[] = INCBIN_U8("graphics/unknown/unknown_3B555C.bin");
+static const struct OamData gOamData_83B557C =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+static void *const gUnknown_083B5584[] =
+{
+ (void *)0x02008000,
+ (void *)0x0200C000,
+ (void *)0x02010000,
+ (void *)0x02014000,
+};
+static const struct SpriteFrameImage gSpriteImageTable_83B5594[] =
+{
+ {(u8 *)0x02008000, 0x800},
+ {(u8 *)0x02008800, 0x800},
+ {(u8 *)0x02009000, 0x800},
+ {(u8 *)0x02009800, 0x800},
+ {(u8 *)0x0200A000, 0x800},
+ {(u8 *)0x0200A800, 0x800},
+ {(u8 *)0x0200B000, 0x800},
+ {(u8 *)0x0200B800, 0x800},
+ {(u8 *)0x0200C000, 0x800},
+ {(u8 *)0x0200C800, 0x800},
+ {(u8 *)0x0200D000, 0x800},
+ {(u8 *)0x0200D800, 0x800},
+ {(u8 *)0x0200E000, 0x800},
+ {(u8 *)0x0200E800, 0x800},
+ {(u8 *)0x0200F000, 0x800},
+ {(u8 *)0x0200F800, 0x800},
+};
+static const struct SpriteFrameImage gSpriteImageTable_83B5614[] =
+{
+ {(u8 *)0x0200C000, 0x800},
+ {(u8 *)0x0200C800, 0x800},
+ {(u8 *)0x0200D000, 0x800},
+ {(u8 *)0x0200D800, 0x800},
+ {(u8 *)0x0200E000, 0x800},
+ {(u8 *)0x0200E800, 0x800},
+ {(u8 *)0x0200F000, 0x800},
+ {(u8 *)0x0200F800, 0x800},
+ {(u8 *)0x02010000, 0x800},
+ {(u8 *)0x02010800, 0x800},
+ {(u8 *)0x02011000, 0x800},
+ {(u8 *)0x02011800, 0x800},
+ {(u8 *)0x02012000, 0x800},
+ {(u8 *)0x02012800, 0x800},
+ {(u8 *)0x02013000, 0x800},
+ {(u8 *)0x02013800, 0x800},
+};
+static const struct SpriteFrameImage gSpriteImageTable_83B5694[] =
+{
+ {(u8 *)0x02010000, 0x800},
+ {(u8 *)0x02010800, 0x800},
+ {(u8 *)0x02011000, 0x800},
+ {(u8 *)0x02011800, 0x800},
+ {(u8 *)0x02012000, 0x800},
+ {(u8 *)0x02012800, 0x800},
+ {(u8 *)0x02013000, 0x800},
+ {(u8 *)0x02013800, 0x800},
+ {(u8 *)0x02014000, 0x800},
+ {(u8 *)0x02014800, 0x800},
+ {(u8 *)0x02015000, 0x800},
+ {(u8 *)0x02015800, 0x800},
+ {(u8 *)0x02016000, 0x800},
+ {(u8 *)0x02016800, 0x800},
+ {(u8 *)0x02017000, 0x800},
+ {(u8 *)0x02017800, 0x800},
+};
+static const struct SpriteFrameImage gSpriteImageTable_83B5714[] =
+{
+ {(u8 *)0x02014000, 0x800},
+ {(u8 *)0x02014800, 0x800},
+ {(u8 *)0x02015000, 0x800},
+ {(u8 *)0x02015800, 0x800},
+ {(u8 *)0x02016000, 0x800},
+ {(u8 *)0x02016800, 0x800},
+ {(u8 *)0x02017000, 0x800},
+ {(u8 *)0x02017800, 0x800},
+ {(u8 *)0x02018000, 0x800},
+ {(u8 *)0x02018800, 0x800},
+ {(u8 *)0x02019000, 0x800},
+ {(u8 *)0x02019800, 0x800},
+ {(u8 *)0x0201A000, 0x800},
+ {(u8 *)0x0201A800, 0x800},
+ {(u8 *)0x0201B000, 0x800},
+ {(u8 *)0x0201B800, 0x800},
+};
+static const struct SpriteFrameImage *const gUnknown_083B5794[] =
+{
+ gSpriteImageTable_83B5594,
+ gSpriteImageTable_83B5614,
+ gSpriteImageTable_83B5694,
+ gSpriteImageTable_83B5714,
+};
+static void nullsub_59(struct Sprite *);
+static const struct SpriteTemplate gUnknown_083B57A4 =
+{
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gOamData_83B557C,
+ .anims = NULL,
+ .images = gSpriteImageTable_83B5594,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = nullsub_59,
+};
+static const u8 gUnknown_083B57BC[][4] =
+{
+ {0, 0, 0, 0},
+ {CHAR_A, 3, CHAR_a, 3},
+ {CHAR_D, 3, CHAR_d, 3},
+ {CHAR_G, 3, CHAR_g, 3},
+ {CHAR_J, 3, CHAR_j, 3},
+ {CHAR_M, 3, CHAR_m, 3},
+ {CHAR_P, 3, CHAR_p, 3},
+ {CHAR_S, 3, CHAR_s, 3},
+ {CHAR_V, 3, CHAR_v, 3},
+ {CHAR_Y, 2, CHAR_y, 2},
+};
+static const struct UnknownStruct3 gUnknown_083B57E4[] =
+{
+ {DexText_SearchForPoke, 0, 0, 5},
+ {DexText_SwitchDex, 6, 0, 5},
+ {DexText_ReturnToDex, 12, 0, 5},
+};
+static const struct UnknownStruct4 gUnknown_083B57FC[] =
+{
+ {DexText_ListByABC, 0, 2, 5, 5, 2, 12},
+ {DexText_ListByColor, 0, 4, 5, 5, 4, 12},
+ {DexText_ListByType, 0, 6, 5, 5, 6, 6},
+ {DexText_ListByType, 0, 6, 5, 11, 6, 6},
+ {DexText_SelectDexList, 0, 8, 5, 5, 8, 12},
+ {DexText_SelectDexMode, 0, 10, 5, 5, 10, 12},
+ {DexText_ExecuteSearchSwitch, 0, 12, 5, 0, 0, 0},
+};
+static const u8 gUnknown_083B5850[][4] =
+{
+ {0xFF, 0xFF, 0xFF, 1},
+ {0xFF, 0xFF, 0, 2},
+ {0xFF, 3, 1, 4},
+ { 2, 0xFF, 1, 4},
+ {0xFF, 0xFF, 2, 5},
+ {0xFF, 0xFF, 4, 6},
+ {0xFF, 0xFF, 5, 0xFF},
+};
+static const u8 gUnknown_083B586C[][4] =
+{
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 5},
+ {0xFF, 0xFF, 4, 6},
+ {0xFF, 0xFF, 5, 0xFF},
+};
+static const u8 gUnknown_083B5888[][4] =
+{
+ {0xFF, 0xFF, 0xFF, 1},
+ {0xFF, 0xFF, 0, 2},
+ {0xFF, 3, 1, 4},
+ { 2, 0xFF, 1, 4},
+ {0xFF, 0xFF, 2, 6},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 4, 0xFF},
+};
+static const u8 gUnknown_083B58A4[][4] =
+{
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 0xFF, 6},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ {0xFF, 0xFF, 4, 0xFF},
+};
+static const struct UnknownStruct2 gUnknown_083B58C0[] =
+{
+ {DexText_HoennDex2, DexText_HoennDex},
+ {DexText_NationalDex2, DexText_NationalDex},
+ {NULL, NULL},
+};
+static const struct UnknownStruct2 gUnknown_083B58D8[] =
+{
+ {DexText_ListByNumber, DexText_NumericalMode},
+ {DexText_ListByABC2, DexText_ABCMode},
+ {DexText_ListByHeavyToLightest, DexText_HeaviestMode},
+ {DexText_ListByLightToHeaviest, DexText_LightestMode},
+ {DexText_ListByTallToSmallest, DexText_TallestMode},
+ {DexText_ListBySmallToTallest, DexText_SmallestMode},
+ {NULL, NULL},
+};
+static const struct UnknownStruct2 gUnknown_083B5910[] =
+{
+ {DexText_Terminator5, DexText_DontSpecify},
+ {DexText_Terminator5, DexText_ABC},
+ {DexText_Terminator5, DexText_DEF},
+ {DexText_Terminator5, DexText_GHI},
+ {DexText_Terminator5, DexText_JKL},
+ {DexText_Terminator5, DexText_MNO},
+ {DexText_Terminator5, DexText_PQR},
+ {DexText_Terminator5, DexText_STU},
+ {DexText_Terminator5, DexText_VWX},
+ {DexText_Terminator5, DexText_YZ},
+ {NULL, NULL},
+};
+static const struct UnknownStruct2 gUnknown_083B5968[] =
+{
+ {DexText_Terminator5, DexText_DontSpecify},
+ {DexText_Terminator5, DexText_Red},
+ {DexText_Terminator5, DexText_Blue},
+ {DexText_Terminator5, DexText_Yellow},
+ {DexText_Terminator5, DexText_Green},
+ {DexText_Terminator5, DexText_Black},
+ {DexText_Terminator5, DexText_Brown},
+ {DexText_Terminator5, DexText_Purple},
+ {DexText_Terminator5, DexText_Gray},
+ {DexText_Terminator5, DexText_White},
+ {DexText_Terminator5, DexText_Pink},
+ {NULL, NULL},
+};
+static const struct UnknownStruct2 gUnknown_083B59C8[] =
+{
+ {DexText_Terminator5, DexText_None},
+ {DexText_Terminator5, gTypeNames[TYPE_NORMAL]},
+ {DexText_Terminator5, gTypeNames[TYPE_FIGHTING]},
+ {DexText_Terminator5, gTypeNames[TYPE_FLYING]},
+ {DexText_Terminator5, gTypeNames[TYPE_POISON]},
+ {DexText_Terminator5, gTypeNames[TYPE_GROUND]},
+ {DexText_Terminator5, gTypeNames[TYPE_ROCK]},
+ {DexText_Terminator5, gTypeNames[TYPE_BUG]},
+ {DexText_Terminator5, gTypeNames[TYPE_GHOST]},
+ {DexText_Terminator5, gTypeNames[TYPE_STEEL]},
+ {DexText_Terminator5, gTypeNames[TYPE_FIRE]},
+ {DexText_Terminator5, gTypeNames[TYPE_WATER]},
+ {DexText_Terminator5, gTypeNames[TYPE_GRASS]},
+ {DexText_Terminator5, gTypeNames[TYPE_ELECTRIC]},
+ {DexText_Terminator5, gTypeNames[TYPE_PSYCHIC]},
+ {DexText_Terminator5, gTypeNames[TYPE_ICE]},
+ {DexText_Terminator5, gTypeNames[TYPE_DRAGON]},
+ {DexText_Terminator5, gTypeNames[TYPE_DARK]},
+ {NULL, NULL},
+};
+static const u8 gUnknown_083B5A60[] = {0, 1};
+static const u8 gUnknown_083B5A62[] = {0, 1, 2, 3, 4, 5};
+static const u8 gUnknown_083B5A68[] = {0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17};
+static const struct UnknownStruct1 gUnknown_083B5A7C[] =
+{
+ {gUnknown_083B5910, 6, 7, 10},
+ {gUnknown_083B5968, 8, 9, 11},
+ {gUnknown_083B59C8, 10, 11, 18},
+ {gUnknown_083B59C8, 12, 13, 18},
+ {gUnknown_083B58D8, 4, 5, 6},
+ {gUnknown_083B58C0, 2, 3, 2},
+};
+static const u8 gUnknown_083B5AAC[] = _("{STR_VAR_1}{CLEAR_TO 43}");
+static const u8 gUnknown_083B5AB2[] = _("{STR_VAR_1}{CLEAR_TO 96}");
+
+static void MainCB(void);
+static void Task_PokedexShowMainScreen(u8 taskId);
+static void Task_PokedexMainScreen(u8 taskId);
+static void sub_808C898(u8 taskId);
+static void Task_PokedexMainScreenMenu(u8 taskId);
+static void sub_808CA64(u8 taskId);
+static void sub_808CAE4(u8 taskId);
+static void sub_808CB8C(u8 taskId);
+static void Task_ClosePokedex(u8 taskId);
+static void sub_808CCC4(u8 taskId);
+static void Task_PokedexResultsScreen(u8 taskId);
+static void sub_808CEF8(u8 taskId);
+static void Task_PokedexResultsScreenMenu(u8 taskId);
+static void sub_808D118(u8 taskId);
+static void sub_808D198(u8 taskId);
+static void Task_PokedexResultsScreenReturnToMainScreen(u8 taskId);
+static void Task_PokedexResultsScreenExitPokedex(u8 taskId);
+static bool8 sub_808D344(u8 a);
+static void sub_808D640(void);
+static void SortPokedex(u8 dexMode, u8 sortMode);
+static void sub_808DEB0(u16 a, u8 b, u8 c, u16 d);
+static void sub_808DF88(u16 a, u8 b, u8 c, u16 d);
+static u8 sub_808DFE4(u16 num, u8 b, u8 c);
+static void sub_808E090(u8 a, u8 b, u16 c);
+static void sub_808E0CC(u16 a, u16 b);
+static bool8 sub_808E208(u8 a, u8 b, u8 c);
+static u16 sub_808E48C(u16 a, u16 b);
+static void sub_808E6BC(void);
+static u8 sub_808E71C(void);
+static u8 sub_808E82C(void);
+static u16 sub_808E888(u16 a1);
+static u32 sub_808E8C8(u16 a, s16 b, s16 c);
+static void sub_808E978(u8 a);
+static void sub_808EDB8(struct Sprite *sprite);
+static void sub_808EE28(struct Sprite *sprite);
+static u8 sub_808F210(struct PokedexListItem *, u8);
+static bool8 sub_808F250(u8 taskId);
+static u8 sub_808F284(struct PokedexListItem *, u8);
+static void Task_InitPageScreenMultistep(u8 taskId);
+static void Task_PageScreenProcessInput(u8 taskId);
+static void sub_808F888(u8 taskId);
+static void Task_ClosePageScreen(u8 taskId);
+static void Task_InitAreaScreenMultistep(u8 taskId);
+static void Task_AreaScreenProcessInput(u8 taskId);
+static void sub_808FA00(u8 taskId);
+static void Task_InitCryScreenMultistep(u8 taskId);
+static void Task_CryScreenProcessInput(u8 taskId);
+static void sub_808FFBC(u8 taskId);
+static void sub_8090040(u8 a);
+static void Task_InitSizeScreenMultistep(u8 taskId);
+static void Task_SizeScreenProcessInput(u8 taskId);
+static void sub_8090498(u8 taskId);
+static void sub_80904FC(u16 a);
+static void sub_8090540(u16 a);
+static void sub_8090584(u8 a, u16 b);
+static void sub_8090644(u8 a, u16 b);
+static void sub_8090750(u8);
+static void sub_8090A3C(u8);
+static void sub_8090B8C(u8);
+static void sub_8090C28(struct Sprite *);
+static void sub_8090C68(void);
+static void sub_8091060(u16);
+static void sub_8091154(u16 order, u8, u8);
+static u8 sub_80911C8(u16 num, u8, u8);
+static u8 sub_8091260(u16 num, u8, u8, u8);
+static void sub_8091304(const u8 *name, u8, u8);
+static void sub_8091458(u16 height, u8 i, u8 i1);
+static void sub_8091564(u16 weight, u8 i, u8 i1);
+static void sub_8091738(u16, u16, u16);
+static void sub_80917CC(u16 i, u16 i1);
+static u16 sub_8091818(u8, u16, u16, u16);
+static u16 sub_80918EC(u16 a, s16 b, s16 c, u16 d);
+static u8 sub_8091A4C(u16 gender, s16, s16, u16);
+static void sub_8091E54(u8);
+static void sub_809204C(u8);
+static void sub_809207C(u8);
+static void sub_809217C(u8);
+static void sub_80921B0(u8);
+static void sub_80923FC(u8);
+static void sub_80924A4(u8);
+static void sub_8092508(u8);
+static void sub_80925CC(u8);
+static void sub_8092644(u8);
+static void sub_80927B8(u8);
+static void sub_80927F0(u8);
+static void sub_8092AB0(u8);
+static void sub_8092AD4(u8, u8);
+static void sub_8092B68(u8);
+static void sub_8092C8C(u8);
+static void sub_8092D78(u8);
+static u8 sub_8092E10(u8, u8);
+static void sub_8092EB0(u8);
+static void sub_809308C(u8);
+
+
+void ResetPokedex(void)
+{
+ u16 i;
+
+ gUnknown_0202FFB8 = 0;
+ gUnknown_0202FFBA = 0x40;
+ gUnknown_03005CE8 = 0;
+ gSaveBlock2.pokedex.unknown1 = 0;
+ gSaveBlock2.pokedex.order = 0;
+ gSaveBlock2.pokedex.nationalMagic = 0;
+ gSaveBlock2.pokedex.unknown2 = 0;
+ gSaveBlock2.pokedex.unownPersonality = 0;
+ gSaveBlock2.pokedex.spindaPersonality = 0;
+ gSaveBlock2.pokedex.unknown3 = 0;
+ DisableNationalPokedex();
+ for (i = 0; i <= 51; i++)
+ {
+ gSaveBlock2.pokedex.owned[i] = 0;
+ gSaveBlock2.pokedex.seen[i] = 0;
+ gSaveBlock1.dexSeen2[i] = 0;
+ gSaveBlock1.dexSeen3[i] = 0;
+ }
+}
+
+void sub_808C0A0(void)
+{
+ gUnknown_0202FFB8 = 0;
+ gUnknown_0202FFBA = 0x40;
+}
+
+static void sub_808C0B8(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void ClearPokedexView(struct PokedexView *pokedexView)
+{
+ u16 i;
+
+ for (i = 0; i < NATIONAL_DEX_COUNT; i++)
+ {
+ pokedexView->unk0[i].dexNum |= 0xFFFF;
+ pokedexView->unk0[i].seen = 0;
+ pokedexView->unk0[i].owned = 0;
+ }
+ pokedexView->unk608 = 0;
+ pokedexView->unk60A_1 = 0;
+ pokedexView->unk60A_2 = 0;
+ pokedexView->pokemonListCount = 0;
+ pokedexView->selectedPokemon = 0;
+ pokedexView->unk610 = 0;
+ pokedexView->dexMode = 0;
+ pokedexView->unk614 = 0;
+ pokedexView->dexOrder = 0;
+ pokedexView->unk618 = 0;
+ pokedexView->unk61A = 0;
+ pokedexView->unk61C = 0;
+ for (i = 0; i <= 3; i++)
+ pokedexView->unk61E[i] |= 0xFFFF;
+ pokedexView->unk628 = 0;
+ pokedexView->unk62A = 0;
+ pokedexView->unk62C = 0;
+ pokedexView->unk62D = 0;
+ pokedexView->unk62E = 0;
+ pokedexView->unk62F = 0;
+ pokedexView->unk630 = 0;
+ pokedexView->unk632 = 0;
+ pokedexView->unk634 = 0;
+ pokedexView->unk636 = 0;
+ pokedexView->unk638 = 0;
+ for (i = 0; i <= 3; i++)
+ pokedexView->unk63A[i] = 0;
+ pokedexView->unk64A = 0;
+ pokedexView->unk64B = 0;
+ pokedexView->unk64C_1 = 0;
+ pokedexView->selectedScreen = 0;
+ pokedexView->unk64F = 0;
+ pokedexView->menuIsOpen = 0;
+ pokedexView->menuCursorPos = 0;
+ pokedexView->menuY = 0;
+ for (i = 0; i <= 7; i++)
+ pokedexView->unk656[i] = 0;
+ for (i = 0; i <= 7; i++)
+ pokedexView->unk65E[i] = 0;
+}
+
+void CB2_InitPokedex(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ {
+ u8 *addr;
+ u32 size;
+
+ SetVBlankCallback(NULL);
+ sub_8091060(0);
+ addr = (u8 *)VRAM;
+ size = VRAM_SIZE;
+ while (1)
+ {
+ DmaFill16(3, 0, addr, 0x1000);
+ addr += 0x1000;
+ size -= 0x1000;
+ if (size <= 0x1000)
+ {
+ DmaFill16(3, 0, addr, size);
+ break;
+ }
+ }
+ DmaClear32(3, OAM, OAM_SIZE);
+ DmaClear16(3, PLTT, PLTT_SIZE);
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 8;
+ SetUpWindowConfig(&gWindowConfig_81E7048);
+ InitMenuWindow(&gWindowConfig_81E7048);
+ gMain.state++;
+ break;
+ case 2:
+ switch (Random() & 3)
+ {
+ case 0:
+ default:
+ gPokedexView = (struct PokedexView *)0x02018000;
+ break;
+ case 1:
+ gPokedexView = (struct PokedexView *)0x02018800;
+ break;
+ case 2:
+ gPokedexView = (struct PokedexView *)0x02019000;
+ break;
+ case 3:
+ gPokedexView = (struct PokedexView *)0x02019800;
+ break;
+ }
+ ClearPokedexView(gPokedexView);
+ CreateTask(Task_PokedexShowMainScreen, 0);
+ gPokedexView->dexMode = gSaveBlock2.pokedex.unknown1;
+ if (!IsNationalPokedexEnabled())
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gSaveBlock2.pokedex.order;
+ gPokedexView->selectedPokemon = gUnknown_0202FFB8;
+ gPokedexView->unk62C = gUnknown_0202FFBA;
+ gPokedexView->selectedScreen = PAGE_SCREEN;
+ gPokedexView->descriptionPageNum = 0;
+ if (!IsNationalPokedexEnabled())
+ {
+ gPokedexView->unk61A = GetHoennPokedexCount(0);
+ gPokedexView->unk61C = GetHoennPokedexCount(1);
+ }
+ else
+ {
+ gPokedexView->unk61A = GetNationalPokedexCount(0);
+ gPokedexView->unk61C = GetNationalPokedexCount(1);
+ }
+ gPokedexView->unk62D = 8;
+ gMain.state++;
+ break;
+ case 3:
+ {
+ u16 savedIme;
+
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= 1;
+ REG_IME = savedIme;
+ REG_DISPSTAT |= 8;
+ SetVBlankCallback(sub_808C0B8);
+ SetMainCallback2(MainCB);
+ SortPokedex(gPokedexView->dexMode, gPokedexView->dexOrder);
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x80);
+ }
+ break;
+ }
+}
+
+u8 unref_sub_808C540(void (*func)(u8))
+{
+ u16 savedIme;
+ u8 taskId;
+
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ remove_some_task();
+ ResetTasks();
+ ResetPaletteFade();
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= 1;
+ REG_IME = savedIme;
+ REG_DISPSTAT |= 0x8;
+ SetVBlankCallback(sub_808C0B8);
+ SetMainCallback2(MainCB);
+ if (!gPokedexView->unk64B)
+ taskId = CreateTask(sub_808CAE4, 0);
+ else
+ taskId = CreateTask(sub_808D198, 0);
+ gTasks[taskId].data[0] = CreateTask(func, 0);
+ return gTasks[taskId].data[0];
+}
+
+static void MainCB(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void Task_PokedexShowMainScreen(u8 taskId)
+{
+ gPokedexView->unk64C_1 = 0;
+ if (sub_808D344(0))
+ gTasks[taskId].func = Task_PokedexMainScreen;
+}
+
+//Hide menu and process input on main screen
+void Task_PokedexMainScreen(u8 taskId)
+{
+ REG_BG0VOFS = gPokedexView->menuY;
+
+ //If menu is open, slide it down, off screen
+ if (gPokedexView->menuY)
+ gPokedexView->menuY -= 8;
+ else
+ {
+ if ((gMain.newKeys & A_BUTTON) && gPokedexView->unk0[gPokedexView->selectedPokemon].seen)
+ {
+ sub_808E6BC();
+ BeginNormalPaletteFade(
+ ~(1 << (gSprites[gPokedexView->selectedMonSpriteId].oam.paletteNum + 16)),
+ 0, 0, 0x10, 0);
+ gSprites[gPokedexView->selectedMonSpriteId].callback = sub_808EDB8;
+ gTasks[taskId].func = sub_808CA64;
+ PlaySE(SE_PIN);
+ }
+ else if (gMain.newKeys & START_BUTTON)
+ {
+ //Open menu
+ gPokedexView->menuY = 0;
+ gPokedexView->menuIsOpen = 1;
+ gPokedexView->menuCursorPos = 0;
+ gTasks[taskId].func = Task_PokedexMainScreenMenu;
+ PlaySE(SE_SELECT);
+ }
+ else if (gMain.newKeys & SELECT_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].data[0] = sub_8091E3C();
+ gPokedexView->unk64F = 0;
+ gPokedexView->unk62A = gPokedexView->unk62C;
+ gPokedexView->unk610 = gPokedexView->selectedPokemon;
+ gPokedexView->unk614 = gPokedexView->dexMode;
+ gPokedexView->unk618 = gPokedexView->dexOrder;
+ gTasks[taskId].func = sub_808CB8C;
+ PlaySE(SE_PC_LOGON);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_ClosePokedex;
+ PlaySE(SE_PC_OFF);
+ }
+ else
+ {
+ //Handle D-pad
+ gPokedexView->selectedPokemon = sub_808E48C(gPokedexView->selectedPokemon, 0xE);
+ if (gPokedexView->unk62E)
+ gTasks[taskId].func = sub_808C898;
+ }
+ }
+}
+
+static void sub_808C898(u8 taskId)
+{
+ if (sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636))
+ gTasks[taskId].func = Task_PokedexMainScreen;
+}
+
+//Bring up menu and process menu input
+static void Task_PokedexMainScreenMenu(u8 taskId)
+{
+ REG_BG0VOFS = gPokedexView->menuY;
+
+ //If menu is not open, slide it up, on screen
+ if (gPokedexView->menuY != 80)
+ gPokedexView->menuY += 8;
+ else
+ {
+ if (gMain.newKeys & A_BUTTON)
+ {
+ switch (gPokedexView->menuCursorPos)
+ {
+ case 0: //BACK TO LIST
+ default:
+ gMain.newKeys |= START_BUTTON; //Exit menu
+ break;
+ case 1: //LIST TOP
+ gPokedexView->selectedPokemon = 0;
+ gPokedexView->unk62C = 0x40;
+ sub_808E82C();
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gMain.newKeys |= START_BUTTON; //Exit menu
+ break;
+ case 2: //LIST BOTTOM
+ gPokedexView->selectedPokemon = gPokedexView->pokemonListCount - 1;
+ gPokedexView->unk62C = gPokedexView->pokemonListCount * 16 + 0x30;
+ sub_808E82C();
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gMain.newKeys |= START_BUTTON; //Exit menu
+ break;
+ case 3: //CLOSE POKEDEX
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_ClosePokedex;
+ PlaySE(SE_PC_OFF);
+ break;
+ }
+ }
+
+ //Exit menu when Start or B is pressed
+ if (gMain.newKeys & (START_BUTTON | B_BUTTON))
+ {
+ gPokedexView->menuIsOpen = 0;
+ gTasks[taskId].func = Task_PokedexMainScreen;
+ PlaySE(SE_SELECT);
+ }
+ else if ((gMain.newAndRepeatedKeys & DPAD_UP) && gPokedexView->menuCursorPos != 0)
+ {
+ gPokedexView->menuCursorPos--;
+ PlaySE(SE_SELECT);
+ }
+ else if ((gMain.newAndRepeatedKeys & DPAD_DOWN) && gPokedexView->menuCursorPos <= 2)
+ {
+ gPokedexView->menuCursorPos++;
+ PlaySE(SE_SELECT);
+ }
+ }
+}
+
+static void sub_808CA64(u8 taskId)
+{
+ if (gSprites[gPokedexView->selectedMonSpriteId].pos1.x == 48
+ && gSprites[gPokedexView->selectedMonSpriteId].pos1.y == 56)
+ {
+ gPokedexView->unk64B = gPokedexView->unk64A;
+ gTasks[taskId].data[0] = sub_808F210(&gPokedexView->unk0[gPokedexView->selectedPokemon], gPokedexView->selectedMonSpriteId);
+ gTasks[taskId].func = sub_808CAE4;
+ }
+}
+
+static void sub_808CAE4(u8 taskId)
+{
+ if (gTasks[gTasks[taskId].data[0]].isActive)
+ {
+ if (gPokedexView->unk64A == 1 && !sub_808F250(gTasks[taskId].data[0]) && sub_808E71C())
+ sub_808F284(&gPokedexView->unk0[gPokedexView->selectedPokemon], gTasks[taskId].data[0]);
+ }
+ else
+ {
+ gUnknown_0202FFB8 = gPokedexView->selectedPokemon;
+ gUnknown_0202FFBA = gPokedexView->unk62C;
+ gTasks[taskId].func = Task_PokedexShowMainScreen;
+ }
+}
+
+static void sub_808CB8C(u8 taskId)
+{
+ bool8 isActive = gTasks[gTasks[taskId].data[0]].isActive;
+
+ if (!isActive)
+ {
+ if (gPokedexView->unk64F != 0)
+ {
+ gPokedexView->selectedPokemon = isActive;
+ gPokedexView->unk62C = 0x40;
+ gTasks[taskId].func = sub_808CCC4;
+ }
+ else
+ {
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
+ if (!IsNationalPokedexEnabled())
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
+ gTasks[taskId].func = Task_PokedexShowMainScreen;
+ }
+ }
+}
+
+static void Task_ClosePokedex(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gSaveBlock2.pokedex.unknown1 = gPokedexView->dexMode;
+ if (!IsNationalPokedexEnabled())
+ gSaveBlock2.pokedex.unknown1 = 0;
+ gSaveBlock2.pokedex.order = gPokedexView->dexOrder;
+ DestroyTask(taskId);
+ SetMainCallback2(sub_805469C);
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100);
+ }
+}
+
+static void sub_808CCC4(u8 taskId)
+{
+ gPokedexView->unk64C_1 = 1;
+ if (sub_808D344(3))
+ gTasks[taskId].func = Task_PokedexResultsScreen;
+}
+
+static void Task_PokedexResultsScreen(u8 taskId)
+{
+ REG_BG0VOFS = gPokedexView->menuY;
+
+ if (gPokedexView->menuY)
+ {
+ gPokedexView->menuY -= 8;
+ }
+ else
+ {
+ if ((gMain.newKeys & A_BUTTON) && gPokedexView->unk0[gPokedexView->selectedPokemon].seen)
+ {
+ u32 a;
+
+ sub_808E6BC();
+ a = (1 << (gSprites[gPokedexView->selectedMonSpriteId].oam.paletteNum + 16));
+ gSprites[gPokedexView->selectedMonSpriteId].callback = sub_808EDB8;
+ BeginNormalPaletteFade(~a, 0, 0, 0x10, 0);
+ gTasks[taskId].func = sub_808D118;
+ PlaySE(SE_PIN);
+ }
+ else if (gMain.newKeys & START_BUTTON)
+ {
+ gPokedexView->menuY = 0;
+ gPokedexView->menuIsOpen = 1;
+ gPokedexView->menuCursorPos = 0;
+ gTasks[taskId].func = Task_PokedexResultsScreenMenu;
+ PlaySE(SE_SELECT);
+ }
+ else if (gMain.newKeys & SELECT_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].data[0] = sub_8091E3C();
+ gPokedexView->unk64F = 0;
+ gTasks[taskId].func = sub_808CB8C;
+ PlaySE(SE_PC_LOGON);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_PokedexResultsScreenReturnToMainScreen;
+ PlaySE(SE_PC_OFF);
+ }
+ else
+ {
+ //Handle D-pad
+ gPokedexView->selectedPokemon = sub_808E48C(gPokedexView->selectedPokemon, 0xE);
+ if (gPokedexView->unk62E)
+ gTasks[taskId].func = sub_808CEF8;
+ }
+ }
+}
+
+static void sub_808CEF8(u8 taskId)
+{
+ if (sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636))
+ gTasks[taskId].func = Task_PokedexResultsScreen;
+}
+
+static void Task_PokedexResultsScreenMenu(u8 taskId)
+{
+ REG_BG0VOFS = gPokedexView->menuY;
+
+ if (gPokedexView->menuY != 96)
+ {
+ gPokedexView->menuY += 8;
+ }
+ else
+ {
+ if (gMain.newKeys & A_BUTTON)
+ {
+ switch (gPokedexView->menuCursorPos)
+ {
+ case 0: //BACK TO LIST
+ default:
+ gMain.newKeys |= START_BUTTON;
+ break;
+ case 1: //LIST TOP
+ gPokedexView->selectedPokemon = 0;
+ gPokedexView->unk62C = 0x40;
+ sub_808E82C();
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gMain.newKeys |= START_BUTTON;
+ break;
+ case 2: //LIST BOTTOM
+ gPokedexView->selectedPokemon = gPokedexView->pokemonListCount - 1;
+ gPokedexView->unk62C = gPokedexView->pokemonListCount * 16 + 0x30;
+ sub_808E82C();
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gMain.newKeys |= START_BUTTON;
+ break;
+ case 3: //BACK TO POKEDEX
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_PokedexResultsScreenReturnToMainScreen;
+ PlaySE(SE_TRACK_DOOR);
+ break;
+ case 4: //CLOSE POKEDEX
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_PokedexResultsScreenExitPokedex;
+ PlaySE(SE_PC_OFF);
+ break;
+ }
+ }
+
+ //Exit menu when Start or B is pressed
+ if (gMain.newKeys & (START_BUTTON | B_BUTTON))
+ {
+ gPokedexView->menuIsOpen = 0;
+ gTasks[taskId].func = Task_PokedexResultsScreen;
+ PlaySE(SE_SELECT);
+ }
+ else if ((gMain.newAndRepeatedKeys & DPAD_UP) && gPokedexView->menuCursorPos)
+ {
+ gPokedexView->menuCursorPos--;
+ PlaySE(SE_SELECT);
+ }
+ else if ((gMain.newAndRepeatedKeys & DPAD_DOWN) && gPokedexView->menuCursorPos <= 3)
+ {
+ gPokedexView->menuCursorPos++;
+ PlaySE(SE_SELECT);
+ }
+ }
+}
+
+static void sub_808D118(u8 taskId)
+{
+ if (gSprites[gPokedexView->selectedMonSpriteId].pos1.x == 48
+ && gSprites[gPokedexView->selectedMonSpriteId].pos1.y == 56)
+ {
+ gPokedexView->unk64B = gPokedexView->unk64A;
+ gTasks[taskId].data[0] = sub_808F210(&gPokedexView->unk0[gPokedexView->selectedPokemon], gPokedexView->selectedMonSpriteId);
+ gTasks[taskId].func = sub_808D198;
+ }
+}
+
+static void sub_808D198(u8 taskId)
+{
+ if (gTasks[gTasks[taskId].data[0]].isActive)
+ {
+ if (gPokedexView->unk64A == 1 && !sub_808F250(gTasks[taskId].data[0]) && sub_808E71C())
+ sub_808F284(&gPokedexView->unk0[gPokedexView->selectedPokemon], gTasks[taskId].data[0]);
+ }
+ else
+ {
+ gTasks[taskId].func = sub_808CCC4;
+ }
+}
+
+static void Task_PokedexResultsScreenReturnToMainScreen(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
+ if (!IsNationalPokedexEnabled())
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
+ gTasks[taskId].func = Task_PokedexShowMainScreen;
+ }
+}
+
+static void Task_PokedexResultsScreenExitPokedex(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
+ if (!IsNationalPokedexEnabled())
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
+ gTasks[taskId].func = Task_ClosePokedex;
+ }
+}
+
+static bool8 sub_808D344(u8 a)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ if (gPaletteFade.active)
+ return 0;
+ SetVBlankCallback(NULL);
+ gPokedexView->unk64A = a;
+ sub_8091060(0);
+ REG_BG2VOFS = gPokedexView->unk62D;
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)(VRAM));
+ LZ77UnCompVram(gUnknown_08E96738, (void *)(VRAM + 0x6800));
+ LZ77UnCompVram(gUnknown_08E9C6DC, (void *)(VRAM + 0x7800));
+ DmaClear16(3, VRAM + 0x6000, 0x500);
+ if (a == 0)
+ LZ77UnCompVram(gUnknown_08E96888, (void *)(VRAM + 0x6500));
+ else
+ LZ77UnCompVram(gUnknown_08E96994, (void *)(VRAM + 0x6500));
+ ResetPaletteFade();
+ if (a == 0)
+ gPokedexView->unk64C_1 = 0;
+ else
+ gPokedexView->unk64C_1 = 1;
+ sub_808D640();
+ gMain.state = 1;
+ break;
+ case 1:
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 8;
+ LoadCompressedObjectPic(&gUnknown_083A05CC[0]);
+ LoadSpritePalettes(gUnknown_083A05DC);
+ sub_808E978(a);
+ gMain.state++;
+ break;
+ case 2:
+ SetUpWindowConfig(&gWindowConfig_81E7048);
+ InitMenuWindow(&gWindowConfig_81E7048);
+ LZ77UnCompVram(gUnknown_0839FA7C, (void *)(VRAM + 0xFF80));
+ gMain.state++;
+ break;
+ case 3:
+ if (a == 0)
+ SortPokedex(gPokedexView->dexMode, gPokedexView->dexOrder);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gPokedexView->menuIsOpen = 0;
+ gPokedexView->menuY = 0;
+ gMain.state++;
+ break;
+ case 4:
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ SetVBlankCallback(sub_808C0B8);
+ gMain.state++;
+ break;
+ case 5:
+ REG_WININ = 0x3F3F;
+ REG_WINOUT = 0x1D3F;
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WIN1H = 0;
+ REG_WIN1V = 0;
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(15) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG1CNT = BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(12) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON | DISPCNT_OBJWIN_ON;
+ gMain.state++;
+ break;
+ case 6:
+ if (!gPaletteFade.active)
+ {
+ gMain.state = 0;
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static void sub_808D640(void)
+{
+ if (gPokedexView->unk64C_1)
+ LoadPalette(sPokedexSearchPalette + 1, 1, sizeof(sPokedexSearchPalette) - sizeof(u16));
+ else if (!IsNationalPokedexEnabled())
+ LoadPalette(gPokedexMenu_Pal + 1, 1, 0xBE);
+ else
+ LoadPalette(sNationalPokedexPalette + 1, 1, sizeof(sNationalPokedexPalette) - sizeof(u16));
+}
+
+static void SortPokedex(u8 dexMode, u8 sortMode)
+{
+ u16 vars[3]; //I have no idea why three regular variables are stored in an array, but whatever.
+ s16 i;
+
+ gPokedexView->pokemonListCount = 0;
+
+ switch (dexMode)
+ {
+ default:
+ case DEX_MODE_HOENN:
+ vars[0] = 202;
+ vars[1] = 1;
+ break;
+ case DEX_MODE_NATIONAL:
+ if (IsNationalPokedexEnabled())
+ {
+ vars[0] = NATIONAL_DEX_COUNT;
+ vars[1] = 0;
+ }
+ else
+ {
+ vars[0] = 202;
+ vars[1] = 1;
+ }
+ break;
+ }
+
+ switch (sortMode)
+ {
+ case 0:
+ if (vars[1])
+ {
+ for (i = 0; i < vars[0]; i++)
+ {
+ vars[2] = HoennToNationalOrder(i + 1);
+ gPokedexView->unk0[i].dexNum = vars[2];
+ gPokedexView->unk0[i].seen = GetSetPokedexFlag(vars[2], 0);
+ gPokedexView->unk0[i].owned = GetSetPokedexFlag(vars[2], 1);
+ if (gPokedexView->unk0[i].seen)
+ gPokedexView->pokemonListCount = i + 1;
+ }
+ }
+ else
+ {
+ bool32 r10;
+ s16 r5;
+
+ r10 = r5 = i = 0;
+ for (i = 0; i < vars[0]; i++)
+ {
+ vars[2] = i + 1;
+ if (GetSetPokedexFlag(vars[2], 0))
+ r10 = 1;
+ if (r10)
+ {
+ asm(""); //Needed to match for some reason
+ gPokedexView->unk0[r5].dexNum = vars[2];
+ gPokedexView->unk0[r5].seen = GetSetPokedexFlag(vars[2], 0);
+ gPokedexView->unk0[r5].owned = GetSetPokedexFlag(vars[2], 1);
+ if (gPokedexView->unk0[r5].seen)
+ gPokedexView->pokemonListCount = r5 + 1;
+ r5++;
+ }
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < 411; i++)
+ {
+ vars[2] = gPokedexOrder_Alphabetical[i];
+
+ if (NationalToHoennOrder(vars[2]) <= vars[0] && GetSetPokedexFlag(vars[2], 0))
+ {
+ gPokedexView->unk0[gPokedexView->pokemonListCount].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->pokemonListCount].seen = 1;
+ gPokedexView->unk0[gPokedexView->pokemonListCount].owned = GetSetPokedexFlag(vars[2], 1);
+ gPokedexView->pokemonListCount++;
+ }
+ }
+ break;
+ case 2:
+ for (i = NATIONAL_DEX_COUNT - 1; i >= 0; i--)
+ {
+ vars[2] = gPokedexOrder_Weight[i];
+
+ if (NationalToHoennOrder(vars[2]) <= vars[0] && GetSetPokedexFlag(vars[2], 1))
+ {
+ gPokedexView->unk0[gPokedexView->pokemonListCount].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->pokemonListCount].seen = 1;
+ gPokedexView->unk0[gPokedexView->pokemonListCount].owned = 1;
+ gPokedexView->pokemonListCount++;
+ }
+ }
+ break;
+ case 3:
+ for (i = 0; i < NATIONAL_DEX_COUNT; i++)
+ {
+ vars[2] = gPokedexOrder_Weight[i];
+
+ if (NationalToHoennOrder(vars[2]) <= vars[0] && GetSetPokedexFlag(vars[2], 1))
+ {
+ gPokedexView->unk0[gPokedexView->pokemonListCount].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->pokemonListCount].seen = 1;
+ gPokedexView->unk0[gPokedexView->pokemonListCount].owned = 1;
+ gPokedexView->pokemonListCount++;
+ }
+ }
+ break;
+ case 4:
+ for (i = NATIONAL_DEX_COUNT - 1; i >=0; i--)
+ {
+ vars[2] = gPokedexOrder_Height[i];
+
+ if (NationalToHoennOrder(vars[2]) <= vars[0] && GetSetPokedexFlag(vars[2], 1))
+ {
+ gPokedexView->unk0[gPokedexView->pokemonListCount].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->pokemonListCount].seen = 1;
+ gPokedexView->unk0[gPokedexView->pokemonListCount].owned = 1;
+ gPokedexView->pokemonListCount++;
+ }
+ }
+ break;
+ case 5:
+ for (i = 0; i < NATIONAL_DEX_COUNT; i++)
+ {
+ vars[2] = gPokedexOrder_Height[i];
+
+ if (NationalToHoennOrder(vars[2]) <= vars[0] && GetSetPokedexFlag(vars[2], 1))
+ {
+ gPokedexView->unk0[gPokedexView->pokemonListCount].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->pokemonListCount].seen = 1;
+ gPokedexView->unk0[gPokedexView->pokemonListCount].owned = 1;
+ gPokedexView->pokemonListCount++;
+ }
+ }
+ break;
+ }
+
+ for (i = gPokedexView->pokemonListCount; i < NATIONAL_DEX_COUNT; i++)
+ {
+ gPokedexView->unk0[i].dexNum |= 0xFFFF;
+ gPokedexView->unk0[i].seen = 0;
+ gPokedexView->unk0[i].owned = 0;
+ }
+}
+
+static void sub_808DBE8(u8 a, u16 b, u16 c)
+{
+ s16 _b;
+ u16 i;
+ u16 r2;
+
+ switch (a)
+ {
+ case 0:
+ default:
+ _b = b - 5;
+ for (i = 0; i <= 10; i++)
+ {
+ if (_b < 0 || _b >= NATIONAL_DEX_COUNT || gPokedexView->unk0[_b].dexNum == 0xFFFF)
+ {
+ sub_808E090(0x11, i * 2, c);
+ }
+ else
+ {
+ sub_808E090(0x11, i * 2, c);
+ if (gPokedexView->unk0[_b].seen)
+ {
+ sub_808DEB0(_b, 0x12, i * 2, c);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, i * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, i * 2);
+ }
+ else
+ {
+ sub_808DEB0(_b, 0x12, i * 2, c);
+ sub_808DF88(0, 0x11, i * 2, c);
+ sub_808DFE4(0, 0x17, i * 2);
+ }
+ }
+ _b++;
+ }
+ break;
+ case 1:
+ _b = b - 5;
+ if (_b < 0 || _b >= NATIONAL_DEX_COUNT || gPokedexView->unk0[_b].dexNum == 0xFFFF)
+ {
+ sub_808E090(0x11, gPokedexView->unk630 * 2, c);
+ }
+ else
+ {
+ sub_808E090(0x11, gPokedexView->unk630 * 2, c);
+ if (gPokedexView->unk0[_b].seen)
+ {
+ sub_808DEB0(_b, 0x12, gPokedexView->unk630 * 2, c);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, gPokedexView->unk630 * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, gPokedexView->unk630 * 2);
+ }
+ else
+ {
+ sub_808DEB0(_b, 0x12, gPokedexView->unk630 * 2, c);
+ sub_808DF88(0, 0x11, gPokedexView->unk630 * 2, c);
+ sub_808DFE4(0, 0x17, gPokedexView->unk630 * 2);
+ }
+ }
+ break;
+ case 2:
+ _b = b + 5;
+ r2 = gPokedexView->unk630 + 10;
+ if (r2 > 15)
+ r2 -= 16;
+ if (_b < 0 || _b >= NATIONAL_DEX_COUNT || gPokedexView->unk0[_b].dexNum == 0xFFFF)
+ sub_808E090(0x11, r2 * 2, c);
+ else
+ {
+ sub_808E090(0x11, r2 * 2, c);
+ if (gPokedexView->unk0[_b].seen)
+ {
+ sub_808DEB0(_b, 0x12, r2 * 2, c);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, r2 * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, r2 * 2);
+ }
+ else
+ {
+ sub_808DEB0(_b, 0x12, r2 * 2, c);
+ sub_808DF88(0, 0x11, r2 * 2, c);
+ sub_808DFE4(0, 0x17, r2 * 2);
+ }
+ }
+ break;
+ }
+}
+
+static void sub_808DEB0(u16 a, u8 b, u8 c, u16 d)
+{
+ u8 text[4];
+ u16 unk[2];
+ u16 r7 = gPokedexView->unk0[a].dexNum;
+
+ if (gPokedexView->dexMode == DEX_MODE_HOENN)
+ r7 = NationalToHoennOrder(r7);
+ unk[0] = 0x3FC;
+ unk[1] = 0x3FD;
+ text[0] = CHAR_0 + r7 / 100;
+ text[1] = CHAR_0 + (r7 % 100) / 10;
+ text[2] = CHAR_0 + (r7 % 100) % 10;
+ text[3] = EOS;
+ *(u16 *)(VRAM + d * 0x800 + c * 0x40 + b * 2) = unk[0];
+ *(u16 *)(VRAM + d * 0x800 + (c + 1) * 0x40 + b * 2) = unk[1];
+ MenuPrint(text, b - 15, c);
+}
+
+static void sub_808DF88(u16 a, u8 b, u8 c, u16 d)
+{
+ u16 unk[2];
+
+ if (a)
+ {
+ unk[0] = 0x3FE;
+ unk[1] = 0x3FF;
+ }
+ else
+ {
+ unk[0] = 0;
+ unk[1] = 0;
+ }
+ *(u16 *)(VRAM + d * 0x800 + c * 0x40 + b * 2) = unk[0];
+ *(u16 *)(VRAM + d * 0x800 + (c + 1) * 0x40 + b * 2) = unk[1];
+}
+
+static u8 sub_808DFE4(u16 num, u8 b, u8 c)
+{
+ u8 text[10];
+ u8 i;
+
+ for (i = 0; i < 10; i++)
+ text[i] = CHAR_SPACE;
+ text[i] = EOS;
+
+ num = NationalPokedexNumToSpecies(num);
+ switch (num)
+ {
+ default:
+ for (i = 0; gSpeciesNames[num][i] != EOS && i < 10; i++)
+ text[i] = gSpeciesNames[num][i];
+ break;
+ case 0:
+ for (i = 0; i < 10; i++)
+ text[i] = CHAR_HYPHEN;
+ break;
+ }
+ MenuPrint_PixelCoords(text, (b - 0x11) * 8 + 0xFC, c * 8, 0);
+ return i;
+}
+
+static void sub_808E090(u8 a, u8 b, u16 c)
+{
+ u8 i;
+
+ for (i = 0; i < 12; i++)
+ {
+ *(u16 *)(VRAM + c * 0x800 + b * 64 + (a + i) * 2) = 0;
+ *(u16 *)(VRAM + c * 0x800 + (b + 1) * 64 + (a + i) * 2) = 0;
+ }
+}
+
+static void sub_808E0CC(u16 a, u16 b)
+{
+ u8 i;
+ u16 unk;
+ u8 spriteId;
+
+ for (i = 0; i < 4; i++)
+ gPokedexView->unk61E[i] = 0xFFFF;
+ gPokedexView->selectedMonSpriteId = 0xFFFF;
+ sub_808DBE8(0, a, b);
+ REG_BG2VOFS = gPokedexView->unk62D;
+
+ unk = sub_808E888(a - 1);
+ if (unk != 0xFFFF)
+ {
+ spriteId = sub_808E8C8(unk, 0x60, 0x50);
+ gSprites[spriteId].callback = sub_808EE28;
+ gSprites[spriteId].data5 = -32;
+ }
+
+ unk = sub_808E888(a);
+ if (unk != 0xFFFF)
+ {
+ spriteId = sub_808E8C8(unk, 0x60, 0x50);
+ gSprites[spriteId].callback = sub_808EE28;
+ gSprites[spriteId].data5 = 0;
+ }
+
+ unk = sub_808E888(a + 1);
+ if (unk != 0xFFFF)
+ {
+ spriteId = sub_808E8C8(unk, 0x60, 0x50);
+ gSprites[spriteId].callback = sub_808EE28;
+ gSprites[spriteId].data5 = 32;
+ }
+
+ gPokedexView->unk630 = 0;
+ gPokedexView->unk632 = 0;
+}
+
+static bool8 sub_808E208(u8 a, u8 b, u8 c)
+{
+ u16 i;
+ u8 foo;
+
+ if (gPokedexView->unk62E)
+ {
+ gPokedexView->unk62E--;
+ switch (a)
+ {
+ case 1:
+ for (i = 0; i < 4; i++)
+ {
+ if (gPokedexView->unk61E[i] != 0xFFFF)
+ gSprites[gPokedexView->unk61E[i]].data5 += b;
+ }
+ foo = 16 * (c - gPokedexView->unk62E) / c;
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk632 * 16 - foo;
+ gPokedexView->unk62C -= gPokedexView->unk628;
+ break;
+ case 2:
+ for (i = 0; i < 4; i++)
+ {
+ if (gPokedexView->unk61E[i] != 0xFFFF)
+ gSprites[gPokedexView->unk61E[i]].data5 -= b;
+ }
+ foo = 16 * (c - gPokedexView->unk62E) / c;
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk632 * 16 + foo;
+ gPokedexView->unk62C += gPokedexView->unk628;
+ break;
+ }
+ return FALSE;
+ }
+ else
+ {
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk630 * 16;
+ return TRUE;
+ }
+}
+
+static void sub_808E398(u8 a, u16 b)
+{
+ u16 unk;
+ u8 spriteId;
+
+ gPokedexView->unk632 = gPokedexView->unk630;
+ switch (a)
+ {
+ case 1:
+ unk = sub_808E888(b - 1);
+ if (unk != 0xFFFF)
+ {
+ spriteId = sub_808E8C8(unk, 0x60, 0x50);
+ gSprites[spriteId].callback = sub_808EE28;
+ gSprites[spriteId].data5 = -64;
+ }
+ if (gPokedexView->unk630 > 0)
+ gPokedexView->unk630--;
+ else
+ gPokedexView->unk630 = 15;
+ break;
+ case 2:
+ unk = sub_808E888(b + 1);
+ if (unk != 0xFFFF)
+ {
+ spriteId = sub_808E8C8(unk, 0x60, 0x50);
+ gSprites[spriteId].callback = sub_808EE28;
+ gSprites[spriteId].data5 = 0x40;
+ }
+ if (gPokedexView->unk630 <= 0xE)
+ gPokedexView->unk630++;
+ else
+ gPokedexView->unk630 = 0;
+ break;
+ }
+}
+
+// Ugly, ugly, ugly. I couldn't get it to match otherwise.
+static u16 sub_808E48C(u16 a, u16 b)
+{
+ u8 r3;
+ u8 r5;
+ u8 i;
+ u16 r6;
+ u8 r10 = 0;
+
+ if (!((gMain.heldKeys & 0x40) && (a > 0)))
+ {
+ //_0808E4B6
+ if (!((gMain.heldKeys & 0x80) && (a < gPokedexView->pokemonListCount - 1)))
+ //_0808E4CE
+ {
+ if ((gMain.newKeys & 0x20) && (a > 0))
+ {
+ r6 = a;
+ //_0808E4E0
+ for (i = 0; i < 7; i++)
+ a = sub_8091818(1, a, 0, gPokedexView->pokemonListCount - 1);
+ gPokedexView->unk62C += 16 * (a - r6);
+ sub_808E82C();
+ sub_808E0CC(a, 0xE);
+ PlaySE(0x6D);
+ }
+ //_0808E53C
+ else if ((gMain.newKeys & 0x10) && (a < gPokedexView->pokemonListCount - 1))
+ {
+ r6 = a;
+ for (i = 0; i < 7; i++)
+ a = sub_8091818(0, a, 0, gPokedexView->pokemonListCount - 1);
+ gPokedexView->unk62C += (a - r6) * 16;
+ sub_808E82C();
+ sub_808E0CC(a, 0xE);
+ PlaySE(0x6D);
+ }
+ _0808E5A2:
+ if (r10 == 0)
+ {
+ gPokedexView->unk638 = 0;
+ return a;
+ }
+ }
+ else
+ {
+ // to _0808E5C4
+ r10 = 2;
+ a = sub_8091818(0, a, 0, gPokedexView->pokemonListCount - 1);
+ sub_808E398(2, a);
+ //goto _0808E60E
+ sub_808DBE8(2, a, b);
+ PlaySE(0x6C);
+ goto _0808E5A2;
+ }
+ }
+ else
+ {
+ //to _0808E5E4
+ r10 = 1;
+ a = sub_8091818(1, a, 0, gPokedexView->pokemonListCount - 1);
+ sub_808E398(1, a);
+ //_0808E60E
+ sub_808DBE8(1, a, b);
+ PlaySE(0x6C);
+ goto _0808E5A2;
+ }
+ //_0808E628
+ r5 = gUnknown_083A05EC[gPokedexView->unk638 / 4];
+ r3 = gUnknown_083A05F1[gPokedexView->unk638 / 4];
+ gPokedexView->unk62E = r3;
+ gPokedexView->unk636 = r3;
+ gPokedexView->unk634 = r5;
+ gPokedexView->unk62F = r10;
+ gPokedexView->unk628 = r5 / 2;
+ sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636);
+ if (gPokedexView->unk638 <= 0xB)
+ gPokedexView->unk638++;
+ return a;
+}
+
+static void sub_808E6BC(void)
+{
+ u16 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ u16 spriteId = gPokedexView->unk61E[i];
+
+ if (gSprites[spriteId].pos2.x == 0 && gSprites[spriteId].pos2.y == 0 && spriteId != 0xFFFF)
+ gPokedexView->selectedMonSpriteId = spriteId;
+ }
+}
+
+static u8 sub_808E71C(void)
+{
+ u16 r2;
+ u16 r4 = gPokedexView->selectedPokemon;
+
+ if ((gMain.newKeys & DPAD_UP) && r4)
+ {
+ r2 = r4;
+ while (r2 != 0)
+ {
+ r2 = sub_8091818(1, r2, 0, gPokedexView->pokemonListCount - 1);
+
+ if (gPokedexView->unk0[r2].seen)
+ {
+ r4 = r2;
+ break;
+ }
+ }
+
+ if (gPokedexView->selectedPokemon == r4)
+ return 0;
+ else
+ {
+ gPokedexView->selectedPokemon = r4;
+ gPokedexView->unk62C -= 16;
+ return 1;
+ }
+ }
+ else if ((gMain.newKeys & DPAD_DOWN) && r4 < gPokedexView->pokemonListCount - 1)
+ {
+ r2 = r4;
+ while (r2 < gPokedexView->pokemonListCount - 1)
+ {
+ r2 = sub_8091818(0, r2, 0, gPokedexView->pokemonListCount - 1);
+
+ if (gPokedexView->unk0[r2].seen)
+ {
+ r4 = r2;
+ break;
+ }
+ }
+
+ if (gPokedexView->selectedPokemon == r4)
+ return 0;
+ else
+ {
+ gPokedexView->selectedPokemon = r4;
+ gPokedexView->unk62C += 16;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static u8 sub_808E82C(void)
+{
+ u16 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gPokedexView->unk61E[i] != 0xFFFF)
+ {
+ DestroySprite(&gSprites[gPokedexView->unk61E[i]]);
+ gPokedexView->unk61E[i] |= 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+static u16 sub_808E888(u16 a1)
+{
+ if (a1 >= NATIONAL_DEX_COUNT || gPokedexView->unk0[a1].dexNum == 0xFFFF)
+ return 0xFFFF;
+ else if (gPokedexView->unk0[a1].seen)
+ return gPokedexView->unk0[a1].dexNum;
+ else
+ return 0;
+}
+
+static u32 sub_808E8C8(u16 a, s16 b, s16 c)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gPokedexView->unk61E[i] == 0xFFFF)
+ {
+ u8 spriteId = sub_80918EC(a, b, c, i);
+
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.priority = 3;
+ gSprites[spriteId].data0 = 0;
+ gSprites[spriteId].data1 = i;
+ gSprites[spriteId].data2 = NationalPokedexNumToSpecies(a);
+ gPokedexView->unk61E[i] = spriteId;
+ return spriteId;
+ }
+ }
+ return 0xFFFF;
+}
+
+static void sub_808E978(u8 a)
+{
+ u8 spriteId;
+ u16 r5;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A053C, 184, 4, 0);
+ gSprites[spriteId].data1 = 0;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A053C, 184, 156, 0);
+ gSprites[spriteId].data1 = 1;
+ gSprites[spriteId].vFlip = TRUE;
+
+ CreateSprite(&gSpriteTemplate_83A0524, 234, 20, 0);
+ CreateSprite(&gSpriteTemplate_83A0554, 16, 138, 0);
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A0554, 48, 138, 0);
+ StartSpriteAnim(&gSprites[spriteId], 3);
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A0554, 16, 158, 0);
+ StartSpriteAnim(&gSprites[spriteId], 2);
+ gSprites[spriteId].data2 = 0x80;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A0554, 48, 158, 0);
+ StartSpriteAnim(&gSprites[spriteId], 1);
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A056C, 0, 80, 2);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 30;
+ gSprites[spriteId].data0 = 0x1E;
+ gSprites[spriteId].data1 = 0;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A056C, 0, 80, 2);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 31;
+ gSprites[spriteId].data0 = 0x1F;
+ gSprites[spriteId].data1 = 0x80;
+
+ if (a == 0)
+ {
+ u32 _a;
+
+ CreateSprite(&gSpriteTemplate_83A0584, 32, 40, 1);
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A0584, 32, 72, 1);
+ StartSpriteAnim(&gSprites[spriteId], 1);
+ _a = 0;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 28, 48, 1);
+ r5 = gPokedexView->unk61A / 100;
+ StartSpriteAnim(&gSprites[spriteId], r5);
+ if (r5 != 0)
+ _a = 1;
+ else
+ gSprites[spriteId].invisible = TRUE;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 34, 48, 1);
+ r5 = (gPokedexView->unk61A % 100) / 10;
+ if (r5 != 0 || _a != 0)
+ StartSpriteAnim(&gSprites[spriteId], r5);
+ else
+ gSprites[spriteId].invisible = TRUE;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 40, 48, 1);
+ r5 = (gPokedexView->unk61A % 100) % 10;
+ StartSpriteAnim(&gSprites[spriteId], r5);
+ _a = 0;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 28, 80, 1);
+ r5 = gPokedexView->unk61C / 100;
+ StartSpriteAnim(&gSprites[spriteId], r5);
+ if (r5 != 0)
+ _a = 1;
+ else
+ gSprites[spriteId].invisible = TRUE;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 34, 80, 1);
+ r5 = (gPokedexView->unk61C % 100) / 10;
+ if (r5 != 0 || _a != 0)
+ StartSpriteAnim(&gSprites[spriteId], r5);
+ else
+ gSprites[spriteId].invisible = TRUE;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A059C, 40, 80, 1);
+ r5 = (gPokedexView->unk61C % 100) % 10;
+ StartSpriteAnim(&gSprites[spriteId], r5);
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A05B4, 140, 96, 1);
+ gSprites[spriteId].invisible = TRUE;
+ }
+ else
+ {
+ spriteId = CreateSprite(&gSpriteTemplate_83A05B4, 140, 80, 1);
+ gSprites[spriteId].invisible = TRUE;
+ }
+}
+
+static void nullsub_58(struct Sprite *sprite)
+{
+}
+
+static void sub_808ED94(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0)
+ DestroySprite(sprite);
+}
+
+//Move Pokemon into position for description page
+static void sub_808EDB8(struct Sprite *sprite)
+{
+ sprite->oam.priority = 0;
+ sprite->oam.affineMode = 0;
+ sprite->pos2.x = 0;
+ sprite->pos2.y = 0;
+ if (sprite->pos1.x != 48 || sprite->pos1.y != 56)
+ {
+ if (sprite->pos1.x > 48)
+ sprite->pos1.x--;
+ if (sprite->pos1.x < 48)
+ sprite->pos1.x++;
+
+ if (sprite->pos1.y > 56)
+ sprite->pos1.y--;
+ if (sprite->pos1.y < 56)
+ sprite->pos1.y++;
+ }
+ else
+ {
+ sprite->callback = nullsub_58;
+ }
+}
+
+static void sub_808EE28(struct Sprite *sprite)
+{
+ u8 data1 = sprite->data1;
+
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ {
+ DestroySprite(sprite);
+ gPokedexView->unk61E[data1] = 0xFFFF;
+ }
+ else
+ {
+ u32 var;
+
+ sprite->pos2.y = gSineTable[(u8)sprite->data5] * 76 / 256;
+ var = 0x10000 / gSineTable[sprite->data5 + 0x40];
+ if (var > 0xFFFF)
+ var = 0xFFFF;
+ SetOamMatrix(sprite->data1 + 1, 0x100, 0, 0, var);
+ sprite->oam.matrixNum = data1 + 1;
+
+ if (sprite->data5 > -64 && sprite->data5 < 64)
+ {
+ sprite->invisible = FALSE;
+ sprite->data0 = 1;
+ }
+ else
+ {
+ sprite->invisible = TRUE;
+ }
+
+ if ((sprite->data5 <= -64 || sprite->data5 >= 64) && sprite->data0 != 0)
+ {
+ DestroySprite(sprite);
+ gPokedexView->unk61E[data1] = 0xFFFF;
+ }
+ }
+}
+
+static void sub_808EF38(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ DestroySprite(sprite);
+ else
+ sprite->pos2.y = gPokedexView->selectedPokemon * 120 / (gPokedexView->pokemonListCount - 1);
+}
+
+static void sub_808EF8C(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ {
+ DestroySprite(sprite);
+ }
+ else
+ {
+ u8 r0;
+
+ if (sprite->data1 != 0)
+ {
+ if (gPokedexView->selectedPokemon == gPokedexView->pokemonListCount - 1)
+ sprite->invisible = TRUE;
+ else
+ sprite->invisible = FALSE;
+ r0 = sprite->data2;
+ }
+ else
+ {
+ if (gPokedexView->selectedPokemon == 0)
+ sprite->invisible = TRUE;
+ else
+ sprite->invisible = FALSE;
+ r0 = sprite->data2 - 128;
+ }
+ sprite->pos2.y = gSineTable[r0] / 64;
+ sprite->data2 = sprite->data2 + 8;
+ if (gPokedexView->menuIsOpen == 0 && gPokedexView->menuY == 0 && sprite->invisible == 0)
+ sprite->invisible = FALSE;
+ else
+ sprite->invisible = TRUE;
+ }
+}
+
+static void sub_808F08C(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ DestroySprite(sprite);
+}
+
+static void sub_808F0B4(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ {
+ DestroySprite(sprite);
+ }
+ else
+ {
+ u8 val;
+ s16 r3;
+ s16 r0;
+
+ val = gPokedexView->unk62C + sprite->data1;
+ r3 = gSineTable[val];
+ r0 = gSineTable[val + 0x40];
+ SetOamMatrix(sprite->data0, r0, r3, -r3, r0);
+
+ val = gPokedexView->unk62C + (sprite->data1 + 0x40);
+ r3 = gSineTable[val];
+ r0 = gSineTable[val + 0x40];
+ sprite->pos2.x = r0 * 40 / 256;
+ sprite->pos2.y = r3 * 40 / 256;
+ }
+}
+
+static void sub_808F168(struct Sprite *sprite)
+{
+ if (gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ {
+ DestroySprite(sprite);
+ }
+ else
+ {
+ u16 r1 = gPokedexView->unk64A == 0 ? 80 : 96;
+
+ if (gPokedexView->menuIsOpen != 0 && gPokedexView->menuY == r1)
+ {
+ sprite->invisible = FALSE;
+ sprite->pos2.y = gPokedexView->menuCursorPos * 16;
+ sprite->pos2.x = gSineTable[(u8)sprite->data2] / 64;
+ sprite->data2 += 8;
+ }
+ else
+ {
+ sprite->invisible = TRUE;
+ }
+ }
+}
+
+static u8 sub_808F210(struct PokedexListItem *item, u8 b)
+{
+ u8 taskId;
+
+ gUnknown_0202FFBC = item;
+ taskId = CreateTask(Task_InitPageScreenMultistep, 0);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 1;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].data[4] = b;
+ return taskId;
+}
+
+static bool8 sub_808F250(u8 taskId)
+{
+ if (gTasks[taskId].data[0] == 0 && gTasks[taskId].func == Task_PageScreenProcessInput)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static u8 sub_808F284(struct PokedexListItem *item, u8 b)
+{
+ gUnknown_0202FFBC = item;
+ gTasks[b].data[0] = 1;
+ gTasks[b].data[1] = 0;
+ gTasks[b].data[2] = 0;
+ gTasks[b].data[3] = 0;
+ return b;
+}
+
+#if ENGLISH
+#define CATEGORY_LEFT (11)
+#elif GERMAN
+#define CATEGORY_LEFT (16)
+#endif
+
+static void Task_InitPageScreenMultistep(u8 taskId)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ if (!gPaletteFade.active)
+ {
+ u16 r2;
+
+ gPokedexView->unk64A = 1;
+ gPokedexView->descriptionPageNum = 0;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ r2 = 0;
+ if (gTasks[taskId].data[1] != 0)
+ r2 += 0x1000;
+ if (gTasks[taskId].data[2] != 0)
+ r2 |= 0x200;
+ sub_8091060(r2);
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_08E96BD4, (void *)(VRAM + 0x7800));
+ sub_8091738(gUnknown_0202FFBC->dexNum, 2, 0x3FC);
+ gMain.state++;
+ break;
+ case 2:
+ sub_80904FC(0xD);
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ sub_808D640();
+ gMain.state++;
+ break;
+ case 3:
+ SetUpWindowConfig(&gWindowConfig_81E7064);
+ InitMenuWindow(&gWindowConfig_81E7064);
+ gMain.state++;
+ break;
+ case 4:
+ if (gPokedexView->dexMode == DEX_MODE_HOENN)
+ sub_8091154(NationalToHoennOrder(gUnknown_0202FFBC->dexNum), 0xD, 3);
+ else
+ sub_8091154(gUnknown_0202FFBC->dexNum, 0xD, 3);
+ sub_80911C8(gUnknown_0202FFBC->dexNum, 0x10, 3);
+ MenuPrint(gDexText_UnknownPoke, CATEGORY_LEFT, 5);
+ MenuPrint(gDexText_UnknownHeight, 16, 7);
+ MenuPrint(gDexText_UnknownWeight, 16, 9);
+ if (gUnknown_0202FFBC->owned)
+ {
+ sub_8091304(gPokedexEntries[gUnknown_0202FFBC->dexNum].categoryName, CATEGORY_LEFT, 5);
+ sub_8091458(gPokedexEntries[gUnknown_0202FFBC->dexNum].height, 16, 7);
+ sub_8091564(gPokedexEntries[gUnknown_0202FFBC->dexNum].weight, 16, 9);
+ MenuPrint(gPokedexEntries[gUnknown_0202FFBC->dexNum].descriptionPage1, 2, 13);
+ sub_80917CC(14, 0x3FC);
+ }
+ else
+ {
+ MenuPrint(gUnknown_083A05F8, 2, 13);
+ LoadPalette(gPlttBufferUnfaded + 1, 0x31, 0x1E);
+ }
+ gMain.state++;
+ break;
+ case 5:
+ if (gTasks[taskId].data[1] == 0)
+ {
+ gTasks[taskId].data[4] = (u16)sub_80918EC(gUnknown_0202FFBC->dexNum, 0x30, 0x38, 0);
+ gSprites[gTasks[taskId].data[4]].oam.priority = 0;
+ }
+ gMain.state++;
+ break;
+ case 6:
+ {
+ u32 r3 = 0;
+
+ if (gTasks[taskId].data[2] != 0)
+ r3 = 0x14;
+ if (gTasks[taskId].data[1] != 0)
+ r3 |= (1 << (gSprites[gTasks[taskId].data[4]].oam.paletteNum + 16));
+ BeginNormalPaletteFade(~r3, 0, 16, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ }
+ break;
+ case 7:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(15) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG1CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON;
+ gMain.state++;
+ break;
+ case 8:
+ if (!gPaletteFade.active)
+ {
+ gMain.state++;
+ if (gTasks[taskId].data[3] == 0)
+ {
+ StopCryAndClearCrySongs();
+ PlayCry2(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum), 0, 0x7D, 0xA);
+ }
+ else
+ {
+ gMain.state++;
+ }
+ }
+ break;
+ case 9:
+ if (!IsCryPlayingOrClearCrySongs())
+ gMain.state++;
+ break;
+ case 10:
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 1;
+ gTasks[taskId].data[3] = 1;
+ gTasks[taskId].func = Task_PageScreenProcessInput;
+ gMain.state = 0;
+ break;
+ }
+}
+
+static void Task_PageScreenProcessInput(u8 taskId)
+{
+ if (gTasks[taskId].data[0] != 0)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = sub_808F888;
+ PlaySE(SE_Z_SCROLL);
+ return;
+ }
+ if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = Task_ClosePageScreen;
+ PlaySE(SE_PC_OFF);
+ return;
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ switch (gPokedexView->selectedScreen)
+ {
+ case PAGE_SCREEN:
+ sub_8090C68();
+ break;
+ case AREA_SCREEN:
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitAreaScreenMultistep;
+ PlaySE(SE_PIN);
+ break;
+ case CRY_SCREEN:
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ PlaySE(SE_PIN);
+ break;
+ case SIZE_SCREEN:
+ if (!gUnknown_0202FFBC->owned)
+ {
+ PlaySE(SE_HAZURE);
+ }
+ else
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitSizeScreenMultistep;
+ PlaySE(SE_PIN);
+ }
+ break;
+ }
+ return;
+ }
+ if (((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ && gPokedexView->selectedScreen > 0)
+ {
+ gPokedexView->selectedScreen--;
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ PlaySE(SE_Z_PAGE);
+ return;
+ }
+ if (((gMain.newKeys & DPAD_RIGHT)
+ || ((gMain.newKeys & R_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ && gPokedexView->selectedScreen < 3)
+ {
+ gPokedexView->selectedScreen++;
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ PlaySE(SE_Z_PAGE);
+ return;
+ }
+}
+
+static void sub_808F888(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+}
+
+static void Task_ClosePageScreen(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ DestroyTask(taskId);
+}
+
+static void Task_InitAreaScreenMultistep(u8 taskId)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk64A = 5;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = AREA_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ sub_8090540(0xD);
+ sub_8090644(1, 0xD);
+ sub_808D640();
+ REG_BG1CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ gMain.state++;
+ break;
+ case 2:
+ ShowPokedexAreaScreen(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum), &gPokedexView->unk64F);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_AreaScreenProcessInput;
+ break;
+ }
+}
+
+static void Task_AreaScreenProcessInput(u8 taskId)
+{
+ if (gPokedexView->unk64F != 0)
+ gTasks[taskId].func = sub_808FA00;
+}
+
+static void sub_808FA00(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (gPokedexView->unk64F)
+ {
+ case 1:
+ default:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ break;
+ }
+ }
+}
+
+static void Task_InitCryScreenMultistep(u8 taskId)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ if (!gPaletteFade.active)
+ {
+ m4aMPlayStop(&gMPlay_BGM);
+ gPokedexView->unk64A = 6;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = CRY_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_0839F8A0, (void *)(VRAM + 0x7000));
+ gMain.state++;
+ break;
+ case 2:
+ sub_8090540(0xD);
+ sub_8090644(2, 0xD);
+ sub_808D640();
+ DmaClear16(3, (void *)(VRAM + 0xF800), 0x500);
+ gMain.state++;
+ break;
+ case 3:
+ SetUpWindowConfig(&gWindowConfig_81E702C);
+ InitMenuWindow(&gWindowConfig_81E702C);
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 4:
+ MenuPrint(gDexText_CryOf, 10, 4);
+ sub_8091260(gUnknown_0202FFBC->dexNum, 10, 6, 2);
+ gMain.state++;
+ break;
+ case 5:
+ gTasks[taskId].data[4] = sub_80918EC(gUnknown_0202FFBC->dexNum, 0x30, 0x38, 0);
+ gSprites[gTasks[taskId].data[4]].oam.priority = 0;
+ gUnknown_03005E98 = 0;
+ gMain.state++;
+ break;
+ case 6:
+ {
+ struct CryRelatedStruct sp8;
+
+ sp8.unk0 = 0x4020;
+ sp8.unk2 = 0x1F;
+ sp8.paletteNo = 8;
+ sp8.yPos = 0x1E;
+ sp8.xPos = 0xC;
+ if (sub_8119E3C(&sp8, 0) != 0)
+ {
+ gMain.state++;
+ gUnknown_03005E98 = 0;
+ }
+ }
+ break;
+ case 7:
+ {
+ struct CryRelatedStruct sp10;
+
+ sp10.unk0 = 0x3000;
+ sp10.unk2 = 0xE;
+ sp10.paletteNo = 9;
+ sp10.xPos = 0x12;
+ sp10.yPos = 3;
+ if (ShowPokedexCryScreen(&sp10, 1) != 0)
+ gMain.state++;
+ }
+ break;
+ case 8:
+ BeginNormalPaletteFade(-0x15, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ break;
+ case 9:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG2CNT = BGCNT_PRIORITY(2) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(14) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG0CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(1) | BGCNT_SCREENBASE(31) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_BG1CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON;
+ gMain.state++;
+ break;
+ case 10:
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_CryScreenProcessInput;
+ break;
+ }
+}
+
+static void Task_CryScreenProcessInput(u8 taskId)
+{
+ sub_8119F88(0);
+
+ if (IsCryPlaying())
+ sub_8090040(1);
+ else
+ sub_8090040(0);
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ sub_8090040(1);
+ sub_811A050(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum));
+ return;
+ }
+ else if (!gPaletteFade.active)
+ {
+ if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 1;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_PC_OFF);
+ return;
+ }
+ if ((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 2;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_Z_PAGE);
+ return;
+ }
+ if ((gMain.newKeys & DPAD_RIGHT)
+ || ((gMain.newKeys & R_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ if (!gUnknown_0202FFBC->owned)
+ {
+ PlaySE(SE_HAZURE);
+ }
+ else
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 3;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_Z_PAGE);
+ }
+ return;
+ }
+ }
+}
+
+static void sub_808FFBC(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ DestroyCryMeterNeedleSprite();
+ switch (gPokedexView->unk64F)
+ {
+ default:
+ case 1:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitAreaScreenMultistep;
+ break;
+ case 3:
+ gTasks[taskId].func = Task_InitSizeScreenMultistep;
+ break;
+ }
+ }
+}
+
+static void sub_8090040(u8 a)
+{
+ u16 unk;
+
+ if (a != 0)
+ unk = 0x392;
+ else
+ unk = 0x2AF;
+ LoadPalette(&unk, 0x5D, 2);
+}
+
+static void Task_InitSizeScreenMultistep(u8 taskId)
+{
+ u8 spriteId;
+
+ switch (gMain.state)
+ {
+ default:
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk64A = 7;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = SIZE_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_0839F988, (void *)(VRAM + 0x7000));
+ gMain.state++;
+ break;
+ case 2:
+ sub_8090540(0xD);
+ sub_8090644(3, 0xD);
+ sub_808D640();
+ gMain.state++;
+ break;
+ case 3:
+ {
+ u8 string[40]; //I hope this is the correct size
+
+ SetUpWindowConfig(&gWindowConfig_81E702C);
+ InitMenuWindow(&gWindowConfig_81E702C);
+ string[0] = EOS;
+ StringAppend(string, gDexText_SizeComparedTo);
+ StringAppend(string, gSaveBlock2.playerName);
+ sub_8072BD8(string, 3, 15, 0xC0);
+ gMain.state++;
+ }
+ break;
+ case 4:
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 5:
+ spriteId = sub_8091A4C(gSaveBlock2.playerGender, 152, 56, 0);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 1;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].pos2.y = gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerOffset;
+ SetOamMatrix(1, gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerScale, 0, 0, gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerScale);
+ LoadPalette(gUnknown_083B4EC4, (gSprites[spriteId].oam.paletteNum + 16) * 16, sizeof(gUnknown_083B4EC4));
+ gMain.state++;
+ break;
+ case 6:
+ spriteId = sub_80918EC(gUnknown_0202FFBC->dexNum, 88, 56, 1);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 2;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].pos2.y = gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonOffset;
+ SetOamMatrix(2, gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonScale, 0, 0, gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonScale);
+ LoadPalette(gUnknown_083B4EC4, (gSprites[spriteId].oam.paletteNum + 16) * 16, sizeof(gUnknown_083B4EC4));
+ gMain.state++;
+ break;
+ case 7:
+ BeginNormalPaletteFade(-0x15, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ break;
+ case 8:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG2CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(14) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON;
+ gMain.state++;
+ break;
+ case 9:
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_SizeScreenProcessInput;
+ }
+ break;
+ }
+}
+
+static void Task_SizeScreenProcessInput(u8 taskId)
+{
+ if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gPokedexView->unk64F = 1;
+ gTasks[taskId].func = sub_8090498;
+ PlaySE(SE_PC_OFF);
+ }
+ else if ((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gPokedexView->unk64F = 2;
+ gTasks[taskId].func = sub_8090498;
+ PlaySE(SE_Z_PAGE);
+ }
+}
+
+static void sub_8090498(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (gPokedexView->unk64F)
+ {
+ default:
+ case 1:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ break;
+ }
+ }
+}
+
+static void sub_80904FC(u16 a)
+{
+ LZ77UnCompVram(gUnknown_08E96ACC, (void *)(VRAM + a * 0x800));
+ DmaClear16(3, (void *)(VRAM + a * 0x800 + 0xC0), 0x440);
+}
+
+static void sub_8090540(u16 a)
+{
+ LZ77UnCompVram(gUnknown_08E96B58, (void *)(VRAM + a * 0x800));
+ DmaClear16(3, (void *)(VRAM + a * 0x800 + 0xC0), 0x440);
+}
+
+#ifdef NONMATCHING
+static void sub_8090584(u8 a, u16 b)
+{
+ u8 i; //r1
+ u8 j; //r3
+ u32 r6;
+ register u8 r7;
+
+ for (i = 0; i < 4; i++)
+ {
+ r7 = i * 5 + 1;
+ r6 = 0x4000;
+
+ if (i == a)
+ r6 = 0x2000;
+
+ for (j = 0; j < 5; j++)
+ {
+ u32 r0 = b * 0x800 + (r7 + j) * 2;
+ u8 *ptr;
+
+ ptr = VRAM;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ ptr = VRAM + 0x40;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ }
+ }
+ r6 = 0x4000;
+ for (j = 0; j < 5; j++)
+ {
+ u32 r0 = b * 0x800 + j * 2;
+ u8 *ptr;
+
+ ptr = VRAM + 0x32;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ ptr = VRAM + 0x72;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ }
+}
+#else
+__attribute__((naked))
+static void sub_8090584(u8 a, u16 b)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ lsls r1, 16\n\
+ lsrs r1, 16\n\
+ mov r9, r1\n\
+ movs r1, 0\n\
+_0809059C:\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r7, r0, 24\n\
+ movs r6, 0x80\n\
+ lsls r6, 7\n\
+ cmp r1, r10\n\
+ bne _080905B2\n\
+ movs r6, 0x80\n\
+ lsls r6, 6\n\
+_080905B2:\n\
+ movs r3, 0\n\
+ mov r0, r9\n\
+ lsls r0, 11\n\
+ mov r12, r0\n\
+ adds r1, 0x1\n\
+ mov r8, r1\n\
+ mov r5, r12\n\
+ ldr r4, _08090634 @ =0x00000fff\n\
+_080905C2:\n\
+ adds r0, r7, r3\n\
+ lsls r0, 1\n\
+ adds r0, r5, r0\n\
+ movs r2, 0xC0\n\
+ lsls r2, 19\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090638 @ =0x06000040\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _080905C2\n\
+ mov r2, r8\n\
+ lsls r0, r2, 24\n\
+ lsrs r1, r0, 24\n\
+ cmp r1, 0x3\n\
+ bls _0809059C\n\
+ movs r6, 0x80\n\
+ lsls r6, 7\n\
+ movs r3, 0\n\
+ mov r5, r12\n\
+ ldr r4, _08090634 @ =0x00000fff\n\
+_08090600:\n\
+ lsls r0, r3, 1\n\
+ adds r0, r5, r0\n\
+ ldr r2, _0809063C @ =0x06000032\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090640 @ =0x06000072\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _08090600\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_08090634: .4byte 0x00000fff\n\
+_08090638: .4byte 0x06000040\n\
+_0809063C: .4byte 0x06000032\n\
+_08090640: .4byte 0x06000072\n\
+ .syntax divided\n");
+}
+#endif
+
+//Nope, can't get this one to match, either.
+#ifdef NONMATCHING
+static void sub_8090644(u8 a, u16 b)
+{
+ u8 i;
+ u8 j;
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 r8 = i * 5 + 1;
+ u32 r5;
+
+ if (i == a || i == 0)
+ r5 = 0x2000;
+ else if (a != 0)
+ r5 = 0x4000;
+
+ for (j = 0; j < 5; j++)
+ {
+ u16 (*vramData)[0x400];
+
+ vramData = (u16 (*)[])VRAM;
+ vramData[b][r8 + j] = vramData[b][r8 + j] & 0xFFF | r5;
+ vramData = (u16 (*)[])(VRAM + 0x40);
+ vramData[b][r8 + j] = vramData[b][r8 + j] & 0xFFF | r5;
+ }
+ }
+
+ for (j = 0; j < 5; j++)
+ {
+ u16 (*vramData)[0x400];
+
+ vramData = (u16 (*)[])(VRAM + 0x32);
+ vramData[b][j] = vramData[b][j] & 0xFFF | 0x4000;
+ vramData = (u16 (*)[])(VRAM + 0x72);
+ vramData[b][j] = vramData[b][j] & 0xFFF | 0x4000;
+ }
+}
+#else
+__attribute__((naked))
+static void sub_8090644(u8 a, u16 b)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ lsls r1, 16\n\
+ lsrs r1, 16\n\
+ mov r9, r1\n\
+ movs r1, 0\n\
+_0809065C:\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r8, r0\n\
+ cmp r1, r10\n\
+ beq _08090670\n\
+ cmp r1, 0\n\
+ bne _08090676\n\
+_08090670:\n\
+ movs r5, 0x80\n\
+ lsls r5, 6\n\
+ b _0809067A\n\
+_08090676:\n\
+ movs r5, 0x80\n\
+ lsls r5, 7\n\
+_0809067A:\n\
+ movs r3, 0\n\
+ mov r0, r9\n\
+ lsls r7, r0, 11\n\
+ adds r1, 0x1\n\
+ mov r12, r1\n\
+ adds r6, r7, 0\n\
+ ldr r4, _080906FC @ =0x00000fff\n\
+_08090688:\n\
+ mov r1, r8\n\
+ adds r0, r1, r3\n\
+ lsls r0, 1\n\
+ adds r0, r6, r0\n\
+ movs r2, 0xC0\n\
+ lsls r2, 19\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090700 @ =0x06000040\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _08090688\n\
+ mov r2, r12\n\
+ lsls r0, r2, 24\n\
+ lsrs r1, r0, 24\n\
+ cmp r1, 0x3\n\
+ bls _0809065C\n\
+ movs r5, 0x80\n\
+ lsls r5, 7\n\
+ movs r3, 0\n\
+ adds r6, r7, 0\n\
+ ldr r4, _080906FC @ =0x00000fff\n\
+_080906C8:\n\
+ lsls r0, r3, 1\n\
+ adds r0, r6, r0\n\
+ ldr r2, _08090704 @ =0x06000032\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090708 @ =0x06000072\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _080906C8\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080906FC: .4byte 0x00000fff\n\
+_08090700: .4byte 0x06000040\n\
+_08090704: .4byte 0x06000032\n\
+_08090708: .4byte 0x06000072\n\
+ .syntax divided\n");
+}
+#endif
+
+u8 sub_809070C(u16 dexNum, u32 b, u32 c)
+{
+ u8 taskId = CreateTask(sub_8090750, 0);
+
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = dexNum;
+ gTasks[taskId].data[12] = b;
+ gTasks[taskId].data[13] = b >> 16;
+ gTasks[taskId].data[14] = c;
+ gTasks[taskId].data[15] = c >> 16;
+ return taskId;
+}
+
+static void sub_8090750(u8 taskId)
+{
+ u8 spriteId;
+ u16 dexNum = gTasks[taskId].data[1];
+ u16 i;
+
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ default:
+ if (!gPaletteFade.active)
+ {
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x100);
+ gTasks[taskId].data[0] = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)(VRAM + 0x4000));
+ LZ77UnCompVram(gUnknown_08E96BD4, (void *)(VRAM + 0x7800));
+ for (i = 0; i < 0x280; i++)
+ {
+#ifndef NONMATCHING
+ asm("");
+#endif
+ *(u16 *)(VRAM + 0x7800 + 2 * i) += 0x2000;
+ }
+ sub_8091738(gTasks[taskId].data[1], 2, 0x3FC);
+ ResetPaletteFade();
+ LoadPalette(gPokedexMenu_Pal + 1, 0x21, 0x9E);
+ gTasks[taskId].data[0]++;
+ break;
+ case 2:
+ SetUpWindowConfig(&gWindowConfig_81E7064);
+ InitMenuWindow(&gWindowConfig_81E7064);
+ DmaClear16(3, (void *)(VRAM + 0xC000), 0x200);
+ gTasks[taskId].data[0]++;
+ break;
+ case 3:
+ sub_8072BD8(gDexText_RegisterComplete, 2, 0, 0xD0);
+ if (!IsNationalPokedexEnabled())
+ sub_8091154(NationalToHoennOrder(dexNum), 13, 3);
+ else
+ sub_8091154(dexNum, 13, 3);
+ sub_80911C8(dexNum, 16, 3);
+ MenuPrint(gDexText_UnknownPoke, CATEGORY_LEFT, 5);
+ MenuPrint(gDexText_UnknownHeight, 16, 7);
+ MenuPrint(gDexText_UnknownWeight, 16, 9);
+ sub_8091304(gPokedexEntries[dexNum].categoryName, CATEGORY_LEFT, 5);
+ sub_8091458(gPokedexEntries[dexNum].height, 16, 7);
+ sub_8091564(gPokedexEntries[dexNum].weight, 16, 9);
+ MenuPrint(gPokedexEntries[dexNum].descriptionPage1, 2, 13);
+ sub_80917CC(14, 0x3FC);
+ gTasks[taskId].data[0]++;
+ break;
+ case 4:
+ spriteId = sub_80918EC(dexNum, 0x30, 0x38, 0);
+ gSprites[spriteId].oam.priority = 0;
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gTasks[taskId].data[3] = spriteId;
+ gTasks[taskId].data[0]++;
+ break;
+ case 5:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(1) | BGCNT_SCREENBASE(15) | BGCNT_16COLOR | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON;
+ gTasks[taskId].data[0]++;
+ break;
+ case 6:
+ if (!gPaletteFade.active)
+ {
+ PlayCry1(NationalPokedexNumToSpecies(dexNum), 0);
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[4] = 0;
+ gTasks[taskId].func = sub_8090A3C;
+ }
+ break;
+ }
+}
+
+static void sub_8090A3C(u8 taskId)
+{
+ if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(0x0000FFFC, 0, 0, 16, 0);
+ gSprites[gTasks[taskId].data[3]].callback = sub_8090C28;
+ gTasks[taskId].func = sub_8090B8C;
+ return;
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ if (gTasks[taskId].data[4] == 0)
+ {
+ u16 r4 = gTasks[taskId].data[1];
+
+ MenuZeroFillWindowRect(2, 13, 27, 19);
+ MenuPrint(gPokedexEntries[r4].descriptionPage2, 2, 13);
+ (*(u16 *)(VRAM + 0x7ACA))++;
+ (*(u16 *)(VRAM + 0x7B0A))++;
+ gTasks[taskId].data[4] = 1;
+ PlaySE(SE_PIN);
+ }
+ else
+ {
+ BeginNormalPaletteFade(0x0000FFFC, 0, 0, 16, 0);
+ gSprites[gTasks[taskId].data[3]].callback = sub_8090C28;
+ gTasks[taskId].func = sub_8090B8C;
+ return;
+ }
+ }
+ gTasks[taskId].data[2]++;
+ if (gTasks[taskId].data[2] & 0x10)
+ LoadPalette(gPokedexMenu_Pal + 1, 0x51, 14);
+ else
+ LoadPalette(gPokedexMenu2_Pal + 1, 0x51, 14);
+}
+
+static void sub_8090B8C(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ u16 species;
+ u32 otId;
+ u32 personality;
+ u8 paletteNum;
+ const u8 *lzPaletteData;
+
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON;
+ CpuCopy16(gUnknown_08D00524, (void *)(VRAM + 0xC000), 0x1000);
+ sub_800D74C();
+ species = NationalPokedexNumToSpecies(gTasks[taskId].data[1]);
+ otId = ((u16)gTasks[taskId].data[13] << 16) | (u16)gTasks[taskId].data[12];
+ personality = ((u16)gTasks[taskId].data[15] << 16) | (u16)gTasks[taskId].data[14];
+ paletteNum = gSprites[gTasks[taskId].data[3]].oam.paletteNum;
+ lzPaletteData = GetMonSpritePalFromOtIdPersonality(species, otId, personality);
+ LoadCompressedPalette(lzPaletteData, 0x100 | paletteNum * 16, 32);
+ DestroyTask(taskId);
+ }
+}
+
+static void sub_8090C28(struct Sprite *sprite)
+{
+ if (sprite->pos1.x < 0x78)
+ sprite->pos1.x += 2;
+ if (sprite->pos1.x > 0x78)
+ sprite->pos1.x -= 2;
+
+ if (sprite->pos1.y < 0x50)
+ sprite->pos1.y += 1;
+ if (sprite->pos1.y > 0x50)
+ sprite->pos1.y -= 1;
+}
+
+static void sub_8090C68(void)
+{
+ if (gUnknown_0202FFBC->owned)
+ {
+ if (gPokedexView->descriptionPageNum == 0)
+ {
+ MenuZeroFillWindowRect(2, 13, 27, 19);
+ MenuPrint(gPokedexEntries[gUnknown_0202FFBC->dexNum].descriptionPage2, 2, 13);
+ gPokedexView->descriptionPageNum = 1;
+ (*(u16 *)(VRAM + 0x7ACA))++;
+ (*(u16 *)(VRAM + 0x7B0A))++;
+ PlaySE(SE_PIN);
+ }
+ else
+ {
+ MenuZeroFillWindowRect(2, 13, 27, 19);
+ MenuPrint(gPokedexEntries[gUnknown_0202FFBC->dexNum].descriptionPage1, 2, 13);
+ gPokedexView->descriptionPageNum = 0;
+ (*(u16 *)(VRAM + 0x7ACA))--;
+ (*(u16 *)(VRAM + 0x7B0A))--;
+ PlaySE(SE_PIN);
+ }
+ }
+}
+
+const u8 *GetPokemonCategory(u16 dexNum)
+{
+ 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 (gSaveBlock2.pokedex.seen[index] & mask)
+ {
+ if ((gSaveBlock2.pokedex.seen[index] & mask) == (gSaveBlock1.dexSeen2[index] & mask)
+ && (gSaveBlock2.pokedex.seen[index] & mask) == (gSaveBlock1.dexSeen3[index] & mask))
+ retVal = 1;
+ else
+ {
+ gSaveBlock2.pokedex.seen[index] &= ~mask;
+ gSaveBlock1.dexSeen2[index] &= ~mask;
+ gSaveBlock1.dexSeen3[index] &= ~mask;
+ retVal = 0;
+ }
+ }
+ break;
+ case FLAG_GET_CAUGHT:
+ if (gSaveBlock2.pokedex.owned[index] & mask)
+ {
+ if ((gSaveBlock2.pokedex.owned[index] & mask) == (gSaveBlock2.pokedex.seen[index] & mask)
+ && (gSaveBlock2.pokedex.owned[index] & mask) == (gSaveBlock1.dexSeen2[index] & mask)
+ && (gSaveBlock2.pokedex.owned[index] & mask) == (gSaveBlock1.dexSeen3[index] & mask))
+ retVal = 1;
+ else
+ {
+ gSaveBlock2.pokedex.owned[index] &= ~mask;
+ gSaveBlock2.pokedex.seen[index] &= ~mask;
+ gSaveBlock1.dexSeen2[index] &= ~mask;
+ gSaveBlock1.dexSeen3[index] &= ~mask;
+ retVal = 0;
+ }
+ }
+ break;
+ case FLAG_SET_SEEN:
+ gSaveBlock2.pokedex.seen[index] |= mask;
+ gSaveBlock1.dexSeen2[index] |= mask;
+ gSaveBlock1.dexSeen3[index] |= mask;
+ break;
+ case FLAG_SET_CAUGHT:
+ gSaveBlock2.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 < 202; 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;
+}
+
+bool8 sub_8090FC0(void)
+{
+ u16 i;
+
+ for (i = 0; i < 200; i++)
+ {
+ if (!GetSetPokedexFlag(HoennToNationalOrder(i + 1), FLAG_GET_CAUGHT))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+u16 sub_8090FF4(void)
+{
+ u16 i;
+
+ for (i = 0; i < 150; i++)
+ {
+ if (GetSetPokedexFlag(i + 1, 1) == 0)
+ return 0;
+ }
+ for (i = 152; i < 250; i++)
+ {
+ if (GetSetPokedexFlag(i + 1, 1) == 0)
+ return 0;
+ }
+ for (i = 252; i < 384; i++)
+ {
+ if (GetSetPokedexFlag(i + 1, 1) == 0)
+ return 0;
+ }
+ return 1;
+}
+
+static void sub_8091060(u16 a)
+{
+ if (!(a & 0x100))
+ {
+ REG_DISPCNT &= 0xFEFF;
+ REG_BG0CNT = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+ }
+ if (!(a & 0x200))
+ {
+ REG_DISPCNT &= 0xFDFF;
+ REG_BG1CNT = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ }
+ if (!(a & 0x400))
+ {
+ REG_DISPCNT &= 0xFBFF;
+ REG_BG2CNT = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ }
+ if (!(a & 0x800))
+ {
+ REG_DISPCNT &= 0xF7FF;
+ REG_BG3CNT = 0;
+ REG_BG3HOFS = 0;
+ REG_BG3VOFS = 0;
+ }
+ if (!(a & 0x1000))
+ {
+ REG_DISPCNT &= 0xEFFF;
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 8;
+ }
+}
+
+static void sub_8091154(u16 order, u8 b, u8 c)
+{
+ u8 str[4];
+
+ str[0] = CHAR_0 + order / 100;
+ str[1] = CHAR_0 + (order % 100) / 10;
+ str[2] = CHAR_0 + (order % 100) % 10;
+ str[3] = EOS;
+ MenuPrint(str, b, c);
+}
+
+static u8 sub_80911C8(u16 num, u8 b, u8 c)
+{
+ u8 str[11];
+ u8 i;
+
+ for (i = 0; i < 11; i++)
+ str[i] = EOS;
+ num = NationalPokedexNumToSpecies(num);
+ switch (num)
+ {
+ default:
+ for (i = 0; gSpeciesNames[num][i] != EOS && i < 10; i++)
+ str[i] = gSpeciesNames[num][i];
+ break;
+ case 0:
+ for (i = 0; i < 10; i++)
+ str[i] = 0xAE;
+ break;
+ }
+ MenuPrint(str, b, c);
+ return i;
+}
+
+static u8 sub_8091260(u16 num, u8 b, u8 c, u8 d)
+{
+ u8 str[40];
+ u8 *end;
+ u8 i;
+
+ end = StringCopy(str, gUnknown_083B5558);
+ str[2] = d;
+ num = NationalPokedexNumToSpecies(num);
+ switch (num)
+ {
+ default:
+ for (i = 0; gSpeciesNames[num][i] != EOS && i < 10; i++)
+ end[i] = gSpeciesNames[num][i];
+ break;
+ case 0:
+ for (i = 0; i < 10; i++)
+ end[i] = 0xAE;
+ break;
+ }
+ end[i] = EOS;
+ MenuPrint(str, b, c);
+ return i;
+}
+
+static void sub_8091304(const u8 *name, u8 left, u8 top)
+{
+ u8 str[32];
+ u8 i;
+#if ENGLISH
+ u8 j;
+#endif
+
+ for (i = 0; name[i] != EOS && i < 11; i++)
+ str[i] = name[i];
+#if ENGLISH
+ for (j = 0; gDexText_UnknownPoke[j] == 0xAC || gDexText_UnknownPoke[j] == 0; j++)
+ ;
+ j--;
+ while (gDexText_UnknownPoke[j] != EOS)
+ str[i++] = gDexText_UnknownPoke[j++];
+#endif
+ str[i] = EOS;
+ sub_8072B80(str, left, top, gDexText_UnknownPoke);
+}
+
+#if ENGLISH
+void unref_sub_80913A4(u16 a, u8 left, u8 top)
+{
+ u8 str[6];
+ bool8 outputted = FALSE;
+ u8 result;
+
+ result = a / 1000;
+ if (result == 0)
+ {
+ str[0] = CHAR_SPACE;
+ outputted = FALSE;
+ }
+ else
+ {
+ str[0] = CHAR_0 + result;
+ outputted = TRUE;
+ }
+
+ result = (a % 1000) / 100;
+ if (result == 0 && !outputted)
+ {
+ str[1] = CHAR_SPACE;
+ outputted = FALSE;
+ }
+ else
+ {
+ str[1] = CHAR_0 + result;
+ outputted = TRUE;
+ }
+
+ str[2] = CHAR_0 + ((a % 1000) % 100) / 10;
+ str[3] = CHAR_PERIOD;
+ str[4] = CHAR_0 + ((a % 1000) % 100) % 10;
+ str[5] = EOS;
+ MenuPrint(str, left, top);
+}
+#elif GERMAN
+void unref_sub_80913A4(u16 arg0, u8 left, u8 top) {
+ u8 buffer[8];
+ int offset;
+ u8 result;
+
+ u8 r6 = 0;
+ offset = 0;
+
+
+ buffer[r6++] = 0xFC;
+ buffer[r6++] = 0x13;
+ r6++;
+
+ result = (arg0 / 1000);
+ if (result == 0)
+ {
+ offset = 6;
+ }
+ else
+ {
+ buffer[r6++] = result + CHAR_0;
+ }
+
+
+ result = (arg0 % 1000) / 100;
+
+ if (result == 0 && offset != 0)
+ {
+ offset += 6;
+ }
+ else
+ {
+ buffer[r6++] = result + CHAR_0;
+ }
+
+ buffer[r6++] = (((arg0 % 1000) % 100) / 10) + CHAR_0;
+ buffer[r6++] = CHAR_COMMA;
+ buffer[r6++] = (((arg0 % 1000) % 100) % 10) + CHAR_0;
+
+ buffer[r6++] = EOS;
+ buffer[2] = offset;
+ MenuPrint(buffer, left, top);
+}
+#endif
+
+#ifdef UNITS_IMPERIAL
+#define CHAR_PRIME (0xB4)
+#define CHAR_DOUBLE_PRIME (0xB2)
+static void sub_8091458(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++] = 0x13;
+ 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_PRIME;
+ buffer[i++] = (inches / 10) + CHAR_0;
+ buffer[i++] = (inches % 10) + CHAR_0;
+ buffer[i++] = CHAR_DOUBLE_PRIME;
+ buffer[i++] = EOS;
+ MenuPrint(buffer, left, top);
+}
+#else
+static void sub_8091458(u16 height, u8 left, u8 top)
+{
+ unref_sub_80913A4(height, left, top);
+}
+#endif
+
+#ifdef UNITS_IMPERIAL
+static void sub_8091564(u16 weight, u8 left, u8 top)
+{
+ u8 buffer[16];
+ u32 lbs;
+ u8 i = 0;
+ bool8 output;
+
+ lbs = (weight * 100000) / 4536;
+ if (lbs % 10 >= 5)
+ lbs += 10;
+ output = FALSE;
+
+ buffer[i] = (lbs / 100000) + CHAR_0;
+ if (buffer[i] == CHAR_0 && output == FALSE)
+ {
+ buffer[i++] = CHAR_SPACE;
+ buffer[i++] = CHAR_SPACE;
+ }
+ else
+ {
+ output = TRUE;
+ i++;
+ }
+
+ lbs = (lbs % 100000);
+ buffer[i] = (lbs / 10000) + CHAR_0;
+ if (buffer[i] == CHAR_0 && output == FALSE)
+ {
+ buffer[i++] = CHAR_SPACE;
+ buffer[i++] = CHAR_SPACE;
+ }
+ else
+ {
+ output = TRUE;
+ i++;
+ }
+
+ lbs = (lbs % 10000);
+ buffer[i] = (lbs / 1000) + CHAR_0;
+ if (buffer[i] == CHAR_0 && output == FALSE)
+ {
+ buffer[i++] = CHAR_SPACE;
+ buffer[i++] = CHAR_SPACE;
+ }
+ else
+ {
+ output = TRUE;
+ i++;
+ }
+ lbs = (lbs % 1000);
+ buffer[i++] = (lbs / 100) + CHAR_0;
+ lbs = (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;
+ MenuPrint(buffer, left, top);
+}
+#else
+static void sub_8091564(u16 arg0, u8 left, u8 top)
+{
+ unref_sub_80913A4(arg0, left, top);
+}
+#endif
+
+static void sub_8091738(u16 num, u16 b, u16 c)
+{
+ u8 arr[0x80];
+ u16 i;
+ u16 j;
+ const u8 *r12;
+ u16 r7;
+ u8 r3;
+
+ r12 = sMonFootprintTable[NationalPokedexNumToSpecies(num)];
+ for (r7 = 0, i = 0; i < 32; i++)
+ {
+ r3 = r12[i];
+ for (j = 0; j < 4; j++)
+ {
+ u32 r1 = j * 2;
+ s32 r2 = (r3 >> r1) & 1;
+
+ if (r3 & (2 << r1))
+ r2 |= 0x10;
+
+// Needed to match
+#ifndef NONMATCHING
+ asm("");asm("");asm("");asm("");asm("");
+#endif
+
+ arr[r7] = r2;
+ r7++;
+ }
+ }
+ CpuCopy16(arr, (u16 *)(VRAM + b * 0x4000 + c * 0x20), 0x80);
+}
+
+static void sub_80917CC(u16 a, u16 b)
+{
+ *(u16 *)(VRAM + a * 0x800 + 0x232) = 0xF000 + b + 0;
+ *(u16 *)(VRAM + a * 0x800 + 0x234) = 0xF000 + b + 1;
+ *(u16 *)(VRAM + a * 0x800 + 0x272) = 0xF000 + b + 2;
+ *(u16 *)(VRAM + a * 0x800 + 0x274) = 0xF000 + b + 3;
+}
+
+static u16 sub_8091818(u8 a, u16 b, u16 c, u16 d)
+{
+ switch (a)
+ {
+ case 1:
+ if (b > c)
+ b--;
+ break;
+ case 0:
+ if (b < d)
+ b++;
+ break;
+ case 3:
+ if (b > c)
+ b--;
+ else
+ b = d;
+ break;
+ case 2:
+ if (b < d)
+ b++;
+ else
+ b = c;
+ break;
+ }
+ return b;
+}
+
+static void nullsub_59(struct Sprite *sprite)
+{
+}
+
+static void sub_8091878(u16 a, u8 b)
+{
+ gUnknown_02024E8C = gUnknown_083B57A4;
+ gUnknown_02024E8C.paletteTag = a;
+ gUnknown_02024E8C.images = gUnknown_083B5794[b];
+ gUnknown_02024E8C.anims = gSpriteAnimTable_81E7C64;
+}
+
+static void sub_80918B0(u16 a, u8 b)
+{
+ gUnknown_02024E8C = gUnknown_083B57A4;
+ gUnknown_02024E8C.paletteTag = a;
+ gUnknown_02024E8C.images = gUnknown_083B5794[b];
+ gUnknown_02024E8C.anims = gUnknown_081EC2A4[0];
+}
+
+u16 sub_80918EC(u16 num, s16 x, s16 y, u16 paletteNum)
+{
+ u8 spriteId;
+
+ num = NationalPokedexNumToSpecies(num);
+ switch (num)
+ {
+ default:
+ DecompressPicFromTable_2(
+ &gMonFrontPicTable[num],
+ gMonFrontPicCoords[num].coords,
+ gMonFrontPicCoords[num].y_offset,
+ (void *)0x02000000,
+ gUnknown_083B5584[paletteNum],
+ num);
+ break;
+ case SPECIES_SPINDA:
+ LoadSpecialPokePic(
+ &gMonFrontPicTable[num],
+ gMonFrontPicCoords[num].coords,
+ gMonFrontPicCoords[num].y_offset,
+ 0x02000000,
+ gUnknown_083B5584[paletteNum],
+ num,
+ gSaveBlock2.pokedex.spindaPersonality,
+ 1);
+ break;
+ case SPECIES_UNOWN:
+ LoadSpecialPokePic(
+ &gMonFrontPicTable[num],
+ gMonFrontPicCoords[num].coords,
+ gMonFrontPicCoords[num].y_offset,
+ 0x02000000,
+ gUnknown_083B5584[paletteNum],
+ num,
+ gSaveBlock2.pokedex.unownPersonality,
+ 1);
+ break;
+ }
+ LoadCompressedPalette(gMonPaletteTable[num].data, 0x100 + paletteNum * 16, 32);
+ sub_8091878(paletteNum, paletteNum);
+ spriteId = CreateSprite(&gUnknown_02024E8C, x, y, 0);
+ gSprites[spriteId].oam.paletteNum = paletteNum;
+ return spriteId;
+}
+
+static u8 sub_8091A4C(u16 gender, s16 x, s16 y, u16 paletteNum)
+{
+ u8 spriteId;
+
+ DecompressPicFromTable_2(
+ &gTrainerFrontPicTable[gender],
+ gTrainerFrontPicCoords[gender].coords,
+ gTrainerFrontPicCoords[gender].y_offset,
+ (void *)0x02000000,
+ gUnknown_083B5584[0],
+ gender);
+ sub_80918B0(gender, 0);
+ spriteId = CreateSprite(&gUnknown_02024E8C, x, y, 0);
+ gSprites[spriteId].oam.paletteNum = paletteNum;
+ return spriteId;
+}
+
+int sub_8091AF8(u8 a, u8 b, u8 abcGroup, u8 bodyColor, u8 type1, u8 type2)
+{
+ u16 species;
+ u16 i;
+ u16 resultsCount;
+ u8 types[2];
+
+ SortPokedex(a, b);
+
+ for (i = 0, resultsCount = 0; i < NATIONAL_DEX_COUNT; i++)
+ {
+ if (gPokedexView->unk0[i].seen)
+ {
+ gPokedexView->unk0[resultsCount] = gPokedexView->unk0[i];
+ resultsCount++;
+ }
+ }
+ gPokedexView->pokemonListCount = resultsCount;
+
+ // Search by name
+ if (abcGroup != 0xFF)
+ {
+ for (i = 0, resultsCount = 0; i < gPokedexView->pokemonListCount; i++)
+ {
+ u8 r3;
+
+ species = NationalPokedexNumToSpecies(gPokedexView->unk0[i].dexNum);
+ r3 = gSpeciesNames[species][0];
+ if ((r3 >= gUnknown_083B57BC[abcGroup][0] && r3 < gUnknown_083B57BC[abcGroup][0] + gUnknown_083B57BC[abcGroup][1])
+ || (r3 >= gUnknown_083B57BC[abcGroup][2] && r3 < gUnknown_083B57BC[abcGroup][2] + gUnknown_083B57BC[abcGroup][3]))
+ {
+ gPokedexView->unk0[resultsCount] = gPokedexView->unk0[i];
+ resultsCount++;
+ }
+ }
+ gPokedexView->pokemonListCount = resultsCount;
+ }
+
+ // Search by body color
+ if (bodyColor != 0xFF)
+ {
+ for (i = 0, resultsCount = 0; i < gPokedexView->pokemonListCount; i++)
+ {
+ species = NationalPokedexNumToSpecies(gPokedexView->unk0[i].dexNum);
+
+ if (bodyColor == gBaseStats[species].bodyColor)
+ {
+ gPokedexView->unk0[resultsCount] = gPokedexView->unk0[i];
+ resultsCount++;
+ }
+ }
+ gPokedexView->pokemonListCount = resultsCount;
+ }
+
+ // Search by type
+ if (type1 != 0xFF || type2 != 0xFF)
+ {
+ if (type1 == 0xFF)
+ {
+ type1 = type2;
+ type2 = 0xFF;
+ }
+
+ if (type2 == 0xFF)
+ {
+ for (i = 0, resultsCount = 0; i < gPokedexView->pokemonListCount; i++)
+ {
+ if (gPokedexView->unk0[i].owned)
+ {
+ species = NationalPokedexNumToSpecies(gPokedexView->unk0[i].dexNum);
+
+ types[0] = gBaseStats[species].type1;
+ types[1] = gBaseStats[species].type2;
+ if (types[0] == type1 || types[1] == type1)
+ {
+ gPokedexView->unk0[resultsCount] = gPokedexView->unk0[i];
+ resultsCount++;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0, resultsCount = 0; i < gPokedexView->pokemonListCount; i++)
+ {
+ if (gPokedexView->unk0[i].owned)
+ {
+ species = NationalPokedexNumToSpecies(gPokedexView->unk0[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))
+ {
+ gPokedexView->unk0[resultsCount] = gPokedexView->unk0[i];
+ resultsCount++;
+ }
+ }
+ }
+ }
+ gPokedexView->pokemonListCount = resultsCount;
+ }
+
+ if (gPokedexView->pokemonListCount != 0)
+ {
+ for (i = gPokedexView->pokemonListCount; i < NATIONAL_DEX_COUNT; i++)
+ {
+ gPokedexView->unk0[i].dexNum = 0xFFFF;
+ gPokedexView->unk0[i].seen = FALSE;
+ gPokedexView->unk0[i].owned = FALSE;
+
+ }
+ }
+
+ return resultsCount;
+}
+
+#if ENGLISH
+#define SUB_8091E20_WIDTH (208)
+#elif GERMAN
+#define SUB_8091E20_WIDTH (216)
+#endif
+
+void sub_8091E20(const u8 *str)
+{
+ sub_8072AB0(str, 9, 120, SUB_8091E20_WIDTH, 32, 1);
+}
+
+u8 sub_8091E3C(void)
+{
+ return CreateTask(sub_8091E54, 0);
+}
+
+static void sub_8091E54(u8 taskId)
+{
+ u16 i;
+
+ switch (gMain.state)
+ {
+ default:
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk64A = 2;
+ sub_8091060(0);
+ LZ77UnCompVram(gPokedexMenuSearch_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_08E96D2C, (void *)(VRAM + 0x7800));
+ LoadPalette(gPokedexMenuSearch_Pal + 1, 1, 0x7E);
+ if (!IsNationalPokedexEnabled())
+ {
+ for (i = 0; i < 17; i++)
+ {
+ ((u16 *)(VRAM + 0x7A80))[i] = ((u16 *)(VRAM + 0x7B00))[i];
+ ((u16 *)(VRAM + 0x7AC0))[i] = ((u16 *)(VRAM + 0x7B40))[i];
+ ((u16 *)(VRAM + 0x7B00))[i] = 1;
+ ((u16 *)(VRAM + 0x7B40))[i] = 1;
+ }
+ }
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ SetUpWindowConfig(&gWindowConfig_81E7064);
+ InitMenuWindow(&gWindowConfig_81E7064);
+ LoadCompressedObjectPic(&gUnknown_083A05CC[0]);
+ LoadSpritePalettes(gUnknown_083A05DC);
+ sub_809308C(taskId);
+ for (i = 0; i < 16; i++)
+ gTasks[taskId].data[i] = 0;
+ sub_8092EB0(taskId);
+ sub_8092AB0(0);
+ sub_8092B68(taskId);
+ gMain.state++;
+ break;
+ case 2:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ gMain.state++;
+ break;
+ case 3:
+ REG_BG3CNT = 0x0F03;
+ REG_DISPCNT = 0x1C40;
+ gMain.state++;
+ break;
+ case 4:
+ if (!gPaletteFade.active)
+ {
+ gTasks[taskId].func = sub_809204C;
+ gMain.state = 0;
+ }
+ break;
+ }
+}
+
+static void sub_809204C(u8 taskId)
+{
+ sub_8092AB0(gTasks[taskId].data[0]);
+ sub_8092B68(taskId);
+ gTasks[taskId].func = sub_809207C;
+}
+
+static void sub_809207C(u8 taskId)
+{
+ if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_PC_OFF);
+ gTasks[taskId].func = sub_80927B8;
+ return;
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ PlaySE(SE_PIN);
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].func = sub_809217C;
+ break;
+ case 1:
+ PlaySE(SE_PIN);
+ gTasks[taskId].data[1] = 4;
+ gTasks[taskId].func = sub_809217C;
+ break;
+ case 2:
+ PlaySE(SE_PC_OFF);
+ gTasks[taskId].func = sub_80927B8;
+ break;
+ }
+ return;
+ }
+ if ((gMain.newKeys & DPAD_LEFT) && gTasks[taskId].data[0] > 0)
+ {
+ PlaySE(SE_Z_PAGE);
+ gTasks[taskId].data[0]--;
+ sub_8092AB0(gTasks[taskId].data[0]);
+ }
+ if ((gMain.newKeys & DPAD_RIGHT) && gTasks[taskId].data[0] < 2)
+ {
+ PlaySE(SE_Z_PAGE);
+ gTasks[taskId].data[0]++;
+ sub_8092AB0(gTasks[taskId].data[0]);
+ }
+}
+
+static void sub_809217C(u8 taskId)
+{
+ sub_8092AD4(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ sub_8092B68(taskId);
+ gTasks[taskId].func = sub_80921B0;
+}
+
+static void sub_80921B0(u8 taskId)
+{
+ const u8 (*r6)[4];
+
+ if (gTasks[taskId].data[0] != 0)
+ {
+ if (!IsNationalPokedexEnabled())
+ r6 = gUnknown_083B58A4;
+ else
+ r6 = gUnknown_083B586C;
+ }
+ else
+ {
+ if (!IsNationalPokedexEnabled())
+ r6 = gUnknown_083B5888;
+ else
+ r6 = gUnknown_083B5850;
+ }
+
+ if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_BOWA);
+ sub_8092EB0(taskId);
+ gTasks[taskId].func = sub_809204C;
+ return;
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ if (gTasks[taskId].data[1] == 6)
+ {
+ if (gTasks[taskId].data[0] != 0)
+ {
+ gUnknown_0202FFBA = 0x40;
+ gPokedexView->unk62A = 0x40;
+ gUnknown_0202FFB8 = 0;
+ gPokedexView->unk610 = 0;
+ gSaveBlock2.pokedex.unknown1 = sub_8092E10(taskId, 5);
+ if (!IsNationalPokedexEnabled())
+ gSaveBlock2.pokedex.unknown1 = 0;
+ gPokedexView->unk614 = gSaveBlock2.pokedex.unknown1;
+ gSaveBlock2.pokedex.order = sub_8092E10(taskId, 4);
+ gPokedexView->unk618 = gSaveBlock2.pokedex.order;
+ PlaySE(SE_PC_OFF);
+ gTasks[taskId].func = sub_80927B8;
+ }
+ else
+ {
+ sub_8091E20(gDexText_Searching);
+ gTasks[taskId].func = sub_80923FC;
+ PlaySE(SE_Z_SEARCH);
+ }
+ }
+ else
+ {
+ PlaySE(SE_PIN);
+ gTasks[taskId].func = sub_80925CC;
+ }
+ return;
+ }
+
+ if ((gMain.newKeys & DPAD_LEFT) && r6[gTasks[taskId].data[1]][0] != 0xFF)
+ {
+ PlaySE(SE_SELECT);
+ gTasks[taskId].data[1] = r6[gTasks[taskId].data[1]][0];
+ sub_8092AD4(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ }
+ if ((gMain.newKeys & DPAD_RIGHT) && r6[gTasks[taskId].data[1]][1] != 0xFF)
+ {
+ PlaySE(SE_SELECT);
+ gTasks[taskId].data[1] = r6[gTasks[taskId].data[1]][1];
+ sub_8092AD4(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ }
+ if ((gMain.newKeys & DPAD_UP) && r6[gTasks[taskId].data[1]][2] != 0xFF)
+ {
+ PlaySE(SE_SELECT);
+ gTasks[taskId].data[1] = r6[gTasks[taskId].data[1]][2];
+ sub_8092AD4(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ }
+ if ((gMain.newKeys & DPAD_DOWN) && r6[gTasks[taskId].data[1]][3] != 0xFF)
+ {
+ PlaySE(SE_SELECT);
+ gTasks[taskId].data[1] = r6[gTasks[taskId].data[1]][3];
+ sub_8092AD4(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ }
+}
+
+static void sub_80923FC(u8 taskId)
+{
+ u8 r10 = sub_8092E10(taskId, 5);
+ u8 r9 = sub_8092E10(taskId, 4);
+ u8 r8 = sub_8092E10(taskId, 0);
+ u8 r6 = sub_8092E10(taskId, 1);
+ u8 r4 = sub_8092E10(taskId, 2);
+ u8 r0 = sub_8092E10(taskId, 3);
+
+ sub_8091AF8(r10, r9, r8, r6, r4, r0);
+ gTasks[taskId].func = sub_80924A4;
+}
+
+static void sub_80924A4(u8 taskId)
+{
+ if (!IsSEPlaying())
+ {
+ if (gPokedexView->pokemonListCount != 0)
+ {
+ PlaySE(SE_SEIKAI);
+ sub_8091E20(gDexText_SearchComplete);
+ }
+ else
+ {
+ PlaySE(SE_HAZURE);
+ sub_8091E20(gDexText_NoMatching);
+ }
+ gTasks[taskId].func = sub_8092508;
+ }
+}
+
+static void sub_8092508(u8 taskId)
+{
+ if (gMain.newKeys & A_BUTTON)
+ {
+ if (gPokedexView->pokemonListCount != 0)
+ {
+ gPokedexView->unk64F = 1;
+ gPokedexView->dexMode = sub_8092E10(taskId, 5);
+ gPokedexView->dexOrder = sub_8092E10(taskId, 4);
+ gTasks[taskId].func = sub_80927B8;
+ PlaySE(SE_PC_OFF);
+ }
+ else
+ {
+ gTasks[taskId].func = sub_809217C;
+ PlaySE(SE_BOWA);
+ }
+ }
+}
+
+static void sub_80925B4(u16 a, int unused)
+{
+ sub_814AD7C(0x90, (a * 2 + 1) * 8);
+}
+
+static void sub_80925CC(u8 taskId)
+{
+ u8 r0;
+ u16 *p1;
+ u16 *p2;
+
+ sub_8092C8C(0);
+ r0 = gTasks[taskId].data[1];
+ p1 = &gTasks[taskId].data[gUnknown_083B5A7C[r0].unk4];
+ p2 = &gTasks[taskId].data[gUnknown_083B5A7C[r0].unk5];
+ gTasks[taskId].data[14] = *p1;
+ gTasks[taskId].data[15] = *p2;
+ sub_8092D78(taskId);
+ CreateBlendedOutlineCursor(16, 0xFFFF, 12, 0x2D9F, 11);
+ sub_80925B4(*p1, 1);
+ gTasks[taskId].func = sub_8092644;
+}
+
+static void sub_8092644(u8 taskId)
+{
+ u8 r1;
+ const struct UnknownStruct2 *r8;
+ u16 *p1;
+ u16 *p2;
+ u16 r2;
+ bool8 r3;
+
+ r1 = gTasks[taskId].data[1];
+ r8 = gUnknown_083B5A7C[r1].unk0;
+ p1 = &gTasks[taskId].data[gUnknown_083B5A7C[r1].unk4];
+ p2 = &gTasks[taskId].data[gUnknown_083B5A7C[r1].unk5];
+ r2 = gUnknown_083B5A7C[r1].unk6 - 1;
+ if (gMain.newKeys & A_BUTTON)
+ {
+ sub_814ADC8();
+ PlaySE(SE_PIN);
+ MenuZeroFillWindowRect(18, 1, 28, 12);
+ sub_8092C8C(1);
+ gTasks[taskId].func = sub_809217C;
+ return;
+ }
+ if (gMain.newKeys & B_BUTTON)
+ {
+ sub_814ADC8();
+ PlaySE(SE_BOWA);
+ MenuZeroFillWindowRect(18, 1, 28, 12);
+ sub_8092C8C(1);
+ *p1 = gTasks[taskId].data[14];
+ *p2 = gTasks[taskId].data[15];
+ gTasks[taskId].func = sub_809217C;
+ return;
+ }
+ r3 = FALSE;
+ if (gMain.newAndRepeatedKeys & DPAD_UP)
+ {
+ if (*p1 != 0)
+ {
+ sub_80925B4(*p1, 0);
+ (*p1)--;
+ sub_80925B4(*p1, 1);
+ r3 = TRUE;
+ }
+ else if (*p2 != 0)
+ {
+ (*p2)--;
+ sub_8092D78(taskId);
+ sub_80925B4(*p1, 1);
+ r3 = TRUE;
+ }
+ if (r3)
+ {
+ PlaySE(SE_SELECT);
+ sub_8091E20(r8[*p1 + *p2].text1);
+ }
+ return;
+ }
+ if (gMain.newAndRepeatedKeys & DPAD_DOWN)
+ {
+ if (*p1 < 5 && *p1 < r2)
+ {
+ sub_80925B4(*p1, 0);
+ (*p1)++;
+ sub_80925B4(*p1, 1);
+ r3 = TRUE;
+ }
+ else if (r2 > 5 && *p2 < r2 - 5)
+ {
+ (*p2)++;
+ sub_8092D78(taskId);
+ sub_80925B4(5, 1);
+ r3 = TRUE;
+ }
+ if (r3)
+ {
+ PlaySE(SE_SELECT);
+ sub_8091E20(r8[*p1 + *p2].text1);
+ }
+ return;
+ }
+}
+
+static void sub_80927B8(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ gTasks[taskId].func = sub_80927F0;
+}
+
+static void sub_80927F0(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ DestroyTask(taskId);
+}
+
+#ifdef NONMATCHING
+void sub_8092810(u8 a, u8 b, u8 c, u8 d)
+{
+ u16 i;
+
+ for (i = 0; i < d; i++)
+ {
+ ((u16 *)VRAM)[15 * 0x400 + c * 32 + i + b] &= 0xFFF;
+ ((u16 *)VRAM)[15 * 0x400 + c * 32 + i + b] |= a << 12;
+
+ ((u16 *)VRAM)[15 * 0x400 + (c + 1) * 32 + i + b] &= 0xFFF;
+ ((u16 *)VRAM)[15 * 0x400 + (c + 1) * 32 + i + b] |= a << 12;
+ }
+}
+#else
+__attribute__((naked))
+void sub_8092810(u8 a, u8 b, u8 c, u8 d)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ lsls r1, 24\n\
+ lsrs r1, 24\n\
+ mov r12, r1\n\
+ lsls r2, 24\n\
+ lsrs r1, r2, 24\n\
+ lsls r3, 24\n\
+ lsrs r5, r3, 8\n\
+ movs r3, 0\n\
+ cmp r5, 0\n\
+ beq _0809285A\n\
+ lsls r7, r1, 6\n\
+ ldr r6, _08092860 @ =0x00000fff\n\
+ lsls r4, r0, 12\n\
+_08092830:\n\
+ mov r0, r12\n\
+ adds r1, r0, r3\n\
+ lsls r1, 1\n\
+ adds r1, r7, r1\n\
+ ldr r0, _08092864 @ =0x06007800\n\
+ adds r2, r1, r0\n\
+ ldrh r0, [r2]\n\
+ ands r0, r6\n\
+ orrs r0, r4\n\
+ strh r0, [r2]\n\
+ ldr r0, _08092868 @ =0x06007840\n\
+ adds r1, r0\n\
+ ldrh r0, [r1]\n\
+ ands r0, r6\n\
+ orrs r0, r4\n\
+ strh r0, [r1]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ cmp r0, r5\n\
+ bcc _08092830\n\
+_0809285A:\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_08092860: .4byte 0x00000fff\n\
+_08092864: .4byte 0x06007800\n\
+_08092868: .4byte 0x06007840\n\
+ .syntax divided\n");
+}
+#endif
+
+static void sub_809286C(u8 a, u8 b, u8 c)
+{
+ u8 r5 = (b & 1) | ((c & 1) << 1);
+
+ switch (a)
+ {
+ case 0:
+ case 1:
+ case 2:
+ sub_8092810(r5, gUnknown_083B57E4[a].unk4, gUnknown_083B57E4[a].unk5, gUnknown_083B57E4[a].unk6);
+ break;
+ case 3:
+ case 4:
+ case 7:
+ case 8:
+ sub_8092810(r5, gUnknown_083B57FC[a - 3].unk4, gUnknown_083B57FC[a - 3].unk5, gUnknown_083B57FC[a - 3].unk6);
+ // fall through
+ case 5:
+ case 6:
+ sub_8092810(r5, gUnknown_083B57FC[a - 3].unk7, gUnknown_083B57FC[a - 3].unk8, gUnknown_083B57FC[a - 3].unk9);
+ break;
+ case 10:
+ sub_8092810(r5, gUnknown_083B57FC[2].unk4, gUnknown_083B57FC[2].unk5, gUnknown_083B57FC[2].unk6);
+ break;
+ case 9:
+ if (!IsNationalPokedexEnabled())
+ sub_8092810(r5, gUnknown_083B57FC[a - 3].unk4, gUnknown_083B57FC[a - 3].unk5 - 2, gUnknown_083B57FC[a - 3].unk6);
+ else
+ sub_8092810(r5, gUnknown_083B57FC[a - 3].unk4, gUnknown_083B57FC[a - 3].unk5, gUnknown_083B57FC[a - 3].unk6);
+ break;
+ }
+}
+
+static void sub_8092964(u8 a)
+{
+ switch (a)
+ {
+ case 0:
+ sub_809286C(0, 0, 0);
+ sub_809286C(1, 1, 0);
+ sub_809286C(2, 1, 0);
+ sub_809286C(3, 1, 0);
+ sub_809286C(4, 1, 0);
+ sub_809286C(10, 1, 0);
+ sub_809286C(5, 1, 0);
+ sub_809286C(6, 1, 0);
+ sub_809286C(7, 1, 0);
+ sub_809286C(8, 1, 0);
+ sub_809286C(9, 1, 0);
+ break;
+ case 1:
+ sub_809286C(0, 1, 0);
+ sub_809286C(1, 0, 0);
+ sub_809286C(2, 1, 0);
+ sub_809286C(3, 1, 1);
+ sub_809286C(4, 1, 1);
+ sub_809286C(10, 1, 1);
+ sub_809286C(5, 1, 1);
+ sub_809286C(6, 1, 1);
+ sub_809286C(7, 1, 0);
+ sub_809286C(8, 1, 0);
+ sub_809286C(9, 1, 0);
+ break;
+ case 2:
+ sub_809286C(0, 1, 0);
+ sub_809286C(1, 1, 0);
+ sub_809286C(2, 0, 0);
+ sub_809286C(3, 1, 1);
+ sub_809286C(4, 1, 1);
+ sub_809286C(10, 1, 1);
+ sub_809286C(5, 1, 1);
+ sub_809286C(6, 1, 1);
+ sub_809286C(7, 1, 1);
+ sub_809286C(8, 1, 1);
+ sub_809286C(9, 1, 1);
+ break;
+ }
+}
+
+static void sub_8092AB0(u8 a)
+{
+ sub_8092964(a);
+ sub_8091E20(gUnknown_083B57E4[a].text);
+}
+
+static void sub_8092AD4(u8 a, u8 b)
+{
+ sub_8092964(a);
+ switch (b)
+ {
+ case 0:
+ sub_809286C(3, 0, 0);
+ break;
+ case 1:
+ sub_809286C(4, 0, 0);
+ break;
+ case 2:
+ sub_809286C(10, 0, 0);
+ sub_809286C(5, 0, 0);
+ break;
+ case 3:
+ sub_809286C(10, 0, 0);
+ sub_809286C(6, 0, 0);
+ break;
+ case 4:
+ sub_809286C(7, 0, 0);
+ break;
+ case 5:
+ sub_809286C(8, 0, 0);
+ break;
+ case 6:
+ sub_809286C(9, 0, 0);
+ break;
+ }
+ sub_8091E20(gUnknown_083B57FC[b].text);
+}
+
+static void sub_8092B68(u8 taskId)
+{
+ u16 var;
+
+ var = gTasks[taskId].data[6] + gTasks[taskId].data[7];
+ StringCopy(gStringVar1, gUnknown_083B5910[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AB2, 45, 16, 1);
+
+ var = gTasks[taskId].data[8] + gTasks[taskId].data[9];
+ StringCopy(gStringVar1, gUnknown_083B5968[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AB2, 45, 32, 1);
+
+ var = gTasks[taskId].data[10] + gTasks[taskId].data[11];
+ StringCopy(gStringVar1, gUnknown_083B59C8[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AAC, 45, 48, 1);
+
+ var = gTasks[taskId].data[12] + gTasks[taskId].data[13];
+ StringCopy(gStringVar1, gUnknown_083B59C8[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AAC, 93, 48, 1);
+
+ var = gTasks[taskId].data[4] + gTasks[taskId].data[5];
+ StringCopy(gStringVar1, gUnknown_083B58D8[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AB2, 45, 64, 1);
+
+ if (IsNationalPokedexEnabled())
+ {
+ var = gTasks[taskId].data[2] + gTasks[taskId].data[3];
+ StringCopy(gStringVar1, gUnknown_083B58C0[var].text2);
+ MenuPrint_PixelCoords(gUnknown_083B5AB2, 45, 80, 1);
+ }
+}
+
+static void sub_8092C8C(u8 a)
+{
+ u16 i;
+ u16 j;
+
+ if (a == 0)
+ {
+ *((u16 *)(VRAM + 0x7800 + 0x22)) = 0xC0B;
+ for (i = 0x12; i < 0x1D; i++)
+ *((u16 *)(VRAM + 0x7800 + i * 2)) = 0x80D;
+ *((u16 *)(VRAM + 0x7800 + 0x3A)) = 0x80B;
+ for (j = 1; j < 13; j++)
+ {
+ *((u16 *)(VRAM + 0x7800 + 0x22 + j * 64)) = 0x40A;
+ for (i = 0x12; i < 0x1D; i++)
+ *((u16 *)(VRAM + 0x7800 + j * 64 + i * 2)) = 2;
+ *((u16 *)(VRAM + 0x7800 + 0x3A + j * 64)) = 0xA;
+ }
+ *((u16 *)(VRAM + 0x7800 + 0x362)) = 0x40B;
+ for (i = 0x12; i < 0x1D; i++)
+ *((u16 *)(VRAM + 0x7800 + 0x340 + i * 2)) = 0xD;
+ *((u16 *)(VRAM + 0x7800 + 0x37A)) = 0xB;
+ }
+ else
+ {
+ for (j = 0; j < 14; j++)
+ {
+ for (i = 0x11; i < 0x1E; i++)
+ {
+ *((u16 *)(VRAM + 0x7800 + j * 64 + i * 2)) = 0x4F;
+ }
+ }
+ }
+}
+
+static void sub_8092D78(u8 taskId)
+{
+ const struct UnknownStruct2 *r6 = gUnknown_083B5A7C[gTasks[taskId].data[1]].unk0;
+ const u16 *r8 = &gTasks[taskId].data[gUnknown_083B5A7C[gTasks[taskId].data[1]].unk4];
+ const u16 *r7 = &gTasks[taskId].data[gUnknown_083B5A7C[gTasks[taskId].data[1]].unk5];
+ u16 i;
+ u16 j;
+
+ MenuZeroFillWindowRect(18, 1, 28, 12);
+ for (i = 0, j = *r7; i < 6 && r6[j].text2 != NULL; i++, j++)
+ {
+#ifndef NONMATCHING
+ j += 0; // Useless statement needed to match
+#endif
+ MenuPrint(r6[j].text2, 18, i * 2 + 1);
+ }
+ sub_8091E20(r6[*r8 + *r7].text1);
+}
+
+static u8 sub_8092E10(u8 taskId, u8 b)
+{
+ const u16 *ptr1 = &gTasks[taskId].data[gUnknown_083B5A7C[b].unk4];
+ const u16 *ptr2 = &gTasks[taskId].data[gUnknown_083B5A7C[b].unk5];
+ u16 r2 = *ptr1 + *ptr2;
+
+ switch (b)
+ {
+ default:
+ return 0;
+ case 5:
+ return gUnknown_083B5A60[r2];
+ case 4:
+ return gUnknown_083B5A62[r2];
+ case 0:
+ if (r2 == 0)
+ return 0xFF;
+ else
+ return r2;
+ case 1:
+ if (r2 == 0)
+ return 0xFF;
+ else
+ return r2 - 1;
+ case 2:
+ case 3:
+ return gUnknown_083B5A68[r2];
+ }
+}
+
+static void sub_8092EB0(u8 taskId)
+{
+ u16 r3;
+
+ switch (gPokedexView->unk614)
+ {
+ default:
+ case 0:
+ r3 = 0;
+ break;
+ case 1:
+ r3 = 1;
+ break;
+ }
+ gTasks[taskId].data[2] = r3;
+
+ switch (gPokedexView->unk618)
+ {
+ default:
+ case 0:
+ r3 = 0;
+ break;
+ case 1:
+ r3 = 1;
+ break;
+ case 2:
+ r3 = 2;
+ break;
+ case 3:
+ r3 = 3;
+ break;
+ case 4:
+ r3 = 4;
+ break;
+ case 5:
+ r3 = 5;
+ break;
+ }
+ gTasks[taskId].data[4] = r3;
+}
+
+static bool8 sub_8092F44(u8 taskId)
+{
+ u8 val1 = gTasks[taskId].data[1];
+ const u16 *ptr = &gTasks[taskId].data[gUnknown_083B5A7C[val1].unk5];
+ u16 val2 = gUnknown_083B5A7C[val1].unk6 - 1;
+
+ if (val2 > 5 && *ptr != 0)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static bool8 sub_8092F8C(u8 taskId)
+{
+ u8 val1 = gTasks[taskId].data[1];
+ const u16 *ptr = &gTasks[taskId].data[gUnknown_083B5A7C[val1].unk5];
+ u16 val2 = gUnknown_083B5A7C[val1].unk6 - 1;
+
+ if (val2 > 5 && *ptr < val2 - 5)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static void sub_8092FD8(struct Sprite *sprite)
+{
+ if (gTasks[sprite->data0].func == sub_8092644)
+ {
+ u8 val;
+
+ if (sprite->data1 != 0)
+ {
+ if (sub_8092F8C(sprite->data0))
+ sprite->invisible = TRUE;
+ else
+ sprite->invisible = FALSE;
+ }
+ else
+ {
+ if (sub_8092F44(sprite->data0))
+ sprite->invisible = TRUE;
+ else
+ sprite->invisible = FALSE;
+ }
+ val = sprite->data2 + sprite->data1 * 128;
+ sprite->pos2.y = gSineTable[val] / 128;
+ sprite->data2 += 8;
+ }
+ else
+ {
+ sprite->invisible = TRUE;
+ }
+}
+
+static void sub_809308C(u8 taskId)
+{
+ u8 spriteId;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A053C, 184, 4, 0);
+ gSprites[spriteId].data0 = taskId;
+ gSprites[spriteId].data1 = 0;
+ gSprites[spriteId].callback = sub_8092FD8;
+
+ spriteId = CreateSprite(&gSpriteTemplate_83A053C, 184, 108, 0);
+ gSprites[spriteId].data0 = taskId;
+ gSprites[spriteId].data1 = 1;
+ gSprites[spriteId].vFlip = TRUE;
+ gSprites[spriteId].callback = sub_8092FD8;
+}
diff --git a/src/pokemon/pokedex_cry_screen.c b/src/pokemon/pokedex_cry_screen.c
new file mode 100644
index 000000000..92fd832fc
--- /dev/null
+++ b/src/pokemon/pokedex_cry_screen.c
@@ -0,0 +1,85 @@
+#include "global.h"
+#include "pokedex_cry_screen.h"
+#include "palette.h"
+#include "sprite.h"
+
+struct Unk201C800 {
+ u8 unk_0;
+ u8 unk_1;
+ u8 unk_2;
+ u8 filler_3;
+ u16 unk_4;
+};
+
+#define EWRAM_1C800 (*(struct Unk201C800 *)(unk_201C000 + 0x800))
+
+extern u8 unk_201C000[];
+
+extern u8 gUnknown_03005E98;
+
+// data/pokedex_cry_screen.o
+extern const u16 gUnknown_083FAE7C[];
+extern const u16 gUnknown_083FAF1C[];
+extern const u8 gUnknown_083FAF3C[];
+extern struct SpriteTemplate gSpriteTemplate_83FB774;
+extern const struct SpriteSheet gCryMeterNeedleSpriteSheets[];
+extern const struct SpritePalette gCryMeterNeedleSpritePalettes[];
+
+#if ENGLISH
+#define CRY_METER_MAP_WIDTH 10
+#elif GERMAN
+#define CRY_METER_MAP_WIDTH 32
+#endif
+
+u8 ShowPokedexCryScreen(struct CryRelatedStruct *cry, u8 arg1) {
+ int returnVal = FALSE;
+
+ switch (gUnknown_03005E98)
+ {
+ case 0:
+ LZ77UnCompVram(gUnknown_083FAF3C, (void *) (VRAM + cry->unk0));
+ LoadPalette(&gUnknown_083FAF1C, cry->paletteNo * 16, 0x20);
+ gUnknown_03005E98 += 1;
+ break;
+
+ case 1:
+ {
+ void *vram;
+ u8 row, col;
+ u32 r12;
+ int x, y;
+
+ vram = (void *) BG_SCREEN_ADDR(cry->unk2);
+
+ r12 = (u32) (cry->unk0 << 18) >> 23;
+
+ for (row = 0; row < 8; row++)
+ {
+ for (col = 0; col < 10; col++)
+ {
+ y = row + cry->yPos;
+ x = col + cry->xPos;
+ *(u16 *) (vram + (y * 64 + x * 2)) = (gUnknown_083FAE7C[row * CRY_METER_MAP_WIDTH + col] | (cry->paletteNo << 12)) + r12;
+ }
+ }
+
+ gUnknown_03005E98 += 1;
+ break;
+ }
+
+ case 2:
+ {
+ LoadSpriteSheets(gCryMeterNeedleSpriteSheets);
+ LoadSpritePalettes(gCryMeterNeedleSpritePalettes);
+ EWRAM_1C800.unk_4 = CreateSprite(&gSpriteTemplate_83FB774, 40 + cry->xPos * 8, 56 + cry->yPos * 8, 1);
+ EWRAM_1C800.unk_0 = 0x20;
+ EWRAM_1C800.unk_1 = 0x20;
+ EWRAM_1C800.unk_2 = 0;
+
+ returnVal = TRUE;
+ break;
+ }
+ }
+
+ return returnVal;
+}
diff --git a/src/pokemon/pokemon_1.c b/src/pokemon/pokemon_1.c
new file mode 100644
index 000000000..1d597cb17
--- /dev/null
+++ b/src/pokemon/pokemon_1.c
@@ -0,0 +1,671 @@
+#include "global.h"
+#include "data2.h"
+#include "items.h"
+#include "main.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "overworld.h"
+#include "species.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "text.h"
+
+//Extracts the upper 16 bits of a 32-bit number
+#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
+
+//Extracts the lower 16 bits of a 32-bit number
+#define LOHALF(n) ((n) & 0xFFFF)
+
+extern u8 unk_2000000[];
+extern u16 gMoveToLearn;
+
+static EWRAM_DATA u8 sLearningMoveTableID = 0;
+
+u8 gPlayerPartyCount;
+struct Pokemon gPlayerParty[6];
+u8 gEnemyPartyCount;
+struct Pokemon gEnemyParty[6];
+
+void ZeroBoxMonData(struct BoxPokemon *boxMon)
+{
+ u8 *raw = (u8 *)boxMon;
+ u32 i;
+ for (i = 0; i < sizeof(struct BoxPokemon); i++)
+ raw[i] = 0;
+}
+
+void ZeroMonData(struct Pokemon *mon)
+{
+ u32 arg;
+ ZeroBoxMonData(&mon->box);
+ arg = 0;
+ SetMonData(mon, MON_DATA_STATUS, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_LEVEL, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_HP, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_MAX_HP, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_ATK, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_DEF, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_SPD, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_SPATK, (u8 *)&arg);
+ SetMonData(mon, MON_DATA_SPDEF, (u8 *)&arg);
+ arg = 255;
+ SetMonData(mon, MON_DATA_MAIL, (u8 *)&arg);
+}
+
+void ZeroPlayerPartyMons(void)
+{
+ s32 i;
+ for (i = 0; i < 6; i++)
+ ZeroMonData(&gPlayerParty[i]);
+}
+
+void ZeroEnemyPartyMons(void)
+{
+ s32 i;
+ for (i = 0; i < 6; i++)
+ ZeroMonData(&gEnemyParty[i]);
+}
+
+void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
+{
+ u32 arg;
+
+ ZeroMonData(mon);
+ CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId);
+ SetMonData(mon, MON_DATA_LEVEL, &level);
+ arg = 255;
+ SetMonData(mon, MON_DATA_MAIL, (u8 *)&arg);
+ CalculateMonStats(mon);
+}
+
+void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
+{
+ u8 speciesName[POKEMON_NAME_LENGTH + 1];
+ u32 personality;
+ u32 value;
+ u16 checksum;
+
+ ZeroBoxMonData(boxMon);
+
+ if (hasFixedPersonality)
+ personality = fixedPersonality;
+ else
+ personality = Random32();
+
+ SetBoxMonData(boxMon, MON_DATA_PERSONALITY, (u8 *)&personality);
+
+ //Determine original trainer ID
+ if (otIdType == 2) //Pokemon cannot be shiny
+ {
+ u32 shinyValue;
+ do
+ {
+ value = Random32();
+ shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
+ } while (shinyValue < 8);
+ }
+ else if (otIdType == 1) //Pokemon has a preset OT ID
+ {
+ value = fixedOtId;
+ }
+ else //Player is the OT
+ {
+ value = gSaveBlock2.playerTrainerId[0]
+ | (gSaveBlock2.playerTrainerId[1] << 8)
+ | (gSaveBlock2.playerTrainerId[2] << 16)
+ | (gSaveBlock2.playerTrainerId[3] << 24);
+ }
+
+ SetBoxMonData(boxMon, MON_DATA_OT_ID, (u8 *)&value);
+
+ checksum = CalculateBoxMonChecksum(boxMon);
+ SetBoxMonData(boxMon, MON_DATA_CHECKSUM, (u8 *)&checksum);
+ EncryptBoxMon(boxMon);
+ GetSpeciesName(speciesName, species);
+ SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName);
+ SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage);
+ SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2.playerName);
+ SetBoxMonData(boxMon, MON_DATA_SPECIES, (u8 *)&species);
+ SetBoxMonData(boxMon, MON_DATA_EXP, (u8 *)&gExperienceTables[gBaseStats[species].growthRate][level]);
+ SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship);
+ value = sav1_map_get_name();
+ SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, (u8 *)&value);
+ SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
+ SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
+ value = 4;
+ SetBoxMonData(boxMon, MON_DATA_POKEBALL, (u8 *)&value);
+ SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2.playerGender);
+
+ if (fixedIV < 32)
+ {
+ SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPD_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV);
+ }
+ else
+ {
+ u32 iv;
+ value = Random();
+
+ iv = value & 0x1F;
+ SetBoxMonData(boxMon, MON_DATA_HP_IV, (u8 *)&iv);
+ iv = (value & 0x3E0) >> 5;
+ SetBoxMonData(boxMon, MON_DATA_ATK_IV, (u8 *)&iv);
+ iv = (value & 0x7C00) >> 10;
+ SetBoxMonData(boxMon, MON_DATA_DEF_IV, (u8 *)&iv);
+
+ value = Random();
+
+ iv = value & 0x1F;
+ SetBoxMonData(boxMon, MON_DATA_SPD_IV, (u8 *)&iv);
+ iv = (value & 0x3E0) >> 5;
+ SetBoxMonData(boxMon, MON_DATA_SPATK_IV, (u8 *)&iv);
+ iv = (value & 0x7C00) >> 10;
+ SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, (u8 *)&iv);
+ }
+
+ if (gBaseStats[species].ability2)
+ {
+ value = personality & 1;
+ SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, (u8 *)&value);
+ }
+
+ GiveBoxMonInitialMoveset(boxMon);
+}
+
+void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature)
+{
+ u32 personality;
+
+ do
+ {
+ personality = Random32();
+ }
+ while (nature != GetNatureFromPersonality(personality));
+
+ CreateMon(mon, species, level, fixedIV, 1, personality, 0, 0);
+}
+
+void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter)
+{
+ u32 personality;
+
+ if ((u8)(unownLetter - 1) < 28)
+ {
+ u16 actualLetter;
+
+ do
+ {
+ personality = Random32();
+ actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28);
+ }
+ while (nature != GetNatureFromPersonality(personality)
+ || gender != GetGenderFromSpeciesAndPersonality(species, personality)
+ || actualLetter != unownLetter - 1);
+ }
+ else
+ {
+ do
+ {
+ personality = Random32();
+ }
+ while (nature != GetNatureFromPersonality(personality)
+ || gender != GetGenderFromSpeciesAndPersonality(species, personality));
+ }
+
+ CreateMon(mon, species, level, fixedIV, 1, personality, 0, 0);
+}
+
+// This is only used to create Wally's Ralts.
+void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level)
+{
+ u32 personality;
+ u32 otId;
+
+ do
+ {
+ otId = Random32();
+ personality = Random32();
+ }
+ while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE);
+ CreateMon(mon, species, level, 32, 1, personality, 1, otId);
+}
+
+void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality)
+{
+ CreateMon(mon, species, level, 0, 1, personality, 0, 0);
+ SetMonData(mon, MON_DATA_IVS, (u8 *)&ivs);
+ CalculateMonStats(mon);
+}
+
+void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId)
+{
+ CreateMon(mon, species, level, 0, 0, 0, 1, otId);
+ SetMonData(mon, MON_DATA_HP_IV, &ivs[0]);
+ SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]);
+ SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]);
+ SetMonData(mon, MON_DATA_SPD_IV, &ivs[3]);
+ SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]);
+ SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]);
+ CalculateMonStats(mon);
+}
+
+void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread)
+{
+ s32 i;
+ s32 statCount = 0;
+ u16 evAmount;
+ u8 temp;
+
+ CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0);
+
+ temp = evSpread;
+
+ for (i = 0; i < 6; i++)
+ {
+ if (temp & 1)
+ statCount++;
+ temp >>= 1;
+ }
+
+ evAmount = 510 / statCount;
+
+ temp = 1;
+
+ for (i = 0; i < 6; i++)
+ {
+ if (evSpread & temp)
+ SetMonData(mon, MON_DATA_HP_EV + i, (u8 *)&evAmount);
+ temp <<= 1;
+ }
+
+ CalculateMonStats(mon);
+}
+
+void sub_803ADE8(struct Pokemon *mon, struct UnknownPokemonStruct *src)
+{
+ s32 i;
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+ u8 language;
+ u8 value;
+
+ CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId);
+
+ for (i = 0; i < 4; i++)
+ SetMonMoveSlot(mon, src->moves[i], i);
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, (u8 *)&src->ppBonuses);
+ SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&src->heldItem);
+
+ StringCopy(nickname, src->nickname);
+
+ if (nickname[0] == 0xFC && nickname[1] == 0x15)
+ language = LANGUAGE_JAPANESE;
+ else
+ language = GAME_LANGUAGE;
+
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ StripExtCtrlCodes(nickname);
+ SetMonData(mon, MON_DATA_NICKNAME, nickname);
+ SetMonData(mon, MON_DATA_FRIENDSHIP, (u8 *)&src->friendship);
+ SetMonData(mon, MON_DATA_HP_EV, (u8 *)&src->hpEV);
+ SetMonData(mon, MON_DATA_ATK_EV, (u8 *)&src->attackEV);
+ SetMonData(mon, MON_DATA_DEF_EV, (u8 *)&src->defenseEV);
+ SetMonData(mon, MON_DATA_SPD_EV, (u8 *)&src->speedEV);
+ SetMonData(mon, MON_DATA_SPATK_EV, (u8 *)&src->spAttackEV);
+ SetMonData(mon, MON_DATA_SPDEF_EV, (u8 *)&src->spDefenseEV);
+ value = src->altAbility;
+ SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
+ value = src->hpIV;
+ SetMonData(mon, MON_DATA_HP_IV, &value);
+ value = src->attackIV;
+ SetMonData(mon, MON_DATA_ATK_IV, &value);
+ value = src->defenseIV;
+ SetMonData(mon, MON_DATA_DEF_IV, &value);
+ value = src->speedIV;
+ SetMonData(mon, MON_DATA_SPD_IV, &value);
+ value = src->spAttackIV;
+ SetMonData(mon, MON_DATA_SPATK_IV, &value);
+ value = src->spDefenseIV;
+ SetMonData(mon, MON_DATA_SPDEF_IV, &value);
+ CalculateMonStats(mon);
+}
+
+void sub_803AF78(struct Pokemon *mon, struct UnknownPokemonStruct *dest)
+{
+ s32 i;
+ u16 heldItem;
+
+ dest->species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ heldItem = 0;
+
+ dest->heldItem = heldItem;
+
+ for (i = 0; i < 4; i++)
+ dest->moves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, NULL);
+
+ dest->level = GetMonData(mon, MON_DATA_LEVEL, NULL);
+ dest->ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ dest->otId = GetMonData(mon, MON_DATA_OT_ID, NULL);
+ dest->hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL);
+ dest->attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL);
+ dest->defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL);
+ dest->speedEV = GetMonData(mon, MON_DATA_SPD_EV, NULL);
+ dest->spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL);
+ dest->spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL);
+ dest->friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
+ dest->hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL);
+ dest->attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL);
+ dest->defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL);
+ dest->speedIV = GetMonData(mon, MON_DATA_SPD_IV, NULL);
+ dest->spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL);
+ dest->spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
+ dest->altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
+ dest->personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL);
+ GetMonData(mon, MON_DATA_NICKNAME, dest->nickname);
+}
+
+u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon)
+{
+ u16 checksum = 0;
+ union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0);
+ union PokemonSubstruct *substruct1 = GetSubstruct(boxMon, boxMon->personality, 1);
+ union PokemonSubstruct *substruct2 = GetSubstruct(boxMon, boxMon->personality, 2);
+ union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3);
+ s32 i;
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct0->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct1->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct2->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct3->raw[i];
+
+ return checksum;
+}
+
+#define CALC_STAT(base, iv, ev, statIndex, field) \
+{ \
+ u8 baseStat = gBaseStats[species].base; \
+ s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \
+ u8 nature = GetNature(mon); \
+ n = nature_stat_mod(nature, n, statIndex); \
+ SetMonData(mon, field, (u8 *)&n); \
+}
+
+void CalculateMonStats(struct Pokemon *mon)
+{
+ s32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL);
+ s32 currentHP = GetMonData(mon, MON_DATA_HP, NULL);
+ s32 hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL);
+ s32 hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL);
+ s32 attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL);
+ s32 attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL);
+ s32 defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL);
+ s32 defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL);
+ s32 speedIV = GetMonData(mon, MON_DATA_SPD_IV, NULL);
+ s32 speedEV = GetMonData(mon, MON_DATA_SPD_EV, NULL);
+ s32 spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL);
+ s32 spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL);
+ s32 spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
+ s32 spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL);
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ s32 level = GetLevelFromMonExp(mon);
+ s32 newMaxHP;
+
+ SetMonData(mon, MON_DATA_LEVEL, (u8 *)&level);
+
+ if (species == SPECIES_SHEDINJA)
+ {
+ newMaxHP = 1;
+ }
+ else
+ {
+ s32 n = 2 * gBaseStats[species].baseHP + hpIV;
+ newMaxHP = (((n + hpEV / 4) * level) / 100) + level + 10;
+ }
+
+ unk_2000000[0x160FA] = newMaxHP - oldMaxHP;
+ if (unk_2000000[0x160FA] == 0)
+ unk_2000000[0x160FA] = 1;
+
+ SetMonData(mon, MON_DATA_MAX_HP, (u8 *)&newMaxHP);
+
+ CALC_STAT(baseAttack, attackIV, attackEV, 1, MON_DATA_ATK)
+ CALC_STAT(baseDefense, defenseIV, defenseEV, 2, MON_DATA_DEF)
+ CALC_STAT(baseSpeed, speedIV, speedEV, 3, MON_DATA_SPD)
+ CALC_STAT(baseSpAttack, spAttackIV, spAttackEV, 4, MON_DATA_SPATK)
+ CALC_STAT(baseSpDefense, spDefenseIV, spDefenseEV, 5, MON_DATA_SPDEF)
+
+ if (species == SPECIES_SHEDINJA)
+ {
+ if (currentHP != 0 || oldMaxHP == 0)
+ currentHP = 1;
+ else
+ return;
+ }
+ else
+ {
+ if (currentHP == 0 && oldMaxHP == 0)
+ currentHP = newMaxHP;
+ else if (currentHP != 0)
+ currentHP += newMaxHP - oldMaxHP;
+ else
+ return;
+ }
+
+ SetMonData(mon, MON_DATA_HP, (u8 *)&currentHP);
+}
+
+void sub_803B4B4(const struct BoxPokemon *src, struct Pokemon *dest)
+{
+ u32 value = 0;
+ dest->box = *src;
+ SetMonData(dest, MON_DATA_STATUS, (u8 *)&value);
+ SetMonData(dest, MON_DATA_HP, (u8 *)&value);
+ SetMonData(dest, MON_DATA_MAX_HP, (u8 *)&value);
+ value = 255;
+ SetMonData(dest, MON_DATA_MAIL, (u8 *)&value);
+ CalculateMonStats(dest);
+}
+
+u8 GetLevelFromMonExp(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u32 exp = GetMonData(mon, MON_DATA_EXP, NULL);
+ s32 level = 1;
+
+ while (level <= 100 && gExperienceTables[gBaseStats[species].growthRate][level] <= exp)
+ level++;
+
+ return level - 1;
+}
+
+u8 GetLevelFromBoxMonExp(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ u32 exp = GetBoxMonData(boxMon, MON_DATA_EXP, NULL);
+ s32 level = 1;
+
+ while (level <= 100 && gExperienceTables[gBaseStats[species].growthRate][level] <= exp)
+ level++;
+
+ return level - 1;
+}
+
+u16 GiveMoveToMon(struct Pokemon *mon, u16 move)
+{
+ return GiveMoveToBoxMon(&mon->box, move);
+}
+
+u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move)
+{
+ s32 i;
+ for (i = 0; i < 4; i++)
+ {
+ u16 existingMove = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, NULL);
+ if (!existingMove)
+ {
+ SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, (u8 *)&move);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &gBattleMoves[move].pp);
+ return move;
+ }
+ if (existingMove == move)
+ return -2;
+ }
+ return -1;
+}
+
+u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!mon->moves[i])
+ {
+ mon->moves[i] = move;
+ mon->pp[i] = gBattleMoves[move].pp;
+ return move;
+ }
+ }
+
+ return -1;
+}
+
+void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot)
+{
+ SetMonData(mon, MON_DATA_MOVE1 + slot, (u8 *)&move);
+ SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp);
+}
+
+void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot)
+{
+ mon->moves[slot] = move;
+ mon->pp[slot] = gBattleMoves[move].pp;
+}
+
+void GiveMonInitialMoveset(struct Pokemon *mon)
+{
+ GiveBoxMonInitialMoveset(&mon->box);
+}
+
+void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ s32 level = GetLevelFromBoxMonExp(boxMon);
+ s32 i;
+
+ for (i = 0; gLevelUpLearnsets[species][i] != (u16)-1; i++)
+ {
+ u16 moveLevel;
+ u16 move;
+
+ moveLevel = (gLevelUpLearnsets[species][i] & 0xFE00);
+
+ if (moveLevel > (level << 9))
+ break;
+
+ move = (gLevelUpLearnsets[species][i] & 0x1FF);
+
+ if (GiveMoveToBoxMon(boxMon, move) == (u16)-1)
+ DeleteFirstMoveAndGiveMoveToBoxMon(boxMon, move);
+ }
+}
+
+u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove)
+{
+ u32 retVal = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, NULL);
+
+ // since you can learn more than one move per level
+ // the game needs to know whether you decided to
+ // learn it or keep the old set to avoid asking
+ // you to learn the same move over and over again
+ if (firstMove)
+ {
+ sLearningMoveTableID = 0;
+
+ while ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) != (level << 9))
+ {
+ sLearningMoveTableID++;
+ if (gLevelUpLearnsets[species][sLearningMoveTableID] == 0xFFFF)
+ return 0;
+ }
+ }
+
+ if ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) == (level << 9))
+ {
+ gMoveToLearn = (gLevelUpLearnsets[species][sLearningMoveTableID] & 0x1FF);
+ sLearningMoveTableID++;
+ retVal = GiveMoveToMon(mon, gMoveToLearn);
+ }
+
+ return retVal;
+}
+
+void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move)
+{
+ s32 i;
+ u16 moves[4];
+ u8 pp[4];
+ u8 ppBonuses;
+
+ for (i = 0; i < 3; i++)
+ {
+ moves[i] = GetMonData(mon, MON_DATA_MOVE2 + i, NULL);
+ pp[i] = GetMonData(mon, MON_DATA_PP2 + i, NULL);
+ }
+
+ ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses >>= 2;
+ moves[3] = move;
+ pp[3] = gBattleMoves[move].pp;
+
+ for (i = 0; i < 4; i++)
+ {
+ SetMonData(mon, MON_DATA_MOVE1 + i, (u8 *)&moves[i]);
+ SetMonData(mon, MON_DATA_PP1 + i, &pp[i]);
+ }
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
+
+void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move)
+{
+ s32 i;
+ u16 moves[4];
+ u8 pp[4];
+ u8 ppBonuses;
+
+ for (i = 0; i < 3; i++)
+ {
+ moves[i] = GetBoxMonData(boxMon, MON_DATA_MOVE2 + i, NULL);
+ pp[i] = GetBoxMonData(boxMon, MON_DATA_PP2 + i, NULL);
+ }
+
+ ppBonuses = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses >>= 2;
+ moves[3] = move;
+ pp[3] = gBattleMoves[move].pp;
+
+ for (i = 0; i < 4; i++)
+ {
+ SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, (u8 *)&moves[i]);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp[i]);
+ }
+
+ SetBoxMonData(boxMon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
diff --git a/src/pokemon/pokemon_2.c b/src/pokemon/pokemon_2.c
new file mode 100644
index 000000000..f02ce6170
--- /dev/null
+++ b/src/pokemon/pokemon_2.c
@@ -0,0 +1,1218 @@
+#include "global.h"
+#include "battle.h"
+#include "data2.h"
+#include "event_data.h"
+#include "main.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "rom_8077ABC.h"
+#include "species.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "strings2.h"
+#include "text.h"
+#include "util.h"
+
+extern u8 gPlayerPartyCount;
+extern u8 gEnemyPartyCount;
+
+extern u16 unk_20160BC[];
+extern struct SecretBaseRecord gSecretBaseRecord;
+extern u32 dword_2017100[];
+extern u16 gBattleTypeFlags;
+extern u8 gActiveBank;
+extern struct BattlePokemon gBattleMons[4];
+extern u16 gCurrentMove;
+extern u8 gLastUsedAbility;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gAbsentBankFlags;
+extern u8 gXXX_CritRelated;
+extern u16 gBattleWeather;
+extern struct BattleEnigmaBerry gEnigmaBerries[];
+extern u16 gBattleMovePower;
+extern u16 gTrainerBattleOpponent;
+extern struct PokemonStorage gPokemonStorage;
+
+EWRAM_DATA struct SpriteTemplate gUnknown_02024E8C = {0};
+
+extern u8 gBadEggNickname[];
+extern const struct SpriteTemplate gSpriteTemplate_8208288[];
+//array of pointers to arrays of pointers to union AnimCmd (We probably need to typedef this.)
+extern u8 gTrainerClassToPicIndex[];
+extern u8 gTrainerClassToNameIndex[];
+extern u8 gSecretBaseTrainerClasses[][5];
+extern u8 gUnknown_08208238[];
+extern u8 gUnknown_0820823C[];
+extern u8 gStatStageRatios[][2];
+extern u8 gHoldEffectToType[][2];
+
+u8 CountAliveMons(u8 a1)
+{
+ s32 i;
+ u8 retVal = 0;
+
+ switch (a1)
+ {
+ case 0:
+ for (i = 0; i < 4; i++)
+ {
+ if (i != gActiveBank && !(gAbsentBankFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ case 1:
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBankSide(i) == GetBankSide(gBankAttacker) && !(gAbsentBankFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ case 2:
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBankSide(i) == GetBankSide(gBankTarget) && !(gAbsentBankFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ }
+
+ return retVal;
+}
+
+u8 sub_803C434(u8 a1)
+{
+ u8 status = GetBankIdentity(a1) & 1;
+
+ status ^= 1;
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ return GetBankByPlayerAI(status);
+ if (CountAliveMons(0) > 1)
+ {
+ u8 val;
+
+ if ((Random() & 1) == 0)
+ val = status ^ 2;
+ else
+ val = status;
+ return GetBankByPlayerAI(val);
+ }
+ else
+ {
+ if ((gAbsentBankFlags & gBitTable[status]))
+ return GetBankByPlayerAI(status ^ 2);
+ else
+ return GetBankByPlayerAI(status);
+ }
+}
+
+u8 GetMonGender(struct Pokemon *mon)
+{
+ return GetBoxMonGender(&mon->box);
+}
+
+u8 GetBoxMonGender(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL);
+
+ switch (gBaseStats[species].genderRatio)
+ {
+ case MON_MALE:
+ case MON_FEMALE:
+ case MON_GENDERLESS:
+ return gBaseStats[species].genderRatio;
+ }
+
+ if (gBaseStats[species].genderRatio > (personality & 0xFF))
+ return MON_FEMALE;
+ else
+ return MON_MALE;
+}
+
+u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
+{
+ switch (gBaseStats[species].genderRatio)
+ {
+ case MON_MALE:
+ case MON_FEMALE:
+ case MON_GENDERLESS:
+ return gBaseStats[species].genderRatio;
+ }
+
+ if (gBaseStats[species].genderRatio > (personality & 0xFF))
+ return MON_FEMALE;
+ else
+ return MON_MALE;
+}
+
+void GetMonSpriteTemplate_803C56C(u16 species, u8 a2)
+{
+ gUnknown_02024E8C = gSpriteTemplate_8208288[a2];
+ gUnknown_02024E8C.paletteTag = species;
+ gUnknown_02024E8C.anims = (const union AnimCmd *const *)gSpriteAnimTable_81E7C64; //Why do I have to cast this?
+}
+
+void GetMonSpriteTemplate_803C5A0(u16 species, u8 a2)
+{
+ gUnknown_02024E8C = gSpriteTemplate_8208288[a2];
+ gUnknown_02024E8C.paletteTag = species;
+ if (a2 == 0 || a2 == 2)
+ gUnknown_02024E8C.anims = gUnknown_081ECACC[species];
+ else
+ gUnknown_02024E8C.anims = gUnknown_081EC2A4[species];
+}
+
+void EncryptBoxMon(struct BoxPokemon *boxMon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ boxMon->secure.raw[i] ^= boxMon->personality;
+ boxMon->secure.raw[i] ^= boxMon->otId;
+ }
+}
+
+void DecryptBoxMon(struct BoxPokemon *boxMon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ boxMon->secure.raw[i] ^= boxMon->otId;
+ boxMon->secure.raw[i] ^= boxMon->personality;
+ }
+}
+
+#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
+case n: \
+ switch (substructType) \
+ { \
+ case 0: \
+ substruct = &substructs ## n [v1]; \
+ break; \
+ case 1: \
+ substruct = &substructs ## n [v2]; \
+ break; \
+ case 2: \
+ substruct = &substructs ## n [v3]; \
+ break; \
+ case 3: \
+ substruct = &substructs ## n [v4]; \
+ break; \
+ } \
+ break;
+
+union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType)
+{
+ union PokemonSubstruct *substruct = NULL;
+
+ union PokemonSubstruct *substructs0 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs1 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs2 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs3 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs4 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs5 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs6 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs7 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs8 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs9 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs10 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs11 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs12 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs13 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs14 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs15 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs16 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs17 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs18 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs19 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs20 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs21 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs22 = boxMon->secure.substructs;
+ union PokemonSubstruct *substructs23 = boxMon->secure.substructs;
+
+ switch (personality % 24)
+ {
+ SUBSTRUCT_CASE( 0,0,1,2,3)
+ SUBSTRUCT_CASE( 1,0,1,3,2)
+ SUBSTRUCT_CASE( 2,0,2,1,3)
+ SUBSTRUCT_CASE( 3,0,3,1,2)
+ SUBSTRUCT_CASE( 4,0,2,3,1)
+ SUBSTRUCT_CASE( 5,0,3,2,1)
+ SUBSTRUCT_CASE( 6,1,0,2,3)
+ SUBSTRUCT_CASE( 7,1,0,3,2)
+ SUBSTRUCT_CASE( 8,2,0,1,3)
+ SUBSTRUCT_CASE( 9,3,0,1,2)
+ SUBSTRUCT_CASE(10,2,0,3,1)
+ SUBSTRUCT_CASE(11,3,0,2,1)
+ SUBSTRUCT_CASE(12,1,2,0,3)
+ SUBSTRUCT_CASE(13,1,3,0,2)
+ SUBSTRUCT_CASE(14,2,1,0,3)
+ SUBSTRUCT_CASE(15,3,1,0,2)
+ SUBSTRUCT_CASE(16,2,3,0,1)
+ SUBSTRUCT_CASE(17,3,2,0,1)
+ SUBSTRUCT_CASE(18,1,2,3,0)
+ SUBSTRUCT_CASE(19,1,3,2,0)
+ SUBSTRUCT_CASE(20,2,1,3,0)
+ SUBSTRUCT_CASE(21,3,1,2,0)
+ SUBSTRUCT_CASE(22,2,3,1,0)
+ SUBSTRUCT_CASE(23,3,2,1,0)
+ }
+
+ return substruct;
+}
+
+u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data)
+{
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ return mon->status;
+ case MON_DATA_LEVEL:
+ return mon->level;
+ case MON_DATA_HP:
+ return mon->hp;
+ case MON_DATA_MAX_HP:
+ return mon->maxHP;
+ case MON_DATA_ATK:
+ return mon->attack;
+ case MON_DATA_DEF:
+ return mon->defense;
+ case MON_DATA_SPD:
+ return mon->speed;
+ case MON_DATA_SPATK:
+ return mon->spAttack;
+ case MON_DATA_SPDEF:
+ return mon->spDefense;
+ case MON_DATA_MAIL:
+ return mon->mail;
+ default:
+ return GetBoxMonData(&mon->box, field, data);
+ }
+}
+
+u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
+{
+ u32 retVal = 0;
+ struct PokemonSubstruct0 *substruct0 = NULL;
+ struct PokemonSubstruct1 *substruct1 = NULL;
+ struct PokemonSubstruct2 *substruct2 = NULL;
+ struct PokemonSubstruct3 *substruct3 = NULL;
+
+ if (field > MON_DATA_10)
+ {
+ substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
+ substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
+ substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
+ substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
+
+ DecryptBoxMon(boxMon);
+
+ if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
+ {
+ boxMon->isBadEgg = 1;
+ boxMon->isEgg = 1;
+ substruct3->isEgg = 1;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ retVal = boxMon->personality;
+ break;
+ case MON_DATA_OT_ID:
+ retVal = boxMon->otId;
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ if (boxMon->isBadEgg)
+ {
+ StringCopy(data, gBadEggNickname);
+ retVal = StringLength(data);
+ }
+ else if (boxMon->isEgg)
+ {
+ StringCopy(data, gEggNickname);
+ retVal = StringLength(data);
+ }
+ else
+ {
+ retVal = 0;
+
+ while (retVal < POKEMON_NAME_LENGTH && boxMon->nickname[retVal] != EOS)
+ {
+ data[retVal] = boxMon->nickname[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ ConvertInternationalString(data, boxMon->language);
+ retVal = StringLength(data);
+ }
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ retVal = boxMon->language;
+ break;
+ case MON_DATA_SANITY_BIT1:
+ retVal = boxMon->isBadEgg;
+ break;
+ case MON_DATA_SANITY_BIT2:
+ retVal = boxMon->hasSpecies;
+ break;
+ case MON_DATA_SANITY_BIT3:
+ retVal = boxMon->isEgg;
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ retVal = 0;
+
+ while (retVal < OT_NAME_LENGTH && boxMon->otName[retVal] != EOS)
+ {
+ data[retVal] = boxMon->otName[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ retVal = boxMon->markings;
+ break;
+ case MON_DATA_CHECKSUM:
+ retVal = boxMon->checksum;
+ break;
+ case MON_DATA_10:
+ retVal = boxMon->unknown;
+ break;
+ case MON_DATA_SPECIES:
+ retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species;
+ break;
+ case MON_DATA_HELD_ITEM:
+ retVal = substruct0->heldItem;
+ break;
+ case MON_DATA_EXP:
+ retVal = substruct0->experience;
+ break;
+ case MON_DATA_PP_BONUSES:
+ retVal = substruct0->ppBonuses;
+ break;
+ case MON_DATA_FRIENDSHIP:
+ retVal = substruct0->friendship;
+ break;
+ case MON_DATA_MOVE1:
+ case MON_DATA_MOVE2:
+ case MON_DATA_MOVE3:
+ case MON_DATA_MOVE4:
+ retVal = substruct1->moves[field - MON_DATA_MOVE1];
+ break;
+ case MON_DATA_PP1:
+ case MON_DATA_PP2:
+ case MON_DATA_PP3:
+ case MON_DATA_PP4:
+ retVal = substruct1->pp[field - MON_DATA_PP1];
+ break;
+ case MON_DATA_HP_EV:
+ retVal = substruct2->hpEV;
+ break;
+ case MON_DATA_ATK_EV:
+ retVal = substruct2->attackEV;
+ break;
+ case MON_DATA_DEF_EV:
+ retVal = substruct2->defenseEV;
+ break;
+ case MON_DATA_SPD_EV:
+ retVal = substruct2->speedEV;
+ break;
+ case MON_DATA_SPATK_EV:
+ retVal = substruct2->spAttackEV;
+ break;
+ case MON_DATA_SPDEF_EV:
+ retVal = substruct2->spDefenseEV;
+ break;
+ case MON_DATA_COOL:
+ retVal = substruct2->cool;
+ break;
+ case MON_DATA_BEAUTY:
+ retVal = substruct2->beauty;
+ break;
+ case MON_DATA_CUTE:
+ retVal = substruct2->cute;
+ break;
+ case MON_DATA_SMART:
+ retVal = substruct2->smart;
+ break;
+ case MON_DATA_TOUGH:
+ retVal = substruct2->tough;
+ break;
+ case MON_DATA_SHEEN:
+ retVal = substruct2->sheen;
+ break;
+ case MON_DATA_POKERUS:
+ retVal = substruct3->pokerus;
+ break;
+ case MON_DATA_MET_LOCATION:
+ retVal = substruct3->metLocation;
+ break;
+ case MON_DATA_MET_LEVEL:
+ retVal = substruct3->metLevel;
+ break;
+ case MON_DATA_MET_GAME:
+ retVal = substruct3->metGame;
+ break;
+ case MON_DATA_POKEBALL:
+ retVal = substruct3->pokeball;
+ break;
+ case MON_DATA_OT_GENDER:
+ retVal = substruct3->otGender;
+ break;
+ case MON_DATA_HP_IV:
+ retVal = substruct3->hpIV;
+ break;
+ case MON_DATA_ATK_IV:
+ retVal = substruct3->attackIV;
+ break;
+ case MON_DATA_DEF_IV:
+ retVal = substruct3->defenseIV;
+ break;
+ case MON_DATA_SPD_IV:
+ retVal = substruct3->speedIV;
+ break;
+ case MON_DATA_SPATK_IV:
+ retVal = substruct3->spAttackIV;
+ break;
+ case MON_DATA_SPDEF_IV:
+ retVal = substruct3->spDefenseIV;
+ break;
+ case MON_DATA_IS_EGG:
+ retVal = substruct3->isEgg;
+ break;
+ case MON_DATA_ALT_ABILITY:
+ retVal = substruct3->altAbility;
+ break;
+ case MON_DATA_COOL_RIBBON:
+ retVal = substruct3->coolRibbon;
+ break;
+ case MON_DATA_BEAUTY_RIBBON:
+ retVal = substruct3->beautyRibbon;
+ break;
+ case MON_DATA_CUTE_RIBBON:
+ retVal = substruct3->cuteRibbon;
+ break;
+ case MON_DATA_SMART_RIBBON:
+ retVal = substruct3->smartRibbon;
+ break;
+ case MON_DATA_TOUGH_RIBBON:
+ retVal = substruct3->toughRibbon;
+ break;
+ case MON_DATA_CHAMPION_RIBBON:
+ retVal = substruct3->championRibbon;
+ break;
+ case MON_DATA_WINNING_RIBBON:
+ retVal = substruct3->winningRibbon;
+ break;
+ case MON_DATA_VICTORY_RIBBON:
+ retVal = substruct3->victoryRibbon;
+ break;
+ case MON_DATA_ARTIST_RIBBON:
+ retVal = substruct3->artistRibbon;
+ break;
+ case MON_DATA_EFFORT_RIBBON:
+ retVal = substruct3->effortRibbon;
+ break;
+ case MON_DATA_GIFT_RIBBON_1:
+ retVal = substruct3->giftRibbon1;
+ break;
+ case MON_DATA_GIFT_RIBBON_2:
+ retVal = substruct3->giftRibbon2;
+ break;
+ case MON_DATA_GIFT_RIBBON_3:
+ retVal = substruct3->giftRibbon3;
+ break;
+ case MON_DATA_GIFT_RIBBON_4:
+ retVal = substruct3->giftRibbon4;
+ break;
+ case MON_DATA_GIFT_RIBBON_5:
+ retVal = substruct3->giftRibbon5;
+ break;
+ case MON_DATA_GIFT_RIBBON_6:
+ retVal = substruct3->giftRibbon6;
+ break;
+ case MON_DATA_GIFT_RIBBON_7:
+ retVal = substruct3->giftRibbon7;
+ break;
+ case MON_DATA_FATEFUL_ENCOUNTER:
+ retVal = substruct3->fatefulEncounter;
+ break;
+ case MON_DATA_SPECIES2:
+ retVal = substruct0->species;
+ if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg))
+ retVal = SPECIES_EGG;
+ break;
+ case MON_DATA_IVS:
+ retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25);
+ break;
+ case MON_DATA_KNOWN_MOVES:
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ u16 *moves = (u16 *)data;
+ s32 i = 0;
+
+ while (moves[i] != 355)
+ {
+ u16 move = moves[i];
+ if (substruct1->moves[0] == move
+ || substruct1->moves[1] == move
+ || substruct1->moves[2] == move
+ || substruct1->moves[3] == move)
+ retVal |= gBitTable[i];
+ i++;
+ }
+ }
+ break;
+ case MON_DATA_RIBBON_COUNT:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal += substruct3->coolRibbon;
+ retVal += substruct3->beautyRibbon;
+ retVal += substruct3->cuteRibbon;
+ retVal += substruct3->smartRibbon;
+ retVal += substruct3->toughRibbon;
+ retVal += substruct3->championRibbon;
+ retVal += substruct3->winningRibbon;
+ retVal += substruct3->victoryRibbon;
+ retVal += substruct3->artistRibbon;
+ retVal += substruct3->effortRibbon;
+ retVal += substruct3->giftRibbon1;
+ retVal += substruct3->giftRibbon2;
+ retVal += substruct3->giftRibbon3;
+ retVal += substruct3->giftRibbon4;
+ retVal += substruct3->giftRibbon5;
+ retVal += substruct3->giftRibbon6;
+ retVal += substruct3->giftRibbon7;
+ }
+ break;
+ case MON_DATA_RIBBONS:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal = substruct3->championRibbon
+ | (substruct3->coolRibbon << 1)
+ | (substruct3->beautyRibbon << 4)
+ | (substruct3->cuteRibbon << 7)
+ | (substruct3->smartRibbon << 10)
+ | (substruct3->toughRibbon << 13)
+ | (substruct3->winningRibbon << 16)
+ | (substruct3->victoryRibbon << 17)
+ | (substruct3->artistRibbon << 18)
+ | (substruct3->effortRibbon << 19)
+ | (substruct3->giftRibbon1 << 20)
+ | (substruct3->giftRibbon2 << 21)
+ | (substruct3->giftRibbon3 << 22)
+ | (substruct3->giftRibbon4 << 23)
+ | (substruct3->giftRibbon5 << 24)
+ | (substruct3->giftRibbon6 << 25)
+ | (substruct3->giftRibbon7 << 26);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (field > MON_DATA_10)
+ EncryptBoxMon(boxMon);
+
+ return retVal;
+}
+
+#define SET8(lhs) (lhs) = *data
+#define SET16(lhs) (lhs) = data[0] + (data[1] << 8)
+#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)
+
+void SetMonData(struct Pokemon *mon, s32 field, const u8 *data)
+{
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ SET32(mon->status);
+ break;
+ case MON_DATA_LEVEL:
+ SET8(mon->level);
+ break;
+ case MON_DATA_HP:
+ SET16(mon->hp);
+ break;
+ case MON_DATA_MAX_HP:
+ SET16(mon->maxHP);
+ break;
+ case MON_DATA_ATK:
+ SET16(mon->attack);
+ break;
+ case MON_DATA_DEF:
+ SET16(mon->defense);
+ break;
+ case MON_DATA_SPD:
+ SET16(mon->speed);
+ break;
+ case MON_DATA_SPATK:
+ SET16(mon->spAttack);
+ break;
+ case MON_DATA_SPDEF:
+ SET16(mon->spDefense);
+ break;
+ case MON_DATA_MAIL:
+ SET8(mon->mail);
+ break;
+ case MON_DATA_SPECIES2:
+ break;
+ default:
+ SetBoxMonData(&mon->box, field, data);
+ break;
+ }
+}
+
+void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const u8 *data)
+{
+ struct PokemonSubstruct0 *substruct0 = NULL;
+ struct PokemonSubstruct1 *substruct1 = NULL;
+ struct PokemonSubstruct2 *substruct2 = NULL;
+ struct PokemonSubstruct3 *substruct3 = NULL;
+
+ if (field > MON_DATA_10)
+ {
+ substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
+ substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
+ substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
+ substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
+
+ DecryptBoxMon(boxMon);
+
+ if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
+ {
+ boxMon->isBadEgg = 1;
+ boxMon->isEgg = 1;
+ substruct3->isEgg = 1;
+ EncryptBoxMon(boxMon);
+ return;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ SET32(boxMon->personality);
+ break;
+ case MON_DATA_OT_ID:
+ SET32(boxMon->otId);
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ s32 i;
+ for (i = 0; i < POKEMON_NAME_LENGTH; i++)
+ boxMon->nickname[i] = data[i];
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ SET8(boxMon->language);
+ break;
+ case MON_DATA_SANITY_BIT1:
+ SET8(boxMon->isBadEgg);
+ break;
+ case MON_DATA_SANITY_BIT2:
+ SET8(boxMon->hasSpecies);
+ break;
+ case MON_DATA_SANITY_BIT3:
+ SET8(boxMon->isEgg);
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ s32 i;
+ for (i = 0; i < OT_NAME_LENGTH; i++)
+ boxMon->otName[i] = data[i];
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ SET8(boxMon->markings);
+ break;
+ case MON_DATA_CHECKSUM:
+ SET16(boxMon->checksum);
+ break;
+ case MON_DATA_10:
+ SET16(boxMon->unknown);
+ break;
+ case MON_DATA_SPECIES:
+ {
+ SET16(substruct0->species);
+ if (substruct0->species)
+ boxMon->hasSpecies = 1;
+ else
+ boxMon->hasSpecies = 0;
+ break;
+ }
+ case MON_DATA_HELD_ITEM:
+ SET16(substruct0->heldItem);
+ break;
+ case MON_DATA_EXP:
+ SET32(substruct0->experience);
+ break;
+ case MON_DATA_PP_BONUSES:
+ SET8(substruct0->ppBonuses);
+ break;
+ case MON_DATA_FRIENDSHIP:
+ SET8(substruct0->friendship);
+ break;
+ case MON_DATA_MOVE1:
+ case MON_DATA_MOVE2:
+ case MON_DATA_MOVE3:
+ case MON_DATA_MOVE4:
+ SET16(substruct1->moves[field - MON_DATA_MOVE1]);
+ break;
+ case MON_DATA_PP1:
+ case MON_DATA_PP2:
+ case MON_DATA_PP3:
+ case MON_DATA_PP4:
+ SET8(substruct1->pp[field - MON_DATA_PP1]);
+ break;
+ case MON_DATA_HP_EV:
+ SET8(substruct2->hpEV);
+ break;
+ case MON_DATA_ATK_EV:
+ SET8(substruct2->attackEV);
+ break;
+ case MON_DATA_DEF_EV:
+ SET8(substruct2->defenseEV);
+ break;
+ case MON_DATA_SPD_EV:
+ SET8(substruct2->speedEV);
+ break;
+ case MON_DATA_SPATK_EV:
+ SET8(substruct2->spAttackEV);
+ break;
+ case MON_DATA_SPDEF_EV:
+ SET8(substruct2->spDefenseEV);
+ break;
+ case MON_DATA_COOL:
+ SET8(substruct2->cool);
+ break;
+ case MON_DATA_BEAUTY:
+ SET8(substruct2->beauty);
+ break;
+ case MON_DATA_CUTE:
+ SET8(substruct2->cute);
+ break;
+ case MON_DATA_SMART:
+ SET8(substruct2->smart);
+ break;
+ case MON_DATA_TOUGH:
+ SET8(substruct2->tough);
+ break;
+ case MON_DATA_SHEEN:
+ SET8(substruct2->sheen);
+ break;
+ case MON_DATA_POKERUS:
+ SET8(substruct3->pokerus);
+ break;
+ case MON_DATA_MET_LOCATION:
+ SET8(substruct3->metLocation);
+ break;
+ case MON_DATA_MET_LEVEL:
+ {
+ u8 metLevel = *data;
+ substruct3->metLevel = metLevel;
+ break;
+ }
+ case MON_DATA_MET_GAME:
+ SET8(substruct3->metGame);
+ break;
+ case MON_DATA_POKEBALL:
+ {
+ u8 pokeball = *data;
+ substruct3->pokeball = pokeball;
+ break;
+ }
+ case MON_DATA_OT_GENDER:
+ SET8(substruct3->otGender);
+ break;
+ case MON_DATA_HP_IV:
+ SET8(substruct3->hpIV);
+ break;
+ case MON_DATA_ATK_IV:
+ SET8(substruct3->attackIV);
+ break;
+ case MON_DATA_DEF_IV:
+ SET8(substruct3->defenseIV);
+ break;
+ case MON_DATA_SPD_IV:
+ SET8(substruct3->speedIV);
+ break;
+ case MON_DATA_SPATK_IV:
+ SET8(substruct3->spAttackIV);
+ break;
+ case MON_DATA_SPDEF_IV:
+ SET8(substruct3->spDefenseIV);
+ break;
+ case MON_DATA_IS_EGG:
+ SET8(substruct3->isEgg);
+ if (substruct3->isEgg)
+ boxMon->isEgg = 1;
+ else
+ boxMon->isEgg = 0;
+ break;
+ case MON_DATA_ALT_ABILITY:
+ SET8(substruct3->altAbility);
+ break;
+ case MON_DATA_COOL_RIBBON:
+ SET8(substruct3->coolRibbon);
+ break;
+ case MON_DATA_BEAUTY_RIBBON:
+ SET8(substruct3->beautyRibbon);
+ break;
+ case MON_DATA_CUTE_RIBBON:
+ SET8(substruct3->cuteRibbon);
+ break;
+ case MON_DATA_SMART_RIBBON:
+ SET8(substruct3->smartRibbon);
+ break;
+ case MON_DATA_TOUGH_RIBBON:
+ SET8(substruct3->toughRibbon);
+ break;
+ case MON_DATA_CHAMPION_RIBBON:
+ SET8(substruct3->championRibbon);
+ break;
+ case MON_DATA_WINNING_RIBBON:
+ SET8(substruct3->winningRibbon);
+ break;
+ case MON_DATA_VICTORY_RIBBON:
+ SET8(substruct3->victoryRibbon);
+ break;
+ case MON_DATA_ARTIST_RIBBON:
+ SET8(substruct3->artistRibbon);
+ break;
+ case MON_DATA_EFFORT_RIBBON:
+ SET8(substruct3->effortRibbon);
+ break;
+ case MON_DATA_GIFT_RIBBON_1:
+ SET8(substruct3->giftRibbon1);
+ break;
+ case MON_DATA_GIFT_RIBBON_2:
+ SET8(substruct3->giftRibbon2);
+ break;
+ case MON_DATA_GIFT_RIBBON_3:
+ SET8(substruct3->giftRibbon3);
+ break;
+ case MON_DATA_GIFT_RIBBON_4:
+ SET8(substruct3->giftRibbon4);
+ break;
+ case MON_DATA_GIFT_RIBBON_5:
+ SET8(substruct3->giftRibbon5);
+ break;
+ case MON_DATA_GIFT_RIBBON_6:
+ SET8(substruct3->giftRibbon6);
+ break;
+ case MON_DATA_GIFT_RIBBON_7:
+ SET8(substruct3->giftRibbon7);
+ break;
+ case MON_DATA_FATEFUL_ENCOUNTER:
+ SET8(substruct3->fatefulEncounter);
+ break;
+ case MON_DATA_IVS:
+ {
+#ifdef BUGFIX_SETMONIVS
+ u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+#else
+ u32 ivs = *data; // Bug: Only the HP IV and the lower 3 bits of the Attack IV are read. The rest become 0.
+#endif
+ substruct3->hpIV = ivs & 0x1F;
+ substruct3->attackIV = (ivs >> 5) & 0x1F;
+ substruct3->defenseIV = (ivs >> 10) & 0x1F;
+ substruct3->speedIV = (ivs >> 15) & 0x1F;
+ substruct3->spAttackIV = (ivs >> 20) & 0x1F;
+ substruct3->spDefenseIV = (ivs >> 25) & 0x1F;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (field > MON_DATA_10)
+ {
+ boxMon->checksum = CalculateBoxMonChecksum(boxMon);
+ EncryptBoxMon(boxMon);
+ }
+}
+
+void CopyMon(void *dest, void *src, size_t size)
+{
+ memcpy(dest, src, size);
+}
+
+u8 GiveMonToPlayer(struct Pokemon *mon)
+{
+ s32 i;
+
+ SetMonData(mon, MON_DATA_OT_NAME, gSaveBlock2.playerName);
+ SetMonData(mon, MON_DATA_OT_GENDER, &gSaveBlock2.playerGender);
+ SetMonData(mon, MON_DATA_OT_ID, gSaveBlock2.playerTrainerId);
+
+ i = 0;
+
+ while (i < 6 && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
+ i++;
+
+ if (i >= 6)
+ return SendMonToPC(mon);
+
+ CopyMon(&gPlayerParty[i], mon, sizeof(*mon));
+ gPlayerPartyCount = i + 1;
+ return 0;
+}
+
+u8 SendMonToPC(struct Pokemon *mon)
+{
+ s32 i = gPokemonStorage.currentBox;
+
+ do
+ {
+ s32 j;
+ for (j = 0; j < 30; j++)
+ {
+ if (GetBoxMonData(&gPokemonStorage.boxes[i][j], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ {
+ MonRestorePP(mon);
+ CopyMon(&gPokemonStorage.boxes[i][j], &mon->box, sizeof(mon->box));
+ return 1;
+ }
+ }
+
+ i++;
+ if (i == 14)
+ i = 0;
+ } while (i != gPokemonStorage.currentBox);
+
+ return 2;
+}
+
+u8 CalculatePlayerPartyCount(void)
+{
+ gPlayerPartyCount = 0;
+
+ while (gPlayerPartyCount < 6
+ && GetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
+ {
+ gPlayerPartyCount++;
+ }
+
+ return gPlayerPartyCount;
+}
+
+u8 CalculateEnemyPartyCount(void)
+{
+ gEnemyPartyCount = 0;
+
+ while (gEnemyPartyCount < 6
+ && GetMonData(&gEnemyParty[gEnemyPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
+ {
+ gEnemyPartyCount++;
+ }
+
+ return gEnemyPartyCount;
+}
+
+u8 sub_803DAA0(void)
+{
+ s32 aliveCount = 0;
+ s32 i;
+ CalculatePlayerPartyCount();
+
+ if (gPlayerPartyCount == 1)
+ return gPlayerPartyCount;
+
+ for (i = 0; i < gPlayerPartyCount; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0
+ && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_NONE
+ && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG)
+ aliveCount++;
+ }
+
+ return (aliveCount > 1) ? 0 : 2;
+}
+
+u8 GetAbilityBySpecies(u16 species, bool8 altAbility)
+{
+ if (altAbility)
+ gLastUsedAbility = gBaseStats[species].ability2;
+ else
+ gLastUsedAbility = gBaseStats[species].ability1;
+
+ return gLastUsedAbility;
+}
+
+u8 GetMonAbility(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
+ return GetAbilityBySpecies(species, altAbility);
+}
+
+void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord)
+{
+ s32 i, j;
+
+ ZeroEnemyPartyMons();
+ memcpy(&gSecretBaseRecord, secretBaseRecord, sizeof(*secretBaseRecord));
+
+ for (i = 0; i < 6; i++)
+ {
+ if (gSecretBaseRecord.partySpecies[i])
+ {
+ CreateMon(&gEnemyParty[i],
+ gSecretBaseRecord.partySpecies[i],
+ gSecretBaseRecord.partyLevels[i],
+ 15,
+ 1,
+ gSecretBaseRecord.partyPersonality[i],
+ 2,
+ 0);
+
+ SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, (u8 *)&gSecretBaseRecord.partyHeldItems[i]);
+
+ for (j = 0; j < 6; j++)
+ SetMonData(&gEnemyParty[i], MON_DATA_HP_EV + j, &gSecretBaseRecord.partyEVs[i]);
+
+ for (j = 0; j < 4; j++)
+ {
+ SetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j, (u8 *)&gSecretBaseRecord.partyMoves[i * 4 + j]);
+ SetMonData(&gEnemyParty[i], MON_DATA_PP1 + j, &gBattleMoves[gSecretBaseRecord.partyMoves[i * 4 + j]].pp);
+ }
+ }
+ }
+
+ gBattleTypeFlags = 8;
+ gTrainerBattleOpponent = 1024;
+}
+
+u8 GetSecretBaseTrainerPicIndex(void)
+{
+ u8 trainerClass = gSecretBaseTrainerClasses[gSecretBaseRecord.gender][gSecretBaseRecord.trainerId[0] % 5];
+ return gTrainerClassToPicIndex[trainerClass];
+}
+
+u8 GetSecretBaseTrainerNameIndex(void)
+{
+ u8 trainerClass = gSecretBaseTrainerClasses[gSecretBaseRecord.gender][gSecretBaseRecord.trainerId[0] % 5];
+ return gTrainerClassToNameIndex[trainerClass];
+}
+
+u8 PlayerPartyAndPokemonStorageFull(void)
+{
+ s32 i;
+
+ for (i = 0; i < 6; i++)
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ return 0;
+
+ return PokemonStorageFull();
+}
+
+u8 PokemonStorageFull(void)
+{
+ s32 i, j;
+
+ for (i = 0; i < 14; i++)
+ for (j = 0; j < 30; j++)
+ if (GetBoxMonData(&gPokemonStorage.boxes[i][j], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ return 0;
+
+ return 1;
+}
+
+void GetSpeciesName(u8 *name, u16 species)
+{
+ s32 i;
+
+ for (i = 0; i <= POKEMON_NAME_LENGTH; i++)
+ {
+ if (species > NUM_SPECIES)
+ name[i] = gSpeciesNames[0][i];
+ else
+ name[i] = gSpeciesNames[species][i];
+
+ if (name[i] == EOS)
+ break;
+ }
+
+ name[i] = EOS;
+}
+
+u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex)
+{
+ u8 basePP = gBattleMoves[move].pp;
+ return basePP + ((basePP * 20 * ((gUnknown_08208238[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100);
+}
+
+void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex)
+{
+ u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses &= gUnknown_0820823C[moveIndex];
+ SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
+
+void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex)
+{
+ mon->ppBonuses &= gUnknown_0820823C[moveIndex];
+}
+
+void CopyPlayerPartyMonToBattleData(u8 battleIndex, u8 partyIndex)
+{
+ s32 i;
+ s8 nickname[POKEMON_NAME_LENGTH * 2];
+
+ gBattleMons[battleIndex].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
+ gBattleMons[battleIndex].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL);
+
+ for (i = 0; i < 4; i++)
+ {
+ gBattleMons[battleIndex].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL);
+ gBattleMons[battleIndex].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL);
+ }
+
+ gBattleMons[battleIndex].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL);
+ gBattleMons[battleIndex].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL);
+ gBattleMons[battleIndex].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL);
+ gBattleMons[battleIndex].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL);
+ gBattleMons[battleIndex].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL);
+ gBattleMons[battleIndex].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL);
+ gBattleMons[battleIndex].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPD_IV, NULL);
+ gBattleMons[battleIndex].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL);
+ gBattleMons[battleIndex].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL);
+ gBattleMons[battleIndex].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL);
+ gBattleMons[battleIndex].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL);
+ gBattleMons[battleIndex].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL);
+ gBattleMons[battleIndex].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL);
+ gBattleMons[battleIndex].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL);
+ gBattleMons[battleIndex].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL);
+ gBattleMons[battleIndex].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL);
+ gBattleMons[battleIndex].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPD, NULL);
+ gBattleMons[battleIndex].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL);
+ gBattleMons[battleIndex].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL);
+ gBattleMons[battleIndex].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL);
+ gBattleMons[battleIndex].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL);
+ gBattleMons[battleIndex].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL);
+ gBattleMons[battleIndex].type1 = gBaseStats[gBattleMons[battleIndex].species].type1;
+ gBattleMons[battleIndex].type2 = gBaseStats[gBattleMons[battleIndex].species].type2;
+ gBattleMons[battleIndex].ability = GetAbilityBySpecies(gBattleMons[battleIndex].species, gBattleMons[battleIndex].altAbility);
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
+ StringCopy10(gBattleMons[battleIndex].nickname, nickname);
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[battleIndex].otName);
+ *(unk_20160BC + GetBankSide(battleIndex)) = gBattleMons[battleIndex].hp;
+
+ for (i = 0; i < 8; i++)
+ gBattleMons[battleIndex].statStages[i] = 6;
+
+ gBattleMons[battleIndex].status2 = 0;
+ sub_80157C4(battleIndex);
+ sub_8032AA8(battleIndex, 0);
+}
diff --git a/src/pokemon/pokemon_3.c b/src/pokemon/pokemon_3.c
new file mode 100644
index 000000000..1eff9b83c
--- /dev/null
+++ b/src/pokemon/pokemon_3.c
@@ -0,0 +1,1380 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_message.h"
+#include "data2.h"
+#include "event_data.h"
+#include "hold_effects.h"
+#include "item.h"
+#include "items.h"
+#include "link.h"
+#include "m4a.h"
+#include "main.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "overworld.h"
+#include "rom_8077ABC.h"
+#include "rom_8094928.h"
+#include "rtc.h"
+#include "songs.h"
+#include "sound.h"
+#include "species.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "text.h"
+#include "util.h"
+
+extern u8 gPlayerPartyCount;
+extern u8 gEnemyPartyCount;
+extern struct BattlePokemon gBattleMons[4];
+extern u8 gActiveBank;
+extern struct BattleEnigmaBerry gEnigmaBerries[];
+extern u16 gSpeciesToHoennPokedexNum[];
+extern u16 gSpeciesToNationalPokedexNum[];
+extern u16 gHoennToNationalOrder[];
+extern u16 gSpeciesIdToCryId[];
+extern u8 gBattleTextBuff1[];
+extern u8 gBattleTextBuff2[];
+extern u8 gDisplayedStringBattle[];
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gStringBank;
+extern u8 gBankInMenu;
+extern struct SpindaSpot gSpindaSpotGraphics[];
+extern s8 gNatureStatTable[][5];
+extern s8 gUnknown_082082FE[][3];
+extern u16 gTrainerBattleOpponent;
+extern u16 gBattleTypeFlags;
+extern u32 gTMHMLearnsets[][2];
+extern u8 gBattleMonForms[];
+extern const u8 BattleText_Wally[];
+extern const u16 gHMMoves[];
+extern s8 gPokeblockFlavorCompatibilityTable[];
+extern u8 gLastUsedAbility;
+extern const u8 BattleText_PreventedSwitch[];
+extern u16 gBattlePartyID[];
+extern u8 gJapaneseNidoranNames[][11];
+
+extern u8 gUnknown_082082F8[];
+extern u8 gUnknown_083FFDB3[];
+extern u8 gUnknown_083FFDD3[];
+extern u8 gUnknown_083FEE5D[];
+extern u8 gUnknown_083FEE92[];
+extern u8 *gUnknown_08400F58[];
+
+bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId)
+{
+ u32 status = GetMonData(mon, MON_DATA_STATUS, 0);
+
+ if (status & healMask)
+ {
+ status &= ~healMask;
+ SetMonData(mon, MON_DATA_STATUS, (u8 *)&status);
+ if (gMain.inBattle && battleId != 4)
+ gBattleMons[battleId].status1 &= ~healMask;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
+{
+ const u8 *temp;
+ const u8 *itemEffect;
+ u8 offset;
+ int i;
+ u8 j;
+ u8 val;
+
+ offset = 6;
+
+ temp = gItemEffectTable[itemId - 13];
+
+ if (!temp && itemId != ITEM_ENIGMA_BERRY)
+ return 0;
+
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ temp = gEnigmaBerries[gActiveBank].itemEffect;
+ }
+
+ itemEffect = temp;
+
+ for (i = 0; i < 6; i++)
+ {
+ switch (i)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (i == effectByte)
+ return 0;
+ break;
+ case 4:
+ val = itemEffect[4];
+ if (val & 0x20)
+ val &= 0xDF;
+ j = 0;
+ while (val)
+ {
+ if (val & 1)
+ {
+ switch (j)
+ {
+ case 2:
+ if (val & 0x10)
+ val &= 0xEF;
+ case 0:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 1:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 3:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 7:
+ if (i == effectByte)
+ return 0;
+ break;
+ }
+ }
+ j++;
+ val >>= 1;
+ if (i == effectByte)
+ effectBit >>= 1;
+ }
+ break;
+ case 5:
+ val = itemEffect[5];
+ j = 0;
+ while (val)
+ {
+ if (val & 1)
+ {
+ switch (j)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 7:
+ if (i == effectByte)
+ return 0;
+ break;
+ }
+ }
+ j++;
+ val >>= 1;
+ if (i == effectByte)
+ effectBit >>= 1;
+ }
+ break;
+ }
+ }
+
+ return offset;
+}
+
+void sub_803F324(int stat)
+{
+ gBankTarget = gBankInMenu;
+ StringCopy(gBattleTextBuff1, gUnknown_08400F58[gUnknown_082082F8[stat]]);
+ StringCopy(gBattleTextBuff2, gUnknown_083FFDB3);
+ StrCpyDecodeToDisplayedStringBattle(gUnknown_083FFDD3);
+}
+
+u8 *sub_803F378(u16 itemId)
+{
+ int i;
+ u8 *itemEffect;
+
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ {
+ itemEffect = gEnigmaBerries[gBankInMenu].itemEffect;
+ }
+ else
+ {
+ itemEffect = gSaveBlock1.enigmaBerry.itemEffect;
+ }
+ }
+ else
+ {
+ itemEffect = (u8 *) gItemEffectTable[itemId - 13];
+ }
+
+ gStringBank = gBankInMenu;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (itemEffect[i] & 0xF)
+ sub_803F324(i * 2);
+ if (itemEffect[i] & 0xF0)
+ {
+ if (i)
+ {
+ sub_803F324(i * 2 + 1);
+ }
+ else
+ {
+ gBankAttacker = gBankInMenu;
+ StrCpyDecodeToDisplayedStringBattle(gUnknown_083FEE92);
+ }
+ }
+ }
+
+ if (itemEffect[3] & 0x80)
+ {
+ gBankAttacker = gBankInMenu;
+ StrCpyDecodeToDisplayedStringBattle(gUnknown_083FEE5D);
+ }
+
+ return gDisplayedStringBattle;
+}
+
+u8 GetNature(struct Pokemon *mon)
+{
+ return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25;
+}
+
+u8 GetNatureFromPersonality(u32 personality)
+{
+ return personality % 25;
+}
+
+u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem)
+{
+ int i;
+ u16 targetSpecies = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ u8 level;
+ u16 friendship;
+ u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0);
+ u16 upperPersonality = personality >> 16;
+ u8 holdEffect;
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1.enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+
+ if (holdEffect == HOLD_EFFECT_PREVENT_EVOLVE && type != 3)
+ return 0;
+
+ switch (type)
+ {
+ case 0:
+ level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
+
+ for (i = 0; i < 5; i++)
+ {
+ switch (gEvolutionTable[species].evolutions[i].method)
+ {
+ case EVO_FRIENDSHIP:
+ if (friendship >= 220)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_DAY:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_NIGHT:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL:
+ if (gEvolutionTable[species].evolutions[i].param <= level)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_GT_DEF:
+ if (gEvolutionTable[species].evolutions[i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_EQ_DEF:
+ if (gEvolutionTable[species].evolutions[i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_LT_DEF:
+ if (gEvolutionTable[species].evolutions[i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_SILCOON:
+ if (gEvolutionTable[species].evolutions[i].param <= level && (upperPersonality % 10) <= 4)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_CASCOON:
+ if (gEvolutionTable[species].evolutions[i].param <= level && (upperPersonality % 10) > 4)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_LEVEL_NINJASK:
+ if (gEvolutionTable[species].evolutions[i].param <= level)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_BEAUTY:
+ if (gEvolutionTable[species].evolutions[i].param <= beauty)
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < 5; i++)
+ {
+ switch (gEvolutionTable[species].evolutions[i].method)
+ {
+ case EVO_TRADE:
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ case EVO_TRADE_ITEM:
+ if (gEvolutionTable[species].evolutions[i].param == heldItem)
+ {
+ heldItem = 0;
+ SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem);
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ }
+ break;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ for (i = 0; i < 5; i++)
+ {
+ if (gEvolutionTable[species].evolutions[i].method == EVO_ITEM
+ && gEvolutionTable[species].evolutions[i].param == evolutionItem)
+ {
+ targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies;
+ break;
+ }
+ }
+ break;
+ }
+
+ return targetSpecies;
+}
+
+u16 HoennPokedexNumToSpecies(u16 hoennNum)
+{
+ u16 species;
+
+ if (!hoennNum)
+ return 0;
+
+ species = 0;
+
+ while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum)
+ species++;
+
+ if (species == 411)
+ return 0;
+
+ return species + 1;
+}
+
+u16 NationalPokedexNumToSpecies(u16 nationalNum)
+{
+ u16 species;
+
+ if (!nationalNum)
+ return 0;
+
+ species = 0;
+
+ while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum)
+ species++;
+
+ if (species == 411)
+ return 0;
+
+ return species + 1;
+}
+
+u16 NationalToHoennOrder(u16 nationalNum)
+{
+ u16 hoennNum;
+
+ if (!nationalNum)
+ return 0;
+
+ hoennNum = 0;
+
+ while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum)
+ hoennNum++;
+
+ if (hoennNum == 411)
+ return 0;
+
+ return hoennNum + 1;
+}
+
+u16 SpeciesToNationalPokedexNum(u16 species)
+{
+ if (!species)
+ return 0;
+
+ return gSpeciesToNationalPokedexNum[species - 1];
+}
+
+u16 SpeciesToHoennPokedexNum(u16 species)
+{
+ if (!species)
+ return 0;
+
+ return gSpeciesToHoennPokedexNum[species - 1];
+}
+
+u16 HoennToNationalOrder(u16 hoennNum)
+{
+ if (!hoennNum)
+ return 0;
+
+ return gHoennToNationalOrder[hoennNum - 1];
+}
+
+u16 SpeciesToCryId(u16 species)
+{
+ if (species <= 250)
+ return species;
+
+ if (species < 276)
+ return 200;
+
+ return gSpeciesIdToCryId[species - 276];
+}
+
+void unref_sub_803F938(u16 species, u32 personality, u8 *dest)
+{
+ if (species == SPECIES_SPINDA && dest != gUnknown_081FAF4C[0] && dest != gUnknown_081FAF4C[2])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4)
+{
+ if (species == SPECIES_SPINDA && a4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
+{
+#ifdef BUGFIX_EVO_NAME
+ u8 language;
+ GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
+ language = GetMonData(mon, MON_DATA_LANGUAGE, &language);
+ if (language == GAME_LANGUAGE && !StringCompareWithoutExtCtrlCodes(gSpeciesNames[oldSpecies], gStringVar1))
+ SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
+#else
+ GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
+ if (!StringCompareWithoutExtCtrlCodes(gSpeciesNames[oldSpecies], gStringVar1))
+ SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
+#endif
+}
+
+bool8 sub_803FBBC(void)
+{
+ bool8 retVal = FALSE;
+ switch (gLinkPlayers[GetMultiplayerId()].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+bool8 sub_803FBFC(u8 id)
+{
+ bool8 retVal = FALSE;
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+s32 sub_803FC34(u16 a1)
+{
+ s32 id;
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ if (gLinkPlayers[id].lp_field_18 == a1)
+ break;
+ return id;
+}
+
+u8 sub_803FC58(u16 trainer)
+{
+ return gTrainers[trainer].encounterMusic_gender & 0x7F;
+}
+
+u16 nature_stat_mod(u8 nature, u16 n, u8 statIndex)
+{
+ if (statIndex < 1 || statIndex > 5)
+ {
+ // should just be "return n", but it wouldn't match without this
+ u16 retVal = n;
+ retVal++;
+ retVal--;
+ return retVal;
+ }
+
+ switch (gNatureStatTable[nature][statIndex - 1])
+ {
+ case 1:
+ return (u16)(n * 110) / 100;
+ case -1:
+ return (u16)(n * 90) / 100;
+ }
+
+ return n;
+}
+
+void AdjustFriendship(struct Pokemon *mon, u8 event)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+ u8 holdEffect;
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ {
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ }
+ else
+ {
+ holdEffect = gSaveBlock1.enigmaBerry.holdEffect;
+ }
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (species && species != SPECIES_EGG)
+ {
+ u8 friendshipLevel = 0;
+ s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
+ if (friendship > 99)
+ friendshipLevel++;
+ if (friendship > 199)
+ friendshipLevel++;
+ if ((event != 5 || !(Random() & 1))
+ && (event != 3
+ || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ && (gTrainers[gTrainerBattleOpponent].trainerClass == 24
+ || gTrainers[gTrainerBattleOpponent].trainerClass == 25
+ || gTrainers[gTrainerBattleOpponent].trainerClass == 32))))
+ {
+ s8 mod = gUnknown_082082FE[event][friendshipLevel];
+ if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ mod = (150 * mod) / 100;
+ friendship += mod;
+ if (mod > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, (u8 *)&friendship);
+ }
+ }
+}
+
+void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
+{
+ u8 evs[NUM_STATS];
+ u16 evIncrease = 0;
+ u16 totalEVs = 0;
+ u16 heldItem;
+ u8 holdEffect;
+ int i;
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0);
+ totalEVs += evs[i];
+ }
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ u8 hasHadPokerus;
+ int multiplier;
+
+ if (totalEVs >= MAX_TOTAL_EVS)
+ break;
+
+ hasHadPokerus = CheckPartyHasHadPokerus(mon, 0);
+
+ if (hasHadPokerus)
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ switch (i)
+ {
+ case 0:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier;
+ break;
+ case 1:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier;
+ break;
+ case 2:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier;
+ break;
+ case 3:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier;
+ break;
+ case 4:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier;
+ break;
+ case 5:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier;
+ break;
+ }
+
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ {
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ }
+ else
+ {
+ holdEffect = gSaveBlock1.enigmaBerry.holdEffect;
+ }
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ evIncrease *= 2;
+
+ if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
+ evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
+
+ if (evs[i] + (s16)evIncrease > 255)
+ {
+ int val1 = (s16)evIncrease + 255;
+ int val2 = evs[i] + evIncrease;
+ evIncrease = val1 - val2;
+ }
+
+ evs[i] += evIncrease;
+ totalEVs += evIncrease;
+ SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]);
+ }
+}
+
+u16 GetMonEVCount(struct Pokemon *mon)
+{
+ int i;
+ u16 count = 0;
+
+ for (i = 0; i < NUM_STATS; i++)
+ count += GetMonData(mon, MON_DATA_HP_EV + i, 0);
+
+ return count;
+}
+
+void RandomlyGivePartyPokerus(struct Pokemon *party)
+{
+ u16 rnd = Random();
+ if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
+ {
+ struct Pokemon *mon;
+
+ do
+ {
+ do
+ {
+ rnd = Random() % PARTY_SIZE;
+ mon = &party[rnd];
+ }
+ while (!GetMonData(mon, MON_DATA_SPECIES, 0));
+ }
+ while (GetMonData(mon, MON_DATA_IS_EGG, 0));
+
+ if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
+ {
+ u8 rnd2;
+
+ do
+ {
+ rnd2 = Random();
+ }
+ while (rnd2 == 0);
+
+ if (rnd2 & 0xF0)
+ rnd2 &= 0x07;
+
+ rnd2 |= (rnd2 << 4);
+ rnd2 &= 0xF3;
+ rnd2++;
+
+ SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
+ }
+ }
+}
+
+u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF)
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0))
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+void UpdatePartyPokerusTime(u16 days)
+{
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
+ if (pokerus & 0xF)
+ {
+ if ((pokerus & 0xF) < days || days > 4)
+ pokerus &= 0xF0;
+ else
+ pokerus -= days;
+
+ SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
+ }
+ }
+ }
+}
+
+void PartySpreadPokerus(struct Pokemon *party)
+{
+ if ((Random() % 3) == 0)
+ {
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
+ u8 curPokerus = pokerus;
+ if (pokerus)
+ {
+ if (pokerus & 0xF)
+ {
+ // spread to adjacent party members
+ if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
+ SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
+ if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
+ {
+ SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
+ i++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool8 TryIncrementMonLevel(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1;
+ if (GetMonData(mon, MON_DATA_EXP, 0) > gExperienceTables[gBaseStats[species].growthRate][nextLevel])
+ {
+ SetMonData(mon, MON_DATA_LEVEL, &nextLevel);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ if (species == SPECIES_EGG)
+ {
+ return 0;
+ }
+ else if (tm < 32)
+ {
+ u32 mask = 1 << tm;
+ return gTMHMLearnsets[species][0] & mask;
+ }
+ else
+ {
+ u32 mask = 1 << (tm - 32);
+ return gTMHMLearnsets[species][1] & mask;
+ }
+}
+
+u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves)
+{
+ u16 learnedMoves[4];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)
+{
+ u8 numMoves = 0;
+ int i;
+
+ for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+
+ return numMoves;
+}
+
+u8 sub_8040574(struct Pokemon *mon)
+{
+ u16 learnedMoves[4];
+ u16 moves[20];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ if (species == SPECIES_EGG)
+ return 0;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u16 SpeciesToPokedexNum(u16 species)
+{
+ if (IsNationalPokedexEnabled())
+ {
+ return SpeciesToNationalPokedexNum(species);
+ }
+ else
+ {
+ species = SpeciesToHoennPokedexNum(species);
+ if (species <= 202)
+ return species;
+ return 0xFFFF;
+ }
+}
+
+void ClearBattleMonForms(void)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ gBattleMonForms[i] = 0;
+}
+
+u16 GetBGM_ForBattle(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
+ return BGM_BATTLE34;
+ if (gBattleTypeFlags & BATTLE_TYPE_REGI)
+ return BGM_BATTLE36;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ return BGM_BATTLE20;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ switch (gTrainers[gTrainerBattleOpponent].trainerClass)
+ {
+ case 2:
+ case 0x31:
+ return BGM_BATTLE30;
+ case 3:
+ case 4:
+ case 0x32:
+ case 0x33:
+ return BGM_BATTLE31;
+ case 0x19:
+ return BGM_BATTLE32;
+ case 0x20:
+ return BGM_BATTLE33;
+ case 0x2E:
+ if (!StringCompare(gTrainers[gTrainerBattleOpponent].trainerName, BattleText_Wally))
+ return BGM_BATTLE20;
+ return BGM_BATTLE35;
+ case 0x18:
+ return BGM_BATTLE38;
+ default:
+ return BGM_BATTLE20;
+ }
+ }
+ return BGM_BATTLE27;
+}
+
+void sub_80408BC(void)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ PlayBGM(GetBGM_ForBattle());
+}
+
+void current_map_music_set__default_for_battle(u16 song)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ if (song)
+ PlayNewMapMusic(song);
+ else
+ PlayNewMapMusic(GetBGM_ForBattle());
+}
+
+const u8 *GetMonSpritePal(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetMonSpritePalFromOtIdPersonality(species, otId, personality);
+}
+
+//Extracts the upper 16 bits of a 32-bit number
+#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
+
+//Extracts the lower 16 bits of a 32-bit number
+#define LOHALF(n) ((n) & 0xFFFF)
+
+const u8 *GetMonSpritePalFromOtIdPersonality(u16 species, u32 otId, u32 personality)
+{
+ u32 shinyValue;
+
+ if (species > SPECIES_EGG)
+ return gMonPaletteTable[0].data;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return gMonShinyPaletteTable[species].data;
+ else
+ return gMonPaletteTable[species].data;
+}
+
+const struct CompressedSpritePalette *GetMonSpritePalStruct(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality);
+}
+
+const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality)
+{
+ u32 shinyValue;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return &gMonShinyPaletteTable[species];
+ else
+ return &gMonPaletteTable[species];
+}
+
+bool32 IsHMMove2(u16 move)
+{
+ int i = 0;
+ while (gHMMoves[i] != 0xFFFF)
+ {
+ if (gHMMoves[i++] == move)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 IsPokeSpriteNotFlipped(u16 species)
+{
+ return gBaseStats[species].noFlip;
+}
+
+s8 sub_8040A54(struct Pokemon *mon, u8 a2)
+{
+ u8 nature = GetNature(mon);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + a2];
+}
+
+s8 GetPokeFlavourRelation(u32 personality, u8 a2)
+{
+ u8 nature = GetNatureFromPersonality(personality);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + a2];
+}
+
+bool8 IsTradedMon(struct Pokemon *mon)
+{
+ u8 otName[8];
+ u32 otId;
+ GetMonData(mon, MON_DATA_OT_NAME, otName);
+ otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ return IsOtherTrainer(otId, otName);
+}
+
+bool8 IsOtherTrainer(u32 otId, u8 *otName)
+{
+ if (otId == (gSaveBlock2.playerTrainerId[0] | (gSaveBlock2.playerTrainerId[1] << 8) | (gSaveBlock2.playerTrainerId[2] << 16) | (gSaveBlock2.playerTrainerId[3] << 24)))
+ {
+ int i;
+
+ for (i = 0; otName[i] != EOS; i++)
+ if (otName[i] != gSaveBlock2.playerName[i])
+ return TRUE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void BoxMonRestorePP(struct BoxPokemon *);
+
+void MonRestorePP(struct Pokemon *mon)
+{
+ BoxMonRestorePP(&mon->box);
+}
+
+void BoxMonRestorePP(struct BoxPokemon *boxMon)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0))
+ {
+ u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0);
+ u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0);
+ u8 pp = CalculatePPWithBonus(move, bonus, i);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp);
+ }
+ }
+}
+
+void sub_8040B8C(void)
+{
+ gLastUsedAbility = BATTLE_STRUCT->unk160C0;;
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 4;
+ gBattleTextBuff1[2] = BATTLE_STRUCT->unk16054;
+ gBattleTextBuff1[4] = EOS;
+ if (!GetBankSide(BATTLE_STRUCT->unk16054))
+ gBattleTextBuff1[3] = pokemon_order_func(gBattlePartyID[BATTLE_STRUCT->unk16054]);
+ else
+ gBattleTextBuff1[3] = gBattlePartyID[BATTLE_STRUCT->unk16054];
+ gBattleTextBuff2[0] = 0xFD;
+ gBattleTextBuff2[1] = 4;
+ gBattleTextBuff2[2] = gBankInMenu;
+ gBattleTextBuff2[3] = pokemon_order_func(gBattlePartyID[gBankInMenu]);
+ gBattleTextBuff2[4] = EOS;
+ StrCpyDecodeBattle(BattleText_PreventedSwitch, gStringVar4);
+}
+
+void SetWildMonHeldItem(void)
+{
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER)))
+ {
+ u16 rnd = Random() % 100;
+ u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
+ if (gBaseStats[species].item1 == gBaseStats[species].item2)
+ {
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, (u8 *)&gBaseStats[species].item1);
+ return;
+ }
+
+ if (rnd > 44)
+ {
+ if (rnd <= 94)
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, (u8 *)&gBaseStats[species].item1);
+ else
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, (u8 *)&gBaseStats[species].item2);
+ }
+ }
+}
+
+bool8 IsShinyOtIdPersonality(u32, u32);
+
+bool8 IsShiny(struct Pokemon *mon)
+{
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return IsShinyOtIdPersonality(otId, personality);
+}
+
+bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
+{
+ bool8 retVal = FALSE;
+ u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ retVal = TRUE;
+ return retVal;
+}
+
+u8 *sub_8040D08(void)
+{
+ u8 id = GetMultiplayerId();
+ return gLinkPlayers[sub_803FC34(gLinkPlayers[id].lp_field_18 ^ 2)].name;
+}
+
+bool32 sub_8040D3C(u16 species, u8 *name, u8 language)
+{
+ bool32 retVal = FALSE;
+ if (species == SPECIES_NIDORAN_M || species == SPECIES_NIDORAN_F)
+ {
+ u8 *speciesName;
+ if (language == GAME_LANGUAGE)
+ {
+ speciesName = gSpeciesNames[species];
+ }
+ else
+ {
+ if (species == SPECIES_NIDORAN_M)
+ speciesName = gJapaneseNidoranNames[0];
+ else
+ speciesName = gJapaneseNidoranNames[1];
+ }
+ if (!StringCompareWithoutExtCtrlCodes(name, speciesName))
+ retVal = TRUE;
+ else
+ retVal = FALSE;
+ }
+ return retVal;
+}
+
+bool32 sub_8040D8C(u16 species, u8 *name)
+{
+ u8 language = GAME_LANGUAGE;
+ if (name[0] == 0xFC && name[1] == 21)
+ language = LANGUAGE_JAPANESE;
+ return sub_8040D3C(species, name, language);
+}
+
+bool32 unref_sub_8040DAC(struct Pokemon *mon)
+{
+ u8 name[12];
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 language = GetMonData(mon, MON_DATA_LANGUAGE, 0);
+ GetMonData(mon, MON_DATA_NICKNAME, name);
+ return sub_8040D3C(species, name, language);
+}
diff --git a/src/pokemon/pokemon_data.c b/src/pokemon/pokemon_data.c
new file mode 100644
index 000000000..6414134fb
--- /dev/null
+++ b/src/pokemon/pokemon_data.c
@@ -0,0 +1,128 @@
+#include "global.h"
+#include "pokemon.h"
+#include "species.h"
+#include "trainer.h"
+#include "abilities.h"
+#include "moves.h"
+#include "hold_effects.h"
+#include "items.h"
+#include "sprite.h"
+#include "data2.h"
+
+#include "data/pokemon/dex_order.h"
+#include "data/pokemon/spinda_spots.h"
+#include "data/pokemon/item_effects.h"
+#include "data/pokemon/nature_stats.h"
+#include "data/pokemon/tmhm_learnsets.h"
+#include "data/pokemon/trainer_class_lookups.h"
+#include "data/pokemon/cry_ids.h"
+#include "data/pokemon/experience_tables.h"
+#include "data/pokemon/base_stats.h"
+#include "data/pokemon/level_up_learnsets.h"
+#include "data/pokemon/evolution.h"
+#include "data/pokemon/level_up_learnset_pointers.h"
+
+const u8 gUnknown_08208238[] = { // Masks for getting PP Up count, also PP Max values
+ 0x03, 0x0c, 0x30, 0xc0
+};
+
+const u8 gUnknown_0820823C[] = { // Masks for setting PP Up count
+ 0xFC, 0xF3, 0xCF, 0x3F
+};
+
+const u8 gUnknown_08208240[] = { // Values added to PP Up count
+ 0x01, 0x04, 0x10, 0x40
+};
+
+const u8 gStatStageRatios[][2] = {
+ {10, 40}, // -6
+ {10, 35}, // -5
+ {10, 30}, // -4
+ {10, 25}, // -3
+ {10, 20}, // -2
+ {10, 15}, // -1
+ {10, 10}, // 0
+ {15, 10}, // 1
+ {20, 10}, // 2
+ {25, 10}, // 3
+ {30, 10}, // 4
+ {35, 10}, // 5
+ {40, 10} // 6
+};
+
+const u8 unknownGameFreakAbbrev_820825E[] = _("ゲーフリ");
+
+const u8 gHoldEffectToType[][2] = {
+ {HOLD_EFFECT_BUG_POWER, TYPE_BUG},
+ {HOLD_EFFECT_STEEL_POWER, TYPE_STEEL},
+ {HOLD_EFFECT_GROUND_POWER, TYPE_GROUND},
+ {HOLD_EFFECT_ROCK_POWER, TYPE_ROCK},
+ {HOLD_EFFECT_GRASS_POWER, TYPE_GRASS},
+ {HOLD_EFFECT_DARK_POWER, TYPE_DARK},
+ {HOLD_EFFECT_FIGHTING_POWER, TYPE_FIGHTING},
+ {HOLD_EFFECT_ELECTRIC_POWER, TYPE_ELECTRIC},
+ {HOLD_EFFECT_WATER_POWER, TYPE_WATER},
+ {HOLD_EFFECT_FLYING_POWER, TYPE_FLYING},
+ {HOLD_EFFECT_POISON_POWER, TYPE_POISON},
+ {HOLD_EFFECT_ICE_POWER, TYPE_ICE},
+ {HOLD_EFFECT_GHOST_POWER, TYPE_GHOST},
+ {HOLD_EFFECT_PSYCHIC_POWER, TYPE_PSYCHIC},
+ {HOLD_EFFECT_FIRE_POWER, TYPE_FIRE},
+ {HOLD_EFFECT_DRAGON_POWER, TYPE_DRAGON},
+ {HOLD_EFFECT_NORMAL_POWER, TYPE_NORMAL}
+};
+
+extern void sub_80105A0(struct Sprite *);
+extern void oac_poke_opponent(struct Sprite *);
+
+const struct SpriteTemplate gSpriteTemplate_8208288[] = {
+ {0xFFFF, 0, &gOamData_81F96F0, NULL, gSpriteImageTable_81E7A10, gSpriteAffineAnimTable_81E7B70, sub_80105A0},
+ {0xFFFF, 0, &gOamData_81F96E8, NULL, gSpriteImageTable_81E7A30, gSpriteAffineAnimTable_81E7BEC, oac_poke_opponent},
+ {0xFFFF, 0, &gOamData_81F96F0, NULL, gSpriteImageTable_81E7A50, gSpriteAffineAnimTable_81E7B70, sub_80105A0},
+ {0xFFFF, 0, &gOamData_81F96E8, NULL, gSpriteImageTable_81E7A70, gSpriteAffineAnimTable_81E7BEC, oac_poke_opponent},
+};
+
+const u8 gSecretBaseTrainerClasses[][5] = {
+ // male
+ {TRAINER_CLASS_YOUNGSTER, TRAINER_CLASS_BUG_CATCHER, TRAINER_CLASS_RICH_BOY, TRAINER_CLASS_CAMPER, TRAINER_CLASS_COOL_TRAINER_M},
+ // female
+ {TRAINER_CLASS_LASS, TRAINER_CLASS_SCHOOL_KID_F, TRAINER_CLASS_LADY, TRAINER_CLASS_PICNICKER, TRAINER_CLASS_COOL_TRAINER_F}
+};
+
+const u8 gUnknown_082082F2[] = {
+ MON_DATA_HP_EV,
+ MON_DATA_ATK_EV,
+ MON_DATA_DEF_EV,
+ MON_DATA_SPD_EV,
+ MON_DATA_SPDEF_EV,
+ MON_DATA_SPATK_EV
+};
+
+const u8 gUnknown_082082F8[] = {1, 1, 3, 2, 4, 6};
+
+const s8 gUnknown_082082FE[][3] = {
+ // Happiness deltas
+ { 5, 3, 2},
+ { 5, 3, 2},
+ { 1, 1, 0},
+ { 3, 2, 1},
+ { 1, 1, 0},
+ { 1, 1, 1},
+ {-1, -1, -1},
+ {-5, -5, -10},
+ {-5, -5, -10}
+};
+
+const u16 gHMMoves[] = {
+ MOVE_CUT,
+ MOVE_FLY,
+ MOVE_SURF,
+ MOVE_STRENGTH,
+ MOVE_FLASH,
+ MOVE_ROCK_SMASH,
+ MOVE_WATERFALL,
+ MOVE_DIVE,
+ 0xffff
+};
+
+const u8 gJapaneseNidoranNames[][11] = {_("ニドラン♂"), _("ニドラン♀")};
diff --git a/src/pokemon/pokemon_icon.c b/src/pokemon/pokemon_icon.c
new file mode 100644
index 000000000..9bb3386e1
--- /dev/null
+++ b/src/pokemon/pokemon_icon.c
@@ -0,0 +1,1273 @@
+#include "global.h"
+#include "graphics.h"
+#include "mail_data.h"
+#include "species.h"
+#include "sprite.h"
+
+#define POKE_ICON_BASE_PAL_TAG 56000
+
+struct MonIconSpriteTemplate
+{
+ const struct OamData *oam;
+ const u8 *image;
+ const union AnimCmd *const *anims;
+ const union AffineAnimCmd *const *affineAnims;
+ void (*callback)(struct Sprite *);
+ u16 paletteTag;
+};
+
+const u8 * const gMonIconTable[] =
+{
+ gMonIcon_Bulbasaur,
+ gMonIcon_Bulbasaur,
+ gMonIcon_Ivysaur,
+ gMonIcon_Venusaur,
+ gMonIcon_Charmander,
+ gMonIcon_Charmeleon,
+ gMonIcon_Charizard,
+ gMonIcon_Squirtle,
+ gMonIcon_Wartortle,
+ gMonIcon_Blastoise,
+ gMonIcon_Caterpie,
+ gMonIcon_Metapod,
+ gMonIcon_Butterfree,
+ gMonIcon_Weedle,
+ gMonIcon_Kakuna,
+ gMonIcon_Beedrill,
+ gMonIcon_Pidgey,
+ gMonIcon_Pidgeotto,
+ gMonIcon_Pidgeot,
+ gMonIcon_Rattata,
+ gMonIcon_Raticate,
+ gMonIcon_Spearow,
+ gMonIcon_Fearow,
+ gMonIcon_Ekans,
+ gMonIcon_Arbok,
+ gMonIcon_Pikachu,
+ gMonIcon_Raichu,
+ gMonIcon_Sandshrew,
+ gMonIcon_Sandslash,
+ gMonIcon_NidoranF,
+ gMonIcon_Nidorina,
+ gMonIcon_Nidoqueen,
+ gMonIcon_NidoranM,
+ gMonIcon_Nidorino,
+ gMonIcon_Nidoking,
+ gMonIcon_Clefairy,
+ gMonIcon_Clefable,
+ gMonIcon_Vulpix,
+ gMonIcon_Ninetales,
+ gMonIcon_Jigglypuff,
+ gMonIcon_Wigglytuff,
+ gMonIcon_Zubat,
+ gMonIcon_Golbat,
+ gMonIcon_Oddish,
+ gMonIcon_Gloom,
+ gMonIcon_Vileplume,
+ gMonIcon_Paras,
+ gMonIcon_Parasect,
+ gMonIcon_Venonat,
+ gMonIcon_Venomoth,
+ gMonIcon_Diglett,
+ gMonIcon_Dugtrio,
+ gMonIcon_Meowth,
+ gMonIcon_Persian,
+ gMonIcon_Psyduck,
+ gMonIcon_Golduck,
+ gMonIcon_Mankey,
+ gMonIcon_Primeape,
+ gMonIcon_Growlithe,
+ gMonIcon_Arcanine,
+ gMonIcon_Poliwag,
+ gMonIcon_Poliwhirl,
+ gMonIcon_Poliwrath,
+ gMonIcon_Abra,
+ gMonIcon_Kadabra,
+ gMonIcon_Alakazam,
+ gMonIcon_Machop,
+ gMonIcon_Machoke,
+ gMonIcon_Machamp,
+ gMonIcon_Bellsprout,
+ gMonIcon_Weepinbell,
+ gMonIcon_Victreebel,
+ gMonIcon_Tentacool,
+ gMonIcon_Tentacruel,
+ gMonIcon_Geodude,
+ gMonIcon_Graveler,
+ gMonIcon_Golem,
+ gMonIcon_Ponyta,
+ gMonIcon_Rapidash,
+ gMonIcon_Slowpoke,
+ gMonIcon_Slowbro,
+ gMonIcon_Magnemite,
+ gMonIcon_Magneton,
+ gMonIcon_Farfetchd,
+ gMonIcon_Doduo,
+ gMonIcon_Dodrio,
+ gMonIcon_Seel,
+ gMonIcon_Dewgong,
+ gMonIcon_Grimer,
+ gMonIcon_Muk,
+ gMonIcon_Shellder,
+ gMonIcon_Cloyster,
+ gMonIcon_Gastly,
+ gMonIcon_Haunter,
+ gMonIcon_Gengar,
+ gMonIcon_Onix,
+ gMonIcon_Drowzee,
+ gMonIcon_Hypno,
+ gMonIcon_Krabby,
+ gMonIcon_Kingler,
+ gMonIcon_Voltorb,
+ gMonIcon_Electrode,
+ gMonIcon_Exeggcute,
+ gMonIcon_Exeggutor,
+ gMonIcon_Cubone,
+ gMonIcon_Marowak,
+ gMonIcon_Hitmonlee,
+ gMonIcon_Hitmonchan,
+ gMonIcon_Lickitung,
+ gMonIcon_Koffing,
+ gMonIcon_Weezing,
+ gMonIcon_Rhyhorn,
+ gMonIcon_Rhydon,
+ gMonIcon_Chansey,
+ gMonIcon_Tangela,
+ gMonIcon_Kangaskhan,
+ gMonIcon_Horsea,
+ gMonIcon_Seadra,
+ gMonIcon_Goldeen,
+ gMonIcon_Seaking,
+ gMonIcon_Staryu,
+ gMonIcon_Starmie,
+ gMonIcon_Mrmime,
+ gMonIcon_Scyther,
+ gMonIcon_Jynx,
+ gMonIcon_Electabuzz,
+ gMonIcon_Magmar,
+ gMonIcon_Pinsir,
+ gMonIcon_Tauros,
+ gMonIcon_Magikarp,
+ gMonIcon_Gyarados,
+ gMonIcon_Lapras,
+ gMonIcon_Ditto,
+ gMonIcon_Eevee,
+ gMonIcon_Vaporeon,
+ gMonIcon_Jolteon,
+ gMonIcon_Flareon,
+ gMonIcon_Porygon,
+ gMonIcon_Omanyte,
+ gMonIcon_Omastar,
+ gMonIcon_Kabuto,
+ gMonIcon_Kabutops,
+ gMonIcon_Aerodactyl,
+ gMonIcon_Snorlax,
+ gMonIcon_Articuno,
+ gMonIcon_Zapdos,
+ gMonIcon_Moltres,
+ gMonIcon_Dratini,
+ gMonIcon_Dragonair,
+ gMonIcon_Dragonite,
+ gMonIcon_Mewtwo,
+ gMonIcon_Mew,
+ gMonIcon_Chikorita,
+ gMonIcon_Bayleef,
+ gMonIcon_Meganium,
+ gMonIcon_Cyndaquil,
+ gMonIcon_Quilava,
+ gMonIcon_Typhlosion,
+ gMonIcon_Totodile,
+ gMonIcon_Croconaw,
+ gMonIcon_Feraligatr,
+ gMonIcon_Sentret,
+ gMonIcon_Furret,
+ gMonIcon_Hoothoot,
+ gMonIcon_Noctowl,
+ gMonIcon_Ledyba,
+ gMonIcon_Ledian,
+ gMonIcon_Spinarak,
+ gMonIcon_Ariados,
+ gMonIcon_Crobat,
+ gMonIcon_Chinchou,
+ gMonIcon_Lanturn,
+ gMonIcon_Pichu,
+ gMonIcon_Cleffa,
+ gMonIcon_Igglybuff,
+ gMonIcon_Togepi,
+ gMonIcon_Togetic,
+ gMonIcon_Natu,
+ gMonIcon_Xatu,
+ gMonIcon_Mareep,
+ gMonIcon_Flaaffy,
+ gMonIcon_Ampharos,
+ gMonIcon_Bellossom,
+ gMonIcon_Marill,
+ gMonIcon_Azumarill,
+ gMonIcon_Sudowoodo,
+ gMonIcon_Politoed,
+ gMonIcon_Hoppip,
+ gMonIcon_Skiploom,
+ gMonIcon_Jumpluff,
+ gMonIcon_Aipom,
+ gMonIcon_Sunkern,
+ gMonIcon_Sunflora,
+ gMonIcon_Yanma,
+ gMonIcon_Wooper,
+ gMonIcon_Quagsire,
+ gMonIcon_Espeon,
+ gMonIcon_Umbreon,
+ gMonIcon_Murkrow,
+ gMonIcon_Slowking,
+ gMonIcon_Misdreavus,
+ gMonIcon_UnownA,
+ gMonIcon_Wobbuffet,
+ gMonIcon_Girafarig,
+ gMonIcon_Pineco,
+ gMonIcon_Forretress,
+ gMonIcon_Dunsparce,
+ gMonIcon_Gligar,
+ gMonIcon_Steelix,
+ gMonIcon_Snubbull,
+ gMonIcon_Granbull,
+ gMonIcon_Qwilfish,
+ gMonIcon_Scizor,
+ gMonIcon_Shuckle,
+ gMonIcon_Heracross,
+ gMonIcon_Sneasel,
+ gMonIcon_Teddiursa,
+ gMonIcon_Ursaring,
+ gMonIcon_Slugma,
+ gMonIcon_Magcargo,
+ gMonIcon_Swinub,
+ gMonIcon_Piloswine,
+ gMonIcon_Corsola,
+ gMonIcon_Remoraid,
+ gMonIcon_Octillery,
+ gMonIcon_Delibird,
+ gMonIcon_Mantine,
+ gMonIcon_Skarmory,
+ gMonIcon_Houndour,
+ gMonIcon_Houndoom,
+ gMonIcon_Kingdra,
+ gMonIcon_Phanpy,
+ gMonIcon_Donphan,
+ gMonIcon_Porygon2,
+ gMonIcon_Stantler,
+ gMonIcon_Smeargle,
+ gMonIcon_Tyrogue,
+ gMonIcon_Hitmontop,
+ gMonIcon_Smoochum,
+ gMonIcon_Elekid,
+ gMonIcon_Magby,
+ gMonIcon_Miltank,
+ gMonIcon_Blissey,
+ gMonIcon_Raikou,
+ gMonIcon_Entei,
+ gMonIcon_Suicune,
+ gMonIcon_Larvitar,
+ gMonIcon_Pupitar,
+ gMonIcon_Tyranitar,
+ gMonIcon_Lugia,
+ gMonIcon_HoOh,
+ gMonIcon_Celebi,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_QuestionMark,
+ gMonIcon_Treecko,
+ gMonIcon_Grovyle,
+ gMonIcon_Sceptile,
+ gMonIcon_Torchic,
+ gMonIcon_Combusken,
+ gMonIcon_Blaziken,
+ gMonIcon_Mudkip,
+ gMonIcon_Marshtomp,
+ gMonIcon_Swampert,
+ gMonIcon_Poochyena,
+ gMonIcon_Mightyena,
+ gMonIcon_Zigzagoon,
+ gMonIcon_Linoone,
+ gMonIcon_Wurmple,
+ gMonIcon_Silcoon,
+ gMonIcon_Beautifly,
+ gMonIcon_Cascoon,
+ gMonIcon_Dustox,
+ gMonIcon_Lotad,
+ gMonIcon_Lombre,
+ gMonIcon_Ludicolo,
+ gMonIcon_Seedot,
+ gMonIcon_Nuzleaf,
+ gMonIcon_Shiftry,
+ gMonIcon_Nincada,
+ gMonIcon_Ninjask,
+ gMonIcon_Shedinja,
+ gMonIcon_Taillow,
+ gMonIcon_Swellow,
+ gMonIcon_Shroomish,
+ gMonIcon_Breloom,
+ gMonIcon_Spinda,
+ gMonIcon_Wingull,
+ gMonIcon_Pelipper,
+ gMonIcon_Surskit,
+ gMonIcon_Masquerain,
+ gMonIcon_Wailmer,
+ gMonIcon_Wailord,
+ gMonIcon_Skitty,
+ gMonIcon_Delcatty,
+ gMonIcon_Kecleon,
+ gMonIcon_Baltoy,
+ gMonIcon_Claydol,
+ gMonIcon_Nosepass,
+ gMonIcon_Torkoal,
+ gMonIcon_Sableye,
+ gMonIcon_Barboach,
+ gMonIcon_Whiscash,
+ gMonIcon_Luvdisc,
+ gMonIcon_Corphish,
+ gMonIcon_Crawdaunt,
+ gMonIcon_Feebas,
+ gMonIcon_Milotic,
+ gMonIcon_Carvanha,
+ gMonIcon_Sharpedo,
+ gMonIcon_Trapinch,
+ gMonIcon_Vibrava,
+ gMonIcon_Flygon,
+ gMonIcon_Makuhita,
+ gMonIcon_Hariyama,
+ gMonIcon_Electrike,
+ gMonIcon_Manectric,
+ gMonIcon_Numel,
+ gMonIcon_Camerupt,
+ gMonIcon_Spheal,
+ gMonIcon_Sealeo,
+ gMonIcon_Walrein,
+ gMonIcon_Cacnea,
+ gMonIcon_Cacturne,
+ gMonIcon_Snorunt,
+ gMonIcon_Glalie,
+ gMonIcon_Lunatone,
+ gMonIcon_Solrock,
+ gMonIcon_Azurill,
+ gMonIcon_Spoink,
+ gMonIcon_Grumpig,
+ gMonIcon_Plusle,
+ gMonIcon_Minun,
+ gMonIcon_Mawile,
+ gMonIcon_Meditite,
+ gMonIcon_Medicham,
+ gMonIcon_Swablu,
+ gMonIcon_Altaria,
+ gMonIcon_Wynaut,
+ gMonIcon_Duskull,
+ gMonIcon_Dusclops,
+ gMonIcon_Roselia,
+ gMonIcon_Slakoth,
+ gMonIcon_Vigoroth,
+ gMonIcon_Slaking,
+ gMonIcon_Gulpin,
+ gMonIcon_Swalot,
+ gMonIcon_Tropius,
+ gMonIcon_Whismur,
+ gMonIcon_Loudred,
+ gMonIcon_Exploud,
+ gMonIcon_Clamperl,
+ gMonIcon_Huntail,
+ gMonIcon_Gorebyss,
+ gMonIcon_Absol,
+ gMonIcon_Shuppet,
+ gMonIcon_Banette,
+ gMonIcon_Seviper,
+ gMonIcon_Zangoose,
+ gMonIcon_Relicanth,
+ gMonIcon_Aron,
+ gMonIcon_Lairon,
+ gMonIcon_Aggron,
+ gMonIcon_Castform,
+ gMonIcon_Volbeat,
+ gMonIcon_Illumise,
+ gMonIcon_Lileep,
+ gMonIcon_Cradily,
+ gMonIcon_Anorith,
+ gMonIcon_Armaldo,
+ gMonIcon_Ralts,
+ gMonIcon_Kirlia,
+ gMonIcon_Gardevoir,
+ gMonIcon_Bagon,
+ gMonIcon_Shelgon,
+ gMonIcon_Salamence,
+ gMonIcon_Beldum,
+ gMonIcon_Metang,
+ gMonIcon_Metagross,
+ gMonIcon_Regirock,
+ gMonIcon_Regice,
+ gMonIcon_Registeel,
+ gMonIcon_Kyogre,
+ gMonIcon_Groudon,
+ gMonIcon_Rayquaza,
+ gMonIcon_Latias,
+ gMonIcon_Latios,
+ gMonIcon_Jirachi,
+ gMonIcon_Deoxys,
+ gMonIcon_Chimecho,
+ gMonIcon_Egg,
+ gMonIcon_UnownB,
+ gMonIcon_UnownC,
+ gMonIcon_UnownD,
+ gMonIcon_UnownE,
+ gMonIcon_UnownF,
+ gMonIcon_UnownG,
+ gMonIcon_UnownH,
+ gMonIcon_UnownI,
+ gMonIcon_UnownJ,
+ gMonIcon_UnownK,
+ gMonIcon_UnownL,
+ gMonIcon_UnownM,
+ gMonIcon_UnownN,
+ gMonIcon_UnownO,
+ gMonIcon_UnownP,
+ gMonIcon_UnownQ,
+ gMonIcon_UnownR,
+ gMonIcon_UnownS,
+ gMonIcon_UnownT,
+ gMonIcon_UnownU,
+ gMonIcon_UnownV,
+ gMonIcon_UnownW,
+ gMonIcon_UnownX,
+ gMonIcon_UnownY,
+ gMonIcon_UnownZ,
+ gMonIcon_UnownExclamationMark,
+ gMonIcon_UnownQuestionMark,
+};
+
+const u8 gMonIconPaletteIndices[] =
+{
+ 0, // ??????????
+ 1, // Bulbasaur
+ 1, // Ivysaur
+ 1, // Venusaur
+ 0, // Charmander
+ 0, // Charmeleon
+ 0, // Charizard
+ 0, // Squirtle
+ 2, // Wartortle
+ 2, // Blastoise
+ 1, // Caterpie
+ 1, // Metapod
+ 0, // Butterfree
+ 1, // Weedle
+ 2, // Kakuna
+ 2, // Beedrill
+ 0, // Pidgey
+ 0, // Pidgeotto
+ 0, // Pidgeot
+ 2, // Rattata
+ 1, // Raticate
+ 0, // Spearow
+ 0, // Fearow
+ 2, // Ekans
+ 2, // Arbok
+ 2, // Pikachu
+ 0, // Raichu
+ 2, // Sandshrew
+ 2, // Sandslash
+ 2, // Nidoran♀
+ 2, // Nidorina
+ 2, // Nidoqueen
+ 2, // Nidoran♂
+ 2, // Nidorino
+ 2, // Nidoking
+ 0, // Clefairy
+ 0, // Clefable
+ 2, // Vulpix
+ 1, // Ninetales
+ 0, // Jigglypuff
+ 0, // Wigglytuff
+ 2, // Zubat
+ 2, // Golbat
+ 1, // Oddish
+ 0, // Gloom
+ 0, // Vileplume
+ 0, // Paras
+ 0, // Parasect
+ 0, // Venonat
+ 2, // Venomoth
+ 2, // Diglett
+ 2, // Dugtrio
+ 1, // Meowth
+ 1, // Persian
+ 1, // Psyduck
+ 2, // Golduck
+ 1, // Mankey
+ 2, // Primeape
+ 0, // Growlithe
+ 0, // Arcanine
+ 0, // Poliwag
+ 0, // Poliwhirl
+ 0, // Poliwrath
+ 2, // Abra
+ 2, // Kadabra
+ 2, // Alakazam
+ 0, // Machop
+ 2, // Machoke
+ 0, // Machamp
+ 1, // Bellsprout
+ 1, // Weepinbell
+ 1, // Victreebel
+ 2, // Tentacool
+ 2, // Tentacruel
+ 1, // Geodude
+ 1, // Graveler
+ 1, // Golem
+ 0, // Ponyta
+ 0, // Rapidash
+ 0, // Slowpoke
+ 0, // Slowbro
+ 0, // Magnemite
+ 0, // Magneton
+ 1, // Farfetch'd
+ 2, // Doduo
+ 2, // Dodrio
+ 2, // Seel
+ 2, // Dewgong
+ 2, // Grimer
+ 2, // Muk
+ 2, // Shellder
+ 2, // Cloyster
+ 2, // Gastly
+ 2, // Haunter
+ 2, // Gengar
+ 2, // Onix
+ 2, // Drowzee
+ 1, // Hypno
+ 2, // Krabby
+ 2, // Kingler
+ 0, // Voltorb
+ 0, // Electrode
+ 0, // Exeggcute
+ 1, // Exeggutor
+ 1, // Cubone
+ 1, // Marowak
+ 2, // Hitmonlee
+ 2, // Hitmonchan
+ 1, // Lickitung
+ 2, // Koffing
+ 2, // Weezing
+ 1, // Rhyhorn
+ 1, // Rhydon
+ 0, // Chansey
+ 0, // Tangela
+ 1, // Kangaskhan
+ 0, // Horsea
+ 0, // Seadra
+ 0, // Goldeen
+ 0, // Seaking
+ 2, // Staryu
+ 2, // Starmie
+ 0, // Mr. mime
+ 1, // Scyther
+ 2, // Jynx
+ 1, // Electabuzz
+ 0, // Magmar
+ 2, // Pinsir
+ 2, // Tauros
+ 0, // Magikarp
+ 0, // Gyarados
+ 2, // Lapras
+ 2, // Ditto
+ 2, // Eevee
+ 0, // Vaporeon
+ 0, // Jolteon
+ 0, // Flareon
+ 0, // Porygon
+ 0, // Omanyte
+ 0, // Omastar
+ 2, // Kabuto
+ 2, // Kabutops
+ 0, // Aerodactyl
+ 1, // Snorlax
+ 0, // Articuno
+ 0, // Zapdos
+ 0, // Moltres
+ 0, // Dratini
+ 0, // Dragonair
+ 2, // Dragonite
+ 2, // Mewtwo
+ 0, // Mew
+ 1, // Chikorita
+ 1, // Bayleef
+ 1, // Meganium
+ 1, // Cyndaquil
+ 1, // Quilava
+ 1, // Typhlosion
+ 2, // Totodile
+ 2, // Croconaw
+ 2, // Feraligatr
+ 2, // Sentret
+ 2, // Furret
+ 2, // Hoothoot
+ 2, // Noctowl
+ 0, // Ledyba
+ 0, // Ledian
+ 1, // Spinarak
+ 0, // Ariados
+ 2, // Crobat
+ 2, // Chinchou
+ 0, // Lanturn
+ 0, // Pichu
+ 0, // Cleffa
+ 1, // Igglybuff
+ 2, // Togepi
+ 2, // Togetic
+ 0, // Natu
+ 0, // Xatu
+ 2, // Mareep
+ 0, // Flaaffy
+ 0, // Ampharos
+ 1, // Bellossom
+ 2, // Marill
+ 2, // Azumarill
+ 1, // Sudowoodo
+ 1, // Politoed
+ 1, // Hoppip
+ 1, // Skiploom
+ 2, // Jumpluff
+ 2, // Aipom
+ 1, // Sunkern
+ 1, // Sunflora
+ 1, // Yanma
+ 0, // Wooper
+ 0, // Quagsire
+ 2, // Espeon
+ 2, // Umbreon
+ 2, // Murkrow
+ 0, // Slowking
+ 0, // Misdreavus
+ 0, // Unown A
+ 0, // Wobbuffet
+ 1, // Girafarig
+ 0, // Pineco
+ 2, // Forretress
+ 2, // Dunsparce
+ 2, // Gligar
+ 0, // Steelix
+ 0, // Snubbull
+ 2, // Granbull
+ 0, // Qwilfish
+ 0, // Scizor
+ 1, // Shuckle
+ 2, // Heracross
+ 0, // Sneasel
+ 0, // Teddiursa
+ 2, // Ursaring
+ 0, // Slugma
+ 0, // Magcargo
+ 2, // Swinub
+ 2, // Piloswine
+ 0, // Corsola
+ 0, // Remoraid
+ 0, // Octillery
+ 0, // Delibird
+ 2, // Mantine
+ 0, // Skarmory
+ 0, // Houndour
+ 0, // Houndoom
+ 0, // Kingdra
+ 0, // Phanpy
+ 0, // Donphan
+ 0, // Porygon2
+ 2, // Stantler
+ 1, // Smeargle
+ 2, // Tyrogue
+ 2, // Hitmontop
+ 1, // Smoochum
+ 1, // Elekid
+ 1, // Magby
+ 1, // Miltank
+ 1, // Blissey
+ 0, // Raikou
+ 2, // Entei
+ 0, // Suicune
+ 1, // Larvitar
+ 0, // Pupitar
+ 1, // Tyranitar
+ 0, // Lugia
+ 1, // Ho-Oh
+ 1, // Celebi
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 0, // ?
+ 1, // Treecko
+ 0, // Grovyle
+ 1, // Sceptile
+ 0, // Torchic
+ 0, // Combusken
+ 0, // Blaziken
+ 0, // Mudkip
+ 0, // Marshtomp
+ 0, // Swampert
+ 2, // Poochyena
+ 2, // Mightyena
+ 2, // Zigzagoon
+ 2, // Linoone
+ 0, // Wurmple
+ 2, // Silcoon
+ 0, // Beautifly
+ 2, // Cascoon
+ 1, // Dustox
+ 1, // Lotad
+ 1, // Lombre
+ 1, // Ludicolo
+ 1, // Seedot
+ 1, // Nuzleaf
+ 0, // Shiftry
+ 1, // Nincada
+ 1, // Ninjask
+ 1, // Shedinja
+ 2, // Taillow
+ 2, // Swellow
+ 1, // Shroomish
+ 1, // Breloom
+ 1, // Spinda
+ 0, // Wingull
+ 0, // Pelipper
+ 2, // Surskit
+ 0, // Masquerain
+ 2, // Wailmer
+ 0, // Wailord
+ 0, // Skitty
+ 2, // Delcatty
+ 1, // Kecleon
+ 1, // Baltoy
+ 0, // Claydol
+ 0, // Nosepass
+ 1, // Torkoal
+ 2, // Sableye
+ 0, // Barboach
+ 0, // Whiscash
+ 0, // Luvdisc
+ 0, // Corphish
+ 0, // Crawdaunt
+ 2, // Feebas
+ 0, // Milotic
+ 0, // Carvanha
+ 0, // Sharpedo
+ 1, // Trapinch
+ 1, // Vibrava
+ 1, // Flygon
+ 2, // Makuhita
+ 1, // Hariyama
+ 1, // Electrike
+ 0, // Manectric
+ 1, // Numel
+ 0, // Camerupt
+ 2, // Spheal
+ 2, // Sealeo
+ 0, // Walrein
+ 1, // Cacnea
+ 1, // Cacturne
+ 2, // Snorunt
+ 0, // Glalie
+ 1, // Lunatone
+ 0, // Solrock
+ 2, // Azurill
+ 0, // Spoink
+ 2, // Grumpig
+ 0, // Plusle
+ 0, // Minun
+ 2, // Mawile
+ 0, // Meditite
+ 0, // Medicham
+ 0, // Swablu
+ 0, // Altaria
+ 0, // Wynaut
+ 0, // Duskull
+ 0, // Dusclops
+ 0, // Roselia
+ 2, // Slakoth
+ 2, // Vigoroth
+ 1, // Slaking
+ 1, // Gulpin
+ 2, // Swalot
+ 1, // Tropius
+ 0, // Whismur
+ 2, // Loudred
+ 2, // Exploud
+ 0, // Clamperl
+ 0, // Huntail
+ 0, // Gorebyss
+ 0, // Absol
+ 0, // Shuppet
+ 0, // Banette
+ 2, // Seviper
+ 0, // Zangoose
+ 1, // Relicanth
+ 2, // Aron
+ 2, // Lairon
+ 2, // Aggron
+ 0, // Castform
+ 0, // Volbeat
+ 2, // Illumise
+ 2, // Lileep
+ 0, // Cradily
+ 0, // Anorith
+ 0, // Armaldo
+ 1, // Ralts
+ 1, // Kirlia
+ 1, // Gardevoir
+ 2, // Bagon
+ 2, // Shelgon
+ 0, // Salamence
+ 0, // Beldum
+ 0, // Metang
+ 0, // Metagross
+ 2, // Regirock
+ 2, // Regice
+ 2, // Registeel
+ 2, // Kyogre
+ 0, // Groudon
+ 1, // Rayquaza
+ 0, // Latias
+ 2, // Latios
+ 0, // Jirachi
+ 0, // Deoxys
+ 0, // Chimecho
+ 1, // Egg
+ 0, // Unown B
+ 0, // Unown C
+ 0, // Unown D
+ 0, // Unown E
+ 0, // Unown F
+ 0, // Unown G
+ 0, // Unown H
+ 0, // Unown I
+ 0, // Unown J
+ 0, // Unown K
+ 0, // Unown L
+ 0, // Unown M
+ 0, // Unown N
+ 0, // Unown O
+ 0, // Unown P
+ 0, // Unown Q
+ 0, // Unown R
+ 0, // Unown S
+ 0, // Unown T
+ 0, // Unown U
+ 0, // Unown V
+ 0, // Unown W
+ 0, // Unown X
+ 0, // Unown Y
+ 0, // Unown Z
+ 0, // Unown Exclamation Mark
+ 0, // Unown Question Mark
+};
+
+const struct SpritePalette gMonIconPaletteTable[] =
+{
+ { gMonIconPalettes[0], POKE_ICON_BASE_PAL_TAG + 0 },
+ { gMonIconPalettes[1], POKE_ICON_BASE_PAL_TAG + 1 },
+ { gMonIconPalettes[2], POKE_ICON_BASE_PAL_TAG + 2 },
+
+// There are only 3 actual palettes. The following are unused
+// and don't point to valid data.
+ { gMonIconPalettes[3], POKE_ICON_BASE_PAL_TAG + 3 },
+ { gMonIconPalettes[4], POKE_ICON_BASE_PAL_TAG + 4 },
+ { gMonIconPalettes[5], POKE_ICON_BASE_PAL_TAG + 5 },
+};
+
+static const struct OamData sMonIconOamData =
+{
+ .size = 2,
+ .priority = 1,
+};
+
+// fastest to slowest
+
+static const union AnimCmd sAnim_0[] =
+{
+ ANIMCMD_FRAME(0, 6),
+ ANIMCMD_FRAME(1, 6),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd sAnim_1[] =
+{
+ ANIMCMD_FRAME(0, 8),
+ ANIMCMD_FRAME(1, 8),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd sAnim_2[] =
+{
+ ANIMCMD_FRAME(0, 14),
+ ANIMCMD_FRAME(1, 14),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd sAnim_3[] =
+{
+ ANIMCMD_FRAME(0, 22),
+ ANIMCMD_FRAME(1, 22),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd sAnim_4[] =
+{
+ ANIMCMD_FRAME(0, 29),
+ ANIMCMD_FRAME(0, 29), // frame 0 is repeated
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd *const sMonIconAnims[] =
+{
+ sAnim_0,
+ sAnim_1,
+ sAnim_2,
+ sAnim_3,
+ sAnim_4,
+};
+
+static const union AffineAnimCmd sAffineAnim_0[] =
+{
+ AFFINEANIMCMD_FRAME(0, 0, 0, 10),
+ AFFINEANIMCMD_END,
+};
+
+static const union AffineAnimCmd sAffineAnim_1[] =
+{
+ AFFINEANIMCMD_FRAME(-2, -2, 0, 122),
+ AFFINEANIMCMD_END,
+};
+
+static const union AffineAnimCmd *const sMonIconAffineAnims[] =
+{
+ sAffineAnim_0,
+ sAffineAnim_1,
+};
+
+const u16 sSpriteImageSizes[3][4] =
+{
+ // square
+ {
+ 0x20, // 1×1
+ 0x80, // 2×2
+ 0x200, // 4×4
+ 0x800, // 8×8
+ },
+
+ // horizontal rectangle
+ {
+ 0x40, // 2×1
+ 0x80, // 4×1
+ 0x100, // 4×2
+ 0x400, // 8×4
+ },
+
+ // vertical rectangle
+ {
+ 0x40, // 1×2
+ 0x80, // 1×4
+ 0x100, // 2×4
+ 0x400, // 4×8
+ },
+};
+
+u16 GetUnownLetterByPersonality(u32);
+const u8 *GetMonIconPtr(u16, u32 personality);
+u8 UpdateMonIconFrame(struct Sprite *);
+u8 CreateMonIconSprite(struct MonIconSpriteTemplate *, s16, s16, u8);
+void sub_809D7E8(struct Sprite *);
+
+// duplicate of sub_809D3A4
+u8 unref_sub_809D26C(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority)
+{
+ u8 spriteId;
+ struct MonIconSpriteTemplate iconTemplate =
+ {
+ .oam = &sMonIconOamData,
+ .image = gMonIconTable[species],
+ .anims = sMonIconAnims,
+ .affineAnims = sMonIconAffineAnims,
+ .callback = callback,
+ .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species],
+ };
+
+ spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority);
+
+ UpdateMonIconFrame(&gSprites[spriteId]);
+
+ return spriteId;
+}
+
+u8 CreateMonIcon(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality)
+{
+ u8 spriteId;
+ struct MonIconSpriteTemplate iconTemplate =
+ {
+ .oam = &sMonIconOamData,
+ .image = GetMonIconPtr(species, personality),
+ .anims = sMonIconAnims,
+ .affineAnims = sMonIconAffineAnims,
+ .callback = callback,
+ .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species],
+ };
+
+ if (species > SPECIES_EGG)
+ iconTemplate.paletteTag = POKE_ICON_BASE_PAL_TAG;
+
+ spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority);
+
+ UpdateMonIconFrame(&gSprites[spriteId]);
+
+ return spriteId;
+}
+
+u8 sub_809D3A4(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority)
+{
+ u8 spriteId;
+ struct MonIconSpriteTemplate iconTemplate =
+ {
+ .oam = &sMonIconOamData,
+ .image = gMonIconTable[species],
+ .anims = sMonIconAnims,
+ .affineAnims = sMonIconAffineAnims,
+ .callback = callback,
+ .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species],
+ };
+
+ spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority);
+
+ UpdateMonIconFrame(&gSprites[spriteId]);
+
+ return spriteId;
+}
+
+u16 mon_icon_convert_unown_species_id(u16 species, u32 personality)
+{
+ u16 result;
+
+ if (species == SPECIES_UNOWN)
+ {
+ u16 letter = GetUnownLetterByPersonality(personality);
+ if (letter == 0)
+ letter = SPECIES_UNOWN;
+ else
+ letter += (SPECIES_UNOWN_B - 1);
+ result = letter;
+ }
+ else
+ {
+ if (species > SPECIES_EGG)
+ result = 260;
+ else
+ result = species;
+ }
+
+ return result;
+}
+
+u16 GetUnownLetterByPersonality(u32 personality)
+{
+ return (((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 0x1C;
+}
+
+u16 sub_809D4A8(u16 species)
+{
+ u16 value;
+
+ if (MailSpeciesToSpecies(species, &value) == SPECIES_UNOWN)
+ {
+ if (value == 0)
+ value += SPECIES_UNOWN;
+ else
+ value += (SPECIES_UNOWN_B - 1);
+ return value;
+ }
+ else
+ {
+ return mon_icon_convert_unown_species_id(species, 0);
+ }
+}
+
+const u8 *GetMonIconPtr(u16 species, u32 personality)
+{
+ u16 convertedSpecies = mon_icon_convert_unown_species_id(species, personality);
+ return gMonIconTable[convertedSpecies];
+}
+
+void sub_809D510(struct Sprite *sprite)
+{
+ sub_809D7E8(sprite);
+}
+
+void sub_809D51C(void)
+{
+ u8 i;
+ for (i = 0; i < 6; i++)
+ LoadSpritePalette(&gMonIconPaletteTable[i]);
+}
+
+// unused
+void SafeLoadMonIconPalette(u16 species)
+{
+ u8 palIndex;
+ if (species > SPECIES_EGG)
+ species = 260;
+ palIndex = gMonIconPaletteIndices[species];
+ if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF)
+ LoadSpritePalette(&gMonIconPaletteTable[palIndex]);
+}
+
+void sub_809D580(u16 species)
+{
+ u8 palIndex = gMonIconPaletteIndices[species];
+ if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF)
+ LoadSpritePalette(&gMonIconPaletteTable[palIndex]);
+}
+
+// unused
+void FreeMonIconPalettes(void)
+{
+ u8 i;
+ for (i = 0; i < 6; i++)
+ FreeSpritePaletteByTag(gMonIconPaletteTable[i].tag);
+}
+
+// unused
+void SafeFreeMonIconPalette(u16 species)
+{
+ u8 palIndex;
+ if (species > SPECIES_EGG)
+ species = 260;
+ palIndex = gMonIconPaletteIndices[species];
+ FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag);
+}
+
+void sub_809D608(u16 species)
+{
+ u8 palIndex;
+ palIndex = gMonIconPaletteIndices[species];
+ FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag);
+}
+
+void sub_809D62C(struct Sprite *sprite)
+{
+ UpdateMonIconFrame(sprite);
+}
+
+// TODO: try to find a way to avoid using asm statement
+u8 UpdateMonIconFrame(struct Sprite *sprite)
+{
+ u8 result = 0;
+
+ if (sprite->animDelayCounter == 0)
+ {
+ s16 frame = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue;
+
+ switch (frame)
+ {
+ case -1:
+ break;
+ case -2:
+ sprite->animCmdIndex = 0;
+ break;
+ default:
+ RequestSpriteCopy(
+ (u8 *)sprite->images + sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] * frame,
+ (u8 *)OBJ_VRAM0 + sprite->oam.tileNum * TILE_SIZE_4BPP,
+ sSpriteImageSizes[sprite->oam.shape][sprite->oam.size]);
+ {
+ register u8 duration asm("r0") = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration;
+ sprite->animDelayCounter = duration;
+ }
+ sprite->animCmdIndex++;
+ result = sprite->animCmdIndex;
+ break;
+ }
+ }
+ else
+ {
+ sprite->animDelayCounter--;
+ }
+ return result;
+}
+
+u8 CreateMonIconSprite(struct MonIconSpriteTemplate *iconTemplate, s16 x, s16 y, u8 subpriority)
+{
+ u8 spriteId;
+
+ struct SpriteFrameImage image = { NULL, sSpriteImageSizes[iconTemplate->oam->shape][iconTemplate->oam->size] };
+
+ struct SpriteTemplate spriteTemplate =
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = iconTemplate->paletteTag,
+ .oam = iconTemplate->oam,
+ .anims = iconTemplate->anims,
+ .images = &image,
+ .affineAnims = iconTemplate->affineAnims,
+ .callback = iconTemplate->callback,
+ };
+
+ spriteId = CreateSprite(&spriteTemplate, x, y, subpriority);
+ gSprites[spriteId].animPaused = TRUE;
+ gSprites[spriteId].animBeginning = FALSE;
+ gSprites[spriteId].images = (const struct SpriteFrameImage *)iconTemplate->image;
+ return spriteId;
+}
+
+void sub_809D7E8(struct Sprite *sprite)
+{
+ struct SpriteFrameImage image = { NULL, sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] };
+ sprite->images = &image;
+ DestroySprite(sprite);
+}
+
+void sub_809D824(struct Sprite *sprite, u8 animNum)
+{
+ sprite->animNum = animNum;
+ sprite->animDelayCounter = 0;
+ sprite->animCmdIndex = 0;
+}
diff --git a/src/pokemon/pokemon_menu.c b/src/pokemon/pokemon_menu.c
new file mode 100644
index 000000000..bc5150a16
--- /dev/null
+++ b/src/pokemon/pokemon_menu.c
@@ -0,0 +1,1200 @@
+#include "global.h"
+#include "pokemon.h"
+#include "pokemon_menu.h"
+#include "party_menu.h"
+#include "palette.h"
+#include "menu.h"
+#include "mail_data.h"
+#include "songs.h"
+#include "sound.h"
+#include "main.h"
+#include "overworld.h"
+#include "menu_helpers.h"
+#include "pokemon_summary_screen.h"
+#include "moves.h"
+#include "data2.h"
+#include "strings.h"
+#include "item_use.h"
+#include "item.h"
+#include "event_data.h"
+#include "mail.h"
+#include "field_player_avatar.h"
+#include "fldeff_softboiled.h"
+#include "braille_puzzles.h"
+#include "field_fadetransition.h"
+#include "field_weather.h"
+#include "field_effect.h"
+#include "field_control_avatar.h"
+#include "metatile_behavior.h"
+#include "fieldmap.h"
+#include "item_menu.h"
+#include "player_pc.h"
+
+/*
+Pokemon menu:
+ The menu that appears when you
+ click on a pokemon in
+ overworld 'pokemon' menu
+*/
+
+struct PokeMenuFieldMoveFunc
+{
+ bool8 (*func)(void);
+ u8 field_1;
+};
+
+extern u8 gUnknown_020384F0;
+extern u8 gUnknown_0202E8F4;
+extern u8 gUnknown_0202E8F5;
+extern u8 gUnknown_0202E8F6;
+extern u8 gUnknown_02038561;
+extern u16 gUnknown_0202E8F8;
+extern u8 ewram[];
+extern void (*gUnknown_03004AE4)(u8 taskID, u16 itemID, TaskFunc func);
+extern TaskFunc gUnknown_03005CF0;
+
+void sub_80E62A0(u8 arg0, struct MailStruct* arg1, void* arg2, u8 arg3);
+void sub_808A520(void);
+void sub_80A61D0(void);
+void CB2_InitFlyRegionMap(void);
+u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem);
+bool8 SetUpFieldMove_Cut(void);
+bool8 SetUpFieldMove_Flash(void);
+bool8 SetUpFieldMove_RockSmash(void);
+bool8 SetUpFieldMove_Strength(void);
+bool8 SetUpFieldMove_Teleport(void);
+bool8 SetUpFieldMove_Dig(void);
+bool8 SetUpFieldMove_SecretPower(void);
+bool8 SetUpFieldMove_SoftBoiled(void);
+bool8 SetUpFieldMove_SoftBoiled(void);
+bool8 SetUpFieldMove_SweetScent(void);
+
+#define sFieldMovesTerminator 0xFF // note: should be changed to 0xFFFF, because currently it makes it impossible to add a field move with 0xFF index
+
+// this file's functions
+static void sub_808A8A8(void);
+static void sub_808B3EC(void);
+static void sub_8089D94(u8 taskID);
+static void sub_8089E4C(u8 taskID);
+static void sub_808A5BC(u8 taskID);
+static void sub_808A8D4(u8 taskID);
+static void sub_808A73C(u8 taskID);
+static void sub_808A848(u8 taskID);
+static void sub_808AAF0(u8 taskID);
+static void sub_808ABF4(u8 taskID);
+static void sub_808AB34(u8 taskID);
+static void sub_808ABA8(u8 taskID);
+static void sub_808B224(u8 taskID);
+static void sub_808B2EC(u8 taskID);
+static void sub_808B2B4(u8 taskID);
+static void sub_808B25C(u8 taskID);
+static void sub_808B1EC(u8 taskID);
+static void sub_808B338(u8 taskID);
+static void sub_808B4A4(u8 taskID);
+static void sub_808B4EC(u8 taskID);
+static void sub_808B5E4(u8 taskID);
+static void PokemonMenu_Summary(u8 taskID);
+static void PokemonMenu_Switch(u8 taskID);
+static void PokemonMenu_Item(u8 taskID);
+static void PokemonMenu_Cancel(u8 taskID);
+static void PokemonMenu_GiveItem(u8 taskID);
+static void PokemonMenu_TakeItem(u8 taskID);
+static void PokemonMenu_TakeMail(u8 taskID);
+static void PokemonMenu_Mail(u8 taskID);
+static void PokemonMenu_ReadMail(u8 taskID);
+static void PokemonMenu_CancelSubmenu(u8 taskID);
+static void PokemonMenu_FieldMove(u8 taskID);
+static bool8 SetUpFieldMove_Waterfall(void);
+static bool8 SetUpFieldMove_Surf(void);
+static bool8 SetUpFieldMove_Fly(void);
+static bool8 SetUpFieldMove_Dive(void);
+
+// ewram data
+
+EWRAM_DATA static u8 sPokeMenuCursorPos = 0;
+EWRAM_DATA static u8 sPokeMenuOptionsNo = 0;
+EWRAM_DATA static u8 sPokeMenuOptionsOrder[8] = {0}; // 4 possible field moves and 4 default options
+
+// iwram common
+u8 gLastFieldPokeMenuOpened;
+void (*gUnknown_03005CE4)(void);
+
+// const data
+
+static const struct MenuAction2 sPokemonMenuActions[] =
+{
+ {OtherText_Summary, PokemonMenu_Summary},
+ {OtherText_Switch2, PokemonMenu_Switch},
+ {OtherText_Item, PokemonMenu_Item},
+ {gOtherText_CancelNoTerminator, PokemonMenu_Cancel},
+ {OtherText_Give2, PokemonMenu_GiveItem},
+ {OtherText_Take2, PokemonMenu_TakeItem},
+ {OtherText_Take, PokemonMenu_TakeMail},
+ {OtherText_Mail, PokemonMenu_Mail},
+ {OtherText_Read2, PokemonMenu_ReadMail},
+ {gOtherText_CancelNoTerminator, PokemonMenu_CancelSubmenu},
+ {gMoveNames[MOVE_CUT], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_FLASH], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_ROCK_SMASH], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_STRENGTH], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_SURF], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_FLY], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_DIVE], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_WATERFALL], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_TELEPORT], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_DIG], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_SECRET_POWER], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_MILK_DRINK], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_SOFT_BOILED], PokemonMenu_FieldMove},
+ {gMoveNames[MOVE_SWEET_SCENT], PokemonMenu_FieldMove},
+};
+
+static const u16 sPokeMenuFieldMoves[] =
+{
+ MOVE_CUT, MOVE_FLASH, MOVE_ROCK_SMASH, MOVE_STRENGTH,
+ MOVE_SURF, MOVE_FLY, MOVE_DIVE, MOVE_WATERFALL,
+ MOVE_TELEPORT, MOVE_DIG, MOVE_SECRET_POWER, MOVE_MILK_DRINK,
+ MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, sFieldMovesTerminator,
+};
+
+static const u8 sUnknown_39F572[] = {4, 5, 9, 0};
+static const struct PartyPopupMenu sUnknown_0839F578 = {3, 6, sUnknown_39F572};
+
+static const u8 sUnknown_39F580[] = {8, 6, 9, 0};
+static const struct PartyPopupMenu sUnknown_0839F584 = {3, 9, sUnknown_39F580};
+
+static const struct PokeMenuFieldMoveFunc sFieldMoveFuncs[] =
+{
+ {SetUpFieldMove_Cut, 0x6},
+ {SetUpFieldMove_Flash, 0x9},
+ {SetUpFieldMove_RockSmash, 0x9},
+ {SetUpFieldMove_Strength, 0x9},
+ {SetUpFieldMove_Surf, 0x7},
+ {SetUpFieldMove_Fly, 0x9},
+ {SetUpFieldMove_Dive, 0x9},
+ {SetUpFieldMove_Waterfall, 0x9},
+ {SetUpFieldMove_Teleport, 0x9},
+ {SetUpFieldMove_Dig, 0x9},
+ {SetUpFieldMove_SecretPower, 0x9},
+ {SetUpFieldMove_SoftBoiled, 0x10},
+ {SetUpFieldMove_SoftBoiled, 0x10},
+ {SetUpFieldMove_SweetScent, 0x9},
+};
+
+void sub_8089A70(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ OpenPartyMenu(0, 0);
+}
+
+static void sub_8089A8C(void)
+{
+ sPokeMenuOptionsNo = 0;
+ // if checking pokemon is an egg, we can't give it an item and it doesn't know any move
+ if (GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_IS_EGG))
+ {
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_SUMMARY);
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_SWITCH);
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_CANCEL);
+ }
+ else
+ {
+ u16 moveID, tableID;
+ for (moveID = 0; moveID < 4; moveID++) // 4, max number of possible field moves
+ {
+ for (tableID = 0; sPokeMenuFieldMoves[tableID] != sFieldMovesTerminator; tableID++)
+ {
+ if (GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_MOVE1 + moveID) == sPokeMenuFieldMoves[tableID])
+ {
+ u8 fieldID = tableID + POKEMENU_FIRST_FIELD_MOVE_ID;
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, fieldID);
+ break;
+ }
+ }
+ }
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_SUMMARY);
+
+ // can't switch a pokemon if it's the only one in the party
+ if (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) != 0)
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_SWITCH);
+
+ if (ItemIsMail(GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HELD_ITEM)))
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_MAIL);
+ else
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_ITEM);
+
+ AppendToList(sPokeMenuOptionsOrder, &sPokeMenuOptionsNo, POKEMENU_CANCEL);
+ }
+}
+
+static void sub_8089BDC(u8 arg0, u8 arg1, u8 arg2, u8 noOfOptions, const struct MenuAction2 *menuActions, const u8 *order, u8 arg6)
+{
+ sub_806D538(5, arg6);
+ MenuDrawTextWindow(arg0, arg1, arg0 + arg2, (noOfOptions * 2) + arg1 + 1);
+ PrintMenuItemsReordered(arg0 + 1, arg1 + 1, noOfOptions, menuActions, order);
+}
+
+void sub_8089C50(u8 arg0, u8 arg1, u8 arg2, u8 noOfOptions, const struct MenuAction2 *menuActions, const u8 *order)
+{
+ sub_8089BDC(arg0, arg1, arg2, noOfOptions, menuActions, order, 1);
+}
+
+static void sub_8089C7C(u8 arg0)
+{
+ u32 r4 = (u8)(18 - (sPokeMenuOptionsNo << 1));
+
+ sub_8089BDC(19, r4, 10, sPokeMenuOptionsNo, sPokemonMenuActions, sPokeMenuOptionsOrder, 3);
+ r4 |= 1;
+ InitMenu(0, 20, r4, sPokeMenuOptionsNo, arg0, 9);
+}
+
+void sub_8089CD4(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (sub_806BD80(taskID))
+ {
+ case 1:
+ PlaySE(SE_SELECT);
+ gLastFieldPokeMenuOpened = sub_806CA38(taskID);
+ GetMonNickname(&gPlayerParty[gLastFieldPokeMenuOpened], gStringVar1);
+ sub_8089A8C();
+ sPokeMenuCursorPos = 0;
+ sub_8089C7C(0);
+ gTasks[taskID].func = sub_8089D94;
+ sub_808B5B4(taskID);
+ break;
+ case 2:
+ PlaySE(SE_SELECT);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_8089E4C;
+ break;
+ }
+ }
+}
+
+static void sub_8089D94(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP)
+ {
+ PlaySE(SE_SELECT);
+ sPokeMenuCursorPos = MoveMenuCursor(-1);
+ sub_808B5B4(taskID);
+ }
+ else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN)
+ {
+ PlaySE(SE_SELECT);
+ sPokeMenuCursorPos = MoveMenuCursor(1);
+ sub_808B5B4(taskID);
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ sPokemonMenuActions[sPokeMenuOptionsOrder[sPokeMenuCursorPos]].func(taskID);
+ sub_808B5B4(taskID);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PokemonMenu_Cancel(taskID);
+ sub_808B5B4(taskID);
+ }
+ }
+}
+
+static void sub_8089E4C(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ gLastFieldPokeMenuOpened = 0;
+ SetMainCallback2(sub_805469C);
+ DestroyTask(taskID);
+ }
+}
+
+static void sub_8089E84(void)
+{
+ GetMonNickname(&gPlayerParty[gLastFieldPokeMenuOpened], gStringVar1);
+ sub_8089A8C();
+ sPokeMenuCursorPos = 0;
+ sub_8089C7C(0);
+}
+
+static void sub_8089EBC(void)
+{
+ do
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gUnknown_020384F0);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ gLastFieldPokeMenuOpened = gUnknown_020384F0;
+ sub_8089E84();
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ } while (sub_80F9344() != TRUE);
+}
+
+static void sub_8089F14(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ sub_806AF4C(0, 0xFF, sub_8089D94, 5);
+ SetMainCallback2(sub_8089EBC);
+}
+
+static void sub_8089F44(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 spriteID = gSprites[gTasks[taskID].data[3] >> 8].data0;
+ DestroyTask(taskID);
+ ewram1B000_alt.unk262 = 1;
+ ShowPokemonSummaryScreen(gPlayerParty, spriteID, gPlayerPartyCount - 1, sub_8089F14, 0);
+ }
+}
+
+static void PokemonMenu_Summary(u8 taskID)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_8089F44;
+}
+
+void sub_808A004(u8 taskID)
+{
+ SetTaskFuncWithFollowupFunc(taskID, sub_806CA60, sub_8089CD4);
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+}
+
+static void PokemonMenu_Switch(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ ewram01000.unkC = sub_806CD5C;
+ ewram01000.array[53553] = 1;
+ sub_808A004(taskID);
+}
+
+static void sub_808A060(u8 taskID)
+{
+ if (gMain.newKeys == DPAD_UP && sPokeMenuCursorPos != 0)
+ {
+ sPokeMenuCursorPos = MoveMenuCursor(-1);
+ PlaySE(SE_SELECT);
+ }
+ if (gMain.newKeys == DPAD_DOWN && sPokeMenuCursorPos != 2)
+ {
+ sPokeMenuCursorPos = MoveMenuCursor(1);
+ PlaySE(SE_SELECT);
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ PartyMenuGetPopupMenuFunc(0, &sUnknown_0839F578, (void *)sPokemonMenuActions, sPokeMenuCursorPos)(taskID);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ sub_806E7D0(0, &sUnknown_0839F578);
+ PokemonMenu_CancelSubmenu(taskID);
+ }
+}
+
+static void sub_808A100(u8 taskID)
+{
+ sub_806E750(0, &sUnknown_0839F578, (void*)(sPokemonMenuActions), 0);
+ sub_806D538(0xD, 2);
+ gTasks[taskID].func = sub_808A060;
+}
+
+static void PokemonMenu_Item(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ sPokeMenuCursorPos = 0;
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ gTasks[taskID].func = sub_808A100;
+}
+
+static void sub_808A180(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 mailID = GetMonData(&gPlayerParty[sub_806CA38(taskID)], MON_DATA_MAIL);
+ DestroyTask(taskID);
+ sub_80E62A0(4, &gSaveBlock1.mail[mailID], sub_808A520, 3);
+ }
+}
+
+static void sub_808A1E0(u8 taskID)
+{
+ if (gUnknown_0202E8F6 != 1)
+ {
+ SetHeldItemIconVisibility(taskID, sub_806CA38(taskID));
+ sub_806D538(0, 0);
+ gTasks[taskID].func = sub_8089CD4;
+ }
+}
+
+static void sub_808A228(u8 taskID)
+{
+ if (ItemIsMail(gScriptItemId) && gUnknown_0202E8F4 != 0)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808A180;
+ }
+ else
+ {
+ MenuZeroFillWindowRect(0, 0, 29, 19);
+ sub_806D538(0, 0);
+ gTasks[taskID].func = sub_8089CD4;
+ }
+}
+
+static void sub_808A2AC(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ PartyMenuTryGiveMonHeldItem(taskID, gScriptItemId, sub_808A228);
+}
+
+static void sub_808A2DC(u8 taskID)
+{
+ u8 mailID = GetMonData(&gPlayerParty[sub_806CA38(taskID)], MON_DATA_MAIL);
+ DestroyTask(taskID);
+ sub_80E62A0(4, &gSaveBlock1.mail[mailID], sub_808A520, 3);
+}
+
+static void sub_808A330(u8 taskID)
+{
+ PartyMenuTryGiveMonHeldItem(taskID, gScriptItemId, sub_808A2DC);
+}
+
+static void sub_808A34C(void)
+{
+ RunTasks();
+}
+
+static void sub_808A358(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+static void sub_808A3A4(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ EWRAM_1B000.unk262 = 3;
+ sub_8089E84();
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+void sub_808A3F8(void)
+{
+ if (ItemIsMail(gScriptItemId))
+ {
+ u8 taskID = CreateTask(sub_808A330, 0);
+ gPaletteFade.bufferTransferDisabled = 1;
+ sub_806BD58(taskID, 0);
+ sub_806C994(taskID, gLastFieldPokeMenuOpened);
+ sub_806BF74(taskID, 0);
+ if (!(bool8)(GetMonData(&gPlayerParty[sub_806CA38(taskID)], MON_DATA_HELD_ITEM)))
+ {
+ SetMainCallback2(sub_808A34C);
+ return;
+ }
+ else
+ DestroyTask(taskID);
+ }
+ gPaletteFade.bufferTransferDisabled = 1;
+ if (gScriptItemId)
+ {
+ sub_806AF4C(0, 0xFF, sub_808A2AC, 0xFF);
+ SetMainCallback2(sub_808A358);
+ }
+ else
+ {
+ sub_806AF4C(0, 0xFF, sub_8089D94, 5);
+ SetMainCallback2(sub_808A3A4);
+ }
+}
+
+static void sub_808A4D4(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+void sub_808A520(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ if (gScriptResult == 0)
+ {
+ if (gUnknown_0202E8F8)
+ RemoveBagItem(gUnknown_0202E8F8, 1);
+ AddBagItem(GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HELD_ITEM), 1);
+ TakeMailFromMon(&gPlayerParty[gLastFieldPokeMenuOpened]);
+ SetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HELD_ITEM, (void*) &gUnknown_0202E8F8);
+ sub_806AF4C(0, 0xFF, sub_8089CD4, 0);
+ }
+ else
+ sub_806AF4C(0, 0xFF, sub_808A5BC, 0xFF);
+ SetMainCallback2(sub_808A4D4);
+}
+
+static void sub_808A5BC(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ DisplayGiveHeldItemMessage(gLastFieldPokeMenuOpened, gScriptItemId, 0);
+ gTasks[taskID].func = sub_808A1E0;
+ }
+}
+
+static void sub_808A604(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(sub_80A61D0);
+ DestroyTask(taskID);
+ }
+}
+
+static void PokemonMenu_GiveItem(u8 taskID)
+{
+ gUnknown_0202E8F5 = sub_806CA38(taskID);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808A604;
+}
+
+static void sub_808A678(u8 taskID)
+{
+ sub_808A8D4(taskID);
+}
+
+static void PokemonMenu_TakeItem(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806D5A4();
+ PartyMenuTryGiveMonHeldItem_806ECE8(taskID, sub_808A678);
+}
+
+static void PokemonMenu_TakeMail(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806D5A4();
+ DoTakeMail(taskID, sub_808A678);
+}
+
+static void PokemonMenu_Mail(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ sPokeMenuCursorPos = 0;
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806E750(0, &sUnknown_0839F584, (void*) sPokemonMenuActions, 0);
+ gTasks[taskID].func = sub_808A73C;
+}
+
+static void sub_808A73C(u8 taskID)
+{
+ if (gMain.newAndRepeatedKeys == DPAD_UP)
+ {
+ PlaySE(SE_SELECT);
+ if (sPokeMenuCursorPos == 0)
+ sPokeMenuCursorPos = MoveMenuCursor(sUnknown_0839F584.unk0 - 1);
+ else
+ sPokeMenuCursorPos = MoveMenuCursor(-1);
+ }
+ if (gMain.newAndRepeatedKeys == DPAD_DOWN)
+ {
+ PlaySE(SE_SELECT);
+ if (sPokeMenuCursorPos == sUnknown_0839F584.unk0 - 1)
+ sPokeMenuCursorPos = MoveMenuCursor(1 - sUnknown_0839F584.unk0);
+ else
+ sPokeMenuCursorPos = MoveMenuCursor(1);
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ PartyMenuGetPopupMenuFunc(0, &sUnknown_0839F584, (void*) sPokemonMenuActions, sPokeMenuCursorPos)(taskID);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ sub_806E7D0(0, &sUnknown_0839F584);
+ PokemonMenu_Cancel(taskID);
+ }
+}
+
+static void PokemonMenu_ReadMail(u8 taskID)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808A848;
+}
+
+static void sub_808A848(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 mailID = GetMonData(&gPlayerParty[sub_806CA38(taskID)], MON_DATA_MAIL);
+ DestroyTask(taskID);
+ HandleReadMail(&gSaveBlock1.mail[mailID], sub_808A8A8, 1);
+ }
+}
+
+static void sub_808A8A8(void)
+{
+ gUnknown_020384F0 = gLastFieldPokeMenuOpened;
+ ewram1B000.unk262 = 4;
+ sub_8089F14();
+}
+
+static void sub_808A8D4(u8 taskID)
+{
+ sPokeMenuCursorPos = 0;
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806D538(0, 0);
+ gTasks[taskID].func = sub_8089CD4;
+}
+
+static void PokemonMenu_Cancel(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ PlaySE(SE_SELECT);
+ sub_808A8D4(taskID);
+}
+
+static void PokemonMenu_CancelSubmenu(u8 taskID)
+{
+ HandleDestroyMenuCursors();
+ PlaySE(SE_SELECT);
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806D5A4();
+ sub_8089C7C(sPokeMenuCursorPos);
+ gTasks[taskID].func = sub_8089D94;
+}
+
+#define IS_SOFTBOILED_MILKDRINK(ID)((ID == (POKEMENU_MILK_DRINK - POKEMENU_FIRST_FIELD_MOVE_ID) || ID == (POKEMENU_SOFT_BOILED - POKEMENU_FIRST_FIELD_MOVE_ID)))
+#define IS_SURF(ID)((ID == (POKEMENU_SURF - POKEMENU_FIRST_FIELD_MOVE_ID)))
+#define IS_FLY(ID)((ID == (POKEMENU_FLY - POKEMENU_FIRST_FIELD_MOVE_ID)))
+
+#define tFieldMoveId data[11]
+
+static void PokemonMenu_FieldMove(u8 taskID)
+{
+ s16* data = gTasks[taskID].data;
+
+ HandleDestroyMenuCursors();
+ tFieldMoveId = sPokeMenuOptionsOrder[sPokeMenuCursorPos] - POKEMENU_FIRST_FIELD_MOVE_ID;
+ if (sub_80F9344() == TRUE)
+ {
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ if (IS_SOFTBOILED_MILKDRINK(tFieldMoveId))
+ sub_806D538(9, 0);
+ else
+ sub_806D538(sFieldMoveFuncs[tFieldMoveId].field_1, 0);
+ gTasks[taskID].func = sub_808ABF4;
+ }
+ else if (tFieldMoveId <= 7 && FlagGet(BADGE01_GET + tFieldMoveId) != TRUE)
+ {
+ // can't use a field HM move without a proper badge
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ sub_806D5A4();
+ sub_806E834(gOtherText_CantBeUsedBadge, 1);
+ gTasks[taskID].func = sub_808AAF0;
+ }
+ else
+ {
+ if (sFieldMoveFuncs[tFieldMoveId].func() == TRUE)
+ {
+ sPokeMenuCursorPos = 0;
+ if (!IS_SOFTBOILED_MILKDRINK(tFieldMoveId))
+ {
+ gTasks[taskID].func = sub_808AB34;
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ }
+ else
+ sub_8133D28(taskID);
+ }
+ else
+ {
+ MenuZeroFillWindowRect(19, 0, 29, 19);
+ if (IS_SURF(tFieldMoveId) && TestPlayerAvatarFlags(8))
+ sub_806D538(8, 0);
+ else
+ sub_806D538(sFieldMoveFuncs[tFieldMoveId].field_1, 0);
+ gTasks[taskID].func = sub_808ABF4;
+ }
+ }
+}
+
+static void sub_808AAF0(u8 taskID)
+{
+ if (gUnknown_0202E8F6 != 1 && (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON))
+ {
+ MenuZeroFillWindowRect(0, 14, 29, 19);
+ PokemonMenu_Cancel(taskID);
+ }
+}
+
+static void sub_808AB34(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ if (!IS_FLY(gTasks[taskID].tFieldMoveId) || ShouldDoBrailleFlyEffect())
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ else
+ SetMainCallback2(CB2_InitFlyRegionMap);
+ DestroyTask(taskID);
+ }
+}
+
+#undef tFieldMoveId
+
+void FieldCallback_Teleport(void)
+{
+ pal_fill_black();
+ CreateTask(sub_808ABA8, 8);
+}
+
+static void sub_808ABA8(u8 taskID)
+{
+ if (sub_807D770() == TRUE)
+ {
+ gFieldEffectArguments[0] = GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_SPECIES);
+ gUnknown_03005CE4();
+ DestroyTask(taskID);
+ }
+}
+
+static void sub_808ABF4(u8 taskID)
+{
+ if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON)
+ {
+ MenuZeroFillWindowRect(1, 17, 28, 18);
+ PokemonMenu_Cancel(taskID);
+ }
+}
+
+static void sub_808AC2C(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ FieldEffectStart(FLDEFF_USE_SURF);
+}
+
+static bool8 SetUpFieldMove_Surf(void)
+{
+ if (PartyHasMonWithSurf() == TRUE && IsPlayerFacingSurfableFishableWater() == TRUE)
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_808AC2C;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void sub_808AC8C(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ FieldEffectStart(FLDEFF_USE_FLY);
+}
+
+static bool8 SetUpFieldMove_Fly(void)
+{
+ if (ShouldDoBrailleFlyEffect())
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = DoBrailleFlyEffect;
+ return TRUE;
+ }
+ if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE)
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_808AC8C;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_808AD0C(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+void sub_808AD58(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ sub_806AF4C(0, 0xFF, sub_8089CD4, 0);
+ SetMainCallback2(sub_808AD0C);
+}
+
+u16 unref_sub_808AD88(void)
+{
+ return GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_SPECIES);
+}
+
+static void sub_808ADAC(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ FieldEffectStart(FLDEFF_USE_DIVE);
+}
+
+static bool8 SetUpFieldMove_Dive(void)
+{
+ gFieldEffectArguments[1] = sub_8068F18();
+ if (gFieldEffectArguments[1])
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_808ADAC;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void sub_808AE08(void)
+{
+ gFieldEffectArguments[0] = gLastFieldPokeMenuOpened;
+ FieldEffectStart(FLDEFF_USE_WATERFALL);
+}
+
+static bool8 SetUpFieldMove_Waterfall(void)
+{
+ s16 x, y;
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ if (MetatileBehavior_IsWaterfall(MapGridGetMetatileBehaviorAt(x, y)) == TRUE
+ && IsPlayerSurfingNorth() == TRUE)
+ {
+ gFieldCallback = FieldCallback_Teleport;
+ gUnknown_03005CE4 = sub_808AE08;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void sub_808AE8C(void)
+{
+ u8 i;
+ u8 arg = gScriptItemId - 33;
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES))
+ {
+ sub_806D668(i);
+ if (GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) || !CanMonLearnTMHM(&gPlayerParty[i], arg))
+ sub_806BC3C(i, 0x9A);
+ else if (pokemon_has_move(&gPlayerParty[i], ItemIdToBattleMoveId(gScriptItemId)))
+ sub_806BC3C(i, 0xA8);
+ else
+ sub_806BC3C(i, 0x8C);
+ }
+ }
+}
+
+static void sub_808AF20(void)
+{
+ u8 i;
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES))
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) || !GetEvolutionTargetSpecies(&gPlayerParty[i], 3, gScriptItemId))
+ {
+ sub_806D668(i);
+ sub_806BC3C(i, 0);
+ }
+ }
+ }
+}
+
+static void sub_808AF80(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ if (gUnknown_02038561 == 0)
+ {
+ switch (CheckIfItemIsTMHMOrEvolutionStone(gScriptItemId))
+ {
+ case 1:
+ sub_808AE8C();
+ break;
+ case 2:
+ sub_808AF20();
+ break;
+ }
+ }
+ if (gLastFieldPokeMenuOpened > 5 || !GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_SPECIES))
+ gLastFieldPokeMenuOpened = 0;
+ sub_806C994(ewram1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(ewram1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+void sub_808B020(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ switch (gUnknown_02038561)
+ {
+ case 0:
+ if (CheckIfItemIsTMHMOrEvolutionStone(gScriptItemId) == 1)
+ sub_806AF4C(0, 0, sub_808B0C0, 20);
+ else
+ sub_806AF4C(0, 0, sub_808B0C0, 3);
+ break;
+ case 4:
+ sub_806AF4C(0, 0, sub_808B1EC, 0xFF);
+ break;
+ case 1:
+ case 3:
+ sub_806AF4C(0, 0, sub_808B0C0, 4);
+ break;
+ }
+ SetMainCallback2(sub_808AF80);
+}
+
+void sub_808B0C0(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ switch (sub_806BD80(taskID))
+ {
+ case 1:
+ gLastFieldPokeMenuOpened = sub_806CA38(taskID);
+ if (GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_IS_EGG))
+ PlaySE(SE_HAZURE);
+ else
+ {
+ sub_806D5A4();
+ if (gUnknown_02038561 == 0)
+ gUnknown_03004AE4(taskID, gScriptItemId, sub_808B224);
+ if (gUnknown_02038561 == 1)
+ {
+ PlaySE(SE_SELECT);
+ PartyMenuTryGiveMonHeldItem(taskID, gScriptItemId, sub_808B2EC);
+ }
+ if (gUnknown_02038561 == 3)
+ {
+ PlaySE(SE_SELECT);
+ PartyMenuTryGiveMonMail(taskID, sub_808B2B4);
+ }
+ }
+ break;
+ case 2:
+ gLastFieldPokeMenuOpened = sub_806CA38(taskID);
+ PlaySE(SE_SELECT);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ if (gUnknown_02038561 == 0 || gUnknown_02038561 == 1)
+ gTasks[taskID].func = sub_808B25C;
+ if (gUnknown_02038561 == 3)
+ gTasks[taskID].func = sub_808B2B4;
+ break;
+ }
+ }
+}
+
+static void sub_808B1EC(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ gUnknown_03004AE4(taskID, gScriptItemId, sub_808B224);
+}
+
+static void sub_808B224(u8 taskID)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808B25C;
+}
+
+static void sub_808B25C(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(sub_80A5B40);
+ DestroyTask(taskID);
+ }
+}
+
+static void sub_808B288(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(Mailbox_ReturnToMailListAfterDeposit);
+ DestroyTask(taskID);
+ }
+}
+
+static void sub_808B2B4(u8 taskID)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808B288;
+}
+
+static void sub_808B2EC(u8 taskID)
+{
+ if (gUnknown_0202E8F4 == 2)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskID].func = sub_808B338;
+ }
+ else
+ sub_808B224(taskID);
+}
+
+static void sub_808B338(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 mailID;
+
+ gLastFieldPokeMenuOpened = sub_806CA38(taskID);
+ mailID = GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_MAIL);
+ DestroyTask(taskID);
+ sub_80E62A0(4, &gSaveBlock1.mail[mailID], sub_808B3EC, 3);
+ }
+}
+
+static void sub_808B3A0(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gLastFieldPokeMenuOpened);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+static void sub_808B3EC(void)
+{
+ IntrCallback callback;
+
+ gPaletteFade.bufferTransferDisabled = 1;
+ if (gScriptResult == 0)
+ {
+ if (gUnknown_0202E8F8)
+ RemoveBagItem(gUnknown_0202E8F8, 1);
+ AddBagItem(GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HELD_ITEM), 1);
+ TakeMailFromMon(&gPlayerParty[gLastFieldPokeMenuOpened]);
+ SetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HELD_ITEM, (void*) &gUnknown_0202E8F8);
+ CreateTask(sub_808B25C, 5);
+ gPaletteFade.bufferTransferDisabled = 0;
+ callback = sub_806AEDC;
+ }
+ else
+ {
+ sub_806AF4C(0, 0, sub_808B4A4, 0xFF);
+ callback = sub_808B3A0;
+ }
+ SetMainCallback2(callback);
+}
+
+static void sub_808B4A4(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ DisplayGiveHeldItemMessage(gLastFieldPokeMenuOpened, gScriptItemId, 1);
+ gTasks[taskID].func = sub_808B4EC;
+ }
+}
+
+static void sub_808B4EC(u8 taskID)
+{
+ if (gUnknown_0202E8F6 != 1)
+ sub_808B224(taskID);
+}
+
+void sub_808B508(u8 taskID)
+{
+ sub_808B224(taskID);
+}
+
+static void sub_808B518(void)
+{
+ while (1)
+ {
+ if (sub_806B124() == TRUE)
+ {
+ sub_806C994(EWRAM_1B000.unk260, gUnknown_020384F0);
+ sub_806BF74(EWRAM_1B000.unk260, 0);
+ SetMainCallback2(sub_806AEDC);
+ break;
+ }
+ if (sub_80F9344() == TRUE)
+ break;
+ }
+}
+
+void sub_808B564(void)
+{
+ gPaletteFade.bufferTransferDisabled = 1;
+ if (sub_809FA30() != 4)
+ sub_806AF4C(0, 0, TaughtMove, 0xFF);
+ else
+ sub_806AF4C(0, 0, StopTryingToTeachMove_806F588, 0xFF);
+ SetMainCallback2(sub_808B518);
+}
+
+void sub_808B5B4(u32 taskID)
+{
+ gUnknown_03005CF0 = gTasks[taskID].func;
+ gTasks[taskID].func = sub_808B5E4;
+ sub_808B5E4(taskID);
+}
+
+static void sub_808B5E4(u8 taskID)
+{
+ if (sub_8055870() != TRUE)
+ gTasks[taskID].func = gUnknown_03005CF0;
+}
diff --git a/src/pokemon/pokemon_size_record.c b/src/pokemon/pokemon_size_record.c
new file mode 100644
index 000000000..f2222bd3b
--- /dev/null
+++ b/src/pokemon/pokemon_size_record.c
@@ -0,0 +1,217 @@
+#include "global.h"
+#include "pokemon_size_record.h"
+#include "data2.h"
+#include "event_data.h"
+#include "pokedex.h"
+#include "species.h"
+#include "string_util.h"
+#include "strings2.h"
+#include "text.h"
+
+struct UnknownStruct
+{
+ u16 unk0;
+ u8 unk2;
+ u16 unk4;
+};
+
+extern u16 gScriptResult;
+
+static const struct UnknownStruct sBigMonSizeTable[] =
+{
+ { 290, 1, 0 },
+ { 300, 1, 10 },
+ { 400, 2, 110 },
+ { 500, 4, 310 },
+ { 600, 20, 710 },
+ { 700, 50, 2710 },
+ { 800, 100, 7710 },
+ { 900, 150, 17710 },
+ { 1000, 150, 32710 },
+ { 1100, 100, -17826 },
+ { 1200, 50, -7826 },
+ { 1300, 20, -2826 },
+ { 1400, 5, -826 },
+ { 1500, 2, -326 },
+ { 1600, 1, -126 },
+ { 1700, 1, -26 },
+};
+
+#define CM_PER_INCH 2.54
+
+static u32 GetMonSizeHash(struct Pokemon *pkmn)
+{
+ // UB: Too few arguments for function 'GetMonData'
+ u16 personality = GetMonData(pkmn, MON_DATA_PERSONALITY);
+ u16 hpIV = GetMonData(pkmn, MON_DATA_HP_IV) & 0xF;
+ u16 attackIV = GetMonData(pkmn, MON_DATA_ATK_IV) & 0xF;
+ u16 defenseIV = GetMonData(pkmn, MON_DATA_DEF_IV) & 0xF;
+ u16 speedIV = GetMonData(pkmn, MON_DATA_SPD_IV) & 0xF;
+ u16 spAtkIV = GetMonData(pkmn, MON_DATA_SPATK_IV) & 0xF;
+ u16 spDefIV = GetMonData(pkmn, MON_DATA_SPDEF_IV) & 0xF;
+ u32 hibyte = ((attackIV ^ defenseIV) * hpIV) ^ (personality & 0xFF);
+ u32 lobyte = ((spAtkIV ^ spDefIV) * speedIV) ^ (personality >> 8);
+
+ return (hibyte << 8) + lobyte;
+}
+
+static u8 TranslateBigMonSizeTableIndex(u16 a)
+{
+ u8 i;
+
+ for (i = 1; i < 15; i++)
+ {
+ if (a < sBigMonSizeTable[i].unk4)
+ return i - 1;
+ }
+ return i;
+}
+
+static u32 GetMonSize(u16 species, u16 b)
+{
+ u64 unk2;
+ u64 unk4;
+ u64 unk0;
+ u32 height;
+ u32 var;
+
+ height = GetPokedexHeightWeight(SpeciesToNationalPokedexNum(species), 0);
+ var = TranslateBigMonSizeTableIndex(b);
+ unk0 = sBigMonSizeTable[var].unk0;
+ unk2 = sBigMonSizeTable[var].unk2;
+ unk4 = sBigMonSizeTable[var].unk4;
+ unk0 += (b - unk4) / unk2;
+ return height * unk0 / 10;
+}
+
+static void FormatMonSizeRecord(u8 *string, u32 size)
+{
+#if ENGLISH
+ u8 decimalPoint[] = _(".");
+#elif GERMAN
+ u8 decimalPoint[] = _(",");
+#endif
+
+#ifdef UNITS_IMPERIAL
+ //Convert size from centimeters to inches
+ size = (double)(size * 10) / (CM_PER_INCH * 10);
+#endif
+
+ string = ConvertIntToDecimalStringN(string, size / 10, 0, 8);
+ string = StringAppend(string, decimalPoint);
+ ConvertIntToDecimalStringN(string, size % 10, 0, 1);
+}
+
+static u8 CompareMonSize(u16 species, u16 *sizeRecord)
+{
+ if (gScriptResult == 0xFF)
+ {
+ return 0;
+ }
+ else
+ {
+ struct Pokemon *pkmn = &gPlayerParty[gScriptResult];
+
+ // UB: Too few arguments for function 'GetMonData'
+ if (GetMonData(pkmn, MON_DATA_IS_EGG) == TRUE || GetMonData(pkmn, MON_DATA_SPECIES) != species)
+ {
+ return 1;
+ }
+ else
+ {
+ u32 oldSize;
+ u32 newSize;
+ u16 sizeParams;
+
+ *(&sizeParams) = GetMonSizeHash(pkmn);
+ newSize = GetMonSize(species, sizeParams);
+ oldSize = GetMonSize(species, *sizeRecord);
+ FormatMonSizeRecord(gStringVar2, newSize);
+ if (newSize <= oldSize)
+ {
+ return 2;
+ }
+ else
+ {
+ *sizeRecord = sizeParams;
+ return 3;
+ }
+ }
+ }
+}
+
+//Stores species name in gStringVar1, trainer's name in gStringVar2, and size in gStringVar3
+static void GetMonSizeRecordInfo(u16 species, u16 *sizeRecord)
+{
+ u32 size = GetMonSize(species, *sizeRecord);
+
+ FormatMonSizeRecord(gStringVar3, size);
+ StringCopy(gStringVar1, gSpeciesNames[species]);
+ if (*sizeRecord == 0x8100)
+ StringCopy(gStringVar2, gOtherText_Marco);
+ else
+ StringCopy(gStringVar2, gSaveBlock2.playerName);
+}
+
+void InitShroomishSizeRecord(void)
+{
+ VarSet(VAR_SHROOMISH_SIZE_RECORD, 0x8100);
+}
+
+void GetShroomishSizeRecordInfo(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_SHROOMISH_SIZE_RECORD);
+
+ GetMonSizeRecordInfo(SPECIES_SHROOMISH, sizeRecord);
+}
+
+void CompareShroomishSize(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_SHROOMISH_SIZE_RECORD);
+
+ gScriptResult = CompareMonSize(SPECIES_SHROOMISH, sizeRecord);
+}
+
+void InitBarboachSizeRecord(void)
+{
+ VarSet(VAR_BARBOACH_SIZE_RECORD, 0x8100);
+}
+
+void GetBarboachSizeRecordInfo(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_BARBOACH_SIZE_RECORD);
+
+ GetMonSizeRecordInfo(SPECIES_BARBOACH, sizeRecord);
+}
+
+void CompareBarboachSize(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_BARBOACH_SIZE_RECORD);
+
+ gScriptResult = CompareMonSize(SPECIES_BARBOACH, sizeRecord);
+}
+
+void GiveGiftRibbonToParty(u8 index, u8 ribbonId)
+{
+ s32 i;
+ bool32 gotRibbon = FALSE;
+ u8 data = 1;
+ u8 arr[] = { 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E };
+
+ if (index < 11 && ribbonId < 65)
+ {
+ gSaveBlock1.giftRibbons[index] = ribbonId;
+ for (i = 0; i < 6; i++)
+ {
+ struct Pokemon *pkmn = &gPlayerParty[i];
+
+ if (GetMonData(pkmn, MON_DATA_SPECIES) != 0 && GetMonData(pkmn, MON_DATA_SANITY_BIT3) == 0)
+ {
+ SetMonData(pkmn, arr[index], &data);
+ gotRibbon = TRUE;
+ }
+ }
+ if (gotRibbon)
+ FlagSet(SYS_RIBBON_GET);
+ }
+}
diff --git a/src/pokemon/pokemon_storage_system.c b/src/pokemon/pokemon_storage_system.c
new file mode 100644
index 000000000..5e97523e2
--- /dev/null
+++ b/src/pokemon/pokemon_storage_system.c
@@ -0,0 +1,99 @@
+#include "global.h"
+#include "pokemon_storage_system.h"
+#include "menu.h"
+#include "string_util.h"
+
+struct StorageAction {
+ u8 *text;
+ u8 format;
+};
+
+extern const struct StorageAction gUnknown_083B6DF4[];
+
+extern const u8 unk_2000000[];
+
+EWRAM_DATA struct PokemonStorage gPokemonStorage = {0};
+
+#define gUnk2002694 (u8 *)(&unk_2000000[0x2694])
+#define gUnk20026A6 (u8 *)(&unk_2000000[0x26a6])
+#define gUnk20011fa (u8 *)(&unk_2000000[0x11fa])
+#define gUnk20026e4 (u8 *)(&unk_2000000[0x26e4])
+
+void sub_8098898(u8 index) {
+ u8 *ptr;
+
+ MenuDrawTextWindow(10, 16, 29, 19);
+
+ switch (gUnknown_083B6DF4[index].format)
+ {
+
+ case 2:
+ ptr = StringCopy(gUnk2002694, gUnknown_083B6DF4[index].text);
+ ptr = StringCopy(ptr, gUnk20011fa);
+ break;
+
+ case 5:
+ ptr = StringCopy(gUnk2002694, gUnknown_083B6DF4[index].text);
+ ptr = StringCopy(ptr, gUnk20026e4);
+ break;
+
+ case 1:
+ // {var} + " is selected."
+ ptr = StringCopy(gUnk2002694, gUnk20011fa);
+ ptr = StringCopy(ptr, gUnknown_083B6DF4[index].text);
+ break;
+
+ case 4:
+ // {var} + " was released."
+ ptr = StringCopy(gUnk2002694, gUnk20026e4);
+#if ENGLISH
+ ptr = StringCopy(ptr, gUnknown_083B6DF4[index].text);
+#elif GERMAN
+ ptr = de_sub_8073174(gUnk2002694, gUnknown_083B6DF4[index].text);
+#endif
+ break;
+
+ case 3:
+ {
+ u8 *stringLength;
+ u8 *text;
+
+ text = gUnknown_083B6DF4[index].text;
+ stringLength = &text[StringLength(text)] + 1;
+
+ ptr = StringCopy(gUnk2002694, gUnknown_083B6DF4[index].text);
+ ptr = StringCopy(ptr, gUnk20011fa);
+ ptr = StringCopy(ptr, stringLength);
+ }
+ break;
+
+ case 6:
+ // "Bye-bye, ".substr(0, -1) + {var} + "Bye-bye, !".substr(-1, 1)
+ {
+ u8 *stringLength;
+ u8 *text;
+
+ text = gUnknown_083B6DF4[index].text;
+ stringLength = &text[StringLength(text)] - 1;
+
+ ptr = StringCopy(gUnk2002694, gUnknown_083B6DF4[index].text);
+ ptr = StringCopy(ptr - 1, gUnk20026e4);
+ ptr = StringCopy(ptr, stringLength);
+ }
+ break;
+
+ case 0:
+ default:
+ ptr = StringCopy(gUnk2002694, gUnknown_083B6DF4[index].text);
+ break;
+ }
+
+ while (ptr < gUnk20026A6)
+ {
+ ptr[0] = CHAR_SPACE;
+ ptr++;
+ }
+
+ ptr[0] = EOS;
+ MenuPrint(gUnk2002694, 11, 17);
+}
diff --git a/src/pokemon/pokemon_summary_screen.c b/src/pokemon/pokemon_summary_screen.c
new file mode 100644
index 000000000..00a0bea29
--- /dev/null
+++ b/src/pokemon/pokemon_summary_screen.c
@@ -0,0 +1,180 @@
+#include "global.h"
+#include "pokemon_summary_screen.h"
+#include "link.h"
+#include "menu.h"
+#include "pokemon.h"
+#include "region_map.h"
+#include "string_util.h"
+#include "strings2.h"
+#include "tv.h"
+
+extern struct Pokemon *unk_2018000;
+
+bool8 PokemonSummaryScreen_CheckOT(struct Pokemon *mon)
+{
+ u32 trainerId;
+
+ if (unk_2018000 == gEnemyParty)
+ {
+ u8 enemyId = GetMultiplayerId() ^ 1;
+ trainerId = gLinkPlayers[enemyId].trainerId & 0xFFFF;
+ StringCopy(gStringVar1, gLinkPlayers[enemyId].name);
+ StripExtCtrlCodes(gStringVar1);
+ }
+ else
+ {
+ trainerId = GetPlayerTrainerId() & 0xFFFF;
+ StringCopy(gStringVar1, gSaveBlock2.playerName);
+ }
+
+ if (trainerId != (GetMonData(mon, MON_DATA_OT_ID) & 0xFFFF))
+ return FALSE;
+
+ GetMonData(mon, MON_DATA_OT_NAME, gStringVar2);
+
+ if (!StringCompareWithoutExtCtrlCodes(gStringVar1, gStringVar2))
+ return TRUE;
+
+ return FALSE;
+}
+
+void PokemonSummaryScreen_PrintEggTrainerMemo(struct Pokemon *mon, u8 left, u8 top)
+{
+ u8 locationMet;
+ u8 gameMet = GetMonData(mon, MON_DATA_MET_GAME);
+
+ if (!(gameMet == VERSION_RUBY || gameMet == VERSION_SAPPHIRE || gameMet == VERSION_EMERALD))
+ {
+ MenuPrint(gOtherText_EggObtainedInTrade, left, top);
+ return;
+ }
+
+ locationMet = GetMonData(mon, MON_DATA_MET_LOCATION);
+
+ if (locationMet == 255)
+ {
+ MenuPrint(gOtherText_EggNicePlace, left, top);
+ return;
+ }
+
+ if (!PokemonSummaryScreen_CheckOT(mon))
+ {
+ MenuPrint(gOtherText_EggObtainedInTrade, left, top);
+ return;
+ }
+
+ asm(""); // needed to match for some reason
+
+ if (locationMet == 253)
+ {
+ MenuPrint(gOtherText_EggHotSprings, left, top);
+ return;
+ }
+
+ MenuPrint(gOtherText_EggDayCare, left, top);
+}
+
+void PokemonSummaryScreen_PrintTrainerMemo(struct Pokemon *pokemon, u8 left, u8 top)
+{
+ u8 locationMet;
+ u8 gameMet;
+ u8 *ptr = gStringVar4;
+ u8 nature = GetNature(pokemon);
+
+#if ENGLISH
+ ptr = sub_80A1E9C(ptr, gNatureNames[nature], 14);
+
+ if (nature != NATURE_BOLD && nature != NATURE_GENTLE)
+ {
+ ptr = StringCopy(ptr, gOtherText_Terminator4);
+ }
+
+ ptr = StringCopy(ptr, gOtherText_Nature);
+#elif GERMAN
+ ptr = StringCopy(gStringVar4, gOtherText_Nature);
+ ptr = sub_80A1E9C(ptr, gNatureNames[nature], 14);
+ ptr = StringCopy(ptr, gOtherText_Terminator4);
+#endif
+
+ if (PokemonSummaryScreen_CheckOT(pokemon) == TRUE)
+ {
+ locationMet = GetMonData(pokemon, MON_DATA_MET_LOCATION);
+
+ if (GetMonData(pokemon, MON_DATA_MET_LEVEL) == 0)
+ {
+ ptr = PokemonSummaryScreen_CopyPokemonLevel(ptr, 5);
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ CopyLocationName(gStringVar1, locationMet);
+ ptr = sub_80A1E9C(ptr, gStringVar1, 14);
+ StringCopy(ptr, gOtherText_Egg2);
+ }
+ else if (locationMet >= 88)
+ {
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ StringCopy(ptr, gOtherText_ObtainedInTrade);
+ }
+ else
+ {
+ u8 levelMet = GetMonData(pokemon, MON_DATA_MET_LEVEL);
+
+ ptr = PokemonSummaryScreen_CopyPokemonLevel(ptr, levelMet);
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ CopyLocationName(gStringVar1, locationMet);
+ ptr = sub_80A1E9C(ptr, gStringVar1, 14);
+ StringCopy(ptr, gOtherText_Met);
+ }
+ }
+ else
+ {
+ gameMet = GetMonData(pokemon, MON_DATA_MET_GAME);
+
+ if (!(gameMet == VERSION_RUBY || gameMet == VERSION_SAPPHIRE || gameMet == VERSION_EMERALD))
+ {
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ StringCopy(ptr, gOtherText_ObtainedInTrade);
+ }
+ else
+ {
+ locationMet = GetMonData(pokemon, MON_DATA_MET_LOCATION);
+ if (locationMet == 0xFF)
+ {
+ u8 levelMet = GetMonData(pokemon, MON_DATA_MET_LEVEL);
+
+ ptr = PokemonSummaryScreen_CopyPokemonLevel(ptr, levelMet);
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ StringCopy(ptr, gOtherText_FatefulEncounter);
+ }
+ else if (locationMet >= 88)
+ {
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ StringCopy(ptr, gOtherText_ObtainedInTrade);
+ }
+ else
+ {
+ u8 levelMet = GetMonData(pokemon, MON_DATA_MET_LEVEL);
+
+ ptr = PokemonSummaryScreen_CopyPokemonLevel(ptr, levelMet);
+ *ptr = CHAR_NEWLINE;
+ ptr++;
+
+ CopyLocationName(gStringVar1, locationMet);
+ ptr = sub_80A1E9C(ptr, gStringVar1, 14);
+ StringCopy(ptr, gOtherText_Met2);
+ }
+ }
+ }
+
+ MenuPrint(gStringVar4, left++, top++);
+}