summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/starter_choose.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/src/starter_choose.c b/src/starter_choose.c
new file mode 100644
index 000000000..0bb6c88b4
--- /dev/null
+++ b/src/starter_choose.c
@@ -0,0 +1,434 @@
+#include "gba/gba.h"
+#include "main.h"
+#include "menu.h"
+#include "palette.h"
+#include "pokemon.h"
+#include "songs.h"
+#include "sound.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "task.h"
+#include "text.h"
+#include "trig.h"
+
+//Functions that need to be put in headers
+void LZ77UnCompVram(const void *src, void *dest);
+void remove_some_task(void);
+void LoadCompressedObjectPic(void *);
+void LoadCompressedObjectPalette(const struct SpritePalette *);
+u16 SpeciesToNationalPokedexNum(u16);
+void DecompressPicFromTable_2(const struct SpriteSheet *, u8, u8, void *, void *, u32);
+
+struct MonCoords
+{
+ u8 x, y;
+};
+
+extern void * const gUnknown_081FAF4C[];
+extern const u8 gStarterChoose_PokeballCoords[][2];
+extern u8 gUnknown_083F66F0[];
+extern u8 gBirchBagTilemap[];
+extern u8 gBirchGrassTilemap[];
+extern u8 gUnknown_083F7794[];
+extern u8 gUnknown_083F77A4[];
+extern u8 gUnknown_083F62EC[];
+extern const u8 gStarterChoose_LabelCoords[][2];
+extern u16 gStarterMons[];
+extern union AffineAnimCmd *gUnknown_083F778C[];
+extern u8 gOtherText_DoYouChoosePoke[];
+extern u16 gScriptResult;
+extern u8 gSpeciesNames[][11];
+extern u8 gOtherText_Poke[];
+extern const struct SpriteSheet gMonFrontPicTable[];
+extern const struct MonCoords gMonFrontPicCoords[];
+extern const struct SpritePalette gMonPaletteTable[];
+extern u8 gUnknown_083F76E4[][2];
+extern u8 gOtherText_BirchInTrouble[];
+
+extern struct WindowConfig gWindowConfig_81E6C3C;
+extern struct WindowConfig gWindowConfig_81E6CE4;
+extern struct SpriteTemplate gSpriteTemplate_83F77E4;
+extern struct SpriteTemplate gSpriteTemplate_83F77CC;
+extern struct SpritePalette gUnknown_083F77B4[];
+extern struct SpriteTemplate gSpriteTemplate_83F77FC;
+extern struct SpriteTemplate gUnknown_02024E8C;
+
+u16 GetStarterPokemon(u16);
+static void MainCallback2(void);
+static void Task_StarterChoose1(u8 taskId);
+static void Task_StarterChoose2(u8 taskId);
+static void Task_StarterChoose3(u8 taskId);
+static void Task_StarterChoose4(u8 taskId);
+static void Task_StarterChoose5(u8 taskId);
+static void Task_StarterChoose6(u8 taskId);
+
+extern u8 *GetPokemonCategory(u16);
+static void CreateStarterPokemonLabel(u8, u8);
+static u8 CreatePokemonFrontSprite(u16, u8, u8);
+void StarterPokemonSpriteAnimCallback(struct Sprite *);
+
+//Task data
+enum {
+ TD_STARTERSELECTION,
+ TD_POKEMON_SPRITE,
+ TD_CIRCLE_SPRITE,
+};
+
+//Retrieves one of the available starter Pokemon
+u16 GetStarterPokemon(u16 n)
+{
+ if(n > 3)
+ n = 0;
+ return gStarterMons[n];
+}
+
+static void VblankCallback(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void CB2_ChooseStarter(void)
+{
+ u16 savedIme;
+ u8 taskId;
+ u8 spriteId;
+
+ SetVBlankCallback(NULL);
+
+ REG_DISPCNT = 0;
+ REG_BG3CNT = 0;
+ REG_BG2CNT = 0;
+ REG_BG1CNT = 0;
+ REG_BG0CNT = 0;
+ REG_BG3HOFS = 0;
+ REG_BG3VOFS = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, 0, PLTT, PLTT_SIZE);
+
+ LZ77UnCompVram(&gUnknown_083F66F0, (void *)VRAM);
+ LZ77UnCompVram(&gBirchBagTilemap, (void *)(VRAM + 0x3000));
+ LZ77UnCompVram(&gBirchGrassTilemap, (void *)(VRAM + 0x3800));
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ LoadPalette(gUnknown_083F62EC, 0, 0x40);
+ LoadCompressedObjectPic(gUnknown_083F7794);
+ LoadCompressedObjectPic(gUnknown_083F77A4);
+ LoadSpritePalettes(gUnknown_083F77B4);
+ SetUpWindowConfig(&gWindowConfig_81E6C3C);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_VBLANK;
+ REG_IME = savedIme;
+ REG_DISPSTAT |= DISPSTAT_VBLANK_INTR;
+
+ SetVBlankCallback(VblankCallback);
+ SetMainCallback2(MainCallback2);
+
+ REG_WININ = 0x3F;
+ REG_WINOUT = 0x1F;
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_BLDCNT = 0xFE;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0x7;
+ REG_BG3CNT = 0x703;
+ REG_BG2CNT = 0x602;
+ REG_BG0CNT = 0x1F08;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON;
+
+ taskId = CreateTask(Task_StarterChoose1, 0);
+ gTasks[taskId].data[TD_STARTERSELECTION] = 1;
+
+ //Create hand sprite
+ spriteId = CreateSprite(&gSpriteTemplate_83F77CC, 120, 56, 2);
+ gSprites[spriteId].data0 = taskId;
+
+ //Create three Pokeball sprites
+ spriteId = CreateSprite(
+ &gSpriteTemplate_83F77E4,
+ gStarterChoose_PokeballCoords[0][0], gStarterChoose_PokeballCoords[0][1], 2);
+ gSprites[spriteId].data0 = taskId;
+ gSprites[spriteId].data1 = 0;
+ spriteId = CreateSprite(
+ &gSpriteTemplate_83F77E4,
+ gStarterChoose_PokeballCoords[1][0], gStarterChoose_PokeballCoords[1][1], 2);
+ gSprites[spriteId].data0 = taskId;
+ gSprites[spriteId].data1 = 1;
+ spriteId = CreateSprite(
+ &gSpriteTemplate_83F77E4,
+ gStarterChoose_PokeballCoords[2][0], gStarterChoose_PokeballCoords[2][1], 2);
+ gSprites[spriteId].data0 = taskId;
+ gSprites[spriteId].data1 = 2;
+}
+
+static void MainCallback2(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void Task_StarterChoose1(u8 taskId)
+{
+ CreateStarterPokemonLabel(0xFF, gTasks[taskId].data[TD_STARTERSELECTION]);
+ MenuDrawTextWindow(2, 14, 27, 19);
+ MenuPrint(gOtherText_BirchInTrouble, 3, 15);
+ gTasks[taskId].func = Task_StarterChoose2;
+}
+
+static void Task_StarterChoose2(u8 taskId)
+{
+ u8 selection = gTasks[taskId].data[TD_STARTERSELECTION];
+
+ if(gMain.newKeys & A_BUTTON)
+ {
+ u8 spriteId;
+
+ MenuZeroFillWindowRect(
+ gStarterChoose_LabelCoords[selection][0],
+ gStarterChoose_LabelCoords[selection][1],
+ gStarterChoose_LabelCoords[selection][0] + 13,
+ gStarterChoose_LabelCoords[selection][1] + 3);
+
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+
+ //Create white circle background
+ spriteId = CreateSprite(
+ &gSpriteTemplate_83F77FC,
+ gStarterChoose_PokeballCoords[selection][0],
+ gStarterChoose_PokeballCoords[selection][1],
+ 1);
+ gTasks[taskId].data[TD_CIRCLE_SPRITE] = spriteId;
+
+ //Create Pokemon sprite
+ spriteId = CreatePokemonFrontSprite(
+ GetStarterPokemon(gTasks[taskId].data[TD_STARTERSELECTION]),
+ gStarterChoose_PokeballCoords[selection][0],
+ gStarterChoose_PokeballCoords[selection][1]);
+ gSprites[spriteId].affineAnims = gUnknown_083F778C;
+ gSprites[spriteId].callback = StarterPokemonSpriteAnimCallback;
+ gTasks[taskId].data[TD_POKEMON_SPRITE] = spriteId;
+
+ gTasks[taskId].func = Task_StarterChoose3;
+ }
+ else
+ {
+ if((gMain.newKeys & DPAD_LEFT) && selection != 0)
+ {
+ gTasks[taskId].data[TD_STARTERSELECTION]--;
+ CreateStarterPokemonLabel(selection, gTasks[taskId].data[TD_STARTERSELECTION]);
+ }
+ else if((gMain.newKeys & DPAD_RIGHT) && selection <= 1)
+ {
+ gTasks[taskId].data[TD_STARTERSELECTION]++;
+ CreateStarterPokemonLabel(selection, gTasks[taskId].data[TD_STARTERSELECTION]);
+ }
+ }
+}
+
+static void Task_StarterChoose3(u8 taskId)
+{
+ if(gSprites[gTasks[taskId].data[TD_CIRCLE_SPRITE]].affineAnimEnded &&
+ gSprites[gTasks[taskId].data[TD_CIRCLE_SPRITE]].pos1.x == 120 &&
+ gSprites[gTasks[taskId].data[TD_CIRCLE_SPRITE]].pos1.y == 64)
+ {
+ gTasks[taskId].func = Task_StarterChoose4;
+ }
+}
+
+static void Task_StarterChoose4(u8 taskId)
+{
+ PlayCry1(GetStarterPokemon(gTasks[taskId].data[TD_STARTERSELECTION]), 0);
+ MenuDrawTextWindow(2, 14, 27, 19);
+ //"Do you choose this POKEMON?"
+ MenuPrint(gOtherText_DoYouChoosePoke, 3, 15);
+ DisplayYesNoMenu(21, 7, 1);
+ gTasks[taskId].func = Task_StarterChoose5;
+}
+
+static void Task_StarterChoose5(u8 taskId)
+{
+ u8 spriteId;
+
+ switch(ProcessMenuInputNoWrap_())
+ {
+ case 0: //YES
+ //Return the starter choice and exit.
+ gScriptResult = gTasks[taskId].data[TD_STARTERSELECTION];
+ SetMainCallback2(gMain.field_8);
+ break;
+ case 1: //NO
+ case -1: //B button
+ PlaySE(SE_SELECT);
+ MenuZeroFillWindowRect(21, 7, 27, 12);
+
+ spriteId = gTasks[taskId].data[TD_POKEMON_SPRITE];
+ FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[spriteId].oam.paletteNum));
+ FreeOamMatrix(gSprites[spriteId].oam.matrixNum);
+ DestroySprite(&gSprites[spriteId]);
+
+ spriteId = gTasks[taskId].data[TD_CIRCLE_SPRITE];
+ FreeOamMatrix(gSprites[spriteId].oam.matrixNum);
+ DestroySprite(&gSprites[spriteId]);
+ gTasks[taskId].func = Task_StarterChoose6;
+ break;
+ }
+}
+
+static void Task_StarterChoose6(u8 taskId)
+{
+ gTasks[taskId].func = Task_StarterChoose1;
+}
+
+static void AddTextColorCtrlCode(u8 *string, u8 bgColor, u8 textColor, u8 shadowColor)
+{
+ *(string++) = EXT_CTRL_CODE_BEGIN;
+ *(string++) = 4;
+ *(string++) = textColor;
+ *(string++) = bgColor;
+ *(string++) = shadowColor;
+}
+
+#define SET_CHAR(str, index, c) \
+{ \
+ u8 *p = str + index; \
+ *p = c; \
+}
+
+static void CreateStarterPokemonLabel(u8 prevSelection, u8 selection)
+{
+ u8 labelText[72];
+ u8 *category;
+ u8 srcIndex;
+ u8 dstIndex;
+ u16 species;
+
+ u8 labelLeft;
+ u8 labelRight;
+ u8 labelTop;
+ u8 labelBottom;
+
+ if(prevSelection != 0xFF)
+ {
+ //Remove the old Pokemon label
+ MenuZeroFillWindowRect(
+ gStarterChoose_LabelCoords[prevSelection][0],
+ gStarterChoose_LabelCoords[prevSelection][1],
+ gStarterChoose_LabelCoords[prevSelection][0] + 13,
+ gStarterChoose_LabelCoords[prevSelection][1] + 3);
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ }
+ species = GetStarterPokemon(selection);
+ category = GetPokemonCategory(SpeciesToNationalPokedexNum(species));
+ AddTextColorCtrlCode(labelText, 0, 15, 8);
+ dstIndex = 5;
+ SET_CHAR(labelText, 5, EXT_CTRL_CODE_BEGIN);
+ SET_CHAR(labelText, 6, 0x11);
+ SET_CHAR(labelText, 7, dstIndex);
+
+ //Copy category string to label
+ dstIndex = 8;
+ srcIndex = 0;
+ while(category[srcIndex] != EOS && srcIndex <= 10)
+ {
+ labelText[dstIndex] = category[srcIndex];
+ srcIndex++;
+ dstIndex++;
+ }
+ labelText[dstIndex++] = CHAR_SPACE;
+
+ //Copy POKEMON string to label
+ StringCopy(labelText + dstIndex, gOtherText_Poke);
+ MenuPrint(
+ labelText,
+ gStarterChoose_LabelCoords[selection][0],
+ gStarterChoose_LabelCoords[selection][1]);
+ AddTextColorCtrlCode(labelText, 0, 15, 8);
+
+ //Copy Pokemon name to label
+ sub_8072C74(labelText + 5, gSpeciesNames[species], 0x6B, 1);
+ MenuPrint(
+ labelText,
+ gStarterChoose_LabelCoords[selection][0],
+ gStarterChoose_LabelCoords[selection][1] + 2);
+
+ labelLeft = gStarterChoose_LabelCoords[selection][0] * 8 + 4;
+ labelRight = (gStarterChoose_LabelCoords[selection][0] + 13) * 8 + 4;
+ labelTop = gStarterChoose_LabelCoords[selection][1] * 8;
+ labelBottom = (gStarterChoose_LabelCoords[selection][1] + 4) * 8;
+ REG_WIN0H = WIN_RANGE(labelLeft, labelRight);
+ REG_WIN0V = WIN_RANGE(labelTop, labelBottom);
+}
+
+void nullsub_72(struct Sprite *sprite)
+{
+
+}
+
+static u8 CreatePokemonFrontSprite(u16 species, u8 x, u8 y)
+{
+ u8 spriteId;
+
+ DecompressPicFromTable_2(
+ &gMonFrontPicTable[species],
+ gMonFrontPicCoords[species].x, gMonFrontPicCoords[species].y,
+ gUnknown_081FAF4C[0], gUnknown_081FAF4C[1],
+ species);
+ LoadCompressedObjectPalette(&gMonPaletteTable[species]);
+ GetMonSpriteTemplate_803C56C(species, 1);
+ spriteId = CreateSprite(&gUnknown_02024E8C, x, y, 0);
+ gSprites[spriteId].callback = nullsub_72;
+ gSprites[spriteId].oam.priority = 0;
+ return spriteId;
+}
+
+//Sprite callback
+void sub_810A62C(struct Sprite *sprite)
+{
+ sprite->pos1.x = gUnknown_083F76E4[gTasks[sprite->data0].data[TD_STARTERSELECTION]][0];
+ sprite->pos1.y = gUnknown_083F76E4[gTasks[sprite->data0].data[TD_STARTERSELECTION]][1];
+ sprite->pos2.y = Sin(sprite->data1, 8);
+ sprite->data1 = (u8)sprite->data1 + 4;
+}
+
+//Sprite callback
+void sub_810A68C(struct Sprite *sprite)
+{
+ if(gTasks[sprite->data0].data[TD_STARTERSELECTION] == sprite->data1)
+ StartSpriteAnimIfDifferent(sprite, 1);
+ else
+ StartSpriteAnimIfDifferent(sprite, 0);
+}
+
+//Sprite callback
+void StarterPokemonSpriteAnimCallback(struct Sprite *sprite)
+{
+ //Move sprite to upper center of screen
+ if(sprite->pos1.x > 120)
+ sprite->pos1.x -= 4;
+ if(sprite->pos1.x <= 119)
+ sprite->pos1.x += 4;
+ if(sprite->pos1.y > 64)
+ sprite->pos1.y -= 2;
+ if(sprite->pos1.y <= 63)
+ sprite->pos1.y += 2;
+}