summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPikalaxALT <PikalaxALT@users.noreply.github.com>2019-08-01 21:04:28 -0400
committerGitHub <noreply@github.com>2019-08-01 21:04:28 -0400
commit201418cd4d3e0c96b8f7f99e6242f2a08b5041b7 (patch)
tree57cbe7905db69e8f7e88327c0d665b49f2dd67fb /src
parent00cf527c16d02fc912666d97a49dc7fedf996225 (diff)
parent6032159d1bc099d4ed112e5e387ebba1d35fe6a9 (diff)
Merge pull request #87 from PikalaxALT/title_screen
Title screen
Diffstat (limited to 'src')
-rw-r--r--src/title_screen.c1056
1 files changed, 1056 insertions, 0 deletions
diff --git a/src/title_screen.c b/src/title_screen.c
new file mode 100644
index 000000000..f4086b2ff
--- /dev/null
+++ b/src/title_screen.c
@@ -0,0 +1,1056 @@
+#include "global.h"
+#include "malloc.h"
+#include "palette.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "task.h"
+#include "main.h"
+#include "new_menu_helpers.h"
+#include "m4a.h"
+#include "scanline_effect.h"
+#include "graphics.h"
+#include "help_system.h"
+#include "intro.h"
+#include "load_save.h"
+#include "sound.h"
+#include "new_game.h"
+#include "save.h"
+#include "main_menu.h"
+#include "clear_save_data_screen.h"
+#include "berry_fix_program.h"
+#include "decompress.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+
+enum TitleScreenScene
+{
+ TITLESCREENSCENE_INIT = 0,
+ TITLESCREENSCENE_FLASHSPRITE,
+ TITLESCREENSCENE_FADEIN,
+ TITLESCREENSCENE_RUN,
+ TITLESCREENSCEEN_RESTART,
+ TITLESCREENSCENE_CRY
+};
+
+#if defined(FIRERED)
+#define TITLE_SPECIES SPECIES_CHARIZARD
+#elif defined(LEAFGREEN)
+#define TITLE_SPECIES SPECIES_VENUSAUR
+#endif
+
+static EWRAM_DATA u8 sTitleScreenTimerTaskId = 0;
+
+static void ResetGpuRegs(void);
+static void CB2_TitleScreenRun(void);
+static void VBlankCB(void);
+static void Task_TitleScreenTimer(u8 taskId);
+static void Task_TitleScreenMain(u8 taskId);
+static void SetTitleScreenScene(s16 * data, u8 a1);
+static void SetTitleScreenScene_Init(s16 * data);
+static void SetTitleScreenScene_FlashSprite(s16 * data);
+static void SetTitleScreenScene_FadeIn(s16 * data);
+static void SetTitleScreenScene_Run(s16 * data);
+static void SetGpuRegsForTitleScreenRun(void);
+static void SetTitleScreenScene_Restart(s16 * data);
+static void SetTitleScreenScene_Cry(s16 * data);
+static void Task_TitleScreen_SlideWin0(u8 taskId);
+static void Task_TitleScreen_PaletteSomething(u8 taskId);
+static void SignalEndTitleScreenPaletteSomethingTask(void);
+static void UpdateScanlineEffectRegBuffer(s16 a0);
+static void ScheduleStopScanlineEffect(void);
+static void LoadMainTitleScreenPalsAndResetBgs(void);
+static void CB2_FadeOutTransitionToSaveClearScreen(void);
+static void CB2_FadeOutTransitionToBerryFix(void);
+static void LoadSpriteGfxAndPals(void);
+static void Task_FlameOrLeafSpawner(u8 taskId);
+static void TitleScreen_srand(u8 taskId, u8 field, u16 seed);
+static u16 TitleScreen_rand(u8 taskId, u8 field);
+static u32 CreateBlankSprite(void);
+static void SetPalOnOrCreateBlankSprite(bool32 a0);
+static u8 CreateSlashSprite(void);
+static void ScheduleHideSlashSprite(u8 spriteId);
+static bool32 IsSlashSpriteHidden(u8 spriteId);
+static void SpriteCallback_Slash(struct Sprite * sprite);
+
+// bg3
+static const u8 sBorderBgTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83BF58C.4bpp.lz");
+static const u8 sBorderBgMap[] = INCBIN_U8("data/graphics/title_screen/unk_83BF5A8.bin.lz");
+
+//sprites
+static const u8 sSlashSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bf64c.4bpp.lz");
+static const u16 sSlashSpritePals[] = INCBIN_U16("data/graphics/title_screen/unk_83bf77c.gbapal");
+static const u8 sFireSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bf79c.4bpp.lz");
+static const u8 sBlankFireSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bfa14.4bpp.lz");
+
+static const struct OamData sOamData_FlameOrLeaf = {
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .shape = ST_OAM_SQUARE,
+ .size = ST_OAM_SIZE_1,
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 0
+};
+
+static const union AnimCmd sSpriteAnims_FlameOrLeaf_0[] = {
+ ANIMCMD_FRAME(0x00, 3),
+ ANIMCMD_FRAME(0x04, 6),
+ ANIMCMD_FRAME(0x08, 6),
+ ANIMCMD_FRAME(0x0c, 6),
+ ANIMCMD_FRAME(0x10, 6),
+ ANIMCMD_FRAME(0x14, 6),
+ ANIMCMD_FRAME(0x18, 6),
+ ANIMCMD_FRAME(0x1c, 6),
+ ANIMCMD_FRAME(0x20, 6),
+ ANIMCMD_FRAME(0x24, 6),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnims_FlameOrLeaf_1[] = {
+ ANIMCMD_FRAME(0x18, 6),
+ ANIMCMD_FRAME(0x1c, 6),
+ ANIMCMD_FRAME(0x20, 6),
+ ANIMCMD_FRAME(0x24, 6),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_FlameOrLeaf[] = {
+ sSpriteAnims_FlameOrLeaf_0,
+ sSpriteAnims_FlameOrLeaf_1
+};
+
+static const struct SpriteTemplate sSpriteTemplate_FlameOrLeaf_State1 = {
+ .tileTag = 0,
+ .paletteTag = 0,
+ .oam = &sOamData_FlameOrLeaf,
+ .anims = sSpriteAnimTable_FlameOrLeaf,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct SpriteTemplate sSpriteTemplate_FlameOrLeaf_State0 = {
+ .tileTag = 1,
+ .paletteTag = 0,
+ .oam = &sOamData_FlameOrLeaf,
+ .anims = sSpriteAnimTable_FlameOrLeaf,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sOamData_UnknownTemptySprite = {
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .shape = ST_OAM_V_RECTANGLE,
+ .size = ST_OAM_SIZE_3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const struct SpriteTemplate sUnknownEmptySprite = {
+ .tileTag = 2,
+ .paletteTag = 2,
+ .oam = &sOamData_UnknownTemptySprite,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sOamData_SlashSprite = {
+ .objMode = ST_OAM_OBJ_WINDOW,
+ .shape = ST_OAM_SQUARE,
+ .size = ST_OAM_SIZE_3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const struct SpriteTemplate sSlashSpriteTemplate = {
+ .tileTag = 3,
+ .paletteTag = 2,
+ .oam = &sOamData_SlashSprite,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct BgTemplate sBgTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 1, // 8bpp
+ .priority = 0,
+ .baseTile = 0
+ }, {
+ .bg = 1,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 1,
+ .baseTile = 0
+ }, {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 2,
+ .baseTile = 0
+ }, {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 28,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 3,
+ .baseTile = 0
+ }
+};
+
+static void (*const sSceneFuncs[])(s16 * data) = {
+ SetTitleScreenScene_Init,
+ SetTitleScreenScene_FlashSprite,
+ SetTitleScreenScene_FadeIn,
+ SetTitleScreenScene_Run,
+ SetTitleScreenScene_Restart,
+ SetTitleScreenScene_Cry
+};
+
+static const struct CompressedSpriteSheet sSpriteSheets[] = {
+ {(const void *)sFireSpriteTiles, 0x500, 0},
+ {(const void *)sBlankFireSpriteTiles, 0x500, 1},
+ {(const void *)gGraphics_TitleScreen_BlankObjTiles, 0x400, 2},
+ {(const void *)sSlashSpriteTiles, 0x800, 3}
+};
+
+static const struct SpritePalette sSpritePals[] = {
+ {sSlashSpritePals, 0},
+ {gGraphics_TitleScreen_FirePals, 2},
+ {}
+};
+
+static const u8 gUnknown_83BFBD4[] = {
+ 0x04, 0x10, 0x1a, 0x20, 0x30, 0xc8, 0xd8, 0xe0, 0xe8, 0x3c, 0x4c, 0x5c, 0x6c, 0x80, 0x90
+};
+
+void CB2_InitTitleScreen(void)
+{
+ switch (gMain.state)
+ {
+ default:
+ gMain.state = 0;
+ // fallthrough
+ case 0:
+ SetVBlankCallback(NULL);
+ StartTimer1();
+ InitHeap(gHeap, HEAP_SIZE);
+ ResetTasks();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetPaletteFade();
+ ResetGpuRegs();
+ DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, (void *)OAM, OAM_SIZE);
+ DmaFill16(3, 0, (void *)PLTT, PLTT_SIZE);
+ ResetBgsAndClearDma3BusyFlags(FALSE);
+ InitBgsFromTemplates(0, sBgTemplates, NELEMS(sBgTemplates));
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ sTitleScreenTimerTaskId = 0xFF;
+ break;
+ case 1:
+ LoadPalette(gGraphics_TitleScreen_PokemonFireRedLogoPals, 0, 0x1A0);
+ DecompressAndCopyTileDataToVram(0, gGraphics_TitleScreen_PokemonFireRedLogoTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(0, gGraphics_TitleScreen_PokemonFireRedLogoMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_CharizardPals, 0xD0, 0x20);
+ DecompressAndCopyTileDataToVram(1, gGraphics_TitleScreen_CharizardTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(1, gGraphics_TitleScreen_CharizardMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xF0, 0x20);
+ DecompressAndCopyTileDataToVram(2, gGraphics_TitleScreen_CopyrightPressStartTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(2, gGraphics_TitleScreen_CopyrightPressStartMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xE0, 0x20);
+ DecompressAndCopyTileDataToVram(3, sBorderBgTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(3, sBorderBgMap, 0, 0, 1);
+ LoadSpriteGfxAndPals();
+ break;
+ case 2:
+ if (!FreeTempTileDataBuffersIfPossible())
+ {
+ BlendPalettes(0x0000FFFF, 0x10, RGB_BLACK);
+ CreateTask(Task_TitleScreenMain, 4);
+ sTitleScreenTimerTaskId = CreateTask(Task_TitleScreenTimer, 2);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_TitleScreenRun);
+ m4aSongNumStart(BGM_FRLG_TITLE);
+ }
+ return;
+ }
+ gMain.state++;
+}
+
+static void ResetGpuRegs(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+}
+
+static void CB2_TitleScreenRun(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+ ScanlineEffect_InitHBlankDmaTransfer();
+
+ if (sTitleScreenTimerTaskId != 0xFF)
+ gTasks[sTitleScreenTimerTaskId].data[0]++;
+}
+
+static void Task_TitleScreenTimer(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[0] >= 2700)
+ {
+ sTitleScreenTimerTaskId = 0xFF;
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_TitleScreenMain(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (JOY_NEW(A_BUTTON | B_BUTTON | START_BUTTON)
+ && data[0] != 3 && data[0] != 4 && data[0] != 5)
+ {
+ ScheduleStopScanlineEffect();
+ LoadMainTitleScreenPalsAndResetBgs();
+ SetPalOnOrCreateBlankSprite(data[5]);
+ SetTitleScreenScene(data, TITLESCREENSCENE_RUN);
+ }
+ else
+ {
+ sSceneFuncs[data[0]](data);
+ }
+}
+
+static void SetTitleScreenScene(s16 * data, u8 a1)
+{
+ data[1] = 0;
+ data[0] = a1;
+}
+
+static void SetTitleScreenScene_Init(s16 * data)
+{
+ struct ScanlineEffectParams params;
+
+ HideBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+
+ params.dmaDest = (volatile void *)REG_ADDR_BLDY;
+ params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ params.initState = 1;
+ params.unused9 = 0;
+
+ CpuFill16(0, gScanlineEffectRegBuffers[0], 0x140);
+ CpuFill16(0, gScanlineEffectRegBuffers[1], 0x140);
+
+ ScanlineEffect_SetParams(params);
+
+ SetTitleScreenScene(data, TITLESCREENSCENE_FLASHSPRITE);
+}
+
+static void SetTitleScreenScene_FlashSprite(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_LIGHTEN);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ data[2] = 0x80;
+ UpdateScanlineEffectRegBuffer(data[2]);
+ data[1]++;
+ break;
+ case 1:
+ data[2] -= 4;
+ UpdateScanlineEffectRegBuffer(data[2]);
+ if (data[2] < 0)
+ {
+ gScanlineEffect.state = 3;
+ data[1]++;
+ }
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ SetTitleScreenScene(data, TITLESCREENSCENE_FADEIN);
+ }
+}
+
+static void SetTitleScreenScene_FadeIn(s16 * data)
+{
+ u32 r4;
+ switch (data[1])
+ {
+ case 0:
+ data[2] = 0;
+ data[1]++;
+ break;
+ case 1:
+ data[2]++;
+ if (data[2] > 10)
+ {
+ TintPalette_GrayScale2(gPlttBufferUnfaded + 0xD0, 0x10);
+ BeginNormalPaletteFade(0x00002000, 9, 0x10, 0, RGB_BLACK);
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 3:
+ data[2]++;
+ if (data[2] > 36)
+ {
+ CreateTask(Task_TitleScreen_SlideWin0, 3);
+ sub_80717A8(0x2000, -4, 0x01, 0x10, RGB(30, 30, 31), 0, 0);
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 4:
+ if (!sub_807185C(0))
+ {
+ sub_80717A8(0x2000, -4, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 5:
+ data[2]++;
+ if (data[2] > 20)
+ {
+ data[2] = 0;
+ sub_80717A8(0x2000, -4, 0x01, 0x10, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 6:
+ if (!sub_807185C(0))
+ {
+ sub_80717A8(0x2000, -4, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 7:
+ data[2]++;
+ if (data[2] > 20)
+ {
+ data[2] = 0;
+ sub_80717A8(0x2000, -3, 0x00, 0x10, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 8:
+ if (!sub_807185C(0))
+ {
+ data[5] = 1;
+ r4 = (0x10000 << CreateBlankSprite()) | 0x00001FFF;
+ BlendPalettes(r4, 0x10, RGB(30, 30, 31));
+ BeginNormalPaletteFade(r4, 1, 0x10, 0x00, RGB(30, 30, 31));
+ ShowBg(0);
+ CpuCopy16(gGraphics_TitleScreen_CharizardPals, gPlttBufferUnfaded + 0xD0, 0x20);
+ sub_80717A8(0x2000, 1, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 9:
+ if (!sub_807185C(0) && !gPaletteFade.active)
+ {
+ SetTitleScreenScene(data, TITLESCREENSCENE_RUN);
+ }
+ break;
+ }
+}
+
+#define KEYSTROKE_DELSAVE (B_BUTTON | SELECT_BUTTON | DPAD_UP)
+#define KEYSTROKE_BERRY_FIX (B_BUTTON | SELECT_BUTTON)
+
+static void SetTitleScreenScene_Run(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ HelpSystem_SetSomeVariable2(1);
+ CreateTask(Task_TitleScreen_PaletteSomething, 0);
+ CreateTask(Task_FlameOrLeafSpawner, 5);
+ SetGpuRegsForTitleScreenRun();
+ data[6] = CreateSlashSprite();
+ sub_812B484();
+ data[1]++;
+ // fallthrough
+ case 1:
+ if (JOY_HELD(KEYSTROKE_DELSAVE) == KEYSTROKE_DELSAVE)
+ {
+ ScheduleHideSlashSprite(data[6]);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(CB2_FadeOutTransitionToSaveClearScreen);
+ }
+ else if (JOY_HELD(KEYSTROKE_BERRY_FIX) == KEYSTROKE_BERRY_FIX)
+ {
+ ScheduleHideSlashSprite(data[6]);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(CB2_FadeOutTransitionToBerryFix);
+ }
+ else if (JOY_NEW(A_BUTTON | START_BUTTON))
+ {
+ SetTitleScreenScene(data, TITLESCREENSCENE_CRY);
+ }
+ else if (!FuncIsActiveTask(Task_TitleScreenTimer))
+ {
+ SetTitleScreenScene(data, TITLESCREENSCEEN_RESTART);
+ }
+ break;
+ }
+}
+
+static void SetGpuRegsForTitleScreenRun(void)
+{
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0x3F, 0x1F));
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_LIGHTEN);
+ SetGpuReg(REG_OFFSET_BLDY, 13);
+}
+
+static void SetTitleScreenScene_Restart(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ ScheduleHideSlashSprite(data[6]);
+ data[1]++;
+ break;
+ case 1:
+ if (!gPaletteFade.active && !IsSlashSpriteHidden(data[6]))
+ {
+ FadeOutMapMusic(10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 3, 0, 0x10, RGB_BLACK);
+ SignalEndTitleScreenPaletteSomethingTask();
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (IsNotWaitingForBGMStop() && !gPaletteFade.active)
+ {
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreen_PaletteSomething));
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 3:
+ data[2]++;
+ if (data[2] >= 20)
+ {
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreen_PaletteSomething));
+ data[1]++;
+ }
+ break;
+ case 4:
+ sub_812B478();
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(sub_80EC864);
+ break;
+ }
+}
+
+static void SetTitleScreenScene_Cry(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ PlayCry1(TITLE_SPECIES, 0);
+ ScheduleHideSlashSprite(data[6]);
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 1:
+ if (data[2] < 90)
+ data[2]++;
+ else if (!IsSlashSpriteHidden(data[6]))
+ {
+ BeginNormalPaletteFade(0x0FFFFFFF, 0, 0, 0x10, RGB_WHITE);
+ SignalEndTitleScreenPaletteSomethingTask();
+ FadeOutBGM(4);
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ SeedRngAndSetTrainerId();
+ SetSaveBlocksPointers();
+ ResetMenuAndMonGlobals();
+ Save_ResetSaveCounters();
+ Save_LoadGameData(0);
+ if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
+ Sav2_ClearSetDefault();
+ SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
+ InitHeap(gHeap, HEAP_SIZE);
+ SetMainCallback2(sub_800C300);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ }
+ break;
+ }
+}
+
+static void Task_TitleScreen_SlideWin0(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WININ, WIN_RANGE(0x00, 0x3F));
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0x00, 0x37));
+ SetGpuReg(REG_OFFSET_WIN0V, 0xA0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00);
+ BlendPalettes(0x00004000, 0, RGB_BLACK);
+ data[0]++;
+ break;
+ case 1:
+ data[1] += 0x180;
+ data[2] = data[1] >> 4;
+ if (data[2] >= 0xF0)
+ {
+ data[2] = 0xF0;
+ data[0]++;
+ }
+ SetGpuReg(REG_OFFSET_WIN0H, data[2]);
+ break;
+ case 2:
+ data[3]++;
+ if (data[3] >= 10)
+ {
+ data[3] = 0;
+ data[0]++;
+ }
+ break;
+ case 3:
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0, 0x3B));
+ SetGpuReg(REG_OFFSET_WIN0H, 0xF0F0);
+ ChangeBgX(2, -0xF000, 0);
+ BlendPalettes(0x00008000, 0, RGB_BLACK);
+ data[1] = 0xF00;
+ data[0]++;
+ break;
+ case 4:
+ data[1] -= 0x180;
+ data[2] = data[1] >> 4;
+ if (data[2] <= 0)
+ {
+ data[2] = 0;
+ data[0]++;
+ }
+ ChangeBgX(2, -data[2] << 8, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, (data[2] << 8) | 0xF0);
+ break;
+ case 5:
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void Task_TitleScreen_PaletteSomething(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 i;
+
+ if (data[15] && gPaletteFade.active)
+ data[14] = 1;
+ if (data[14] && !gPaletteFade.active)
+ DestroyTask(taskId);
+ else
+ {
+ if (!data[1])
+ data[2] = 60;
+ else
+ data[2] = 30;
+ data[0]++;
+ if (data[0] >= data[2])
+ {
+ data[0] = 0;
+ data[1] ^= 1;
+ if (data[1])
+ {
+ for (i = 0; i < 5; i++)
+ {
+ gPlttBufferUnfaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[6];
+ gPlttBufferFaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[6];
+ }
+ }
+ else
+ {
+ for (i = 0; i < 5; i++)
+ {
+ gPlttBufferUnfaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[1 + i];
+ gPlttBufferFaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[1 + i];
+ }
+ }
+ if (data[14])
+ {
+ BlendPalettes(0x00008000, gPaletteFade.y, gPaletteFade.blendColor);
+ }
+ }
+ }
+}
+
+static void SignalEndTitleScreenPaletteSomethingTask(void)
+{
+ u8 taskId = FindTaskIdByFunc(Task_TitleScreen_PaletteSomething);
+ gTasks[taskId].data[15] = TRUE;
+}
+
+static void UpdateScanlineEffectRegBuffer(s16 a0)
+{
+ s32 i;
+
+ if (a0 >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0] = 16;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ if (a0 + i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0 + i] = 15 - i;
+ }
+ if (a0 - i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0 - i] = 15 - i;
+ }
+ }
+ for (i = a0 + 16; i < 160; i++)
+ {
+ if (i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = 0;
+ }
+ }
+ for (i = a0 - 16; i >= 0; i--)
+ {
+ if (i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = 0;
+ }
+ }
+}
+
+static void ScheduleStopScanlineEffect(void)
+{
+ if (gScanlineEffect.state)
+ gScanlineEffect.state = 3;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+}
+
+static void LoadMainTitleScreenPalsAndResetBgs(void)
+{
+ u8 taskId;
+
+ taskId = FindTaskIdByFunc(Task_TitleScreen_SlideWin0);
+ if (taskId != 0xFF)
+ DestroyTask(taskId);
+
+ sub_8071898();
+ ResetPaletteFadeControl();
+ LoadPalette(gGraphics_TitleScreen_PokemonFireRedLogoPals, 0x00, 0x1A0);
+ LoadPalette(gGraphics_TitleScreen_CharizardPals, 0xD0, 0x20);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xF0, 0x20);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xE0, 0x20);
+ ResetBgPositions();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(0);
+ ShowBg(3);
+}
+
+static void CB2_FadeOutTransitionToSaveClearScreen(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_SaveClearScreen_Init);
+}
+
+static void CB2_FadeOutTransitionToBerryFix(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ m4aMPlayAllStop();
+ SetMainCallback2(mb_berry_fix_serve);
+ }
+}
+
+static void LoadSpriteGfxAndPals(void)
+{
+ s32 i;
+
+ for (i = 0; i < NELEMS(sSpriteSheets); i++)
+ LoadCompressedSpriteSheet(&sSpriteSheets[i]);
+ LoadSpritePalettes(sSpritePals);
+}
+
+static void SpriteCallback_TitleScreenFlameOrLeaf(struct Sprite * sprite)
+{
+ s16 * data = sprite->data;
+ sprite->data[0] -= data[1];
+ sprite->pos1.x = sprite->data[0] >> 4;
+ if (sprite->pos1.x < -8)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+ data[2] += data[3];
+ sprite->pos1.y = data[2] >> 4;
+ if (sprite->pos1.y < 0x10 || sprite->pos1.y > 0xc8)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+#if defined(FIRERED)
+ if (sprite->animEnded)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+ if (data[7] != 0 && --data[7] == 0)
+ {
+ StartSpriteAnim(sprite, 0);
+ sprite->invisible = FALSE;
+ }
+#elif defined(LEAFGREEN)
+ if (!data[5])
+ {
+ s32 r2;
+ s32 r1;
+ data[6]++;
+ r2 = data[1] * data[6];
+ r1 = data[6] * data[3];
+ r2 = (r2 * r2) >> 4;
+ r1 = (r1 * r1) >> 4;
+ if (r2 + r1 >= 0x510)
+ data[5] = TRUE;
+ }
+#endif
+}
+
+static bool32 CreateFlameOrLeafSprite(s32 x, s32 y, s32 xspeed, s32 yspeed, bool32 templateId)
+{
+ u8 spriteId;
+ if (templateId)
+ {
+ spriteId = CreateSprite(&sSpriteTemplate_FlameOrLeaf_State1, x, y, 0);
+ }
+ else
+ {
+ spriteId = CreateSprite(&sSpriteTemplate_FlameOrLeaf_State0, x, y, 0);
+ }
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].data[0] = x << 4;
+ gSprites[spriteId].data[1] = xspeed;
+ gSprites[spriteId].data[2] = y << 4;
+ gSprites[spriteId].data[3] = yspeed;
+ gSprites[spriteId].data[4] = 0;
+ gSprites[spriteId].data[5] = (xspeed * yspeed) % 16;
+ gSprites[spriteId].data[6] = templateId;
+ gSprites[spriteId].callback = SpriteCallback_TitleScreenFlameOrLeaf;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void Task_FlameOrLeafSpawner(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 x, y, xspeed, yspeed, templateId;
+ s32 i;
+
+ switch (data[0])
+ {
+ case 0:
+ TitleScreen_srand(taskId, 3, 30840);
+ data[0]++;
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] >= data[2])
+ {
+ data[1] = 0;
+ TitleScreen_rand(taskId, 3);
+ data[2] = 18;
+ xspeed = (TitleScreen_rand(taskId, 3) % 4) - 2;
+ yspeed = (TitleScreen_rand(taskId, 3) % 8) - 16;
+ y = (TitleScreen_rand(taskId, 3) % 3) + 0x74;
+ x = TitleScreen_rand(taskId, 3) % 240;
+ CreateFlameOrLeafSprite(
+ x,
+ y,
+ xspeed,
+ yspeed,
+ (TitleScreen_rand(taskId, 3) % 16) < 8 ? 0 : 1
+ );
+ for (i = 0; i < 15; i++)
+ {
+ CreateFlameOrLeafSprite(
+ data[5] + gUnknown_83BFBD4[i],
+ y,
+ xspeed,
+ yspeed,
+ 1
+ );
+ xspeed = (TitleScreen_rand(taskId, 3) % 4) - 2;
+ yspeed = (TitleScreen_rand(taskId, 3) % 8) - 16;
+ }
+ data[5]++;
+ if (data[5] > 3)
+ data[5] = 0;
+ }
+ }
+}
+
+static void TitleScreen_srand(u8 taskId, u8 field, u16 seed)
+{
+ SetWordTaskArg(taskId, field, seed);
+}
+
+static u16 TitleScreen_rand(u8 taskId, u8 field)
+{
+ u32 rngval;
+
+ rngval = GetWordTaskArg(taskId, field);
+ rngval = rngval * 1103515245 + 24691;
+ SetWordTaskArg(taskId, field, rngval);
+ return rngval >> 16;
+}
+
+static u32 CreateBlankSprite(void)
+{
+ CreateSprite(&sUnknownEmptySprite, 0x18, 0x90, 0);
+ return IndexOfSpritePaletteTag(2);
+}
+
+static void SetPalOnOrCreateBlankSprite(bool32 mode)
+{
+ u32 palIdx;
+
+ if (mode)
+ {
+ palIdx = IndexOfSpritePaletteTag(2);
+ LoadPalette(gGraphics_TitleScreen_FirePals, palIdx * 16 + 0x100, 0x20);
+ }
+ else
+ CreateBlankSprite();
+}
+
+static u8 CreateSlashSprite(void)
+{
+ u8 spriteId = CreateSprite(&sSlashSpriteTemplate, -0x20, 0x1B, 1);
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].callback = SpriteCallback_Slash;
+ gSprites[spriteId].data[1] = 540;
+ }
+ return spriteId;
+}
+
+static void ScheduleHideSlashSprite(u8 spriteId)
+{
+ if (spriteId != MAX_SPRITES)
+ gSprites[spriteId].data[2] = TRUE;
+}
+
+static bool32 IsSlashSpriteHidden(u8 spriteId)
+{
+ if (spriteId != MAX_SPRITES)
+ return gSprites[spriteId].data[0] ^ 2 ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+static void SpriteCallback_Slash(struct Sprite * sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ if (sprite->data[2])
+ {
+ sprite->invisible = TRUE;
+ sprite->data[0] = 2;
+ }
+ sprite->data[1]--;
+ if (sprite->data[1] == 0)
+ {
+ sprite->invisible = FALSE;
+ sprite->data[0] = 1;
+ }
+ break;
+ case 1:
+ sprite->pos1.x += 9;
+ if (sprite->pos1.x == 67)
+ {
+ sprite->pos1.y -= 7;
+ }
+ if (sprite->pos1.x == 148)
+ {
+ sprite->pos1.y += 7;
+ }
+ if (sprite->pos1.x > 272)
+ {
+ sprite->invisible = TRUE;
+ if (sprite->data[2])
+ sprite->data[0] = 2;
+ else
+ {
+ sprite->pos1.x = -0x20;
+ sprite->data[1] = 540;
+ sprite->data[0] = 0;
+ }
+ }
+ break;
+ case 2:
+ break;
+ }
+}