diff options
author | Martin Griffin <martinrgriffin@gmail.com> | 2019-12-27 14:50:07 +0000 |
---|---|---|
committer | Martin Griffin <martinrgriffin@gmail.com> | 2019-12-27 16:31:07 +0000 |
commit | 8fb5ce57900a607348d7d6d01ce9f699867d0c2b (patch) | |
tree | 8e729050f6f175f7ae8824b015219774e6a53ab9 /src/field_screen_effect.c | |
parent | 4d7a5b165f96dd1788364523eb160041157d3004 (diff) |
Decompile field_screen_effect
Diffstat (limited to 'src/field_screen_effect.c')
-rw-r--r-- | src/field_screen_effect.c | 271 |
1 files changed, 270 insertions, 1 deletions
diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 19ed25950..09808659d 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -1,6 +1,19 @@ #include "global.h" +#include "field_screen_effect.h" +#include "gpu_regs.h" +#include "overworld.h" +#include "scanline_effect.h" +#include "script.h" +#include "task.h" -void SetFlashScanlineEffectWindowBoundary(u16 *dest, u32 y, s32 left, s32 right) +static const u16 sFlashLevelPixelRadii[] = { + 0x00c8, 0x0048, 0x0038, 0x0028, 0x0018, 0x0000 +}; + +static void Task_EnableScriptAfterMusicFade(u8 taskId); +static void Task_BarnDoorWipeChild(u8 taskId); + +static void SetFlashScanlineEffectWindowBoundary(u16 *dest, u32 y, s32 left, s32 right) { if (y <= 160) { @@ -73,3 +86,259 @@ void SetFlashScanlineEffectWindowBoundaries(u16 *dest, s32 centerX, s32 centerY, } } } + +#define tState data[0] +#define tFlashCenterX data[1] +#define tFlashCenterY data[2] +#define tCurFlashRadius data[3] +#define tDestFlashRadius data[4] +#define tFlashRadiusDelta data[5] +#define tClearScanlineEffect data[6] + +static void UpdateFlashLevelEffect(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + SetFlashScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius); + tState = 1; + break; + case 1: + SetFlashScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius); + tState = 0; + tCurFlashRadius += tFlashRadiusDelta; + if (tCurFlashRadius > tDestFlashRadius) + { + if (tClearScanlineEffect == TRUE) + { + ScanlineEffect_Stop(); + tState = 2; + } + else + { + DestroyTask(taskId); + } + } + break; + case 2: + ScanlineEffect_Clear(); + DestroyTask(taskId); + break; + } +} + +static void sub_807EF7C(u8 taskId) +{ + if (!FuncIsActiveTask(UpdateFlashLevelEffect)) + { + EnableBothScriptContexts(); + DestroyTask(taskId); + } +} + +static void sub_807EFA4(void) +{ + if (!FuncIsActiveTask(sub_807EF7C)) + CreateTask(sub_807EF7C, 80); +} + +static u8 sub_807EFC8(s32 centerX, s32 centerY, s32 initialFlashRadius, s32 destFlashRadius, bool32 clearScanlineEffect, u8 delta) +{ + u8 taskId = CreateTask(UpdateFlashLevelEffect, 80); + s16 *data = gTasks[taskId].data; + + tCurFlashRadius = initialFlashRadius; + tDestFlashRadius = destFlashRadius; + tFlashCenterX = centerX; + tFlashCenterY = centerY; + tClearScanlineEffect = clearScanlineEffect; + + if (initialFlashRadius < destFlashRadius) + tFlashRadiusDelta = delta; + else + tFlashRadiusDelta = -delta; + + return taskId; +} + +#undef tState +#undef tCurFlashRadius +#undef tDestFlashRadius +#undef tFlashRadiusDelta +#undef tClearScanlineEffect + +void AnimateFlash(u8 flashLevel) +{ + u8 curFlashLevel = Overworld_GetFlashLevel(); + bool32 value = FALSE; + if (!flashLevel) + value = TRUE; + sub_807EFC8(120, 80, sFlashLevelPixelRadii[curFlashLevel], sFlashLevelPixelRadii[flashLevel], value, 2); + sub_807EFA4(); + ScriptContext2_Enable(); +} + +void WriteFlashScanlineEffectBuffer(u8 flashLevel) +{ + if (flashLevel) + { + SetFlashScanlineEffectWindowBoundaries(&gScanlineEffectRegBuffers[0][0], 120, 80, sFlashLevelPixelRadii[flashLevel]); + CpuFastCopy(&gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 240 * 8); + } +} + +void sub_807F0B0(void) +{ + Overworld_FadeOutMapMusic(); + CreateTask(Task_EnableScriptAfterMusicFade, 80); +} + +static void Task_EnableScriptAfterMusicFade(u8 taskId) +{ + if (BGMusicStopped() == TRUE) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} + +#define tState data[9] +#define tDirection data[10] +#define DIR_WIPE_IN 0 // From edges to center. +#define DIR_WIPE_OUT 1 // From center to edges. +#define tChildOffset data[0] + +static void DoInwardBarnDoorFade(void) +{ + u8 taskId = CreateTask(Task_BarnDoorWipe, 80); + gTasks[taskId].tDirection = DIR_WIPE_IN; +} + +void DoOutwardBarnDoorWipe(void) +{ + u8 taskId = CreateTask(Task_BarnDoorWipe, 80); + gTasks[taskId].tDirection = DIR_WIPE_OUT; +} + +static void BarnDoorWipeSaveGpuRegs(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + data[0] = GetGpuReg(REG_OFFSET_DISPCNT); + data[1] = GetGpuReg(REG_OFFSET_WININ); + data[2] = GetGpuReg(REG_OFFSET_WINOUT); + data[3] = GetGpuReg(REG_OFFSET_BLDCNT); + data[4] = GetGpuReg(REG_OFFSET_BLDALPHA); + data[5] = GetGpuReg(REG_OFFSET_WIN0H); + data[6] = GetGpuReg(REG_OFFSET_WIN0V); + data[7] = GetGpuReg(REG_OFFSET_WIN1H); + data[8] = GetGpuReg(REG_OFFSET_WIN1V); +} + +static void BarnDoorWipeLoadGpuRegs(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + SetGpuReg(REG_OFFSET_DISPCNT, data[0]); + SetGpuReg(REG_OFFSET_WININ, data[1]); + SetGpuReg(REG_OFFSET_WINOUT, data[2]); + SetGpuReg(REG_OFFSET_BLDCNT, data[3]); + SetGpuReg(REG_OFFSET_BLDALPHA, data[4]); + SetGpuReg(REG_OFFSET_WIN0H, data[5]); + SetGpuReg(REG_OFFSET_WIN0V, data[6]); + SetGpuReg(REG_OFFSET_WIN1H, data[7]); + SetGpuReg(REG_OFFSET_WIN1V, data[8]); +} + +void Task_BarnDoorWipe(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + switch (tState) + { + case 0: + BarnDoorWipeSaveGpuRegs(taskId); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN1_ON); + if (data[10] == 0) + { + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN1H, WIN_RANGE(240, 255)); + SetGpuReg(REG_OFFSET_WIN0V, 255); + SetGpuReg(REG_OFFSET_WIN1V, 255); + } + else + { + SetGpuReg(REG_OFFSET_WIN0H, 120); + SetGpuReg(REG_OFFSET_WIN0V, 255); + SetGpuReg(REG_OFFSET_WIN1H, WIN_RANGE(120, 255)); + SetGpuReg(REG_OFFSET_WIN1V, 255); + } + SetGpuReg(REG_OFFSET_WININ, 0); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + tState = 1; + break; + case 1: + CreateTask(Task_BarnDoorWipeChild, 80); + tState = 2; + break; + case 2: + if (!FuncIsActiveTask(Task_BarnDoorWipeChild)) + { + tState = 3; + } + break; + case 3: + BarnDoorWipeLoadGpuRegs(taskId); + DestroyTask(taskId); + break; + } +} + +// TODO: Find an implicit way to generate lhs/rhs shifts. +static void Task_BarnDoorWipeChild(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u8 parentTaskId = FindTaskIdByFunc(Task_BarnDoorWipe); + u32 lhs, rhs; + if (gTasks[parentTaskId].tDirection == DIR_WIPE_IN) + { + lhs = (u16)tChildOffset; + rhs = (u16)(240 - lhs); + if ((s16)lhs > 120) + { + DestroyTask(taskId); + return; + } + } + else + { + u16 offset = tChildOffset; + u32 lhs2 = (120 - offset) << 16; + u32 rhs2 = (120 + offset) << 16; + lhs = lhs2 >> 16; + rhs = rhs2 >> 16; + if ((s16)(lhs2 >> 16) < 0) + { + DestroyTask(taskId); + return; + } + } + lhs <<= 16; + SetGpuReg(REG_OFFSET_WIN0H, lhs >> 16); + SetGpuReg(REG_OFFSET_WIN1H, WIN_RANGE((((s16)rhs) << 16) >> 16, 240)); + lhs = (s32)lhs >> 16; + if ((s32)lhs <= 89) + { + tChildOffset += 4; + } + else + { + tChildOffset += 2; + } +} + +#undef tState +#undef tDirection +#undef DIR_WIPE_IN +#undef DIR_WIPE_OUT +#undef tChildOffset |