Added inter-time-of-day blending.
This commit is contained in:
parent
3bd46b5b7a
commit
22c429d0d6
4 changed files with 181 additions and 52 deletions
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
} 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;
|
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();
|
||||||
|
|
152
src/palette.c
152
src/palette.c
|
@ -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
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
continue;
|
} else {
|
||||||
|
altBlendIndices = 0;
|
||||||
}
|
}
|
||||||
r = data1->r;
|
while (palDataSrc != palDataSrcEnd) {
|
||||||
g = data1->g;
|
u32 palDataSrcColor = *palDataSrc;
|
||||||
b = data1->b;
|
s32 r = (palDataSrcColor << 27) >> 27;
|
||||||
blendData = (altBlendIndices && altBlendIndices & (1 << i)) ? data3 : data2;
|
s32 g = (palDataSrcColor << 22) >> 27;
|
||||||
gPlttBufferFaded[index] = RGB(r + (((blendData->r - r) * coeff) >> 4),
|
s32 b = (palDataSrcColor << 17) >> 27;
|
||||||
g + (((blendData->g - g) * coeff) >> 4),
|
|
||||||
b + (((blendData->b - b) * coeff) >> 4));
|
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);
|
|
||||||
palettes >>= 1;
|
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;
|
||||||
|
} while (palettes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendPalettesUnfaded(u32 selectedPalettes, u8 coeff, u16 color)
|
void BlendPalettesUnfaded(u32 selectedPalettes, u8 coeff, u16 color)
|
||||||
|
|
Loading…
Reference in a new issue