diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/credits.c | 4 | ||||
-rw-r--r-- | src/field_weather.c | 1320 | ||||
-rw-r--r-- | src/field_weather_util.c | 12 |
3 files changed, 1334 insertions, 2 deletions
diff --git a/src/credits.c b/src/credits.c index e0d57a2a4..4d7bbd67b 100644 --- a/src/credits.c +++ b/src/credits.c @@ -910,7 +910,7 @@ static s32 RollCredits(void) case CREDITSSCRCMD_MAPNEXT: sCreditsMgr->mainseqno = CREDITSSCENE_MAPNEXT_DESTROYWINDOW; sCreditsMgr->whichMon = sCreditsScript[sCreditsMgr->scrcmdidx].param; - FieldWeather_StartFadingOutCreditsMap(1, 0, 0x3FFFFFFF); + FadeSelectedPals(1, 0, 0x3FFFFFFF); break; case CREDITSSCRCMD_MAP: sCreditsMgr->mainseqno = CREDITSSCENE_MAP_LOADMAP_CREATESPRITES; @@ -1305,7 +1305,7 @@ static s32 RollCredits(void) "\tldr r2, _080F3E0C @ =0x3fffffff\n" "\tmovs r0, 0x1\n" "\tmovs r1, 0\n" - "\tbl FieldWeather_StartFadingOutCreditsMap\n" + "\tbl FadeSelectedPals\n" "\tb _080F3E94\n" "\t.align 2, 0\n" "_080F3E04: .4byte sCreditsMgr\n" diff --git a/src/field_weather.c b/src/field_weather.c new file mode 100644 index 000000000..fb5f4eee7 --- /dev/null +++ b/src/field_weather.c @@ -0,0 +1,1320 @@ +#include "global.h" +#include "gflib.h" +#include "blend_palette.h" +#include "field_effect.h" +#include "field_weather.h" +#include "field_weather_util.h" +#include "task.h" +#include "trig.h" +#include "constants/field_weather.h" +#include "constants/weather.h" +#include "constants/songs.h" + +#define DROUGHT_COLOR_INDEX(color) ((((color) >> 1) & 0xF) | (((color) >> 2) & 0xF0) | (((color) >> 3) & 0xF00)) + +enum +{ + GAMMA_NONE, + GAMMA_NORMAL, + GAMMA_ALT, +}; + +struct RGBColor +{ + u16 r:5; + u16 g:5; + u16 b:5; +}; + +struct WeatherPaletteData +{ + u16 gammaShiftColors[8][0x1000]; // 0x1000 is the number of bytes that make up all palettes. +}; + +struct WeatherCallbacks +{ + void (*initVars)(void); + void (*main)(void); + void (*initAll)(void); + bool8 (*finish)(void); +}; + +struct Weather +{ + union + { + struct + { + struct Sprite *rainSprites[MAX_RAIN_SPRITES]; + struct Sprite *snowflakeSprites[101]; + struct Sprite *cloudSprites[NUM_CLOUD_SPRITES]; + } s1; + struct + { + u8 filler0[0xA0]; + struct Sprite *fogHSprites[NUM_FOG_HORIZONTAL_SPRITES]; + struct Sprite *ashSprites[NUM_ASH_SPRITES]; + struct Sprite *fogDSprites[NUM_FOG_DIAGONAL_SPRITES]; + struct Sprite *sandstormSprites1[NUM_SANDSTORM_SPRITES]; + struct Sprite *sandstormSprites2[NUM_SWIRL_SANDSTORM_SPRITES]; + } s2; + } sprites; + u8 gammaShifts[19][32]; + u8 altGammaShifts[19][32]; + s8 gammaIndex; + s8 gammaTargetIndex; + u8 gammaStepDelay; + u8 gammaStepFrameCounter; + u16 fadeDestColor; + /*0x6C6*/ u8 palProcessingState; + /*0x6C7*/ u8 fadeScreenCounter; + /*0x6C8*/ bool8 readyForInit; + /*0x6C9*/ u8 taskId; + /*0x6CA*/ u8 unknown_6CA; + u8 unknown_6CB; + u16 initStep; + u16 finishStep; + u8 currWeather; + u8 nextWeather; + u8 weatherGfxLoaded; + bool8 weatherChangeComplete; + u8 weatherPicSpritePalIndex; + u8 altGammaSpritePalIndex; + u16 rainSpriteVisibleCounter; + u8 curRainSpriteIndex; + u8 targetRainSpriteCount; + u8 rainSpriteCount; + u8 rainSpriteVisibleDelay; + u8 isDownpour; + u8 rainStrength; + /*0x6DE*/ u8 cloudSpritesCreated; + u8 filler_6DF[1]; + u16 snowflakeVisibleCounter; + u16 unknown_6E2; + u8 snowflakeSpriteCount; + u8 targetSnowflakeSpriteCount; + u16 unknown_6E6; + u16 thunderCounter; + u8 unknown_6EA; + u8 unknown_6EB; + u8 unknown_6EC; + u8 thunderTriggered; + u16 fogHScrollPosX; + u16 fogHScrollCounter; + u16 fogHScrollOffset; + u8 lightenedFogSpritePals[6]; + u8 lightenedFogSpritePalsCount; + u8 fogHSpritesCreated; + u16 ashBaseSpritesX; + u16 unknown_6FE; + u8 ashSpritesCreated; + u8 filler_701[3]; + u32 sandstormXOffset; + u32 sandstormYOffset; + u8 filler_70C[2]; + u16 sandstormBaseSpritesX; + u16 sandstormPosY; + u16 sandstormWaveIndex; + u16 sandstormWaveCounter; + u8 sandstormSpritesCreated; + u8 sandstormSwirlSpritesCreated; + u16 fogDBaseSpritesX; + u16 fogDPosY; + u16 fogDScrollXCounter; + u16 fogDScrollYCounter; + u16 fogDXOffset; + u16 fogDYOffset; + u8 fogDSpritesCreated; + u8 filler_725[1]; + u16 bubblesDelayCounter; + u16 bubblesDelayIndex; + u16 bubblesCoordsIndex; + u16 bubblesSpriteCount; + u8 bubblesSpritesCreated; + u8 filler_72F; + u16 currBlendEVA; + u16 currBlendEVB; + u16 targetBlendEVA; + u16 targetBlendEVB; + u8 blendUpdateCounter; + u8 blendFrameCounter; + u8 blendDelay; + u8 filler_73B[0x3C-0x3B]; + s16 unknown_73C; + s16 unknown_73E; + s16 unknown_740; + s16 unknown_742; + u8 filler_744[0xD-4]; + s8 loadDroughtPalsIndex; + u8 loadDroughtPalsOffset; +}; + +EWRAM_DATA struct Weather gWeather = {}; +EWRAM_DATA u8 sFieldEffectPaletteGammaTypes[32] = {}; +EWRAM_DATA const u8 *sPaletteGammaTypes = NULL; +EWRAM_DATA u16 gUnknown_20386A8 = 0; + +void Task_WeatherMain(u8 taskId); +void Task_WeatherInit(u8 taskId); +void None_Init(void); +void None_Main(void); +bool8 None_Finish(void); +void BuildGammaShiftTables(void); +void UpdateWeatherGammaShift(void); +void ApplyGammaShift(u8 startPalIndex, u8 numPalettes, s8 gammaIndex); +void ApplyGammaShiftWithBlend(u8 startPalIndex, u8 numPalettes, s8 gammaIndex, u8 blendCoeff, u16 blendColor); +void ApplyDroughtGammaShiftWithBlend(s8 gammaIndex, u8 blendCoeff, u16 blendColor); +void FadeInScreenWithWeather(void); +bool8 FadeInScreen_RainShowShade(void); +bool8 FadeInScreen_Drought(void); +bool8 FadeInScreen_FogHorizontal(void); +void DoNothing(void); +void ApplyFogBlend(u8 blendCoeff, u16 blendColor); +bool8 LightenSpritePaletteInFog(u8 paletteIndex); +void Weather_SetBlendCoeffs(u8, u8); +bool8 Ash_Finish(void); +bool8 Bubbles_Finish(void); +bool8 Clouds_Finish(void); +bool8 Fog1_Finish(void); +bool8 Fog2_Finish(void); +bool8 LightRain_Finish(void); +bool8 Rain_Finish(void); +bool8 Sandstorm_Finish(void); +bool8 Snow_Finish(void); +bool8 sub_807B434(void); +bool8 sub_807B6BC(void); +bool8 sub_807D8D0(void); +void Ash_InitAll(void); +void Ash_InitVars(void); +void Ash_Main(void); +void Bubbles_InitAll(void); +void Bubbles_InitVars(void); +void Bubbles_Main(void); +void Clouds_InitAll(void); +void Clouds_InitVars(void); +void Clouds_Main(void); +void Drought_InitAll(void); +void Drought_InitVars(void); +void Drought_Main(void); +void Fog1_InitAll(void); +void Fog1_InitVars(void); +void Fog1_Main(void); +void Fog2_InitAll(void); +void Fog2_InitVars(void); +void Fog2_Main(void); +void LightRain_InitAll(void); +void LightRain_InitVars(void); +void LightRain_Main(void); +void Rain_Main(void); +void Sandstorm_InitAll(void); +void Sandstorm_InitVars(void); +void Sandstorm_Main(void); +void Snow_InitAll(void); +void Snow_InitVars(void); +void Weather11_InitAll(void); +void Weather11_InitVars(void); +void Weather2_InitAll(void); +void Weather2_InitVars(void); +void nullsub_48(void); +void nullsub_49(void); +void snowflakes_progress2(void); +void sub_807C2E4(void); +void sub_807C358(void); +void sub_807C388(void); +void sub_807C3F4(void); + +const u32 gUnknown_83BFBE4[] = INCBIN_U32("graphics/field_effects/unk_83BFBE4.bin.lz"); +const u32 gUnknown_83C0408[] = INCBIN_U32("graphics/field_effects/unk_83C0408.bin.lz"); +const u32 gUnknown_83C0C00[] = INCBIN_U32("graphics/field_effects/unk_83C0C00.bin.lz"); +const u32 gUnknown_83C139C[] = INCBIN_U32("graphics/field_effects/unk_83C139C.bin.lz"); +const u32 gUnknown_83C1BB8[] = INCBIN_U32("graphics/field_effects/unk_83C1BB8.bin.lz"); +const u32 gUnknown_83C2380[] = INCBIN_U32("graphics/field_effects/unk_83C2380.bin.lz"); + +const u32 *const gUnknown_83C2BA4[] = { + gUnknown_83BFBE4, + gUnknown_83C0408, + gUnknown_83C0C00, + gUnknown_83C139C, + gUnknown_83C1BB8, + gUnknown_83C2380 +}; + +struct Weather *const gWeatherPtr = &gWeather; + +const struct WeatherCallbacks sWeatherFuncs[] = { + {None_Init, None_Main, None_Init, None_Finish}, + {Clouds_InitVars, Clouds_Main, Clouds_InitAll, Clouds_Finish}, + {Weather2_InitVars, nullsub_48, Weather2_InitAll, sub_807B434}, + {LightRain_InitVars, LightRain_Main, LightRain_InitAll, LightRain_Finish}, + {Snow_InitVars, snowflakes_progress2, Snow_InitAll, Snow_Finish}, + {sub_807C2E4, Rain_Main, sub_807C358, Rain_Finish}, + {Fog1_InitVars, Fog1_Main, Fog1_InitAll, Fog1_Finish}, + {Ash_InitVars, Ash_Main, Ash_InitAll, Ash_Finish}, + {Sandstorm_InitVars, Sandstorm_Main, Sandstorm_InitAll, Sandstorm_Finish}, + {Fog2_InitVars, Fog2_Main, Fog2_InitAll, Fog2_Finish}, + {Fog1_InitVars, Fog1_Main, Fog1_InitAll, Fog1_Finish}, + {Weather11_InitVars, nullsub_49, Weather11_InitAll, sub_807D8D0}, + {Drought_InitVars, Drought_Main, Drought_InitAll, sub_807B6BC}, + {sub_807C388, Rain_Main, sub_807C3F4, Rain_Finish}, + {Bubbles_InitVars, Bubbles_Main, Bubbles_InitAll, Bubbles_Finish}, +}; + +void (*const gWeatherPalStateFuncs[])(void) = { + UpdateWeatherGammaShift, + FadeInScreenWithWeather, + DoNothing, + DoNothing +}; + +const u8 sBasePaletteGammaTypes[32] = { + // background palettes + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NONE, + GAMMA_NONE, + GAMMA_NONE, + // sprite palettes + GAMMA_ALT, + GAMMA_NORMAL, + GAMMA_ALT, + GAMMA_ALT, + GAMMA_ALT, + GAMMA_ALT, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_ALT, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, + GAMMA_NORMAL, +}; + +const u16 gUnknown_83C2CE0[] = INCBIN_U16("graphics/field_effects/unk_83C2CE0.gbapal"); + +// code +void StartWeather(void) +{ + if (!FuncIsActiveTask(Task_WeatherMain)) + { + u8 index = AllocSpritePalette(0x1200); + CpuCopy32(gUnknown_83C2CE0, &gPlttBufferUnfaded[0x100 + index * 16], 32); + sub_8083598(index); + BuildGammaShiftTables(); + gWeatherPtr->altGammaSpritePalIndex = index; + gWeatherPtr->weatherPicSpritePalIndex = index; + gWeatherPtr->rainSpriteCount = 0; + gWeatherPtr->curRainSpriteIndex = 0; + gWeatherPtr->cloudSpritesCreated = 0; + gWeatherPtr->snowflakeSpriteCount = 0; + gWeatherPtr->ashSpritesCreated = 0; + gWeatherPtr->fogHSpritesCreated = 0; + gWeatherPtr->fogDSpritesCreated = 0; + gWeatherPtr->sandstormSpritesCreated = 0; + gWeatherPtr->sandstormSwirlSpritesCreated = 0; + gWeatherPtr->bubblesSpritesCreated = 0; + gWeatherPtr->lightenedFogSpritePalsCount = 0; + Weather_SetBlendCoeffs(16, 0); + gWeatherPtr->currWeather = 0; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + gWeatherPtr->readyForInit = FALSE; + gWeatherPtr->weatherChangeComplete = TRUE; + gWeatherPtr->taskId = CreateTask(Task_WeatherInit, 80); + } +} + +void SetNextWeather(u8 weather) +{ + if (weather != WEATHER_RAIN && weather != WEATHER_RAIN_THUNDERSTORM && weather != WEATHER_DOWNPOUR) + { + PlayRainStoppingSoundEffect(); + } + + if (gWeatherPtr->nextWeather != weather && gWeatherPtr->currWeather == weather) + { + sWeatherFuncs[weather].initVars(); + } + + gWeatherPtr->weatherChangeComplete = FALSE; + gWeatherPtr->nextWeather = weather; + gWeatherPtr->finishStep = 0; +} + + +void SetCurrentAndNextWeather(u8 weather) +{ + PlayRainStoppingSoundEffect(); + gWeatherPtr->currWeather = weather; + gWeatherPtr->nextWeather = weather; +} + +void SetCurrentAndNextWeatherNoDelay(u8 weather) +{ + PlayRainStoppingSoundEffect(); + gWeatherPtr->currWeather = weather; + gWeatherPtr->nextWeather = weather; + // Overrides the normal delay during screen fading. + gWeatherPtr->readyForInit = TRUE; +} + +void Task_WeatherInit(u8 taskId) +{ + // Waits until it's ok to initialize weather. + // When the screen fades in, this is set to TRUE. + if (gWeatherPtr->readyForInit) + { + sWeatherFuncs[gWeatherPtr->currWeather].initAll(); + gTasks[taskId].func = Task_WeatherMain; + } +} + +void Task_WeatherMain(u8 taskId) +{ + if (gWeatherPtr->currWeather != gWeatherPtr->nextWeather) + { + if (!sWeatherFuncs[gWeatherPtr->currWeather].finish() + /*&& gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_OUT*/) + { + // Finished cleaning up previous weather. Now transition to next weather. + sWeatherFuncs[gWeatherPtr->nextWeather].initVars(); + gWeatherPtr->gammaStepFrameCounter = 0; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_CHANGING_WEATHER; + gWeatherPtr->currWeather = gWeatherPtr->nextWeather; + gWeatherPtr->weatherChangeComplete = TRUE; + } + } + else + { + sWeatherFuncs[gWeatherPtr->currWeather].main(); + } + + gWeatherPalStateFuncs[gWeatherPtr->palProcessingState](); +} + + +void None_Init(void) +{ + gWeatherPtr->gammaTargetIndex = 0; + gWeatherPtr->gammaStepDelay = 0; +} + +void None_Main(void) +{ +} + +u8 None_Finish(void) +{ + return 0; +} + +// Builds two tables that contain gamma shifts for palette colors. +// It's unclear why the two tables aren't declared as const arrays, since +// this function always builds the same two tables. +void BuildGammaShiftTables(void) +{ + u16 v0; + u8 (*gammaTable)[32]; + u16 v2; + u16 v4; + u16 v5; + u16 gammaIndex; + u16 v9; + u32 v10; + u16 v11; + s16 dunno; + + sPaletteGammaTypes = sBasePaletteGammaTypes; + for (v0 = 0; v0 <= 1; v0++) + { + if (v0 == 0) + gammaTable = gWeatherPtr->gammaShifts; + else + gammaTable = gWeatherPtr->altGammaShifts; + + for (v2 = 0; v2 < 32; v2++) + { + v4 = v2 << 8; + if (v0 == 0) + v5 = (v2 << 8) / 16; + else + v5 = 0; + for (gammaIndex = 0; gammaIndex <= 2; gammaIndex++) + { + v4 = (v4 - v5); + gammaTable[gammaIndex][v2] = v4 >> 8; + } + v9 = v4; + v10 = 0x1f00 - v4; + if ((0x1f00 - v4) < 0) + { + v10 += 0xf; + } + v11 = v10 >> 4; + if (v2 < 12) + { + for (; gammaIndex < 19; gammaIndex++) + { + v4 += v11; + dunno = v4 - v9; + if (dunno > 0) + v4 -= (dunno + ((u16)dunno >> 15)) >> 1; + gammaTable[gammaIndex][v2] = v4 >> 8; + if (gammaTable[gammaIndex][v2] > 0x1f) + gammaTable[gammaIndex][v2] = 0x1f; + } + } + else + { + for (; gammaIndex < 19; gammaIndex++) + { + v4 += v11; + gammaTable[gammaIndex][v2] = v4 >> 8; + if (gammaTable[gammaIndex][v2] > 0x1f) + gammaTable[gammaIndex][v2] = 0x1f; + } + } + } + } +} + +// When the weather is changing, it gradually updates the palettes +// towards the desired gamma shift. +void UpdateWeatherGammaShift(void) +{ + if (gWeatherPtr->gammaIndex == gWeatherPtr->gammaTargetIndex) + { + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + } + else + { + if (++gWeatherPtr->gammaStepFrameCounter >= gWeatherPtr->gammaStepDelay) + { + gWeatherPtr->gammaStepFrameCounter = 0; + if (gWeatherPtr->gammaIndex < gWeatherPtr->gammaTargetIndex) + gWeatherPtr->gammaIndex++; + else + gWeatherPtr->gammaIndex--; + + ApplyGammaShift(0, 32, gWeatherPtr->gammaIndex); + } + } +} + +void FadeInScreenWithWeather(void) +{ + if (++gWeatherPtr->unknown_6CB > 1) + gWeatherPtr->unknown_6CA = 0; + + switch (gWeatherPtr->currWeather) + { + case WEATHER_RAIN: + case WEATHER_RAIN_THUNDERSTORM: + case WEATHER_DOWNPOUR: + case WEATHER_SNOW: + case WEATHER_SHADE: + if (FadeInScreen_RainShowShade() == FALSE) + { + gWeatherPtr->gammaIndex = 3; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + } + break; + case WEATHER_DROUGHT: + if (FadeInScreen_Drought() == FALSE) + { + gWeatherPtr->gammaIndex = -6; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + } + break; + case WEATHER_FOG_HORIZONTAL: + if (FadeInScreen_FogHorizontal() == FALSE) + { + gWeatherPtr->gammaIndex = 0; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + } + break; + case WEATHER_VOLCANIC_ASH: + case WEATHER_SANDSTORM: + case WEATHER_FOG_DIAGONAL: + case WEATHER_UNDERWATER: + default: + if (!gPaletteFade.active) + { + gWeatherPtr->gammaIndex = gWeatherPtr->gammaTargetIndex; + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; + } + break; + } +} + +bool8 FadeInScreen_RainShowShade(void) +{ + if (gWeatherPtr->fadeScreenCounter == 16) + return FALSE; + + if (++gWeatherPtr->fadeScreenCounter >= 16) + { + ApplyGammaShift(0, 32, 3); + gWeatherPtr->fadeScreenCounter = 16; + return FALSE; + } + + ApplyGammaShiftWithBlend(0, 32, 3, 16 - gWeatherPtr->fadeScreenCounter, gWeatherPtr->fadeDestColor); + return TRUE; +} + +bool8 FadeInScreen_Drought(void) +{ + if (gWeatherPtr->fadeScreenCounter == 16) + return FALSE; + + if (++gWeatherPtr->fadeScreenCounter >= 16) + { + ApplyGammaShift(0, 32, -6); + gWeatherPtr->fadeScreenCounter = 16; + return FALSE; + } + + ApplyDroughtGammaShiftWithBlend(-6, 16 - gWeatherPtr->fadeScreenCounter, gWeatherPtr->fadeDestColor); + return TRUE; +} + +bool8 FadeInScreen_FogHorizontal(void) +{ + if (gWeatherPtr->fadeScreenCounter == 16) + return FALSE; + + gWeatherPtr->fadeScreenCounter++; + ApplyFogBlend(16 - gWeatherPtr->fadeScreenCounter, gWeatherPtr->fadeDestColor); + return TRUE; +} + +void DoNothing(void) +{ } + +void ApplyGammaShift(u8 startPalIndex, u8 numPalettes, s8 gammaIndex) +{ + u16 curPalIndex; + u16 palOffset; + u8 *gammaTable; + u16 i; + + if (gammaIndex > 0) + { + gammaIndex--; + palOffset = startPalIndex * 16; + numPalettes += startPalIndex; + curPalIndex = startPalIndex; + + // Loop through the speficied palette range and apply necessary gamma shifts to the colors. + while (curPalIndex < numPalettes) + { + if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE) + { + // No palette change. + CpuFastCopy(gPlttBufferUnfaded + palOffset, gPlttBufferFaded + palOffset, 16 * sizeof(u16)); + palOffset += 16; + } + else + { + u8 r, g, b; + + if (sPaletteGammaTypes[curPalIndex] == GAMMA_ALT || curPalIndex - 16 == gWeatherPtr->altGammaSpritePalIndex) + gammaTable = gWeatherPtr->altGammaShifts[gammaIndex]; + else + gammaTable = gWeatherPtr->gammaShifts[gammaIndex]; + + for (i = 0; i < 16; i++) + { + // Apply gamma shift to the original color. + struct RGBColor baseColor = *(struct RGBColor *)&gPlttBufferUnfaded[palOffset]; + r = gammaTable[baseColor.r]; + g = gammaTable[baseColor.g]; + b = gammaTable[baseColor.b]; + gPlttBufferFaded[palOffset++] = (b << 10) | (g << 5) | r; + } + } + + curPalIndex++; + } + } + else if (gammaIndex < 0) + { + // A negative gammIndex value means that the blending will come from the special Drought weather's palette tables. + // Dummied out in FRLG + + // gammaIndex = -gammaIndex - 1; + // palOffset = startPalIndex * 16; + // numPalettes += startPalIndex; + // curPalIndex = startPalIndex; + // + // CpuFastCopy(gPlttBufferUnfaded + palOffset, gPlttBufferFaded + palOffset, 16 * sizeof(u16)); + // while (curPalIndex < numPalettes) + // { + // if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE) + // { + // // No palette change. + // palOffset += 16; + // } + // else + // { + // + // for (i = 0; i < 16; i++) + // { + // gPlttBufferFaded[palOffset] = sDroughtWeatherColors[gammaIndex][DROUGHT_COLOR_INDEX(gPlttBufferUnfaded[palOffset])]; + // palOffset++; + // } + // } + // + // curPalIndex++; + // } + } + else + { + // No palette blending. + CpuFastCopy(gPlttBufferUnfaded + startPalIndex * 16, gPlttBufferFaded + startPalIndex * 16, numPalettes * 16 * sizeof(u16)); + } +} + +void ApplyGammaShiftWithBlend(u8 startPalIndex, u8 numPalettes, s8 gammaIndex, u8 blendCoeff, u16 blendColor) +{ + u16 palOffset; + u16 curPalIndex; + u16 i; + struct RGBColor color = *(struct RGBColor *)&blendColor; + u8 rBlend = color.r; + u8 gBlend = color.g; + u8 bBlend = color.b; + + palOffset = startPalIndex * 16; + numPalettes += startPalIndex; + gammaIndex--; + curPalIndex = startPalIndex; + + while (curPalIndex < numPalettes) + { + if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE) + { + // No gamma shift. Simply blend the colors. + BlendPalette(palOffset, 16, blendCoeff, blendColor); + palOffset += 16; + } + else + { + u8 *gammaTable; + + if (sPaletteGammaTypes[curPalIndex] == GAMMA_NORMAL) + gammaTable = gWeatherPtr->gammaShifts[gammaIndex]; + else + gammaTable = gWeatherPtr->altGammaShifts[gammaIndex]; + + for (i = 0; i < 16; i++) + { + struct RGBColor baseColor = *(struct RGBColor *)&gPlttBufferUnfaded[palOffset]; + u8 r = gammaTable[baseColor.r]; + u8 g = gammaTable[baseColor.g]; + u8 b = gammaTable[baseColor.b]; + + // Apply gamma shift and target blend color to the original color. + r += ((rBlend - r) * blendCoeff) >> 4; + g += ((gBlend - g) * blendCoeff) >> 4; + b += ((bBlend - b) * blendCoeff) >> 4; + gPlttBufferFaded[palOffset++] = (b << 10) | (g << 5) | r; + } + } + + curPalIndex++; + } +} + +void ApplyDroughtGammaShiftWithBlend(s8 gammaIndex, u8 blendCoeff, u16 blendColor) +{ + struct RGBColor color; + u8 rBlend; + u8 gBlend; + u8 bBlend; + u16 curPalIndex; + u16 palOffset; + u16 i; + + gammaIndex = -gammaIndex - 1; + color = *(struct RGBColor *)&blendColor; + rBlend = color.r; + gBlend = color.g; + bBlend = color.b; + palOffset = 0; + for (curPalIndex = 0; curPalIndex < 32; curPalIndex++) + { + if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE) + { + // No gamma shift. Simply blend the colors. + BlendPalette(palOffset, 16, blendCoeff, blendColor); + palOffset += 16; + } + else + { + for (i = 0; i < 16; i++) + { + u32 offset; + struct RGBColor color1; + struct RGBColor color2; + u8 r1, g1, b1; + u8 r2, g2, b2; + + color1 = *(struct RGBColor *)&gPlttBufferUnfaded[palOffset]; + r1 = color1.r; + g1 = color1.g; + b1 = color1.b; + + r1 += ((rBlend - r1) * blendCoeff) >> 4; + g1 += ((gBlend - g1) * blendCoeff) >> 4; + b1 += ((bBlend - b1) * blendCoeff) >> 4; + + gPlttBufferFaded[palOffset++] = (b1 << 10) | (g1 << 5) | r1; + } + } + } +} + +void ApplyFogBlend(u8 blendCoeff, u16 blendColor) +{ + struct RGBColor color; + u8 rBlend; + u8 gBlend; + u8 bBlend; + u16 curPalIndex; + + BlendPalette(0, 256, blendCoeff, blendColor); + color = *(struct RGBColor *)&blendColor; + rBlend = color.r; + gBlend = color.g; + bBlend = color.b; + + for (curPalIndex = 16; curPalIndex < 32; curPalIndex++) + { + if (LightenSpritePaletteInFog(curPalIndex)) + { + u16 palEnd = (curPalIndex + 1) * 16; + u16 palOffset = curPalIndex * 16; + + while (palOffset < palEnd) + { + struct RGBColor color = *(struct RGBColor *)&gPlttBufferUnfaded[palOffset]; + u8 r = color.r; + u8 g = color.g; + u8 b = color.b; + + r += ((28 - r) * 3) >> 2; + g += ((31 - g) * 3) >> 2; + b += ((28 - b) * 3) >> 2; + + r += ((rBlend - r) * blendCoeff) >> 4; + g += ((gBlend - g) * blendCoeff) >> 4; + b += ((bBlend - b) * blendCoeff) >> 4; + + gPlttBufferFaded[palOffset] = (b << 10) | (g << 5) | r; + palOffset++; + } + } + else + { + BlendPalette(curPalIndex * 16, 16, blendCoeff, blendColor); + } + } +} + +void MarkFogSpritePalToLighten(u8 paletteIndex) +{ + if (gWeatherPtr->lightenedFogSpritePalsCount < 6) + { + gWeatherPtr->lightenedFogSpritePals[gWeatherPtr->lightenedFogSpritePalsCount] = paletteIndex; + gWeatherPtr->lightenedFogSpritePalsCount++; + } +} + +bool8 LightenSpritePaletteInFog(u8 paletteIndex) +{ + u16 i; + + for (i = 0; i < gWeatherPtr->lightenedFogSpritePalsCount; i++) + { + if (gWeatherPtr->lightenedFogSpritePals[i] == paletteIndex) + return TRUE; + } + + return FALSE; +} + +void sub_807A790(s8 gammaIndex) +{ + if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE) + { + ApplyGammaShift(0, 32, gammaIndex); + gWeatherPtr->gammaIndex = gammaIndex; + } +} + +void sub_807A7C4(u8 gammaIndex, u8 gammaTargetIndex, u8 gammaStepDelay) +{ + if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE) + { + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_CHANGING_WEATHER; + gWeatherPtr->gammaIndex = gammaIndex; + gWeatherPtr->gammaTargetIndex = gammaTargetIndex; + gWeatherPtr->gammaStepFrameCounter = 0; + gWeatherPtr->gammaStepDelay = gammaStepDelay; + sub_807A790(gammaIndex); + } +} + +void FadeScreen(u8 mode, s8 delay) +{ + u32 fadeColor; + bool8 fadeOut; + bool8 useWeatherPal; + + switch (mode) + { + case FADE_FROM_BLACK: + fadeColor = RGB_BLACK; + fadeOut = FALSE; + break; + case FADE_FROM_WHITE: + fadeColor = RGB_WHITEALPHA; + fadeOut = FALSE; + break; + case FADE_TO_BLACK: + fadeColor = RGB_BLACK; + fadeOut = TRUE; + break; + case FADE_TO_WHITE: + fadeColor = RGB_WHITEALPHA; + fadeOut = TRUE; + break; + default: + return; + } + + switch (gWeatherPtr->currWeather) + { + case WEATHER_RAIN: + case WEATHER_RAIN_THUNDERSTORM: + case WEATHER_DOWNPOUR: + case WEATHER_SNOW: + case WEATHER_FOG_HORIZONTAL: + case WEATHER_SHADE: + case WEATHER_DROUGHT: + useWeatherPal = TRUE; + break; + default: + useWeatherPal = FALSE; + break; + } + + if (fadeOut) + { + if (useWeatherPal) + CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400); + + BeginNormalPaletteFade(0xFFFFFFFF, delay, 0, 16, fadeColor); + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT; + } + else + { + gWeatherPtr->fadeDestColor = fadeColor; + if (useWeatherPal) + gWeatherPtr->fadeScreenCounter = 0; + else + BeginNormalPaletteFade(0xFFFFFFFF, delay, 16, 0, fadeColor); + + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_IN; + gWeatherPtr->unknown_6CA = 1; + gWeatherPtr->unknown_6CB = 0; + Weather_SetBlendCoeffs(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB); + gWeatherPtr->readyForInit = TRUE; + } +} + +void FadeSelectedPals(u8 mode, s8 delay, u32 selectedPalettes) +{ + u32 fadeColor; + bool8 fadeOut; + bool8 useWeatherPal; + + switch (mode) + { + case FADE_FROM_BLACK: + fadeColor = RGB_BLACK; + fadeOut = FALSE; + break; + case FADE_FROM_WHITE: + fadeColor = RGB_WHITEALPHA; + fadeOut = FALSE; + break; + case FADE_TO_BLACK: + fadeColor = RGB_BLACK; + fadeOut = TRUE; + break; + case FADE_TO_WHITE: + fadeColor = RGB_WHITEALPHA; + fadeOut = TRUE; + break; + default: + return; + } + + switch (gWeatherPtr->currWeather) + { + case WEATHER_RAIN: + case WEATHER_RAIN_THUNDERSTORM: + case WEATHER_DOWNPOUR: + case WEATHER_SNOW: + case WEATHER_FOG_HORIZONTAL: + case WEATHER_SHADE: + case WEATHER_DROUGHT: + useWeatherPal = TRUE; + break; + default: + useWeatherPal = FALSE; + break; + } + + if (fadeOut) + { + if (useWeatherPal) + CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400); + + BeginNormalPaletteFade(selectedPalettes, delay, 0, 16, fadeColor); + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT; + } + else + { + gWeatherPtr->fadeDestColor = fadeColor; + if (useWeatherPal) + gWeatherPtr->fadeScreenCounter = 0; + else + BeginNormalPaletteFade(selectedPalettes, delay, 16, 0, fadeColor); + + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_IN; + gWeatherPtr->unknown_6CA = 1; + gWeatherPtr->unknown_6CB = 0; + Weather_SetBlendCoeffs(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB); + gWeatherPtr->readyForInit = TRUE; + } +} + + +bool8 IsWeatherNotFadingIn(void) +{ + return (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_IN); +} + +void UpdateSpritePaletteWithWeather(u8 spritePaletteIndex) +{ + u16 paletteIndex = 16 + spritePaletteIndex; + u16 i; + + switch (gWeatherPtr->palProcessingState) + { + case WEATHER_PAL_STATE_SCREEN_FADING_IN: + if (gWeatherPtr->unknown_6CA != 0) + { + if (gWeatherPtr->currWeather == WEATHER_FOG_HORIZONTAL) + MarkFogSpritePalToLighten(paletteIndex); + paletteIndex *= 16; + for (i = 0; i < 16; i++) + gPlttBufferFaded[paletteIndex + i] = gWeatherPtr->fadeDestColor; + } + break; + case WEATHER_PAL_STATE_SCREEN_FADING_OUT: + paletteIndex *= 16; + CpuFastCopy(gPlttBufferFaded + paletteIndex, gPlttBufferUnfaded + paletteIndex, 32); + BlendPalette(paletteIndex, 16, gPaletteFade.y, gPaletteFade.blendColor); + break; + // WEATHER_PAL_STATE_CHANGING_WEATHER + // WEATHER_PAL_STATE_CHANGING_IDLE + default: + if (gWeatherPtr->currWeather != WEATHER_FOG_HORIZONTAL) + { + ApplyGammaShift(paletteIndex, 1, gWeatherPtr->gammaIndex); + } + else + { + paletteIndex *= 16; + BlendPalette(paletteIndex, 16, 12, RGB(28, 31, 28)); + } + break; + } +} + +void ApplyWeatherGammaShiftToPal(u8 paletteIndex) +{ + ApplyGammaShift(paletteIndex, 1, gWeatherPtr->gammaIndex); +} + +u8 sub_80ABF20(void) +{ + if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_SCREEN_FADING_IN) + return gWeatherPtr->unknown_6CA; + else + return 0; +} + +void LoadCustomWeatherSpritePalette(const u16 *palette) +{ + LoadPalette(palette, 0x100 + gWeatherPtr->weatherPicSpritePalIndex * 16, 32); + UpdateSpritePaletteWithWeather(gWeatherPtr->weatherPicSpritePalIndex); +} + +static void LoadDroughtWeatherPalette(u8 *gammaIndexPtr, u8 *a1) +{ + // Dummied out in FRLG + // *gammaIndexPtr = 0x20; + // *a1 = 0x20; +} + +void ResetDroughtWeatherPaletteLoading(void) +{ + gWeatherPtr->loadDroughtPalsIndex = 1; + gWeatherPtr->loadDroughtPalsOffset = 1; +} + +bool8 LoadDroughtWeatherPalettes(void) +{ + if (gWeatherPtr->loadDroughtPalsIndex < 32) + { + LoadDroughtWeatherPalette(&gWeatherPtr->loadDroughtPalsIndex, &gWeatherPtr->loadDroughtPalsOffset); + if (gWeatherPtr->loadDroughtPalsIndex < 32) + return TRUE; + } + return FALSE; +} + +void sub_807AC50(s8 gammaIndex) +{ + sub_807A790(-gammaIndex - 1); +} + +void sub_807AC60(void) +{ + gWeatherPtr->unknown_73C = 0; + gWeatherPtr->unknown_740 = 0; + gWeatherPtr->unknown_742 = 0; + gWeatherPtr->unknown_73E = 0; + gUnknown_20386A8 = 5; +} + +void sub_807AC98(void) +{ + switch (gWeatherPtr->unknown_742) + { + case 0: + if (++gWeatherPtr->unknown_740 > gUnknown_20386A8) + { + gWeatherPtr->unknown_740 = 0; + sub_807AC50(gWeatherPtr->unknown_73C++); + if (gWeatherPtr->unknown_73C > 5) + { + gWeatherPtr->unknown_73E = gWeatherPtr->unknown_73C; + gWeatherPtr->unknown_742 = 1; + gWeatherPtr->unknown_740 = 0x3C; + } + } + break; + case 1: + gWeatherPtr->unknown_740 = (gWeatherPtr->unknown_740 + 3) & 0x7F; + gWeatherPtr->unknown_73C = ((gSineTable[gWeatherPtr->unknown_740] - 1) >> 6) + 2; + if (gWeatherPtr->unknown_73C != gWeatherPtr->unknown_73E) + sub_807AC50(gWeatherPtr->unknown_73C); + gWeatherPtr->unknown_73E = gWeatherPtr->unknown_73C; + break; + case 2: + if (++gWeatherPtr->unknown_740 > gUnknown_20386A8) + { + gWeatherPtr->unknown_740 = 0; + sub_807AC50(--gWeatherPtr->unknown_73C); + if (gWeatherPtr->unknown_73C == 3) + gWeatherPtr->unknown_742 = 0; + } + break; + } +} + +void Weather_SetBlendCoeffs(u8 eva, u8 evb) +{ + gWeatherPtr->currBlendEVA = eva; + gWeatherPtr->currBlendEVB = evb; + gWeatherPtr->targetBlendEVA = eva; + gWeatherPtr->targetBlendEVB = evb; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(eva, evb)); +} + +void Weather_SetTargetBlendCoeffs(u8 eva, u8 evb, int delay) +{ + gWeatherPtr->targetBlendEVA = eva; + gWeatherPtr->targetBlendEVB = evb; + gWeatherPtr->blendDelay = delay; + gWeatherPtr->blendFrameCounter = 0; + gWeatherPtr->blendUpdateCounter = 0; +} + +bool8 Weather_UpdateBlend(void) +{ + if (gWeatherPtr->currBlendEVA == gWeatherPtr->targetBlendEVA + && gWeatherPtr->currBlendEVB == gWeatherPtr->targetBlendEVB) + return TRUE; + + if (++gWeatherPtr->blendFrameCounter > gWeatherPtr->blendDelay) + { + gWeatherPtr->blendFrameCounter = 0; + gWeatherPtr->blendUpdateCounter++; + + // Update currBlendEVA and currBlendEVB on alternate frames + if (gWeatherPtr->blendUpdateCounter & 1) + { + if (gWeatherPtr->currBlendEVA < gWeatherPtr->targetBlendEVA) + gWeatherPtr->currBlendEVA++; + else if (gWeatherPtr->currBlendEVA > gWeatherPtr->targetBlendEVA) + gWeatherPtr->currBlendEVA--; + } + else + { + if (gWeatherPtr->currBlendEVB < gWeatherPtr->targetBlendEVB) + gWeatherPtr->currBlendEVB++; + else if (gWeatherPtr->currBlendEVB > gWeatherPtr->targetBlendEVB) + gWeatherPtr->currBlendEVB--; + } + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB)); + + if (gWeatherPtr->currBlendEVA == gWeatherPtr->targetBlendEVA + && gWeatherPtr->currBlendEVB == gWeatherPtr->targetBlendEVB) + return TRUE; + + return FALSE; +} + +void sub_807AF00(u8 a) +{ + switch (a) + { + case 1: + SetWeather(WEATHER_SUNNY_CLOUDS); + break; + case 2: + SetWeather(WEATHER_SUNNY); + break; + case 3: + SetWeather(WEATHER_RAIN); + break; + case 4: + SetWeather(WEATHER_SNOW); + break; + case 5: + SetWeather(WEATHER_RAIN_THUNDERSTORM); + break; + case 6: + SetWeather(WEATHER_FOG_HORIZONTAL); + break; + case 7: + SetWeather(WEATHER_FOG_DIAGONAL); + break; + case 8: + SetWeather(WEATHER_VOLCANIC_ASH); + break; + case 9: + SetWeather(WEATHER_SANDSTORM); + break; + case 10: + SetWeather(WEATHER_SHADE); + break; + } +} + +u8 GetCurrentWeather(void) +{ + return gWeatherPtr->currWeather; +} + +void SetRainStrengthFromSoundEffect(u16 soundEffect) +{ + if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_OUT) + { + switch (soundEffect) + { + case SE_T_KOAME: + gWeatherPtr->rainStrength = 0; + break; + case SE_T_OOAME: + gWeatherPtr->rainStrength = 1; + break; + case SE_T_AME: + gWeatherPtr->rainStrength = 2; + break; + default: + return; + } + + PlaySE(soundEffect); + } +} + +void PlayRainStoppingSoundEffect(void) +{ + if (IsSpecialSEPlaying()) + { + switch (gWeatherPtr->rainStrength) + { + case 0: + PlaySE(SE_T_KOAME_E); + break; + case 1: + PlaySE(SE_T_OOAME_E); + break; + case 2: + default: + PlaySE(SE_T_AME_E); + break; + } + } +} + +u8 IsWeatherChangeComplete(void) +{ + return gWeatherPtr->weatherChangeComplete; +} + +void SetWeatherScreenFadeOut(void) +{ + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT; +} + +void sub_807B070(void) +{ + gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE; +} + +void PreservePaletteInWeather(u8 preservedPalIndex) +{ + CpuCopy16(sBasePaletteGammaTypes, sFieldEffectPaletteGammaTypes, 32); + sFieldEffectPaletteGammaTypes[preservedPalIndex] = GAMMA_NONE; + sPaletteGammaTypes = sFieldEffectPaletteGammaTypes; +} + +void ResetPreservedPalettesInWeather(void) +{ + sPaletteGammaTypes = sBasePaletteGammaTypes; +} diff --git a/src/field_weather_util.c b/src/field_weather_util.c new file mode 100644 index 000000000..ed1ce5236 --- /dev/null +++ b/src/field_weather_util.c @@ -0,0 +1,12 @@ +#include "global.h" + +const u16 gUnknown_83C2D00[] = INCBIN_U16("graphics/field_effects/unk_83C2D00.gbapal"); +const u16 gUnknown_83C2D20[] = INCBIN_U16("graphics/field_effects/unk_83C2D20.gbapal"); +const u16 gUnknown_83C2D40[] = INCBIN_U16("graphics/field_effects/unk_83C2D40.4bpp"); +const u16 gWeatherFog1Tiles[] = INCBIN_U16("graphics/field_effects/unk_83C3540.4bpp"); +const u16 gUnknown_83C3D40[] = INCBIN_U16("graphics/field_effects/unk_83C3D40.4bpp"); +const u16 gUnknown_83C4540[] = INCBIN_U16("graphics/field_effects/unk_83C4540.4bpp"); +const u16 gUnknown_83C4580[] = INCBIN_U16("graphics/field_effects/unk_83C4580.4bpp"); +const u16 gUnknown_83C45C0[] = INCBIN_U16("graphics/field_effects/unk_83C45C0.4bpp"); +const u16 gUnknown_83C55C0[] = INCBIN_U16("graphics/field_effects/unk_83C55C0.4bpp"); +const u16 gUnknown_83C5BC0[] = INCBIN_U16("graphics/field_effects/unk_83C5BC0.4bpp"); |