From 4bb7abb520dabd862cc0be3e85fd6e8f5f9b8878 Mon Sep 17 00:00:00 2001 From: Ariel Antonitis Date: Wed, 21 Apr 2021 02:53:24 -0400 Subject: [PATCH] Fixed palette fades during intermediate times of day. --- include/palette.h | 10 +++++-- src/overworld.c | 5 +++- src/palette.c | 74 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/include/palette.h b/include/palette.h index 4fbde048aa..4b7abd865c 100644 --- a/include/palette.h +++ b/include/palette.h @@ -28,7 +28,13 @@ enum struct PaletteFadeControl { - u32 multipurpose1; + u32 multipurpose1; // This field needs to exist or errors will occur + u16 blendColor1:15; + u16 tint1:1; + u32 tint0:1; + u32 coeff0:5; + u32 coeff1:5; + u32 weight:9; u8 delayCounter:6; u16 y:5; // blend coefficient u16 targetY:5; // target blend coefficient @@ -66,7 +72,7 @@ u8 UpdatePaletteFade(void); void ResetPaletteFade(void); void ReadPlttIntoBuffers(void); bool8 BeginNormalPaletteFade(u32, s8, u8, u8, u16); -bool8 BeginTimeOfDayPaletteFade(u32, s8, u8, u8, u16); +bool8 BeginTimeOfDayPaletteFade(u32, s8, u8, u8, struct BlendSettings *, struct BlendSettings *, u16); bool8 unref_sub_8073D3C(u32, u8, u8, u8, u16); void unref_sub_8073D84(u8, u32 *); void ResetPaletteStructByUid(u16); diff --git a/src/overworld.c b/src/overworld.c index 0028d976f4..53b693a834 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1514,7 +1514,10 @@ static bool8 FadePalettesWithTime(void) { // Only used to fade back in gTimeOfDay = UpdateTimeOfDay(); if (MapHasNaturalLight(gMapHeader.mapType)) { ResetPaletteFade(); - BeginTimeOfDayPaletteFade(0xFFFFFFFF, 0, 16, sTimeOfDayBlendVars[gTimeOfDay].coeff, sTimeOfDayBlendVars[gTimeOfDay].blendColor); + BeginTimeOfDayPaletteFade(0xFFFFFFFF, 0, 16, 0, + (struct BlendSettings *)&sTimeOfDayBlendVars[currentTimeBlend.time0], + (struct BlendSettings *)&sTimeOfDayBlendVars[currentTimeBlend.time1], + currentTimeBlend.weight); } } diff --git a/src/palette.c b/src/palette.c index e1c9628aa2..9015a42ee8 100644 --- a/src/palette.c +++ b/src/palette.c @@ -55,6 +55,7 @@ static u8 UpdateTimeOfDayPaletteFade(void); static void UpdateBlendRegisters(void); static bool8 IsSoftwarePaletteFadeFinishing(void); static void Task_BlendPalettesGradually(u8 taskId); +static void BlendPalettesFine(u32 palettes, u16 *src, u16 *dst, u32 coeff, u32 color); // palette buffers require alignment with agbcc because // unaligned word reads are issued in BlendPalette otherwise @@ -204,10 +205,10 @@ bool8 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targe } // Like normal palette fade but respects sprite/tile palettes immune to time of day fading -bool8 BeginTimeOfDayPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, u16 blendColor) +// Blend color here is always assumed to be 0 (black). +bool8 BeginTimeOfDayPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, struct BlendSettings *bld0, struct BlendSettings *bld1, u16 weight) { u8 temp; - u16 color = blendColor; if (gPaletteFade.active) { @@ -228,10 +229,17 @@ bool8 BeginTimeOfDayPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 ta gPaletteFade_delay = delay; gPaletteFade.y = startY; gPaletteFade.targetY = targetY; - gPaletteFade.blendColor = color; gPaletteFade.active = 1; gPaletteFade.mode = TIME_OF_DAY_FADE; + gPaletteFade.blendColor = bld0->blendColor; + gPaletteFade.coeff0 = bld0->coeff; + gPaletteFade.tint0 = bld0->isTint; + gPaletteFade.blendColor1 = bld1->blendColor; + gPaletteFade.coeff1 = bld1->coeff; + gPaletteFade.tint1 = bld1->isTint; + gPaletteFade.weight = weight; + if (startY < targetY) gPaletteFade.yDec = 0; else @@ -462,6 +470,12 @@ static u8 UpdateTimeOfDayPaletteFade(void) u8 paletteNum; u16 paletteOffset; u16 selectedPalettes; + u16 timePalettes = 0; // palettes passed to the time-blender + u16 copyPalettes; + u16 * src; + u16 * dst; + struct BlendSettings bld0; + struct BlendSettings bld1; if (!gPaletteFade.active) return PALETTE_FADE_STATUS_DONE; @@ -491,22 +505,47 @@ static u8 UpdateTimeOfDayPaletteFade(void) paletteOffset = 256; } - for (paletteNum = 0; paletteNum < 16; paletteNum++, selectedPalettes >>= 1, paletteOffset += 16) { - if (selectedPalettes & 1) { - if (gPaletteFade.yDec) { - if (gPaletteFade.objPaletteToggle) { // sprite palettes - if (gPaletteFade.y >= gPaletteFade.targetY || GetSpritePaletteTagByPaletteNum(paletteNum) & 0x8000) - TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor); - // tile palettes - } else if (gPaletteFade.y >= gPaletteFade.targetY || (paletteNum >= 13 && paletteNum <= 15)) { - TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor); - } - } else { - TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor); - } + // Extract blend settings from palette fade struct TODO: Embed struct within gPaletteFade + bld0.blendColor = gPaletteFade.blendColor; + bld0.coeff = gPaletteFade.coeff0; + bld0.isTint = gPaletteFade.tint0; + bld1.blendColor = gPaletteFade.blendColor1; + bld1.coeff = gPaletteFade.coeff1; + bld1.isTint = gPaletteFade.tint1; + + src = gPlttBufferUnfaded + paletteOffset; + dst = gPlttBufferFaded + paletteOffset; + + // First pply TOD blend to relevant subset of palettes + if (gPaletteFade.objPaletteToggle) { // Sprite palettes, don't blend those with tags + u8 i; + u16 j = 1; + for (i = 0; i < 16; i++, j <<= 1) { // Mask out palettes that should not be light blended + if ((selectedPalettes & j) && !(GetSpritePaletteTagByPaletteNum(i) >> 15)) + timePalettes |= j; + } + + } else { // tile palettes, don't blend [13, 15] + timePalettes = selectedPalettes &= ~0xE000; + } + TimeMixPalettes(timePalettes, src, dst, &bld0, &bld1, gPaletteFade.weight); + + // palettes that were not blended above must be copied through + if ((copyPalettes = ~timePalettes)) { + u16 * src1 = src; + u16 * dst1 = dst; + while (copyPalettes) { + if (copyPalettes & 1) + CpuFastCopy(src1, dst1, 64); + copyPalettes >>= 1; + src1 += 16; + dst1 += 16; } } + // Then, blend from faded->faded with native BlendPalettes + BlendPalettesFine(selectedPalettes, dst, dst, gPaletteFade.y, 0); + gPaletteFade.objPaletteToggle ^= 1; if (!gPaletteFade.objPaletteToggle) @@ -981,8 +1020,7 @@ static void BlendPalettesFine(u32 palettes, u16 *src, u16 *dst, u32 coeff, u32 c do { if (palettes & 1) { u16 *srcEnd = src + 16; - *dst++ = *src++; // transparency is copied-through - while (src != srcEnd) { + while (src != srcEnd) { // Transparency is blended because it can matter for tile palettes u32 srcColor = *src; s32 r = (srcColor << 27) >> 27; s32 g = (srcColor << 22) >> 27;