Added inter-time-of-day blending.

This commit is contained in:
Ariel Antonitis 2021-04-19 00:07:42 -04:00
parent 3bd46b5b7a
commit 22c429d0d6
4 changed files with 181 additions and 52 deletions

View file

@ -44,6 +44,12 @@ struct LinkPlayerObjectEvent
u8 movementMode; u8 movementMode;
}; };
struct __attribute__((packed)) TimeBlendSettings {
u16 weight:9;
u16 time1:3;
u16 time0:3;
};
// Exported RAM declarations // Exported RAM declarations
extern struct WarpData gLastUsedWarp; extern struct WarpData gLastUsedWarp;
extern struct LinkPlayerObjectEvent gLinkPlayerObjectEvents[4]; extern struct LinkPlayerObjectEvent gLinkPlayerObjectEvents[4];

View file

@ -77,9 +77,9 @@ void BlendPalettes(u32 selectedPalettes, u8 coeff, u16 color);
void BlendPalettesUnfaded(u32, u8, u16); void BlendPalettesUnfaded(u32, u8, u16);
void BlendPalettesGradually(u32 selectedPalettes, s8 delay, u8 coeff, u8 coeffTarget, u16 color, u8 priority, u8 id); void BlendPalettesGradually(u32 selectedPalettes, s8 delay, u8 coeff, u8 coeffTarget, u16 color, u8 priority, u8 id);
void AveragePalettes(u16 *palette0, u16* palette1, u16* dest, u16 weight); void AveragePalettes(u16 *palette0, u16* palette1, u16* dest, u16 weight);
void TimeBlendPalette(u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor); void TimeBlendPalette(u16 palOffset, u32 coeff, u32 blendColor);
void TintPalette_RGB_Copy(u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor); void TintPalette_RGB_Copy(u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor);
void TimeBlendPalettes(u32 palettes, u8 coeff, u16 color); void TimeBlendPalettes(u32 palettes, u32 coeff, u32 blendColor);
void TintPalette_GrayScale(u16 *palette, u16 count); void TintPalette_GrayScale(u16 *palette, u16 count);
void TintPalette_GrayScale2(u16 *palette, u16 count); void TintPalette_GrayScale2(u16 *palette, u16 count);
void TintPalette_SepiaTone(u16 *palette, u16 count); void TintPalette_SepiaTone(u16 *palette, u16 count);

View file

