diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/title_screen.c | 1056 |
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; + } +} |