diff --git a/src/field_specials.c b/src/field_specials.c index 1c5cfa987b..33ed031918 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -64,6 +64,7 @@ #include "constants/battle_frontier.h" #include "constants/weather.h" #include "constants/metatile_labels.h" +#include "constants/rgb.h" #include "palette.h" #define TAG_ITEM_ICON 5500 @@ -3395,7 +3396,7 @@ void SetDeoxysRockPalette(void) u32 paletteNum = IndexOfSpritePaletteTag(OBJ_EVENT_PAL_TAG_BIRTH_ISLAND_STONE); LoadPalette(&sDeoxysRockPalettes[(u8)VarGet(VAR_DEOXYS_ROCK_LEVEL)], OBJ_PLTT_ID(paletteNum), PLTT_SIZEOF(4)); // Set faded to all black, weather blending handled during fade-in - CpuFill16(0, &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], 32); + CpuFill16(RGB_BLACK, &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], PLTT_SIZE_4BPP); } void SetPCBoxToSendMon(u8 boxId) diff --git a/src/field_weather_effect.c b/src/field_weather_effect.c index 1d24927859..f8d8fa0ac4 100644 --- a/src/field_weather_effect.c +++ b/src/field_weather_effect.c @@ -1386,20 +1386,20 @@ static void DestroyFogHorizontalSprites(void); // Updates just the color of shadows to match special weather blending u8 UpdateShadowColor(u16 color) { - u8 paletteNum = IndexOfSpritePaletteTag(TAG_WEATHER_START); - u16 ALIGNED(4) tempBuffer[16]; - u16 blendedColor; - if (paletteNum != 0xFF) { - u16 index = (paletteNum+16)*16+SHADOW_COLOR_INDEX; - gPlttBufferUnfaded[index] = gPlttBufferFaded[index] = color; - // Copy to temporary buffer, blend, and keep just the shadow color index - CpuFastCopy(&gPlttBufferFaded[index-SHADOW_COLOR_INDEX], tempBuffer, 32); - UpdateSpritePaletteWithTime(paletteNum); - blendedColor = gPlttBufferFaded[index]; - CpuFastCopy(tempBuffer, &gPlttBufferFaded[index-SHADOW_COLOR_INDEX], 32); - gPlttBufferFaded[index] = blendedColor; - } - return paletteNum; + u8 paletteNum = IndexOfSpritePaletteTag(TAG_WEATHER_START); + u16 ALIGNED(4) tempBuffer[16]; + u16 blendedColor; + if (paletteNum < 16) { + u16 index = OBJ_PLTT_ID(paletteNum)+SHADOW_COLOR_INDEX; + gPlttBufferUnfaded[index] = gPlttBufferFaded[index] = color; + // Copy to temporary buffer, blend, and keep just the shadow color index + CpuFastCopy(&gPlttBufferFaded[index-SHADOW_COLOR_INDEX], tempBuffer, PLTT_SIZE_4BPP); + UpdateSpritePaletteWithTime(paletteNum); + blendedColor = gPlttBufferFaded[index]; + CpuFastCopy(tempBuffer, &gPlttBufferFaded[index-SHADOW_COLOR_INDEX], PLTT_SIZE_4BPP); + gPlttBufferFaded[index] = blendedColor; + } + return paletteNum; } void FogHorizontal_InitVars(void) diff --git a/src/overworld.c b/src/overworld.c index 9c4bd0cdfb..cbe0347768 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1473,9 +1473,9 @@ void CB1_Overworld(void) const struct BlendSettings gTimeOfDayBlend[] = { - [TIME_OF_DAY_NIGHT] = {.coeff = 10, .blendColor = TINT_NIGHT, .isTint = TRUE}, - [TIME_OF_DAY_TWILIGHT] = {.coeff = 4, .blendColor = 0xA8B0E0, .isTint = TRUE}, - [TIME_OF_DAY_DAY] = {.coeff = 0, .blendColor = 0}, + [TIME_OF_DAY_NIGHT] = {.coeff = 10, .blendColor = TINT_NIGHT, .isTint = TRUE}, + [TIME_OF_DAY_TWILIGHT] = {.coeff = 4, .blendColor = 0xA8B0E0, .isTint = TRUE}, + [TIME_OF_DAY_DAY] = {.coeff = 0, .blendColor = 0}, }; u8 UpdateTimeOfDay(void) { @@ -1523,8 +1523,12 @@ u8 UpdateTimeOfDay(void) { } bool8 MapHasNaturalLight(u8 mapType) { // Whether a map type is naturally lit/outside - return mapType == MAP_TYPE_TOWN || mapType == MAP_TYPE_CITY || mapType == MAP_TYPE_ROUTE - || mapType == MAP_TYPE_OCEAN_ROUTE; + return ( + mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_OCEAN_ROUTE + ); } // Update & mix day / night bg palettes (into unfaded) @@ -1553,38 +1557,42 @@ void UpdateAltBgPalettes(u16 palettes) { } void UpdatePalettesWithTime(u32 palettes) { - if (MapHasNaturalLight(gMapHeader.mapType)) { - u32 i; - u32 mask = 1 << 16; - if (palettes >= 0x10000) - for (i = 0; i < 16; i++, mask <<= 1) - if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(i))) - palettes &= ~(mask); + if (MapHasNaturalLight(gMapHeader.mapType)) { + u32 i; + u32 mask = 1 << 16; + if (palettes >= (1 << 16)) + for (i = 0; i < 16; i++, mask <<= 1) + if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(i))) + palettes &= ~(mask); palettes &= PALETTES_MAP | PALETTES_OBJECTS; // Don't blend UI pals if (!palettes) - return; - TimeMixPalettes(palettes, - gPlttBufferUnfaded, - gPlttBufferFaded, - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], - currentTimeBlend.weight); - } + return; + TimeMixPalettes( + palettes, + gPlttBufferUnfaded, + gPlttBufferFaded, + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], + currentTimeBlend.weight + ); + } } u8 UpdateSpritePaletteWithTime(u8 paletteNum) { - if (MapHasNaturalLight(gMapHeader.mapType)) { - if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(paletteNum))) - return paletteNum; - TimeMixPalettes(1, - &gPlttBufferUnfaded[OBJ_PLTT_ID(paletteNum)], - &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], - currentTimeBlend.weight); - } - return paletteNum; + if (MapHasNaturalLight(gMapHeader.mapType)) { + if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(paletteNum))) + return paletteNum; + TimeMixPalettes( + 1, + &gPlttBufferUnfaded[OBJ_PLTT_ID(paletteNum)], + &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], + currentTimeBlend.weight + ); + } + return paletteNum; } static void OverworldBasic(void) @@ -1600,19 +1608,20 @@ static void OverworldBasic(void) DoScheduledBgTilemapCopiesToVram(); // Every minute if no palette fade is active, update TOD blending as needed if (!gPaletteFade.active && ++gTimeUpdateCounter >= 3600) { - struct TimeBlendSettings cachedBlend = { - .time0 = currentTimeBlend.time0, - .time1 = currentTimeBlend.time1, - .weight = currentTimeBlend.weight, - }; - gTimeUpdateCounter = 0; - UpdateTimeOfDay(); - if (cachedBlend.time0 != currentTimeBlend.time0 - || cachedBlend.time1 != currentTimeBlend.time1 - || cachedBlend.weight != currentTimeBlend.weight) { + struct TimeBlendSettings cachedBlend = { + .time0 = currentTimeBlend.time0, + .time1 = currentTimeBlend.time1, + .weight = currentTimeBlend.weight, + }; + gTimeUpdateCounter = 0; + UpdateTimeOfDay(); + if (cachedBlend.time0 != currentTimeBlend.time0 + || cachedBlend.time1 != currentTimeBlend.time1 + || cachedBlend.weight != currentTimeBlend.weight) + { UpdateAltBgPalettes(PALETTES_BG); UpdatePalettesWithTime(PALETTES_ALL); - } + } } } diff --git a/src/palette.c b/src/palette.c index a8be1867a7..ddc0688209 100644 --- a/src/palette.c +++ b/src/palette.c @@ -525,15 +525,15 @@ static u8 UpdateTimeOfDayPaletteFade(void) // 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, 32); - copyPalettes >>= 1; - src1 += 16; - dst1 += 16; - } + u16 * src1 = src; + u16 * dst1 = dst; + while (copyPalettes) { + if (copyPalettes & 1) + CpuFastCopy(src1, dst1, 32); + copyPalettes >>= 1; + src1 += 16; + dst1 += 16; + } } // Then, blend from faded->faded with native BlendPalettes @@ -1330,58 +1330,59 @@ void TintPalette_CustomTone(u16 *palette, u16 count, u16 rTone, u16 gTone, u16 b // Tints from Unfaded to Faded, using a 15-bit GBA color void TintPalette_RGB_Copy(u16 palOffset, u32 blendColor) { - s32 newR, newG, newB, rTone, gTone, bTone; - u16 * src = gPlttBufferUnfaded + palOffset; - u16 * dst = gPlttBufferFaded + palOffset; - u32 defaultBlendColor = DEFAULT_LIGHT_COLOR; - u16 *srcEnd = src + 16; - u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through unchanged - u32 altBlendColor; - - newR = ((blendColor << 27) >> 27) << 3; - newG = ((blendColor << 22) >> 27) << 3; - newB = ((blendColor << 17) >> 27) << 3; - - if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend - // Note that bit 0 of altBlendIndices specifies color 1 - altBlendColor = src[14]; // color 15 - if (altBlendColor >> 15) { // Set alternate blend color - rTone = ((altBlendColor << 27) >> 27) << 3; - gTone = ((altBlendColor << 22) >> 27) << 3; - bTone = ((altBlendColor << 17) >> 27) << 3; - } else { // Set default blend color - rTone = ((defaultBlendColor << 27) >> 27) << 3; - gTone = ((defaultBlendColor << 22) >> 27) << 3; - bTone = ((defaultBlendColor << 17) >> 27) << 3; + s32 newR, newG, newB, rTone, gTone, bTone; + u16 * src = gPlttBufferUnfaded + palOffset; + u16 * dst = gPlttBufferFaded + palOffset; + u32 defaultBlendColor = DEFAULT_LIGHT_COLOR; + u16 *srcEnd = src + 16; + u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through unchanged + u32 altBlendColor; + + newR = ((blendColor << 27) >> 27) << 3; + newG = ((blendColor << 22) >> 27) << 3; + newB = ((blendColor << 17) >> 27) << 3; + + if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend + // Note that bit 0 of altBlendIndices specifies color 1 + altBlendColor = src[14]; // color 15 + if (altBlendColor >> 15) { // Set alternate blend color + rTone = ((altBlendColor << 27) >> 27) << 3; + gTone = ((altBlendColor << 22) >> 27) << 3; + bTone = ((altBlendColor << 17) >> 27) << 3; + } else { // Set default blend color + rTone = ((defaultBlendColor << 27) >> 27) << 3; + gTone = ((defaultBlendColor << 22) >> 27) << 3; + bTone = ((defaultBlendColor << 17) >> 27) << 3; + } + } else { + altBlendIndices = 0; } - } else { - altBlendIndices = 0; - } - while (src != srcEnd) { - u32 srcColor = *src; - s32 r = (srcColor << 27) >> 27; - s32 g = (srcColor << 22) >> 27; - s32 b = (srcColor << 17) >> 27; - if (altBlendIndices & 1) { - r = (u16)((rTone * r)) >> 8; - g = (u16)((gTone * g)) >> 8; - b = (u16)((bTone * b)) >> 8; - } else { // Use provided blend color - r = (u16)((newR * r)) >> 8; - g = (u16)((newG * g)) >> 8; - b = (u16)((newB * b)) >> 8; + while (src != srcEnd) { + u32 srcColor = *src; + s32 r = (srcColor << 27) >> 27; + s32 g = (srcColor << 22) >> 27; + s32 b = (srcColor << 17) >> 27; + + if (altBlendIndices & 1) { + r = (u16)((rTone * r)) >> 8; + g = (u16)((gTone * g)) >> 8; + b = (u16)((bTone * b)) >> 8; + } else { // Use provided blend color + r = (u16)((newR * r)) >> 8; + g = (u16)((newG * g)) >> 8; + b = (u16)((newB * b)) >> 8; + } + if (r > 31) + r = 31; + if (g > 31) + g = 31; + if (b > 31) + b = 31; + src++; + *dst++ = RGB2(r, g, b); + altBlendIndices >>= 1; } - if (r > 31) - r = 31; - if (g > 31) - g = 31; - if (b > 31) - b = 31; - src++; - *dst++ = RGB2(r, g, b); - altBlendIndices >>= 1; - } } #define tCoeff data[0] diff --git a/src/palette_util.c b/src/palette_util.c index bcf8c34819..54549ffcce 100755 --- a/src/palette_util.c +++ b/src/palette_util.c @@ -385,8 +385,7 @@ void UpdatePulseBlend(struct PulseBlend *pulseBlend) if (--pulseBlendPalette->delayCounter == 0xFF) { pulseBlendPalette->delayCounter = pulseBlendPalette->pulseBlendSettings.delay; - // TODO: Optimize pulse blending - CpuFastCopy(gPlttBufferUnfaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, gPlttBufferFaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, 32); + CpuFastCopy(gPlttBufferUnfaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, gPlttBufferFaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, PLTT_SIZE_4BPP); UpdatePalettesWithTime(1 << (pulseBlendPalette->pulseBlendSettings.paletteOffset >> 4)); // pulseBlendSettings has a numColors field, but it is only ever set to 16 (for mirage tower) // So, it's ok to use the fine blending here which blends the entire palette