@ -186,7 +186,9 @@ static u16 (*sPlayerKeyInterceptCallback)(u32);
static bool8 sReceivingFromLink; static bool8 sReceivingFromLink;
static u8 sRfuKeepAliveTimer; static u8 sRfuKeepAliveTimer;
u8 static gTimeOfDayState; static u8 gTimeOfDayState;
static u8 timeCounter;
static struct TimeBlendSettings currentTimeBlend;
// IWRAM common // IWRAM common
u16 *gBGTilemapBuffers1; u16 *gBGTilemapBuffers1;
@ -1472,12 +1474,39 @@ static const struct TimeOfDayBlend sTimeOfDayBlendVars[] =
}; };
u8 UpdateTimeOfDay(void) { u8 UpdateTimeOfDay(void) {
s8 hours, minutes;
RtcCalcLocalTime(); RtcCalcLocalTime();
if (gLocalTime.hours >= 20 || gLocalTime.hours < 4) hours = gLocalTime.hours;
return gTimeOfDay = TIME_OF_DAY_NIGHT; minutes = gLocalTime.minutes;
else if (gLocalTime.hours >= 10 && gLocalTime.hours < 20) if (hours >= 22 || hours < 4) {
currentTimeBlend.weight = 256;
return gTimeOfDay = currentTimeBlend.time0 = currentTimeBlend.time1 = TIME_OF_DAY_NIGHT;
} else if (hours >= 4 && hours < 7) { // night->twilight
currentTimeBlend.time0 = TIME_OF_DAY_NIGHT;
currentTimeBlend.time1 = TIME_OF_DAY_TWILIGHT;
currentTimeBlend.weight = 256 - 256 * ((hours - 4) * 60 + minutes) / ((7-4)*60);
return gTimeOfDay = TIME_OF_DAY_DAY; return gTimeOfDay = TIME_OF_DAY_DAY;
return gTimeOfDay = TIME_OF_DAY_TWILIGHT; } else if (hours >= 7 && hours < 10) { // twilight->day
currentTimeBlend.time0 = TIME_OF_DAY_TWILIGHT;
currentTimeBlend.time1 = TIME_OF_DAY_DAY;
currentTimeBlend.weight = 256 - 256 * ((hours - 7) * 60 + minutes) / ((10-7)*60);
return gTimeOfDay = TIME_OF_DAY_DAY;
} else if (hours >= 10 && hours < 18) { // day
currentTimeBlend.weight = 256;
return gTimeOfDay = currentTimeBlend.time0 = currentTimeBlend.time1 = TIME_OF_DAY_DAY;
} else if (hours >= 18 && hours < 20) { // day->twilight
currentTimeBlend.time0 = TIME_OF_DAY_DAY;
currentTimeBlend.time1 = TIME_OF_DAY_TWILIGHT;
currentTimeBlend.weight = 256 - 256 * ((hours - 18) * 60 + minutes) / ((20-18)*60);
return gTimeOfDay = TIME_OF_DAY_TWILIGHT;
} else if (hours >= 20 && hours < 22) { // twilight->night
currentTimeBlend.time0 = TIME_OF_DAY_TWILIGHT;
currentTimeBlend.time1 = TIME_OF_DAY_NIGHT;
currentTimeBlend.weight = 256 - 256 * ((hours - 20) * 60 + minutes) / ((22-20)*60);
return gTimeOfDay = TIME_OF_DAY_NIGHT;
} else { // This should never occur
return TIME_OF_DAY_MAX;
}
} }
static bool8 MapHasNaturalLight(u8 mapType) { // Weather a map type is naturally lit/outside static bool8 MapHasNaturalLight(u8 mapType) { // Weather a map type is naturally lit/outside
@ -1485,7 +1514,7 @@ static bool8 MapHasNaturalLight(u8 mapType) { // Weather a map type is naturally
|| mapType == MAP_TYPE_OCEAN_ROUTE; || mapType == MAP_TYPE_OCEAN_ROUTE;
} }
static bool8 FadePalettesWithTime(void) { static bool8 FadePalettesWithTime(void) { // Only used to fade back in
gTimeOfDayState = 0; gTimeOfDayState = 0;
gTimeOfDay = UpdateTimeOfDay(); gTimeOfDay = UpdateTimeOfDay();
if (MapHasNaturalLight(gMapHeader.mapType)) { if (MapHasNaturalLight(gMapHeader.mapType)) {
@ -1495,8 +1524,7 @@ static bool8 FadePalettesWithTime(void) {
} }
void UpdatePalettesWithTime(u32 palettes) { void UpdatePalettesWithTime(u32 palettes) {
// Only blend if not transitioning between times and the map type allows if (MapHasNaturalLight(gMapHeader.mapType)) {
if (gTimeOfDayState == 0 && MapHasNaturalLight(gMapHeader.mapType)) {
u8 i, j; u8 i, j;
u16 tempPaletteBuffer[16]; u16 tempPaletteBuffer[16];
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
@ -1509,10 +1537,14 @@ void UpdatePalettesWithTime(u32 palettes) {
return; return;
for (i = 0; palettes; i++) { for (i = 0; palettes; i++) {
if (palettes & 1) { if (palettes & 1) {
TimeBlendPalette(i*16, 16, sTimeOfDayBlendVars[gTimeOfDay].coeff, sTimeOfDayBlendVars[gTimeOfDay].blendColor); TimeBlendPalette(i*16, sTimeOfDayBlendVars[currentTimeBlend.time0].coeff, sTimeOfDayBlendVars[currentTimeBlend.time0].blendColor);
if (currentTimeBlend.weight == 256) {
palettes >>= 1;
continue;
}
CpuFastCopy(&gPlttBufferFaded[i*16], tempPaletteBuffer, 32); CpuFastCopy(&gPlttBufferFaded[i*16], tempPaletteBuffer, 32);
TimeBlendPalette(i*16, 16, sTimeOfDayBlendVars[TIME_OF_DAY_TWILIGHT].coeff, sTimeOfDayBlendVars[TIME_OF_DAY_TWILIGHT].blendColor); TimeBlendPalette(i*16, sTimeOfDayBlendVars[currentTimeBlend.time1].coeff, sTimeOfDayBlendVars[currentTimeBlend.time1].blendColor);
AveragePalettes(tempPaletteBuffer, &gPlttBufferFaded[i*16], &gPlttBufferFaded[i*16], 256); AveragePalettes(tempPaletteBuffer, &gPlttBufferFaded[i*16], &gPlttBufferFaded[i*16], currentTimeBlend.weight);
} }
palettes >>= 1; palettes >>= 1;
} }
@ -1535,6 +1567,19 @@ static void OverworldBasic(void)
UpdatePaletteFade(); UpdatePaletteFade();
UpdateTilesetAnimations(); UpdateTilesetAnimations();
DoScheduledBgTilemapCopiesToVram(); DoScheduledBgTilemapCopiesToVram();
if (!(gPaletteFade.active || (timeCounter++ % 60))) {
struct TimeBlendSettings cachedBlend = {
.time0 = currentTimeBlend.time0,
.time1 = currentTimeBlend.time1,
.weight = currentTimeBlend.weight,
};
timeCounter = 0;
UpdateTimeOfDay();
if (cachedBlend.time0 != currentTimeBlend.time0
|| cachedBlend.time1 != currentTimeBlend.time1
|| cachedBlend.weight != currentTimeBlend.weight)
UpdatePalettesWithTime(0xFFFFFFFF);
}
} }
// This CB2 is used when starting // This CB2 is used when starting
@ -1545,9 +1590,7 @@ void CB2_OverworldBasic(void)
void CB2_Overworld(void) void CB2_Overworld(void)
{ {
u32 *debugPtr = (u32*) 0x0203de00;
bool32 fading = (gPaletteFade.active != 0); bool32 fading = (gPaletteFade.active != 0);
*debugPtr = (u32) &gTimeOfDay;
if (fading) if (fading)
SetVBlankCallback(NULL); SetVBlankCallback(NULL);
OverworldBasic(); OverworldBasic();

View file

@ -496,13 +496,13 @@ static u8 UpdateTimeOfDayPaletteFade(void)
if (gPaletteFade.yDec) { if (gPaletteFade.yDec) {
if (gPaletteFade.objPaletteToggle) { // sprite palettes if (gPaletteFade.objPaletteToggle) { // sprite palettes
if (gPaletteFade.y >= gPaletteFade.targetY || GetSpritePaletteTagByPaletteNum(paletteNum) & 0x8000) if (gPaletteFade.y >= gPaletteFade.targetY || GetSpritePaletteTagByPaletteNum(paletteNum) & 0x8000)
TimeBlendPalette(paletteOffset, 16, gPaletteFade.y, gPaletteFade.blendColor); TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor);
// tile palettes // tile palettes
} else if (gPaletteFade.y >= gPaletteFade.targetY || (paletteNum >= 13 && paletteNum <= 15)) { } else if (gPaletteFade.y >= gPaletteFade.targetY || (paletteNum >= 13 && paletteNum <= 15)) {
TimeBlendPalette(paletteOffset, 16, gPaletteFade.y, gPaletteFade.blendColor); TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor);
} }
} else { } else {
TimeBlendPalette(paletteOffset, 16, gPaletteFade.y, gPaletteFade.blendColor); TimeBlendPalette(paletteOffset, gPaletteFade.y, gPaletteFade.blendColor);
} }
} }
} }
@ -1010,45 +1010,125 @@ void AveragePalettes(u16 *palette0, u16* palette1, u16* dest, u16 weight) {
#define DEFAULT_LIGHT_COLOR 0x3f9f #define DEFAULT_LIGHT_COLOR 0x3f9f
// Like BlendPalette, but ignores blendColor if the transparency high bit is set // Like BlendPalette, but ignores blendColor if the transparency high bit is set
void TimeBlendPalette(u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor) { // Optimization help by lucktyphlosion
u16 i; void TimeBlendPalette(u16 palOffset, u32 coeff, u32 blendColor) {
u16 defaultBlendColor = DEFAULT_LIGHT_COLOR; s32 newR, newG, newB, defR, defG, defB;
s8 r, g, b; u16 * palDataSrc = gPlttBufferUnfaded + palOffset;
struct PlttData *data2 = (struct PlttData *)&blendColor; u16 * palDataDst = gPlttBufferFaded + palOffset;
struct PlttData *data3; u32 defaultBlendColor = DEFAULT_LIGHT_COLOR;
struct PlttData *blendData; u16 *palDataSrcEnd = palDataSrc + 16;
u16 altBlendIndices = 0; u16 altBlendIndices = *palDataDst++ = *palDataSrc++; // color 0 is copied through unchanged
for (i = 0; i < numEntries; i++) { u32 altBlendColor;
u16 index = i + palOffset;
struct PlttData *data1 = (struct PlttData *)&gPlttBufferUnfaded[index]; coeff *= 2;
if (i == 0) { newR = (blendColor << 27) >> 27;
if (data1->unused_15) { // Color 0 is a bitmask for which colors to blend; color 15 is the alt blend color newG = (blendColor << 22) >> 27;
gPlttBufferFaded[index] = gPlttBufferUnfaded[index]; newB = (blendColor << 17) >> 27;
altBlendIndices = gPlttBufferUnfaded[index] << 1; // bit 0 specifies color 1, etc.
data3 = (struct PlttData *)&gPlttBufferUnfaded[index+15]; if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend
if (!data3->unused_15) // use default blend color instead // Note that bit 0 of altBlendIndices specifies color 1
data3 = (struct PlttData *)&defaultBlendColor; altBlendColor = palDataSrc[14]; // color 15
} if (altBlendColor >> 15) { // Set alternate blend color
continue; defR = (altBlendColor << 27) >> 27;
defG = (altBlendColor << 22) >> 27;
defB = (altBlendColor << 17) >> 27;
} else { // Set default blend color
defR = (defaultBlendColor << 27) >> 27;
defG = (defaultBlendColor << 22) >> 27;
defB = (defaultBlendColor << 17) >> 27;
} }
r = data1->r; } else {
g = data1->g; altBlendIndices = 0;
b = data1->b; }
blendData = (altBlendIndices && altBlendIndices & (1 << i)) ? data3 : data2; while (palDataSrc != palDataSrcEnd) {
gPlttBufferFaded[index] = RGB(r + (((blendData->r - r) * coeff) >> 4), u32 palDataSrcColor = *palDataSrc;
g + (((blendData->g - g) * coeff) >> 4), s32 r = (palDataSrcColor << 27) >> 27;
b + (((blendData->b - b) * coeff) >> 4)); s32 g = (palDataSrcColor << 22) >> 27;
s32 b = (palDataSrcColor << 17) >> 27;
if (altBlendIndices & 1) {
*palDataDst = ((r + (((defR - r) * coeff) >> 5)) << 0)
| ((g + (((defG - g) * coeff) >> 5)) << 5)
| ((b + (((defB - b) * coeff) >> 5)) << 10);
} else { // Use provided blend color
*palDataDst = ((r + (((newR - r) * coeff) >> 5)) << 0)
| ((g + (((newG - g) * coeff) >> 5)) << 5)
| ((b + (((newB - b) * coeff) >> 5)) << 10);
}
palDataSrc++;
palDataDst++;
altBlendIndices >>= 1;
} }
} }
// Apply time effect to a series of palettes void TimeBlendPalettes(u32 palettes, u32 coeff, u32 blendColor) {
void TimeBlendPalettes(u32 palettes, u8 coeff, u16 color) { s32 newR, newG, newB, defR, defG, defB, altR, altG, altB;
u16 paletteOffset; u16 * palDataSrc;
for (paletteOffset = 0; palettes; paletteOffset += 16) { u16 * palDataDst;
if (palettes & 1) u32 defaultBlendColor = DEFAULT_LIGHT_COLOR;
TimeBlendPalette(paletteOffset, 16, coeff, color);
if (!palettes)
return;
coeff *= 2;
newR = (blendColor << 27) >> 27;
newG = (blendColor << 22) >> 27;
newB = (blendColor << 17) >> 27;
defR = (defaultBlendColor << 27) >> 27;
defG = (defaultBlendColor << 22) >> 27;
defB = (defaultBlendColor << 17) >> 27;
palDataSrc = gPlttBufferUnfaded;
palDataDst = gPlttBufferFaded;
do {
if (palettes & 1) {
u16 *palDataSrcEnd = palDataSrc + 16;
u16 altBlendIndices = *palDataDst++ = *palDataSrc++; // color 0 is copied through
u32 altBlendColor;
if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend
// Note that bit 0 of altBlendIndices specifies color 1
altBlendColor = palDataSrc[14]; // color 15
if (altBlendColor >> 15) { // Set alternate blend color
altR = (altBlendColor << 27) >> 27;
altG = (altBlendColor << 22) >> 27;
altB = (altBlendColor << 17) >> 27;
} else {
altBlendColor = 0;
}
} else {
altBlendIndices = 0;
}
while (palDataSrc != palDataSrcEnd) {
u32 palDataSrcColor = *palDataSrc;
s32 r = (palDataSrcColor << 27) >> 27;
s32 g = (palDataSrcColor << 22) >> 27;
s32 b = (palDataSrcColor << 17) >> 27;
if (altBlendIndices & 1) {
if (altBlendColor) { // Use alternate blend color
*palDataDst = ((r + (((altR - r) * coeff) >> 5)) << 0)
| ((g + (((altG - g) * coeff) >> 5)) << 5)
| ((b + (((altB - b) * coeff) >> 5)) << 10);
} else { // Use default blend color
*palDataDst = ((r + (((defR - r) * coeff) >> 5)) << 0)
| ((g + (((defG - g) * coeff) >> 5)) << 5)
| ((b + (((defB - b) * coeff) >> 5)) << 10);
}
} else { // Use provided blend color
*palDataDst = ((r + (((newR - r) * coeff) >> 5)) << 0)
| ((g + (((newG - g) * coeff) >> 5)) << 5)
| ((b + (((newB - b) * coeff) >> 5)) << 10);
}
palDataSrc++;
palDataDst++;
altBlendIndices >>= 1;
}
} else {
palDataSrc += 16;
palDataDst += 16;
}
palettes >>= 1; palettes >>= 1;
} } while (palettes);
} }
void BlendPalettesUnfaded(u32 selectedPalettes, u8 coeff, u16 color) void BlendPalettesUnfaded(u32 selectedPalettes, u8 coeff, u16 color)