From 16c31d61b44e7ece18e0d2039449d2ae4a0710e0 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 25 Jan 2025 20:58:22 -0500 Subject: [PATCH] fix: removed fadescreenswapbuffers palette dependence, via hardware fade --- asm/macros/event.inc | 9 +++++---- src/event_object_movement.c | 2 ++ src/field_weather.c | 6 +++++- src/scrcmd.c | 17 +++++++++-------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 7125e71643..06396af8d2 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1674,13 +1674,14 @@ .4byte \text .endm - @ Equivalent to fadescreen but copies gPlttBufferUnfaded to gPaletteDecompressionBuffer on the fade out - @ and the reverse on the fade in, in effect saving gPlttBufferUnfaded to restore it. - @ If nowait set, does not wait for the fade to complete + @ Equivalent to fadescreen but uses a hardware fade and darken/lighten blend modes, + @ to avoid modifying palettes at all. + @ Useful for fade-out/fade-in without leaving the overworld or entering a new scene. + @ If nowait set, doesn't wait for the fade to complete .macro fadescreenswapbuffers mode:req, nowait=0 .byte 0xdc .byte \mode - .byte \nowait + .byte \nowait .endm @ Buffers the specified trainer's class name to the given string var. diff --git a/src/event_object_movement.c b/src/event_object_movement.c index f7f0f3e2df..18ca30bb96 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2397,6 +2397,8 @@ void UpdateLightSprite(struct Sprite *sprite) { return; } + // Note to self: Don't set window registers during hardware fade! + switch (sprite->data[5]) { // lightType case 0: if (gPaletteFade.active) { // if palette fade is active, don't flicker since the timer won't be updated diff --git a/src/field_weather.c b/src/field_weather.c index 2bcaa2f857..199cff15e1 100644 --- a/src/field_weather.c +++ b/src/field_weather.c @@ -818,6 +818,7 @@ void FadeScreen(u8 mode, s8 delay) // fades screen using BLDY // Note: This enables blending in all windows; // These bits may need to be disabled later +// (i.e if blending lighting effects using WINOBJ) u16 FadeScreenHardware(u8 mode, s8 delay) { u16 bldCnt = GetGpuReg(REG_OFFSET_BLDCNT) & BLDCNT_TGT2_ALL; bldCnt |= BLDCNT_TGT1_ALL; @@ -1008,7 +1009,10 @@ void Weather_SetBlendCoeffs(u8 eva, u8 evb) gWeatherPtr->currBlendEVB = evb; gWeatherPtr->targetBlendEVA = eva; gWeatherPtr->targetBlendEVB = evb; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(eva, evb)); + + // don't update BLDALPHA if a hardware fade is on-screen + if ((GetGpuReg(REG_OFFSET_BLDCNT) & BLDCNT_EFFECT_EFF_MASK) < BLDCNT_EFFECT_LIGHTEN) + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(eva, evb)); } void Weather_SetTargetBlendCoeffs(u8 eva, u8 evb, int delay) diff --git a/src/scrcmd.c b/src/scrcmd.c index a51e81aa91..edca8dbbbe 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -23,6 +23,7 @@ #include "field_tasks.h" #include "field_weather.h" #include "fieldmap.h" +#include "gpu_regs.h" #include "item.h" #include "lilycove_lady.h" #include "main.h" @@ -661,19 +662,19 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx) switch (mode) { - case FADE_TO_BLACK: - case FADE_TO_WHITE: - default: - CpuCopy32(gPlttBufferUnfaded, gPaletteDecompressionBuffer, PLTT_SIZE); - FadeScreen(mode, 0); - break; case FADE_FROM_BLACK: case FADE_FROM_WHITE: - CpuCopy32(gPaletteDecompressionBuffer, gPlttBufferUnfaded, PLTT_SIZE); - FadeScreen(mode, 0); + // Restore last weather blend before fading in, + // since BLDALPHA was modified by fade-out + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB) + ); break; } + FadeScreenHardware(mode, 0); + if (nowait) return FALSE; SetupNativeScript(ctx, IsPaletteNotActive);