#include "global.h" #include "battle.h" #include "title_screen.h" #include "sprite.h" #include "gba/m4a_internal.h" #include "clear_save_data_menu.h" #include "decompress.h" #include "event_data.h" #include "intro.h" #include "m4a.h" #include "main.h" #include "main_menu.h" #include "palette.h" #include "reset_rtc_screen.h" #include "berry_fix_program.h" #include "sound.h" #include "sprite.h" #include "task.h" #include "scanline_effect.h" #include "gpu_regs.h" #include "trig.h" #include "graphics.h" #include "constants/rgb.h" #include "constants/songs.h" #define VERSION_BANNER_RIGHT_TILEOFFSET 64 #define VERSION_BANNER_LEFT_X 98 #define VERSION_BANNER_RIGHT_X 162 #define VERSION_BANNER_Y 2 #define VERSION_BANNER_Y_GOAL 66 #define START_BANNER_X 128 #define CLEAR_SAVE_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_UP) #define RESET_RTC_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_LEFT) #define BERRY_UPDATE_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON) #define A_B_START_SELECT (A_BUTTON | B_BUTTON | START_BUTTON | SELECT_BUTTON) static void MainCB2(void); static void Task_TitleScreenPhase1(u8); static void Task_TitleScreenPhase2(u8); static void Task_TitleScreenPhase3(u8); static void CB2_GoToMainMenu(void); static void CB2_GoToClearSaveDataScreen(void); static void CB2_GoToResetRtcScreen(void); static void CB2_GoToBerryFixScreen(void); static void CB2_GoToCopyrightScreen(void); static void UpdateLegendaryMarkingColor(u8); static void SpriteCB_VersionBannerLeft(struct Sprite *sprite); static void SpriteCB_VersionBannerRight(struct Sprite *sprite); static void SpriteCB_PressStartCopyrightBanner(struct Sprite *sprite); static void SpriteCB_PokemonLogoShine(struct Sprite *sprite); // const rom data static const u16 sUnusedUnknownPal[] = INCBIN_U16("graphics/title_screen/unk_853EF78.gbapal"); static const u32 sTitleScreenRayquazaGfx[] = INCBIN_U32("graphics/title_screen/rayquaza.4bpp.lz"); static const u32 sTitleScreenRayquazaTilemap[] = INCBIN_U32("graphics/title_screen/rayquaza.bin.lz"); static const u32 sTitleScreenLogoShineGfx[] = INCBIN_U32("graphics/title_screen/logo_shine.4bpp.lz"); static const u32 sTitleScreenCloudsGfx[] = INCBIN_U32("graphics/title_screen/clouds.4bpp.lz"); // Used to blend "Emerald Version" as it passes over over the Pokémon banner. // Also used by the intro to blend the Game Freak name/logo in and out as they appear and disappear const u16 gTitleScreenAlphaBlend[64] = { BLDALPHA_BLEND(16, 0), BLDALPHA_BLEND(16, 1), BLDALPHA_BLEND(16, 2), BLDALPHA_BLEND(16, 3), BLDALPHA_BLEND(16, 4), BLDALPHA_BLEND(16, 5), BLDALPHA_BLEND(16, 6), BLDALPHA_BLEND(16, 7), BLDALPHA_BLEND(16, 8), BLDALPHA_BLEND(16, 9), BLDALPHA_BLEND(16, 10), BLDALPHA_BLEND(16, 11), BLDALPHA_BLEND(16, 12), BLDALPHA_BLEND(16, 13), BLDALPHA_BLEND(16, 14), BLDALPHA_BLEND(16, 15), BLDALPHA_BLEND(15, 16), BLDALPHA_BLEND(14, 16), BLDALPHA_BLEND(13, 16), BLDALPHA_BLEND(12, 16), BLDALPHA_BLEND(11, 16), BLDALPHA_BLEND(10, 16), BLDALPHA_BLEND(9, 16), BLDALPHA_BLEND(8, 16), BLDALPHA_BLEND(7, 16), BLDALPHA_BLEND(6, 16), BLDALPHA_BLEND(5, 16), BLDALPHA_BLEND(4, 16), BLDALPHA_BLEND(3, 16), BLDALPHA_BLEND(2, 16), BLDALPHA_BLEND(1, 16), BLDALPHA_BLEND(0, 16), [32 ... 63] = BLDALPHA_BLEND(0, 16) }; static const struct OamData sVersionBannerLeftOamData = { .y = DISPLAY_HEIGHT, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .mosaic = 0, .bpp = ST_OAM_8BPP, .shape = SPRITE_SHAPE(64x32), .x = 0, .matrixNum = 0, .size = SPRITE_SIZE(64x32), .tileNum = 0, .priority = 0, .paletteNum = 0, .affineParam = 0, }; static const struct OamData sVersionBannerRightOamData = { .y = DISPLAY_HEIGHT, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .mosaic = 0, .bpp = ST_OAM_8BPP, .shape = SPRITE_SHAPE(64x32), .x = 0, .matrixNum = 0, .size = SPRITE_SIZE(64x32), .tileNum = 0, .priority = 0, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sVersionBannerLeftAnimSequence[] = { ANIMCMD_FRAME(0, 30), ANIMCMD_END, }; static const union AnimCmd sVersionBannerRightAnimSequence[] = { ANIMCMD_FRAME(VERSION_BANNER_RIGHT_TILEOFFSET, 30), ANIMCMD_END, }; static const union AnimCmd *const sVersionBannerLeftAnimTable[] = { sVersionBannerLeftAnimSequence, }; static const union AnimCmd *const sVersionBannerRightAnimTable[] = { sVersionBannerRightAnimSequence, }; static const struct SpriteTemplate sVersionBannerLeftSpriteTemplate = { .tileTag = 1000, .paletteTag = 1000, .oam = &sVersionBannerLeftOamData, .anims = sVersionBannerLeftAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_VersionBannerLeft, }; static const struct SpriteTemplate sVersionBannerRightSpriteTemplate = { .tileTag = 1000, .paletteTag = 1000, .oam = &sVersionBannerRightOamData, .anims = sVersionBannerRightAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_VersionBannerRight, }; static const struct CompressedSpriteSheet sSpriteSheet_EmeraldVersion[] = { { .data = gTitleScreenEmeraldVersionGfx, .size = 0x1000, .tag = 1000 }, {}, }; static const struct OamData sOamData_CopyrightBanner = { .y = DISPLAY_HEIGHT, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .mosaic = 0, .bpp = ST_OAM_4BPP, .shape = SPRITE_SHAPE(32x8), .x = 0, .matrixNum = 0, .size = SPRITE_SIZE(32x8), .tileNum = 0, .priority = 0, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sCopyrightBannerAnim0[] = { ANIMCMD_FRAME(1, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim1[] = { ANIMCMD_FRAME(5, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim2[] = { ANIMCMD_FRAME(9, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim3[] = { ANIMCMD_FRAME(13, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim4[] = { ANIMCMD_FRAME(17, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim5[] = { ANIMCMD_FRAME(21, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim6[] = { ANIMCMD_FRAME(25, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim7[] = { ANIMCMD_FRAME(29, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim8[] = { ANIMCMD_FRAME(33, 4), ANIMCMD_END, }; static const union AnimCmd sCopyrightBannerAnim9[] = { ANIMCMD_FRAME(37, 4), ANIMCMD_END, }; static const union AnimCmd *const sStartCopyrightBannerAnimTable[] = { sCopyrightBannerAnim0, sCopyrightBannerAnim1, sCopyrightBannerAnim2, sCopyrightBannerAnim3, sCopyrightBannerAnim4, sCopyrightBannerAnim5, sCopyrightBannerAnim6, sCopyrightBannerAnim7, sCopyrightBannerAnim8, sCopyrightBannerAnim9, }; static const struct SpriteTemplate sStartCopyrightBannerSpriteTemplate = { .tileTag = 1001, .paletteTag = 1001, .oam = &sOamData_CopyrightBanner, .anims = sStartCopyrightBannerAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_PressStartCopyrightBanner, }; static const struct CompressedSpriteSheet sSpriteSheet_PressStart[] = { { .data = gTitleScreenPressStartGfx, .size = 0x520, .tag = 1001 }, {}, }; static const struct SpritePalette sSpritePalette_PressStart[] = { { .data = gTitleScreenPressStartPal, .tag = 1001 }, {}, }; static const struct OamData sPokemonLogoShineOamData = { .y = DISPLAY_HEIGHT, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .mosaic = 0, .bpp = ST_OAM_4BPP, .shape = SPRITE_SHAPE(64x64), .x = 0, .matrixNum = 0, .size = SPRITE_SIZE(64x64), .tileNum = 0, .priority = 0, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sPokemonLogoShineAnimSequence[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_END, }; static const union AnimCmd *const sPokemonLogoShineAnimTable[] = { sPokemonLogoShineAnimSequence, }; static const struct SpriteTemplate sPokemonLogoShineSpriteTemplate = { .tileTag = 1002, .paletteTag = 1001, .oam = &sPokemonLogoShineOamData, .anims = sPokemonLogoShineAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_PokemonLogoShine, }; static const struct CompressedSpriteSheet sPokemonLogoShineSpriteSheet[] = { { .data = sTitleScreenLogoShineGfx, .size = 0x800, .tag = 1002 }, {}, }; // code static void SpriteCB_VersionBannerLeft(struct Sprite *sprite) { if (gTasks[sprite->data[1]].data[1] != 0) { sprite->oam.objMode = ST_OAM_OBJ_NORMAL; sprite->y = VERSION_BANNER_Y_GOAL; } else { if (sprite->y != VERSION_BANNER_Y_GOAL) sprite->y++; if (sprite->data[0] != 0) sprite->data[0]--; SetGpuReg(REG_OFFSET_BLDALPHA, gTitleScreenAlphaBlend[sprite->data[0]]); } } static void SpriteCB_VersionBannerRight(struct Sprite *sprite) { if (gTasks[sprite->data[1]].data[1] != 0) { sprite->oam.objMode = ST_OAM_OBJ_NORMAL; sprite->y = VERSION_BANNER_Y_GOAL; } else { if (sprite->y != VERSION_BANNER_Y_GOAL) sprite->y++; } } static void SpriteCB_PressStartCopyrightBanner(struct Sprite *sprite) { if (sprite->data[0] == 1) { sprite->data[1]++; // Alternate between hidden and shown every 16th frame if (sprite->data[1] & 16) sprite->invisible = FALSE; else sprite->invisible = TRUE; } else { sprite->invisible = FALSE; } } static void CreatePressStartBanner(s16 x, s16 y) { u8 i; u8 spriteId; x -= 64; for (i = 0; i < 5; i++, x += 32) { spriteId = CreateSprite(&sStartCopyrightBannerSpriteTemplate, x, y, 0); StartSpriteAnim(&gSprites[spriteId], i); gSprites[spriteId].data[0] = 1; } } static void CreateCopyrightBanner(s16 x, s16 y) { u8 i; u8 spriteId; x -= 64; for (i = 0; i < 5; i++, x += 32) { spriteId = CreateSprite(&sStartCopyrightBannerSpriteTemplate, x, y, 0); StartSpriteAnim(&gSprites[spriteId], i + 5); } } static void SpriteCB_PokemonLogoShine(struct Sprite *sprite) { if (sprite->x < DISPLAY_WIDTH + 32) { if (sprite->data[0]) // Flash background { u16 backgroundColor; if (sprite->x < DISPLAY_WIDTH / 2) { // Brighten background color if (sprite->data[1] < 31) sprite->data[1]++; if (sprite->data[1] < 31) sprite->data[1]++; } else { // Darken background color if (sprite->data[1] != 0) sprite->data[1]--; if (sprite->data[1] != 0) sprite->data[1]--; } backgroundColor = _RGB(sprite->data[1], sprite->data[1], sprite->data[1]); if (sprite->x == DISPLAY_WIDTH / 2 + 12 || sprite->x == DISPLAY_WIDTH / 2 + 16 || sprite->x == DISPLAY_WIDTH / 2 + 20 || sprite->x == DISPLAY_WIDTH / 2 + 24) gPlttBufferFaded[0] = RGB(24, 31, 12); else gPlttBufferFaded[0] = backgroundColor; } sprite->x += 4; } else { gPlttBufferFaded[0] = RGB_BLACK; DestroySprite(sprite); } } static void SpriteCB_PokemonLogoShine2(struct Sprite *sprite) { if (sprite->x < DISPLAY_WIDTH + 32) sprite->x += 8; else DestroySprite(sprite); } static void StartPokemonLogoShine(u8 flashBg) { u8 spriteId; switch (flashBg) { case 0: case 2: spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0); gSprites[spriteId].oam.objMode = ST_OAM_OBJ_WINDOW; gSprites[spriteId].data[0] = flashBg; break; case 1: spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0); gSprites[spriteId].oam.objMode = ST_OAM_OBJ_WINDOW; gSprites[spriteId].data[0] = flashBg; gSprites[spriteId].invisible = TRUE; spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0); gSprites[spriteId].callback = SpriteCB_PokemonLogoShine2; gSprites[spriteId].oam.objMode = ST_OAM_OBJ_WINDOW; spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, -80, 68, 0); gSprites[spriteId].callback = SpriteCB_PokemonLogoShine2; gSprites[spriteId].oam.objMode = ST_OAM_OBJ_WINDOW; break; } } static void VBlankCB(void) { ScanlineEffect_InitHBlankDmaTransfer(); LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); } #define tCounter data[0] #define tSkipToNext data[1] void CB2_InitTitleScreen(void) { switch (gMain.state) { default: case 0: SetVBlankCallback(NULL); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetGpuReg(REG_OFFSET_BLDY, 0); *((u16 *)PLTT) = RGB_WHITE; SetGpuReg(REG_OFFSET_DISPCNT, 0); SetGpuReg(REG_OFFSET_BG2CNT, 0); SetGpuReg(REG_OFFSET_BG1CNT, 0); SetGpuReg(REG_OFFSET_BG0CNT, 0); SetGpuReg(REG_OFFSET_BG2HOFS, 0); SetGpuReg(REG_OFFSET_BG2VOFS, 0); SetGpuReg(REG_OFFSET_BG1HOFS, 0); SetGpuReg(REG_OFFSET_BG1VOFS, 0); SetGpuReg(REG_OFFSET_BG0HOFS, 0); SetGpuReg(REG_OFFSET_BG0VOFS, 0); DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); DmaFill32(3, 0, (void *)OAM, OAM_SIZE); DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); ResetPaletteFade(); gMain.state = 1; break; case 1: // bg2 LZ77UnCompVram(gTitleScreenPokemonLogoGfx, (void *)(BG_CHAR_ADDR(0))); LZ77UnCompVram(gTitleScreenPokemonLogoTilemap, (void *)(BG_SCREEN_ADDR(9))); LoadPalette(gTitleScreenBgPalettes, 0, 0x1E0); // bg3 LZ77UnCompVram(sTitleScreenRayquazaGfx, (void *)(BG_CHAR_ADDR(2))); LZ77UnCompVram(sTitleScreenRayquazaTilemap, (void *)(BG_SCREEN_ADDR(26))); // bg1 LZ77UnCompVram(sTitleScreenCloudsGfx, (void *)(BG_CHAR_ADDR(3))); LZ77UnCompVram(gTitleScreenCloudsTilemap, (void *)(BG_SCREEN_ADDR(27))); ScanlineEffect_Stop(); ResetTasks(); ResetSpriteData(); FreeAllSpritePalettes(); gReservedSpritePaletteCount = 9; LoadCompressedSpriteSheet(&sSpriteSheet_EmeraldVersion[0]); LoadCompressedSpriteSheet(&sSpriteSheet_PressStart[0]); LoadCompressedSpriteSheet(&sPokemonLogoShineSpriteSheet[0]); LoadPalette(gTitleScreenEmeraldVersionPal, 0x100, 0x20); LoadSpritePalette(&sSpritePalette_PressStart[0]); gMain.state = 2; break; case 2: { u8 taskId = CreateTask(Task_TitleScreenPhase1, 0); gTasks[taskId].tCounter = 256; gTasks[taskId].tSkipToNext = FALSE; gTasks[taskId].data[2] = -16; gTasks[taskId].data[3] = -32; gMain.state = 3; break; } case 3: BeginNormalPaletteFade(PALETTES_ALL, 1, 0x10, 0, RGB_WHITEALPHA); SetVBlankCallback(VBlankCB); gMain.state = 4; break; case 4: PanFadeAndZoomScreen(0x78, 0x50, 0x100, 0); SetGpuReg(REG_OFFSET_BG2X_L, -29 * 256); SetGpuReg(REG_OFFSET_BG2X_H, -1); SetGpuReg(REG_OFFSET_BG2Y_L, -32 * 256); SetGpuReg(REG_OFFSET_BG2Y_H, -1); SetGpuReg(REG_OFFSET_WIN0H, 0); SetGpuReg(REG_OFFSET_WIN0V, 0); SetGpuReg(REG_OFFSET_WIN1H, 0); SetGpuReg(REG_OFFSET_WIN1V, 0); SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ); SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WINOBJ_ALL); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_LIGHTEN); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetGpuReg(REG_OFFSET_BLDY, 12); SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(26) | BGCNT_16COLOR | BGCNT_TXT256x256); SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(3) | BGCNT_SCREENBASE(27) | BGCNT_16COLOR | BGCNT_TXT256x256); SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(9) | BGCNT_256COLOR | BGCNT_AFF256x256); EnableInterrupts(INTR_FLAG_VBLANK); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_OBJWIN_ON); m4aSongNumStart(MUS_TITLE); gMain.state = 5; break; case 5: if (!UpdatePaletteFade()) { StartPokemonLogoShine(0); ScanlineEffect_InitWave(0, DISPLAY_HEIGHT, 4, 4, 0, SCANLINE_EFFECT_REG_BG1HOFS, TRUE); SetMainCallback2(MainCB2); } break; } } static void MainCB2(void) { RunTasks(); AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); } // Shine the Pokemon logo two more times, and fade in the version banner static void Task_TitleScreenPhase1(u8 taskId) { // Skip to next phase when A, B, Start, or Select is pressed if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].data[1] != 0) { gTasks[taskId].tSkipToNext = TRUE; gTasks[taskId].tCounter = 0; } if (gTasks[taskId].tCounter != 0) { u16 frameNum = gTasks[taskId].tCounter; if (frameNum == 176) StartPokemonLogoShine(1); else if (frameNum == 64) StartPokemonLogoShine(2); gTasks[taskId].tCounter--; } else { u8 spriteId; SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_OBJ_ON); SetGpuReg(REG_OFFSET_WININ, 0); SetGpuReg(REG_OFFSET_WINOUT, 0); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); SetGpuReg(REG_OFFSET_BLDY, 0); // Create left side of version banner spriteId = CreateSprite(&sVersionBannerLeftSpriteTemplate, VERSION_BANNER_LEFT_X, VERSION_BANNER_Y, 0); gSprites[spriteId].data[0] = 64; gSprites[spriteId].data[1] = taskId; // Create right side of version banner spriteId = CreateSprite(&sVersionBannerRightSpriteTemplate, VERSION_BANNER_RIGHT_X, VERSION_BANNER_Y, 0); gSprites[spriteId].data[1] = taskId; gTasks[taskId].tCounter = 144; gTasks[taskId].func = Task_TitleScreenPhase2; } } // Create "Press Start" and copyright banners, and slide Pokemon logo up static void Task_TitleScreenPhase2(u8 taskId) { u32 yPos; // Skip to next phase when A, B, Start, or Select is pressed if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].tSkipToNext) { gTasks[taskId].tSkipToNext = TRUE; gTasks[taskId].tCounter = 0; } if (gTasks[taskId].tCounter != 0) { gTasks[taskId].tCounter--; } else { gTasks[taskId].tSkipToNext = TRUE; SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BD); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(6, 15)); SetGpuReg(REG_OFFSET_BLDY, 0); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON); CreatePressStartBanner(START_BANNER_X, 108); CreateCopyrightBanner(START_BANNER_X, 148); gTasks[taskId].data[4] = 0; gTasks[taskId].func = Task_TitleScreenPhase3; } if (!(gTasks[taskId].tCounter & 3) && gTasks[taskId].data[2] != 0) gTasks[taskId].data[2]++; if (!(gTasks[taskId].tCounter & 1) && gTasks[taskId].data[3] != 0) gTasks[taskId].data[3]++; // Slide Pokemon logo up yPos = gTasks[taskId].data[3] * 256; SetGpuReg(REG_OFFSET_BG2Y_L, yPos); SetGpuReg(REG_OFFSET_BG2Y_H, yPos / 0x10000); gTasks[taskId].data[5] = 15; gTasks[taskId].data[6] = 6; } // Show Rayquaza silhouette and process main title screen input static void Task_TitleScreenPhase3(u8 taskId) { if ((JOY_NEW(A_BUTTON)) || (JOY_NEW(START_BUTTON))) { FadeOutBGM(4); BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_WHITEALPHA); SetMainCallback2(CB2_GoToMainMenu); } else if (JOY_HELD(CLEAR_SAVE_BUTTON_COMBO) == CLEAR_SAVE_BUTTON_COMBO) { SetMainCallback2(CB2_GoToClearSaveDataScreen); } else if (JOY_HELD(RESET_RTC_BUTTON_COMBO) == RESET_RTC_BUTTON_COMBO) { FadeOutBGM(4); BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); SetMainCallback2(CB2_GoToResetRtcScreen); } else if (JOY_HELD(BERRY_UPDATE_BUTTON_COMBO) == BERRY_UPDATE_BUTTON_COMBO) { FadeOutBGM(4); BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); SetMainCallback2(CB2_GoToBerryFixScreen); } else { SetGpuReg(REG_OFFSET_BG2Y_L, 0); SetGpuReg(REG_OFFSET_BG2Y_H, 0); gTasks[taskId].tCounter++; if (gTasks[taskId].tCounter & 1) { gTasks[taskId].data[4]++; gBattle_BG1_Y = gTasks[taskId].data[4] / 2; gBattle_BG1_X = 0; } UpdateLegendaryMarkingColor(gTasks[taskId].tCounter); if ((gMPlayInfo_BGM.status & 0xFFFF) == 0) { BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_WHITEALPHA); SetMainCallback2(CB2_GoToCopyrightScreen); } } } static void CB2_GoToMainMenu(void) { if (!UpdatePaletteFade()) SetMainCallback2(CB2_InitMainMenu); } static void CB2_GoToCopyrightScreen(void) { if (!UpdatePaletteFade()) SetMainCallback2(CB2_InitCopyrightScreenAfterTitleScreen); } static void CB2_GoToClearSaveDataScreen(void) { if (!UpdatePaletteFade()) SetMainCallback2(CB2_InitClearSaveDataScreen); } static void CB2_GoToResetRtcScreen(void) { if (!UpdatePaletteFade()) SetMainCallback2(CB2_InitResetRtcScreen); } static void CB2_GoToBerryFixScreen(void) { if (!UpdatePaletteFade()) { m4aMPlayAllStop(); SetMainCallback2(CB2_InitBerryFixProgram); } } static void UpdateLegendaryMarkingColor(u8 frameNum) { if ((frameNum % 4) == 0) // Change color every 4th frame { s32 intensity = Cos(frameNum, 128) + 128; s32 r = 31 - ((intensity * 32 - intensity) / 256); s32 g = 31 - (intensity * 22 / 256); s32 b = 12; u16 color = RGB(r, g, b); LoadPalette(&color, 0xEF, sizeof(color)); } }