summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcus Huderle <huderlem@gmail.com>2018-12-09 07:56:53 -0600
committerGitHub <noreply@github.com>2018-12-09 07:56:53 -0600
commit5e09850c17bd1d09ab77e4f09a6b1682c210f0ad (patch)
treed5c1023549cb38f6a039bcdc29fbf90b01160935 /src
parent0b91d2948a431a5d44166544897a550061c01a31 (diff)
parentc46499b05c81f1d1a872a33ce5b2fd9a20964dc7 (diff)
Merge pull request #435 from DizzyEggg/weather
Decompile fieldmap
Diffstat (limited to 'src')
-rw-r--r--src/battle_transition.c4
-rw-r--r--src/battle_util.c18
-rw-r--r--src/clock.c2
-rw-r--r--src/decoration.c2
-rw-r--r--src/egg_hatch.c6
-rw-r--r--src/field_control_avatar.c3
-rw-r--r--src/field_effect.c26
-rw-r--r--src/field_screen.c15
-rw-r--r--src/field_screen_effect.c1261
-rw-r--r--src/field_specials.c2
-rw-r--r--src/field_weather.c1095
-rw-r--r--src/field_weather_effect.c2471
-rw-r--r--src/fldeff_flash.c4
-rw-r--r--src/fldeff_sweetscent.c5
-rwxr-xr-xsrc/item_use.c2
-rw-r--r--src/learn_move.c34
-rw-r--r--src/overworld.c17
-rw-r--r--src/player_pc.c3
-rw-r--r--src/pokemon_storage_system.c2
-rw-r--r--src/record_mixing.c2
-rw-r--r--src/rom_8011DC0.c2
-rw-r--r--src/scrcmd.c1
-rw-r--r--src/secret_base.c4
-rwxr-xr-xsrc/shop.c2
-rw-r--r--src/start_menu.c18
25 files changed, 4904 insertions, 97 deletions
diff --git a/src/battle_transition.c b/src/battle_transition.c
index f74102467..37a8cd63f 100644
--- a/src/battle_transition.c
+++ b/src/battle_transition.c
@@ -59,7 +59,7 @@ typedef bool8 (*TransitionSpriteCallback)(struct Sprite *sprite);
extern const struct OamData gEventObjectBaseOam_32x32;
-extern void sub_80AC3D0(void);
+extern void SetWeatherScreenFadeOut(void);
// this file's functions
static void LaunchBattleTransitionTask(u8 transitionId);
@@ -981,7 +981,7 @@ static void Task_BattleTransitionMain(u8 taskId)
static bool8 Transition_Phase1(struct Task *task)
{
- sub_80AC3D0();
+ SetWeatherScreenFadeOut();
CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
if (sPhase1_Tasks[task->tTransitionId] != NULL)
{
diff --git a/src/battle_util.c b/src/battle_util.c
index 4c9ef75d9..2ddd4f550 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -17,13 +17,13 @@
#include "string_util.h"
#include "battle_message.h"
#include "constants/battle_string_ids.h"
+#include "constants/weather.h"
#include "battle_ai_script_commands.h"
#include "battle_controllers.h"
#include "event_data.h"
#include "link.h"
#include "berry.h"
-
-extern u8 weather_get_current(void);
+#include "field_weather.h"
// rom const data
static const u16 sSoundMovesTable[] =
@@ -1827,11 +1827,11 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
case ABILITYEFFECT_SWITCH_IN_WEATHER:
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
{
- switch (weather_get_current())
+ switch (GetCurrentWeather())
{
- case 3:
- case 5:
- case 13:
+ case WEATHER_RAIN_LIGHT:
+ case WEATHER_RAIN_MED:
+ case WEATHER_RAIN_HEAVY:
if (!(gBattleWeather & WEATHER_RAIN_ANY))
{
gBattleWeather = (WEATHER_RAIN_TEMPORARY | WEATHER_RAIN_PERMANENT);
@@ -1840,7 +1840,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
effect++;
}
break;
- case 8:
+ case WEATHER_SANDSTORM:
if (!(gBattleWeather & WEATHER_SANDSTORM_ANY))
{
gBattleWeather = (WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY);
@@ -1849,7 +1849,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
effect++;
}
break;
- case 12:
+ case WEATHER_DROUGHT:
if (!(gBattleWeather & WEATHER_SUN_ANY))
{
gBattleWeather = (WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY);
@@ -1862,7 +1862,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
}
if (effect)
{
- gBattleCommunication[MULTISTRING_CHOOSER] = weather_get_current();
+ gBattleCommunication[MULTISTRING_CHOOSER] = GetCurrentWeather();
BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts);
}
break;
diff --git a/src/clock.c b/src/clock.c
index 91eb5f16d..aea6c2088 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -5,7 +5,7 @@
#include "lottery_corner.h"
#include "dewford_trend.h"
#include "tv.h"
-#include "field_screen.h"
+#include "field_weather.h"
#include "berry.h"
#include "main.h"
#include "overworld.h"
diff --git a/src/decoration.c b/src/decoration.c
index b45dec334..dd691721a 100644
--- a/src/decoration.c
+++ b/src/decoration.c
@@ -16,7 +16,7 @@
#include "field_weather.h"
#include "field_player_avatar.h"
#include "field_camera.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "event_object_movement.h"
#include "list_menu.h"
#include "menu_helpers.h"
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
index 77296c707..ed25a2c68 100644
--- a/src/egg_hatch.c
+++ b/src/egg_hatch.c
@@ -30,7 +30,7 @@
#include "field_weather.h"
#include "international_string_util.h"
#include "naming_screen.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "battle.h" // to get rid of later
struct EggHatchData
@@ -60,7 +60,7 @@ extern const u32 gUnknown_08331F60[]; // tilemap gameboy circle
extern const u8 gText_HatchedFromEgg[];
extern const u8 gText_NickHatchPrompt[];
-extern void play_some_sound(void);
+extern void PlayRainSoundEffect(void);
extern u16 sub_80D22D0(void);
extern u8 CountPartyAliveNonEggMonsExcept(u8);
@@ -581,7 +581,7 @@ static void Task_EggHatchPlayBGM(u8 taskID)
if (gTasks[taskID].data[0] == 0)
{
StopMapMusic();
- play_some_sound();
+ PlayRainSoundEffect();
}
if (gTasks[taskID].data[0] == 1)
PlayBGM(MUS_ME_SHINKA);
diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c
index c52f5190f..829d72c34 100644
--- a/src/field_control_avatar.c
+++ b/src/field_control_avatar.c
@@ -8,10 +8,9 @@
#include "event_scripts.h"
#include "fieldmap.h"
#include "field_control_avatar.h"
-#include "field_fadetransition.h"
#include "field_player_avatar.h"
#include "field_poison.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_specials.h"
#include "fldeff_80F9BCC.h"
#include "item_menu.h"
diff --git a/src/field_effect.c b/src/field_effect.c
index 40e15c733..1442c611a 100644
--- a/src/field_effect.c
+++ b/src/field_effect.c
@@ -6,7 +6,7 @@
#include "field_effect.h"
#include "field_effect_helpers.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "fieldmap.h"
#include "fldeff_groundshake.h"
@@ -244,7 +244,7 @@ extern void pal_fill_for_maplights(void);
extern void sub_80E1558(u8);
extern void sub_80E1570(void);
extern bool8 sub_80E1584(void);
-extern void sub_80AF0B4(void);
+extern void WarpFadeScreen(void);
// .rodata
const u32 gNewGameBirchPic[] = INCBIN_U32("graphics/birch_speech/birch.4bpp");
@@ -1593,8 +1593,8 @@ static void sub_80B7004(struct Task *task)
static void sub_80B7050(void)
{
- music_something();
- sub_80AF0B4();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
}
static void sub_80B7060(void)
@@ -1943,8 +1943,8 @@ static bool8 sub_80B7704(struct Task *task, struct EventObject *eventObject, str
static bool8 sub_80B77F8(struct Task *task, struct EventObject *eventObject, struct Sprite *sprite)
{
- music_something();
- sub_80AF0B4();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
task->data[0]++;
return FALSE;
}
@@ -2099,8 +2099,8 @@ static bool8 sub_80B7BCC(struct Task *task, struct EventObject *eventObject, str
{
if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH))
{
- music_something();
- sub_80AF0B4();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
task->data[0]++;
}
return FALSE;
@@ -2161,8 +2161,8 @@ static void EscapeRopeFieldEffect_Step1(struct Task *task)
u8 spinDirections[5] = {DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH};
if (task->data[14] != 0 && (--task->data[14]) == 0)
{
- music_something();
- sub_80AF0B4();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
}
eventObject = &gEventObjects[gPlayerAvatar.eventObjectId];
if (!EventObjectIsMovementOverridden(eventObject) || EventObjectClearHeldMovementIfFinished(eventObject))
@@ -2314,8 +2314,8 @@ static void TeleportFieldEffectTask3(struct Task *task)
if (task->data[4] >= 0xa8)
{
task->data[0]++;
- music_something();
- sub_80AF0B4();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
}
}
@@ -3123,7 +3123,7 @@ static void sub_80B9474(struct Task *task)
{
if (sub_80B9508(task->data[1]))
{
- sub_80AF0B4();
+ WarpFadeScreen();
task->data[0]++;
}
}
diff --git a/src/field_screen.c b/src/field_screen.c
deleted file mode 100644
index 2d33d237f..000000000
--- a/src/field_screen.c
+++ /dev/null
@@ -1,15 +0,0 @@
-
-// Includes
-#include "global.h"
-
-// Static type declarations
-
-// Static RAM declarations
-IWRAM_DATA u8 *gUnknown_03000F50;
-IWRAM_DATA u32 filler_03000f54;
-
-// Static ROM declarations
-
-// .rodata
-
-// .text
diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c
new file mode 100644
index 000000000..b0572b393
--- /dev/null
+++ b/src/field_screen_effect.c
@@ -0,0 +1,1261 @@
+#include "global.h"
+#include "cable_club.h"
+#include "event_data.h"
+#include "fieldmap.h"
+#include "field_camera.h"
+#include "field_door.h"
+#include "field_effect.h"
+#include "event_object_movement.h"
+#include "field_player_avatar.h"
+#include "field_screen_effect.h"
+#include "field_special_scene.h"
+#include "field_weather.h"
+// #include "fldeff_flash.h"
+#include "gpu_regs.h"
+#include "link.h"
+#include "link_rfu.h"
+#include "load_save.h"
+#include "main.h"
+#include "menu.h"
+#include "event_obj_lock.h"
+#include "metatile_behavior.h"
+#include "palette.h"
+#include "overworld.h"
+#include "scanline_effect.h"
+#include "script.h"
+#include "sound.h"
+#include "start_menu.h"
+#include "task.h"
+#include "text.h"
+#include "constants/event_object_movement_constants.h"
+#include "constants/songs.h"
+#include "constants/rgb.h"
+
+extern bool32 sub_81D6534(void);
+extern bool8 walkrun_is_standing_still(void);
+extern void ScriptUnfreezeEventObjects(void);
+extern void sub_81BE72C(void);
+extern void sub_80FB768(void);
+extern void sub_808D194(void);
+extern void sub_808D1C8(void);
+extern bool32 sub_808D1B4(void);
+extern bool32 sub_808D1E8(void);
+extern void sub_80B6B68(void);
+extern void sub_80B6E4C(u8, u8);
+extern void sub_80B75D8(u8);
+extern void sub_80B7A74(u8);
+extern void sub_808C0A8(u8);
+extern u8 GetMapPairFadeToType(u8, u8);
+extern u8 GetMapPairFadeFromType(u8, u8);
+
+extern const u16 gUnknown_82EC7CC[];
+
+// This file's functions.
+static void sub_8080B9C(u8);
+static void task_map_chg_seq_0807E20C(u8);
+static void task_map_chg_seq_0807E2CC(u8);
+static void task0A_fade_n_map_maybe(u8);
+static void sub_808115C(u8);
+static void palette_bg_faded_fill_white(void);
+static void sub_80AF438(u8);
+static bool32 sub_80AF71C(void);
+static void task0A_mpl_807E31C(u8 taskId);
+static void sub_80AFA0C(u8 taskId);
+static void sub_80AFA88(u8 taskId);
+static void task50_0807F0C8(u8);
+
+// const
+const u16 sFlashLevelPixelRadii[] = { 200, 72, 64, 56, 48, 40, 32, 24, 0 };
+const s32 gMaxFlashLevel = 8;
+
+const struct ScanlineEffectParams sFlashEffectParams =
+{
+ (void *)REG_ADDR_WIN0H,
+ ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1,
+ 1
+};
+
+// code
+static void palette_bg_faded_fill_white(void)
+{
+ CpuFastFill16(RGB_WHITE, gPlttBufferFaded, PLTT_SIZE);
+}
+
+static void palette_bg_faded_fill_black(void)
+{
+ CpuFastFill16(RGB_BLACK, gPlttBufferFaded, PLTT_SIZE);
+}
+
+void pal_fill_for_maplights(void)
+{
+ u8 previousMapType = GetLastUsedWarpMapType();
+ switch (GetMapPairFadeFromType(previousMapType, Overworld_GetMapTypeOfSaveblockLocation()))
+ {
+ case 0:
+ palette_bg_faded_fill_black();
+ FadeScreen(FADE_FROM_BLACK, 0);
+ break;
+ case 1:
+ palette_bg_faded_fill_white();
+ FadeScreen(FADE_FROM_WHITE, 0);
+ }
+}
+
+static void sub_80AF08C(void)
+{
+ palette_bg_faded_fill_white();
+ FadeScreen(FADE_FROM_WHITE, 8);
+}
+
+void pal_fill_black(void)
+{
+ palette_bg_faded_fill_black();
+ FadeScreen(FADE_FROM_BLACK, 0);
+}
+
+void WarpFadeScreen(void)
+{
+ u8 currentMapType = Overworld_GetMapTypeOfSaveblockLocation();
+ switch (GetMapPairFadeToType(currentMapType, GetDestinationWarpMapHeader()->mapType))
+ {
+ case 0:
+ FadeScreen(FADE_TO_BLACK, 0);
+ break;
+ case 1:
+ FadeScreen(FADE_TO_WHITE, 0);
+ }
+}
+
+static void sub_80AF0F4(u8 arg)
+{
+ sub_808C0A8(!arg);
+}
+
+static void task0A_nop_for_a_while(u8 taskId)
+{
+ if (sub_80AF71C() == TRUE)
+ DestroyTask(taskId);
+}
+
+void sub_80AF128(void)
+{
+ ScriptContext2_Enable();
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_black();
+ CreateTask(task0A_nop_for_a_while, 10);
+}
+
+static void task0A_asap_script_env_2_enable_and_set_ctx_running(u8 taskID)
+{
+ if (sub_80AF71C() == TRUE)
+ {
+ DestroyTask(taskID);
+ EnableBothScriptContexts();
+ }
+}
+
+void sub_80AF168(void)
+{
+ ScriptContext2_Enable();
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_black();
+ CreateTask(task0A_asap_script_env_2_enable_and_set_ctx_running, 10);
+}
+
+void sub_80AF188(void)
+{
+ ScriptContext2_Enable();
+ pal_fill_black();
+ CreateTask(task0A_asap_script_env_2_enable_and_set_ctx_running, 10);
+}
+
+static void task_mpl_807DD60(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ task->data[1] = sub_80B3050();
+ task->data[0]++;
+ break;
+ case 1:
+ if (gTasks[task->data[1]].isActive != TRUE)
+ {
+ pal_fill_for_maplights();
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ if (sub_80AF71C() == TRUE)
+ {
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_80AF214(void)
+{
+ ScriptContext2_Enable();
+ Overworld_PlaySpecialMapMusic();
+ palette_bg_faded_fill_black();
+ CreateTask(task_mpl_807DD60, 10);
+}
+
+static void sub_80AF234(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ sub_800ADF8();
+ task->data[0]++;
+ break;
+ case 1:
+ if (!sub_800A520())
+ {
+ if (++task->data[1] > 1800)
+ sub_8011170(0x6000);
+ }
+ else
+ {
+ pal_fill_for_maplights();
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ if (sub_80AF71C() == TRUE)
+ {
+ sub_8009F18();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_80AF2B4(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ sub_800ADF8();
+ task->data[0]++;
+ break;
+ case 1:
+ if (sub_800A520())
+ {
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ sub_8009F18();
+ sub_8086C2C();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80AF314(void)
+{
+ ScriptContext2_Enable();
+ Overworld_PlaySpecialMapMusic();
+ palette_bg_faded_fill_black();
+ CreateTask(sub_80AF234, 10);
+}
+
+static void sub_80AF334(void)
+{
+ s16 x, y;
+ u8 behavior;
+ TaskFunc func;
+
+ PlayerGetDestCoords(&x, &y);
+ behavior = MapGridGetMetatileBehaviorAt(x, y);
+ if (MetatileBehavior_IsDoor(behavior) == TRUE)
+ func = sub_80AF438;
+ else if (MetatileBehavior_IsNonAnimDoor(behavior) == TRUE)
+ func = task_map_chg_seq_0807E20C;
+ else
+ func = task_map_chg_seq_0807E2CC;
+ CreateTask(func, 10);
+}
+
+void mapldr_default(void)
+{
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_for_maplights();
+ sub_80AF334();
+ ScriptContext2_Enable();
+}
+
+void sub_80AF3B0(void)
+{
+ Overworld_PlaySpecialMapMusic();
+ sub_80AF08C();
+ sub_80AF334();
+ ScriptContext2_Enable();
+}
+
+void sub_80AF3C8(void)
+{
+ if (!sub_81D6534())
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_black();
+ sub_80AF334();
+ ScriptContext2_Enable();
+}
+
+void sub_80AF3E8(void)
+{
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_for_maplights();
+ PlaySE(SE_TK_WARPOUT);
+ CreateTask(task0A_mpl_807E31C, 10);
+ ScriptContext2_Enable();
+}
+
+void sub_80AF40C(void)
+{
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_for_maplights();
+ PlaySE(SE_TK_WARPOUT);
+ CreateTask(task_map_chg_seq_0807E2CC, 10);
+ ScriptContext2_Enable();
+ sub_8085540(0xE);
+}
+
+static void sub_80AF438(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ s16 *x = &task->data[2];
+ s16 *y = &task->data[3];
+
+ switch (task->data[0])
+ {
+ case 0:
+ sub_80AF0F4(0);
+ FreezeEventObjects();
+ PlayerGetDestCoords(x, y);
+ FieldSetDoorOpened(*x, *y);
+ task->data[0] = 1;
+ break;
+ case 1:
+ if (sub_80AF71C())
+ {
+ u8 eventObjId;
+ sub_80AF0F4(1);
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectSetHeldMovement(&gEventObjects[eventObjId], MOVEMENT_ACTION_WALK_NORMAL_DOWN);
+ task->data[0] = 2;
+ }
+ break;
+ case 2:
+ if (walkrun_is_standing_still())
+ {
+ u8 eventObjId;
+ task->data[1] = FieldAnimateDoorClose(*x, *y);
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectClearHeldMovementIfFinished(&gEventObjects[eventObjId]);
+ task->data[0] = 3;
+ }
+ break;
+ case 3:
+ if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE)
+ {
+ UnfreezeEventObjects();
+ task->data[0] = 4;
+ }
+ break;
+ case 4:
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void task_map_chg_seq_0807E20C(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ s16 *x = &task->data[2];
+ s16 *y = &task->data[3];
+
+ switch (task->data[0])
+ {
+ case 0:
+ sub_80AF0F4(0);
+ FreezeEventObjects();
+ PlayerGetDestCoords(x, y);
+ task->data[0] = 1;
+ break;
+ case 1:
+ if (sub_80AF71C())
+ {
+ u8 eventObjId;
+ sub_80AF0F4(1);
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectSetHeldMovement(&gEventObjects[eventObjId], GetWalkNormalMovementAction(GetPlayerFacingDirection()));
+ task->data[0] = 2;
+ }
+ break;
+ case 2:
+ if (walkrun_is_standing_still())
+ {
+ UnfreezeEventObjects();
+ task->data[0] = 3;
+ }
+ break;
+ case 3:
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void task_map_chg_seq_0807E2CC(u8 taskId)
+{
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ ScriptContext2_Enable();
+ gTasks[taskId].data[0]++;
+ break;
+ case 1:
+ if (sub_80AF71C())
+ {
+ UnfreezeEventObjects();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void sub_80AF660(u8 taskId)
+{
+ if (sub_80AF71C() == TRUE)
+ {
+ DestroyTask(taskId);
+ CreateTask(sub_809FA34, 80);
+ }
+}
+
+void sub_80AF688(void)
+{
+ pal_fill_black();
+ CreateTask(sub_80AF660, 0x50);
+ ScriptContext2_Enable();
+}
+
+bool8 sub_80AF6A4(void)
+{
+ sub_809FA18();
+ return FALSE;
+}
+
+static void task_mpl_807E3C8(u8 taskId)
+{
+ if (sub_80AF71C() == 1)
+ {
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ ScriptUnfreezeEventObjects();
+ }
+}
+
+void sub_80AF6D4(void)
+{
+ ScriptContext2_Enable();
+ pal_fill_black();
+ CreateTask(task_mpl_807E3C8, 10);
+}
+
+void sub_80AF6F0(void)
+{
+ ScriptContext2_Enable();
+ Overworld_PlaySpecialMapMusic();
+ pal_fill_black();
+ CreateTask(task_mpl_807E3C8, 10);
+}
+
+static bool32 PaletteFadeActive(void)
+{
+ return gPaletteFade.active;
+}
+
+static bool32 sub_80AF71C(void)
+{
+ if (IsWeatherNotFadingIn() == TRUE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void sub_80AF734(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlayRainSoundEffect();
+ PlaySE(SE_KAIDAN);
+ gFieldCallback = mapldr_default;
+ CreateTask(sub_80AFA0C, 10);
+}
+
+void sp13E_warp_to_last_warp(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlayRainSoundEffect();
+ gFieldCallback = mapldr_default;
+ CreateTask(sub_80AFA0C, 10);
+}
+
+void sub_80AF79C(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ FadeScreen(FADE_TO_WHITE, 8);
+ PlayRainSoundEffect();
+ gFieldCallback = sub_80AF3B0;
+ CreateTask(sub_80AFA0C, 10);
+}
+
+void sub_80AF7D0(void)
+{
+ ScriptContext2_Enable();
+ gFieldCallback = mapldr_default;
+ CreateTask(sub_80AFA88, 10);
+}
+
+void sp13F_fall_to_last_warp(void)
+{
+ sp13E_warp_to_last_warp();
+ gFieldCallback = sub_80B6B68;
+}
+
+void sub_80AF80C(u8 metatileBehavior)
+{
+ ScriptContext2_Enable();
+ sub_80B6E4C(metatileBehavior, 10);
+}
+
+void sub_80AF828(void)
+{
+ ScriptContext2_Enable();
+ sub_80B75D8(10);
+}
+
+void sub_80AF838(void)
+{
+ ScriptContext2_Enable();
+ sub_80B7A74(10);
+}
+
+void sub_80AF848(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlaySE(SE_TK_WARPIN);
+ CreateTask(sub_80AFA0C, 10);
+ gFieldCallback = sub_80AF3E8;
+}
+
+void sub_80AF87C(void)
+{
+ sub_8085540(1);
+ ScriptContext2_Enable();
+ SaveEventObjects();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlaySE(SE_TK_WARPIN);
+ CreateTask(sub_80AFA0C, 10);
+ gFieldCallback = sub_80AF40C;
+}
+
+void sub_80AF8B8(void)
+{
+ ScriptContext2_Enable();
+ WarpFadeScreen();
+ CreateTask(sub_80AFA0C, 10);
+ gFieldCallback = sub_80FB768;
+}
+
+static void sub_80AF8E0(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ ScriptContext2_Enable();
+ task->data[0]++;
+ break;
+ case 1:
+ if (!PaletteFadeActive() && BGMusicStopped())
+ task->data[0]++;
+ break;
+ case 2:
+ WarpIntoMap();
+ SetMainCallback2(sub_8086074);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80AF948(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlaySE(SE_KAIDAN);
+ CreateTask(sub_80AF8E0, 10);
+}
+
+static void sub_80AF96C(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ ClearLinkCallback_2();
+ FadeScreen(FADE_TO_BLACK, 0);
+ TryFadeOutOldMapMusic();
+ PlaySE(SE_KAIDAN);
+ data[0]++;
+ break;
+ case 1:
+ if (!PaletteFadeActive() && BGMusicStopped())
+ {
+ sub_800AC34();
+ data[0]++;
+ }
+ break;
+ case 2:
+ if (!gReceivedRemoteLinkPlayers)
+ {
+ WarpIntoMap();
+ SetMainCallback2(CB2_LoadMap);
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_80AF9F8(void)
+{
+ CreateTask(sub_80AF96C, 10);
+}
+
+static void sub_80AFA0C(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ ScriptContext2_Enable();
+ task->data[0]++;
+ break;
+ case 1:
+ if (!PaletteFadeActive())
+ {
+ if (task->data[1] == 0)
+ {
+ sub_81BE72C();
+ task->data[1] = 1;
+ }
+ if (BGMusicStopped())
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ WarpIntoMap();
+ SetMainCallback2(CB2_LoadMap);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void sub_80AFA88(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ s16 *x = &task->data[2];
+ s16 *y = &task->data[3];
+
+ switch (task->data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ PlayerGetDestCoords(x, y);
+ PlaySE(GetDoorSoundEffect(*x, *y - 1));
+ task->data[1] = FieldAnimateDoorOpen(*x, *y - 1);
+ task->data[0] = 1;
+ break;
+ case 1:
+ if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE)
+ {
+ u8 eventObjId;
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectClearHeldMovementIfActive(&gEventObjects[eventObjId]);
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectSetHeldMovement(&gEventObjects[eventObjId], MOVEMENT_ACTION_WALK_NORMAL_UP);
+ task->data[0] = 2;
+ }
+ break;
+ case 2:
+ if (walkrun_is_standing_still())
+ {
+ u8 eventObjId;
+ task->data[1] = FieldAnimateDoorClose(*x, *y - 1);
+ eventObjId = GetEventObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ EventObjectClearHeldMovementIfFinished(&gEventObjects[eventObjId]);
+ sub_80AF0F4(0);
+ task->data[0] = 3;
+ }
+ break;
+ case 3:
+ if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE)
+ {
+ task->data[0] = 4;
+ }
+ break;
+ case 4:
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlayRainSoundEffect();
+ task->data[0] = 0;
+ task->func = sub_80AFA0C;
+ break;
+ }
+}
+
+static void task0A_fade_n_map_maybe(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ ScriptContext2_Enable();
+ task->data[0]++;
+ break;
+ case 1:
+ if (!PaletteFadeActive() && BGMusicStopped())
+ {
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ WarpIntoMap();
+ SetMainCallback2(sub_8086024);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80AFC60(void)
+{
+ ScriptContext2_Enable();
+ TryFadeOutOldMapMusic();
+ WarpFadeScreen();
+ PlayRainSoundEffect();
+ PlaySE(SE_KAIDAN);
+ gFieldCallback = sub_80AF3C8;
+ CreateTask(task0A_fade_n_map_maybe, 10);
+}
+
+static void SetFlashScanlineEffectWindowBoundary(u16 *dest, u32 y, s32 left, s32 right)
+{
+ if (y <= 160)
+ {
+ if (left < 0)
+ left = 0;
+ if (left > 255)
+ left = 255;
+ if (right < 0)
+ right = 0;
+ if (right > 255)
+ right = 255;
+ dest[y] = (left << 8) | right;
+ }
+}
+
+static void SetFlashScanlineEffectWindowBoundaries(u16 *dest, s32 centerX, s32 centerY, s32 radius)
+{
+ s32 r = radius;
+ s32 v2 = radius;
+ s32 v3 = 0;
+ while (r >= v3)
+ {
+ SetFlashScanlineEffectWindowBoundary(dest, centerY - v3, centerX - r, centerX + r);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY + v3, centerX - r, centerX + r);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY - r, centerX - v3, centerX + v3);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY + r, centerX - v3, centerX + v3);
+ v2 -= (v3 * 2) - 1;
+ v3++;
+ if (v2 < 0)
+ {
+ v2 += 2 * (r - 1);
+ r--;
+ }
+ }
+}
+
+static void SetFlash2ScanlineEffectWindowBoundary(u16 *dest, u32 y, s32 left, s32 right)
+{
+ if (y <= 160)
+ {
+ if (left < 0)
+ left = 0;
+ if (left > 240)
+ left = 240;
+ if (right < 0)
+ right = 0;
+ if (right > 240)
+ right = 240;
+ dest[y] = (left << 8) | right;
+ }
+}
+
+static void SetFlash2ScanlineEffectWindowBoundaries(u16 *dest, s32 centerX, s32 centerY, s32 radius)
+{
+ s32 r = radius;
+ s32 v2 = radius;
+ s32 v3 = 0;
+ while (r >= v3)
+ {
+ SetFlash2ScanlineEffectWindowBoundary(dest, centerY - v3, centerX - r, centerX + r);
+ SetFlash2ScanlineEffectWindowBoundary(dest, centerY + v3, centerX - r, centerX + r);
+ SetFlash2ScanlineEffectWindowBoundary(dest, centerY - r, centerX - v3, centerX + v3);
+ SetFlash2ScanlineEffectWindowBoundary(dest, centerY + r, centerX - v3, centerX + v3);
+ v2 -= (v3 * 2) - 1;
+ v3++;
+ if (v2 < 0)
+ {
+ v2 += 2 * (r - 1);
+ r--;
+ }
+ }
+}
+
+#define tFlashCenterX data[1]
+#define tFlashCenterY data[2]
+#define tCurFlashRadius data[3]
+#define tDestFlashRadius data[4]
+#define tFlashRadiusDelta data[5]
+#define tClearScanlineEffect data[6]
+
+static void UpdateFlashLevelEffect(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ SetFlashScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius);
+ data[0] = 1;
+ break;
+ case 1:
+ SetFlashScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius);
+ data[0] = 0;
+ tCurFlashRadius += tFlashRadiusDelta;
+ if (tCurFlashRadius > tDestFlashRadius)
+ {
+ if (tClearScanlineEffect == 1)
+ {
+ ScanlineEffect_Stop();
+ data[0] = 2;
+ }
+ else
+ {
+ DestroyTask(taskId);
+ }
+ }
+ break;
+ case 2:
+ ScanlineEffect_Clear();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void UpdateFlash2LevelEffect(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ SetFlash2ScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius);
+ data[0] = 1;
+ break;
+ case 1:
+ SetFlash2ScanlineEffectWindowBoundaries(gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], tFlashCenterX, tFlashCenterY, tCurFlashRadius);
+ data[0] = 0;
+ tCurFlashRadius += tFlashRadiusDelta;
+ if (tCurFlashRadius > tDestFlashRadius)
+ {
+ if (tClearScanlineEffect == 1)
+ {
+ ScanlineEffect_Stop();
+ data[0] = 2;
+ }
+ else
+ {
+ DestroyTask(taskId);
+ }
+ }
+ break;
+ case 2:
+ ScanlineEffect_Clear();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void sub_80AFF90(u8 taskId)
+{
+ if (!FuncIsActiveTask(UpdateFlashLevelEffect))
+ {
+ EnableBothScriptContexts();
+ DestroyTask(taskId);
+ }
+}
+
+static void sub_80AFFB8(void)
+{
+ if (!FuncIsActiveTask(sub_80AFF90))
+ CreateTask(sub_80AFF90, 80);
+}
+
+static u8 sub_80AFFDC(s32 centerX, s32 centerY, s32 initialFlashRadius, s32 destFlashRadius, s32 clearScanlineEffect, u8 delta)
+{
+ u8 taskId = CreateTask(UpdateFlashLevelEffect, 80);
+ s16 *data = gTasks[taskId].data;
+
+ tCurFlashRadius = initialFlashRadius;
+ tDestFlashRadius = destFlashRadius;
+ tFlashCenterX = centerX;
+ tFlashCenterY = centerY;
+ tClearScanlineEffect = clearScanlineEffect;
+
+ if (initialFlashRadius < destFlashRadius)
+ tFlashRadiusDelta = delta;
+ else
+ tFlashRadiusDelta = -delta;
+
+ return taskId;
+}
+
+static u8 sub_80B003C(s32 centerX, s32 centerY, s32 initialFlashRadius, s32 destFlashRadius, s32 clearScanlineEffect, u8 delta)
+{
+ u8 taskId = CreateTask(UpdateFlash2LevelEffect, 80);
+ s16 *data = gTasks[taskId].data;
+
+ tCurFlashRadius = initialFlashRadius;
+ tDestFlashRadius = destFlashRadius;
+ tFlashCenterX = centerX;
+ tFlashCenterY = centerY;
+ tClearScanlineEffect = clearScanlineEffect;
+
+ if (initialFlashRadius < destFlashRadius)
+ tFlashRadiusDelta = delta;
+ else
+ tFlashRadiusDelta = -delta;
+
+ return taskId;
+}
+
+#undef tCurFlashRadius
+#undef tDestFlashRadius
+#undef tFlashRadiusDelta
+#undef tClearScanlineEffect
+
+void sub_80B009C(u8 flashLevel)
+{
+ u8 curFlashLevel = Overworld_GetFlashLevel();
+ u8 value = 0;
+ if (!flashLevel)
+ value = 1;
+ sub_80AFFDC(120, 80, sFlashLevelPixelRadii[curFlashLevel], sFlashLevelPixelRadii[flashLevel], value, 1);
+ sub_80AFFB8();
+ ScriptContext2_Enable();
+}
+
+void WriteFlashScanlineEffectBuffer(u8 flashLevel)
+{
+ if (flashLevel)
+ {
+ SetFlashScanlineEffectWindowBoundaries(&gScanlineEffectRegBuffers[0][0], 120, 80, sFlashLevelPixelRadii[flashLevel]);
+ CpuFastSet(&gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 480);
+ }
+}
+
+void door_upload_tiles(void)
+{
+ SetFlashScanlineEffectWindowBoundaries(&gScanlineEffectRegBuffers[0][0], 120, 80, gSaveBlock2Ptr->frontier.field_E68);
+ CpuFastSet(&gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 480);
+}
+
+static void task0A_mpl_807E31C(u8 taskId)
+{
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ ScriptContext2_Enable();
+ sub_808D194();
+ gTasks[taskId].data[0]++;
+ break;
+ case 1:
+ if (sub_80AF71C() && sub_808D1B4() != TRUE)
+ {
+ UnfreezeEventObjects();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void sub_80B01BC(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ FreezeEventObjects();
+ ScriptContext2_Enable();
+ PlaySE(SE_TK_WARPIN);
+ sub_808D1C8();
+ task->data[0]++;
+ break;
+ case 1:
+ if (!sub_808D1E8())
+ {
+ WarpFadeScreen();
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ if (!PaletteFadeActive() && BGMusicStopped())
+ task->data[0]++;
+ break;
+ case 3:
+ WarpIntoMap();
+ SetMainCallback2(CB2_LoadMap);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80B0244(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(sub_80AFA0C, 10);
+ gFieldCallback = sub_80AF3E8;
+}
+
+void sub_80B0268(void)
+{
+ ScriptContext2_Enable();
+ gFieldCallback = mapldr_default;
+ CreateTask(sub_80B01BC, 10);
+}
+
+static void sub_80B028C(u8 a1)
+{
+ int i;
+ u16 color[1];
+
+ if (!a1)
+ color[0] = RGB_RED;
+ else
+ color[0] = RGB_BLUE;
+
+ for (i = 0; i < 16; i++)
+ {
+ LoadPalette(color, 0xF0 + i, 2);
+ }
+}
+
+static bool8 sub_80B02C8(u16 a1)
+{
+ u8 lo = REG_BLDALPHA & 0xFF;
+ u8 hi = REG_BLDALPHA >> 8;
+
+ if (a1)
+ {
+ if (lo)
+ {
+ lo--;
+ }
+ }
+ else
+ {
+ if (hi < 0x10)
+ {
+ hi++;
+ }
+ }
+
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(lo, hi));
+
+ if (lo == 0 && hi == 0x10)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void sub_80B0318(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ data[6] = REG_DISPCNT;
+ data[7] = REG_BLDCNT;
+ data[8] = REG_BLDALPHA;
+ data[9] = REG_WININ;
+ data[10] = REG_WINOUT;
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN1_ON);
+ SetGpuRegBits(REG_OFFSET_BLDCNT, gUnknown_82EC7CC[0]);
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 7));
+ SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
+ SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ);
+ sub_8199C30(0, 0, 0, 0x1E, 0x14, 0xF);
+ schedule_bg_copy_tilemap_to_vram(0);
+ SetFlash2ScanlineEffectWindowBoundaries(&gScanlineEffectRegBuffers[0][0], data[2], data[3], 1);
+ CpuFastSet(&gScanlineEffectRegBuffers[0], &gScanlineEffectRegBuffers[1], 480);
+ ScanlineEffect_SetParams(sFlashEffectParams);
+ data[0] = 1;
+ break;
+ case 1:
+ sub_8199DF0(0, 17, 0, 1);
+ sub_80B028C(data[1]);
+ sub_80B003C(data[2], data[3], 1, 160, 1, 2);
+ data[0] = 2;
+ break;
+ case 2:
+ if (!FuncIsActiveTask(UpdateFlash2LevelEffect))
+ {
+ EnableBothScriptContexts();
+ data[0] = 3;
+ }
+ break;
+ case 3:
+ InstallCameraPanAheadCallback();
+ SetCameraPanningCallback(NULL);
+ data[5] = 0;
+ data[4] = 4;
+ data[0] = 4;
+ break;
+ case 4:
+ data[4]--;
+ if (!data[4])
+ {
+ s32 panning;
+ data[4] = 4;
+ data[5] ^= 1;
+ if (data[5])
+ panning = 4;
+ else
+ panning = -4;
+ SetCameraPanning(0, panning);
+ }
+ break;
+ case 6:
+ InstallCameraPanAheadCallback();
+ data[4] = 8;
+ data[0] = 7;
+ break;
+ case 7:
+ data[4]--;
+ if (!data[4])
+ {
+ data[4] = 8;
+ data[5] ^= 1;
+ if (sub_80B02C8(data[5]) == TRUE)
+ {
+ data[0] = 5;
+ sub_8199DF0(0, 0, 0, 1);
+ }
+ }
+ break;
+ case 5:
+ SetGpuReg(REG_OFFSET_WIN0H, 255);
+ SetGpuReg(REG_OFFSET_DISPCNT, data[6]);
+ SetGpuReg(REG_OFFSET_BLDCNT, data[7]);
+ SetGpuReg(REG_OFFSET_BLDALPHA, data[8]);
+ SetGpuReg(REG_OFFSET_WININ, data[9]);
+ SetGpuReg(REG_OFFSET_WINOUT, data[10]);
+ EnableBothScriptContexts();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80B0534(void)
+{
+ u8 taskId = CreateTask(sub_80B0318, 80);
+ s16 *data = gTasks[taskId].data;
+
+ if (gSpecialVar_Result == 0)
+ {
+ data[1] = 0;
+ data[2] = 104;
+ }
+ else if (gSpecialVar_Result == 1)
+ {
+ data[1] = 1;
+ data[2] = 136;
+ }
+ else if (gSpecialVar_Result == 2)
+ {
+ data[1] = 0;
+ data[2] = 120;
+ }
+ else
+ {
+ data[1] = 1;
+ data[2] = 120;
+ }
+
+ data[3] = 80;
+}
+
+void sub_80B058C(void)
+{
+ u8 taskId = FindTaskIdByFunc(sub_80B0318);
+ gTasks[taskId].data[0] = 6;
+}
+
+void sub_80B05B4(void)
+{
+ Overworld_FadeOutMapMusic();
+ CreateTask(task50_0807F0C8, 80);
+}
+
+static void task50_0807F0C8(u8 taskId)
+{
+ if (BGMusicStopped() == TRUE)
+ {
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+}
diff --git a/src/field_specials.c b/src/field_specials.c
index b47df09fc..3a50e272e 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -12,7 +12,7 @@
#include "field_effect.h"
#include "field_message_box.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_specials.h"
#include "field_weather.h"
#include "international_string_util.h"
diff --git a/src/field_weather.c b/src/field_weather.c
new file mode 100644
index 000000000..f0615dabf
--- /dev/null
+++ b/src/field_weather.c
@@ -0,0 +1,1095 @@
+#include "global.h"
+#include "constants/songs.h"
+#include "constants/weather.h"
+#include "constants/rgb.h"
+#include "util.h"
+#include "event_object_movement.h"
+#include "field_weather.h"
+#include "main.h"
+#include "menu.h"
+#include "palette.h"
+#include "random.h"
+#include "script.h"
+#include "start_menu.h"
+#include "sound.h"
+#include "sprite.h"
+#include "task.h"
+#include "trig.h"
+#include "gpu_regs.h"
+
+#define MACRO1(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);
+};
+
+// This file's functions.
+static bool8 LightenSpritePaletteInFog(u8);
+static void BuildGammaShiftTables(void);
+static void UpdateWeatherGammaShift(void);
+static void ApplyGammaShift(u8 startPalIndex, u8 numPalettes, s8 gammaIndex);
+static void ApplyGammaShiftWithBlend(u8 startPalIndex, u8 numPalettes, s8 gammaIndex, u8 blendCoeff, u16 blendColor);
+static void ApplyDroughtGammaShiftWithBlend(s8 gammaIndex, u8 blendCoeff, u16 blendColor);
+static void ApplyFogBlend(u8 blendCoeff, u16 blendColor);
+static bool8 FadeInScreen_RainShowShade(void);
+static bool8 FadeInScreen_Drought(void);
+static bool8 FadeInScreen_Fog1(void);
+static void FadeInScreenWithWeather(void);
+static void DoNothing(void);
+static void Task_WeatherInit(u8 taskId);
+static void Task_WeatherMain(u8 taskId);
+static void None_Init(void);
+static void None_Main(void);
+static u8 None_Finish(void);
+
+// EWRAM
+EWRAM_DATA struct Weather gWeather = {0};
+EWRAM_DATA static u8 sFieldEffectPaletteGammaTypes[32] = {0};
+
+// IWRAM bss
+IWRAM_DATA static const u8 *sPaletteGammaTypes;
+
+// CONST
+extern const u16 gUnknown_0854014C[][4096];
+
+// This is a pointer to gWeather. All code in this file accesses gWeather directly,
+// while code in other field weather files accesses gWeather through this pointer.
+// This is likely the result of compiler optimization, since using the pointer in
+// this file produces the same result as accessing gWeather directly.
+struct Weather *const gWeatherPtr = &gWeather;
+
+static const struct WeatherCallbacks sWeatherFuncs[] =
+{
+ {None_Init, None_Main, None_Init, None_Finish},
+ {Clouds_InitVars, Clouds_Main, Clouds_InitAll, Clouds_Finish},
+ {Weather2_InitVars, Weather2_Main, Weather2_InitAll, Weather2_Finish},
+ {LightRain_InitVars, LightRain_Main, LightRain_InitAll, LightRain_Finish},
+ {Snow_InitVars, Snow_Main, Snow_InitAll, Snow_Finish},
+ {MedRain_InitVars, Rain_Main, MedRain_InitAll, 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},
+ {Shade_InitVars, Shade_Main, Shade_InitAll, Shade_Finish},
+ {Drought_InitVars, Drought_Main, Drought_InitAll, Drought_Finish},
+ {HeavyRain_InitVars, Rain_Main, HeavyRain_InitAll, Rain_Finish},
+ {Bubbles_InitVars, Bubbles_Main, Bubbles_InitAll, Bubbles_Finish},
+};
+
+void (*const gWeatherPalStateFuncs[])(void) =
+{
+ UpdateWeatherGammaShift, // WEATHER_PAL_STATE_CHANGING_WEATHER
+ FadeInScreenWithWeather, // WEATHER_PAL_STATE_SCREEN_FADING_IN
+ DoNothing, // WEATHER_PAL_STATE_SCREEN_FADING_OUT
+ DoNothing, // WEATHER_PAL_STATE_IDLE
+};
+
+// This table specifies which of the gamma shift tables should be
+// applied to each of the background and sprite palettes.
+static 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_NORMAL,
+ 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_083970E8[] = INCBIN_U16("graphics/weather/0.gbapal");
+
+// code
+void StartWeather(void)
+{
+ if (!FuncIsActiveTask(Task_WeatherMain))
+ {
+ u8 index = AllocSpritePalette(0x1200);
+ CpuCopy32(gUnknown_083970E8, &gPlttBufferUnfaded[0x100 + index * 16], 32);
+ BuildGammaShiftTables();
+ gWeatherPtr->altGammaSpritePalIndex = index;
+ gWeatherPtr->weatherPicSpritePalIndex = AllocSpritePalette(0x1201);
+ gWeatherPtr->rainSpriteCount = 0;
+ gWeatherPtr->unknown_6D8 = 0;
+ gWeatherPtr->cloudSpritesCreated = 0;
+ gWeatherPtr->snowflakeSpriteCount = 0;
+ gWeatherPtr->ashSpritesCreated = 0;
+ gWeatherPtr->fog1SpritesCreated = 0;
+ gWeatherPtr->fog2SpritesCreated = 0;
+ gWeatherPtr->sandstormSprites1Created = 0;
+ gWeatherPtr->sandstormSprites2Created = 0;
+ gWeatherPtr->unknown_72E = 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 ChangeWeather(u8 weather)
+{
+ if (weather != WEATHER_RAIN_LIGHT && weather != WEATHER_RAIN_MED && weather != WEATHER_RAIN_HEAVY)
+ {
+ PlayRainSoundEffect();
+ }
+
+ if (gWeatherPtr->nextWeather != weather && gWeatherPtr->currWeather == weather)
+ {
+ sWeatherFuncs[weather].initVars();
+ }
+
+ gWeatherPtr->weatherChangeComplete = FALSE;
+ gWeatherPtr->nextWeather = weather;
+ gWeatherPtr->finishStep = 0;
+}
+
+void sub_80AB104(u8 weather)
+{
+ PlayRainSoundEffect();
+ gWeatherPtr->currWeather = weather;
+ gWeatherPtr->nextWeather = weather;
+}
+
+void sub_80AB130(u8 weather)
+{
+ PlayRainSoundEffect();
+ gWeatherPtr->currWeather = weather;
+ gWeatherPtr->nextWeather = weather;
+ gWeatherPtr->readyForInit = TRUE;
+}
+
+static 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;
+ }
+}
+
+static 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]();
+}
+
+static void None_Init(void)
+{
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 0;
+}
+
+static void None_Main(void)
+{
+}
+
+static 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.
+static 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.
+static void UpdateWeatherGammaShift(void)
+{
+ if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_OUT)
+ {
+ 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);
+ }
+ }
+ }
+}
+
+static void FadeInScreenWithWeather(void)
+{
+ if (++gWeatherPtr->unknown_6CB > 1)
+ gWeatherPtr->unknown_6CA = 0;
+
+ switch (gWeatherPtr->currWeather)
+ {
+ case WEATHER_RAIN_LIGHT:
+ case WEATHER_RAIN_MED:
+ case WEATHER_RAIN_HEAVY:
+ 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_1:
+ if (FadeInScreen_Fog1() == FALSE)
+ {
+ gWeatherPtr->gammaIndex = 0;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ case WEATHER_ASH:
+ case WEATHER_SANDSTORM:
+ case WEATHER_FOG_2:
+ case WEATHER_FOG_3:
+ default:
+ if (!gPaletteFade.active)
+ {
+ gWeatherPtr->gammaIndex = gWeatherPtr->gammaTargetIndex;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ }
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static bool8 FadeInScreen_Fog1(void)
+{
+ if (gWeatherPtr->fadeScreenCounter == 16)
+ return FALSE;
+
+ gWeatherPtr->fadeScreenCounter++;
+ ApplyFogBlend(16 - gWeatherPtr->fadeScreenCounter, gWeatherPtr->fadeDestColor);
+ return TRUE;
+}
+
+static void DoNothing(void)
+{ }
+
+static 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.
+ gammaIndex = -gammaIndex - 1;
+ palOffset = startPalIndex * 16;
+ numPalettes += startPalIndex;
+ curPalIndex = startPalIndex;
+
+ while (curPalIndex < numPalettes)
+ {
+ if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE)
+ {
+ // No palette change.
+ CpuFastCopy(gPlttBufferUnfaded + palOffset, gPlttBufferFaded + palOffset, 16 * sizeof(u16));
+ palOffset += 16;
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ gPlttBufferFaded[palOffset] = gUnknown_0854014C[gammaIndex][MACRO1(gPlttBufferUnfaded[palOffset])];
+ palOffset++;
+ }
+ }
+
+ curPalIndex++;
+ }
+ }
+ else
+ {
+ // No palette blending.
+ CpuFastCopy(gPlttBufferUnfaded + startPalIndex * 16, gPlttBufferFaded + startPalIndex * 16, numPalettes * 16 * sizeof(u16));
+ }
+}
+
+static 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++;
+ }
+}
+
+static 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;
+
+ offset = ((b1 & 0x1E) << 7) | ((g1 & 0x1E) << 3) | ((r1 & 0x1E) >> 1);
+ color2 = *(struct RGBColor *)&gUnknown_0854014C[gammaIndex][offset];
+ r2 = color2.r;
+ g2 = color2.g;
+ b2 = color2.b;
+
+ r2 += ((rBlend - r2) * blendCoeff) >> 4;
+ g2 += ((gBlend - g2) * blendCoeff) >> 4;
+ b2 += ((bBlend - b2) * blendCoeff) >> 4;
+
+ gPlttBufferFaded[palOffset++] = (b2 << 10) | (g2 << 5) | r2;
+ }
+ }
+ }
+}
+
+static 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);
+ }
+ }
+}
+
+static void MarkFogSpritePalToLighten(u8 paletteIndex)
+{
+ if (gWeatherPtr->lightenedFogSpritePalsCount < 6)
+ {
+ gWeatherPtr->lightenedFogSpritePals[gWeatherPtr->lightenedFogSpritePalsCount] = paletteIndex;
+ gWeatherPtr->lightenedFogSpritePalsCount++;
+ }
+}
+
+static bool8 LightenSpritePaletteInFog(u8 paletteIndex)
+{
+ u16 i;
+
+ for (i = 0; i < gWeatherPtr->lightenedFogSpritePalsCount; i++)
+ {
+ if (gWeatherPtr->lightenedFogSpritePals[i] == paletteIndex)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void sub_80ABC48(s8 gammaIndex)
+{
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE)
+ {
+ ApplyGammaShift(0, 32, gammaIndex);
+ gWeatherPtr->gammaIndex = gammaIndex;
+ }
+}
+
+void sub_80ABC7C(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_80ABC48(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_LIGHT:
+ case WEATHER_RAIN_MED:
+ case WEATHER_RAIN_HEAVY:
+ case WEATHER_SNOW:
+ case WEATHER_FOG_1:
+ 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;
+ }
+}
+
+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_1)
+ 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_1)
+ {
+ 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)
+{
+ *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_80ABFE0(s8 gammaIndex)
+{
+ sub_80ABC48(-gammaIndex - 1);
+}
+
+void sub_80ABFF0(void)
+{
+ gWeatherPtr->unknown_73C = 0;
+ gWeatherPtr->unknown_740 = 0;
+ gWeatherPtr->unknown_742 = 0;
+ gWeatherPtr->unknown_73E = 0;
+}
+
+void sub_80AC01C(void)
+{
+ switch (gWeatherPtr->unknown_742)
+ {
+ case 0:
+ if (++gWeatherPtr->unknown_740 > 5)
+ {
+ gWeatherPtr->unknown_740 = 0;
+ sub_80ABFE0(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_80ABFE0(gWeatherPtr->unknown_73C);
+ gWeatherPtr->unknown_73E = gWeatherPtr->unknown_73C;
+ break;
+ case 2:
+ if (++gWeatherPtr->unknown_740 > 5)
+ {
+ gWeatherPtr->unknown_740 = 0;
+ sub_80ABFE0(--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_80AC274(u8 a)
+{
+ switch (a)
+ {
+ case 1:
+ SetWeather(WEATHER_CLOUDS);
+ break;
+ case 2:
+ SetWeather(WEATHER_SUNNY);
+ break;
+ case 3:
+ SetWeather(WEATHER_RAIN_LIGHT);
+ break;
+ case 4:
+ SetWeather(WEATHER_SNOW);
+ break;
+ case 5:
+ SetWeather(WEATHER_RAIN_MED);
+ break;
+ case 6:
+ SetWeather(WEATHER_FOG_1);
+ break;
+ case 7:
+ SetWeather(WEATHER_FOG_2);
+ break;
+ case 8:
+ SetWeather(WEATHER_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 PlayRainSoundEffect(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_80AC3E4(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_effect.c b/src/field_weather_effect.c
new file mode 100644
index 000000000..2ec51a722
--- /dev/null
+++ b/src/field_weather_effect.c
@@ -0,0 +1,2471 @@
+#include "global.h"
+#include "event_object_movement.h"
+#include "field_weather.h"
+#include "overworld.h"
+#include "random.h"
+#include "script.h"
+#include "constants/weather.h"
+#include "constants/songs.h"
+#include "sound.h"
+#include "sprite.h"
+#include "task.h"
+#include "trig.h"
+#include "gpu_regs.h"
+
+// This file's functions.
+void sub_80AC6B4(struct Sprite *);
+
+// EWRAM
+EWRAM_DATA static u8 gUnknown_02038BC4 = 0;
+EWRAM_DATA static u16 gUnknown_02038BC6 = 0;
+
+// CONST
+const u16 gUnknown_0854C290[] = INCBIN_U16("graphics/weather/1.gbapal");
+const u16 gUnknown_0854C2B0[] = INCBIN_U16("graphics/weather/2.gbapal");
+const u8 gWeatherFog2Tiles[] = INCBIN_U8("graphics/weather/fog2.4bpp");
+const u8 gWeatherFog1Tiles[] = INCBIN_U8("graphics/weather/fog1.4bpp");
+const u8 gWeatherCloudTiles[] = INCBIN_U8("graphics/weather/cloud.4bpp");
+const u8 gWeatherSnow1Tiles[] = INCBIN_U8("graphics/weather/snow0.4bpp");
+const u8 gWeatherSnow2Tiles[] = INCBIN_U8("graphics/weather/snow1.4bpp");
+const u8 gWeatherBubbleTiles[] = INCBIN_U8("graphics/weather/bubble.4bpp");
+const u8 gWeatherAshTiles[] = INCBIN_U8("graphics/weather/ash.4bpp");
+const u8 gWeatherRainTiles[] = INCBIN_U8("graphics/weather/rain.4bpp");
+const u8 gWeatherSandstormTiles[] = INCBIN_U8("graphics/weather/sandstorm.4bpp");
+
+static const struct Coords16 gUnknown_0854FB50[] =
+{
+ { 0, 66},
+ { 5, 73},
+ {10, 78},
+};
+
+static const struct SpriteSheet sCloudSpriteSheet = {gWeatherCloudTiles, sizeof(gWeatherCloudTiles), 0x1200};
+
+static const struct OamData gOamData_839A9DC =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 1,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd gSpriteAnim_839A9E4[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const gSpriteAnimTable_839A9EC[] =
+{
+ gSpriteAnim_839A9E4,
+};
+
+static const struct SpriteTemplate sCloudSpriteTemplate =
+{
+ .tileTag = 4608,
+ .paletteTag = 4609,
+ .oam = &gOamData_839A9DC,
+ .anims = gSpriteAnimTable_839A9EC,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80AC6B4,
+};
+
+//------------------------------------------------------------------------------
+// Clouds
+//------------------------------------------------------------------------------
+
+void Clouds_InitVars(void)
+{
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->initStep = 0;
+ if (gWeatherPtr->cloudSpritesCreated == FALSE)
+ Weather_SetBlendCoeffs(0, 16);
+}
+
+void Clouds_InitAll(void)
+{
+ Clouds_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Clouds_Main();
+}
+
+void CreateCloudSprites(void);
+
+void Clouds_Main(void)
+{
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateCloudSprites();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ Weather_SetTargetBlendCoeffs(12, 8, 1);
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (Weather_UpdateBlend())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ }
+}
+
+void sub_807E0A0(void);
+
+bool8 Clouds_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 1);
+ gWeatherPtr->finishStep++;
+ return TRUE;
+ case 1:
+ if (Weather_UpdateBlend())
+ {
+ sub_807E0A0();
+ gWeatherPtr->finishStep++;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+// Weather 2
+//------------------------------------------------------------------------------
+
+void Weather2_InitVars(void)
+{
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+}
+
+void Weather2_InitAll(void)
+{
+ Weather2_InitVars();
+}
+
+void Weather2_Main(void)
+{
+}
+
+bool8 Weather2_Finish(void)
+{
+ return 0;
+}
+
+void CreateCloudSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->cloudSpritesCreated == TRUE)
+ return;
+ LoadSpriteSheet(&sCloudSpriteSheet);
+ LoadCustomWeatherSpritePalette(gUnknown_0854C290);
+ for (i = 0; i < 3; i++)
+ {
+ u8 spriteId = CreateSprite(&sCloudSpriteTemplate, 0, 0, 0xFF);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ struct Sprite *sprite;
+
+ gWeatherPtr->sprites.s1.cloudSprites[i] = &gSprites[spriteId];
+ sprite = gWeatherPtr->sprites.s1.cloudSprites[i];
+ sub_8093038(gUnknown_0854FB50[i].x + 7, gUnknown_0854FB50[i].y + 7, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->coordOffsetEnabled = TRUE;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s1.cloudSprites[i] = NULL;
+ }
+ }
+ gWeatherPtr->cloudSpritesCreated = TRUE;
+}
+
+void sub_807E0A0(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->cloudSpritesCreated == FALSE)
+ return;
+ for (i = 0; i < 3; i++)
+ {
+ if (gWeatherPtr->sprites.s1.cloudSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s1.cloudSprites[i]);
+ }
+ FreeSpriteTilesByTag(0x1200);
+ gWeatherPtr->cloudSpritesCreated = FALSE;
+}
+
+void sub_80AC6B4(struct Sprite *sprite)
+{
+ sprite->data[0] = (sprite->data[0] + 1) & 1;
+ if (sprite->data[0] != 0)
+ sprite->pos1.x--;
+}
+
+//------------------------------------------------------------------------------
+// Drought
+//------------------------------------------------------------------------------
+
+void Drought_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 0;
+}
+
+void Drought_InitAll(void)
+{
+ Drought_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Drought_Main();
+}
+
+void Drought_Main(void)
+{
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_CHANGING_WEATHER)
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ ResetDroughtWeatherPaletteLoading();
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (LoadDroughtWeatherPalettes() == FALSE)
+ gWeatherPtr->initStep++;
+ break;
+ case 3:
+ sub_80ABFF0();
+ gWeatherPtr->initStep++;
+ break;
+ case 4:
+ sub_80AC01C();
+ if (gWeatherPtr->unknown_73C == 6)
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ default:
+ sub_80AC01C();
+ break;
+ }
+}
+
+bool8 Drought_Finish(void)
+{
+ return 0;
+}
+
+void task50_0807B6D4(u8);
+
+void sub_80AC81C(void)
+{
+ CreateTask(task50_0807B6D4, 0x50);
+}
+
+#define tState data[0]
+#define tBlendY data[1]
+#define tBlendDelay data[2]
+#define tWinRange data[3]
+
+void task50_0807B6D4(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->tState)
+ {
+ case 0:
+ task->tBlendY = 0;
+ task->tBlendDelay = 0;
+ task->tWinRange = REG_WININ;
+ SetGpuReg(REG_OFFSET_WININ, WIN_RANGE(63, 63));
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_EFFECT_LIGHTEN);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ task->tState++;
+ // fall through
+ case 1:
+ task->tBlendY += 3;
+ if (task->tBlendY > 16)
+ task->tBlendY = 16;
+ SetGpuReg(REG_OFFSET_BLDY, task->tBlendY);
+ if (task->tBlendY >= 16)
+ task->tState++;
+ break;
+ case 2:
+ task->tBlendDelay++;
+ if (task->tBlendDelay > 9)
+ {
+ task->tBlendDelay = 0;
+ task->tBlendY--;
+ if (task->tBlendY <= 0)
+ {
+ task->tBlendY = 0;
+ task->tState++;
+ }
+ SetGpuReg(REG_OFFSET_BLDY, task->tBlendY);
+ }
+ break;
+ case 3:
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ SetGpuReg(REG_OFFSET_WININ, task->tWinRange);
+ task->tState++;
+ break;
+ case 4:
+ EnableBothScriptContexts();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+#undef tState
+#undef tBlendY
+#undef tBlendDelay
+#undef tWinRange
+
+//------------------------------------------------------------------------------
+// Light Rain
+//------------------------------------------------------------------------------
+
+void LightRain_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->unknown_6D6 = 0;
+ gWeatherPtr->unknown_6DB = 8;
+ gWeatherPtr->unknown_6DC = 0;
+ gWeatherPtr->unknown_6D9 = 10;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ SetRainStrengthFromSoundEffect(SE_T_KOAME);
+}
+
+void LightRain_InitAll(void)
+{
+ LightRain_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ LightRain_Main();
+}
+
+void LoadRainSpriteSheet(void);
+u8 CreateRainSprite(void);
+u8 sub_807E8E8(void);
+
+void LightRain_Main(void)
+{
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ LoadRainSpriteSheet();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (CreateRainSprite() == 0)
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (sub_807E8E8() == FALSE)
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ }
+}
+
+void DestroyRainSprites(void);
+
+bool8 LightRain_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ if (gWeatherPtr->nextWeather == WEATHER_RAIN_LIGHT
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_MED
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_HEAVY)
+ {
+ gWeatherPtr->finishStep = 0xFF;
+ return FALSE;
+ }
+ else
+ {
+ gWeatherPtr->unknown_6D9 = 0;
+ gWeatherPtr->finishStep++;
+ }
+ // fall through
+ case 1:
+ if (sub_807E8E8() == FALSE)
+ {
+ DestroyRainSprites();
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// defined below
+extern const s16 gUnknown_0839AABC[][2];
+extern const u16 gUnknown_0839AAC4[][2];
+
+void sub_807E4EC(struct Sprite *sprite)
+{
+ u32 randVal;
+ u16 r6;
+ s32 r4;
+ s32 r0;
+
+ if (sprite->data[1] == 0)
+ sprite->data[1] = 361;
+ randVal = sprite->data[1] * 1103515245 + 12345;
+ sprite->data[1] = ((randVal & 0x7FFF0000) >> 16) % 600;
+
+ r6 = gUnknown_0839AAC4[gWeatherPtr->unknown_6DC][0];
+
+ r4 = sprite->data[1] % 30;
+ sprite->data[2] = r4 * 8; // useless assignment
+
+ r0 = sprite->data[1] / 30;
+ sprite->data[3] = r0 * 8; // useless assignment
+
+ sprite->data[2] = r4;
+ sprite->data[2] <<= 7;
+
+ sprite->data[3] = r0;
+ sprite->data[3] <<= 7;
+
+ sprite->data[2] -= gUnknown_0839AABC[gWeatherPtr->unknown_6DC][0] * r6;
+ sprite->data[3] -= gUnknown_0839AABC[gWeatherPtr->unknown_6DC][1] * r6;
+
+ StartSpriteAnim(sprite, 0);
+ sprite->data[4] = 0;
+ sprite->coordOffsetEnabled = FALSE;
+ sprite->data[0] = r6;
+}
+
+void sub_807E5C0(struct Sprite *sprite)
+{
+ if (sprite->data[4] == 0)
+ {
+ sprite->data[2] += gUnknown_0839AABC[gWeatherPtr->unknown_6DC][0];
+ sprite->data[3] += gUnknown_0839AABC[gWeatherPtr->unknown_6DC][1];
+ sprite->pos1.x = sprite->data[2] >> 4;
+ sprite->pos1.y = sprite->data[3] >> 4;
+
+ if (sprite->data[5] != 0
+ && (sprite->pos1.x >= -8 && sprite->pos1.x <= 248)
+ && sprite->pos1.y >= -16 && sprite->pos1.y <= 176)
+ sprite->invisible = FALSE;
+ else
+ sprite->invisible = TRUE;
+
+ sprite->data[0]--;
+ if (sprite->data[0] == 0)
+ {
+ StartSpriteAnim(sprite, gWeatherPtr->unknown_6DC + 1);
+ sprite->data[4] = 1;
+ sprite->pos1.x -= gSpriteCoordOffsetX;
+ sprite->pos1.y -= gSpriteCoordOffsetY;
+ sprite->coordOffsetEnabled = TRUE;
+ }
+ }
+ else if (sprite->animEnded)
+ {
+ sprite->invisible = TRUE;
+ sub_807E4EC(sprite);
+ }
+}
+
+void sub_807E6C4(struct Sprite *sprite)
+{
+ if (sprite->data[0] == 0)
+ {
+ sub_807E4EC(sprite);
+ sprite->callback = sub_807E5C0;
+ }
+ else
+ {
+ sprite->data[0]--;
+ }
+}
+
+void sub_807E6F0(struct Sprite *sprite, u16 b)
+{
+ u16 r8 = gUnknown_0839AAC4[gWeatherPtr->unknown_6DC][0];
+ u16 r6 = b / (gUnknown_0839AAC4[gWeatherPtr->unknown_6DC][1] + r8);
+ u16 r4 = b % (gUnknown_0839AAC4[gWeatherPtr->unknown_6DC][1] + r8);
+
+ while (--r6 != 0xFFFF)
+ sub_807E4EC(sprite);
+ if (r4 < r8)
+ {
+ while (--r4 != 0xFFFF)
+ sub_807E5C0(sprite);
+ sprite->data[6] = 0;
+ }
+ else
+ {
+ sprite->data[0] = r4 - r8;
+ sprite->invisible = TRUE;
+ sprite->data[6] = 1;
+ }
+}
+
+extern const struct SpriteSheet sRainSpriteSheet; // defined below
+
+void LoadRainSpriteSheet(void)
+{
+ LoadSpriteSheet(&sRainSpriteSheet);
+}
+
+static const struct Coords16 sRainSpriteCoords[] =
+{
+ { 0, 0},
+ { 0, 160},
+ { 0, 64},
+ {144, 224},
+ {144, 128},
+ { 32, 32},
+ { 32, 192},
+ { 32, 96},
+ { 72, 128},
+ { 72, 32},
+ { 72, 192},
+ {216, 96},
+ {216, 0},
+ {104, 160},
+ {104, 64},
+ {104, 224},
+ {144, 0},
+ {144, 160},
+ {144, 64},
+ { 32, 224},
+ { 32, 128},
+ { 72, 32},
+ { 72, 192},
+ { 48, 96},
+};
+
+static const struct OamData gOamData_839AA68 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 2,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 2,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 2,
+ .affineParam = 0,
+};
+
+static const union AnimCmd gSpriteAnim_839AA70[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd gSpriteAnim_839AA78[] =
+{
+ ANIMCMD_FRAME(8, 3),
+ ANIMCMD_FRAME(32, 2),
+ ANIMCMD_FRAME(40, 2),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AA88[] =
+{
+ ANIMCMD_FRAME(8, 3),
+ ANIMCMD_FRAME(16, 3),
+ ANIMCMD_FRAME(24, 4),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const gSpriteAnimTable_839AA98[] =
+{
+ gSpriteAnim_839AA70,
+ gSpriteAnim_839AA78,
+ gSpriteAnim_839AA88,
+};
+
+static const struct SpriteTemplate sRainSpriteTemplate =
+{
+ .tileTag = 4614,
+ .paletteTag = 4608,
+ .oam = &gOamData_839AA68,
+ .anims = gSpriteAnimTable_839AA98,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_807E5C0,
+};
+
+const s16 gUnknown_0839AABC[][2] =
+{
+ {-104, 208},
+ {-160, 320},
+};
+
+const u16 gUnknown_0839AAC4[][2] =
+{
+ {18, 7},
+ {12, 10},
+};
+
+static const struct SpriteSheet sRainSpriteSheet = {gWeatherRainTiles, sizeof(gWeatherRainTiles), 0x1206};
+
+static const struct OamData gOamData_839AAD4 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteFrameImage gSpriteImageTable_839AADC[] =
+{
+ {gWeatherSnow1Tiles, sizeof(gWeatherSnow1Tiles)},
+ {gWeatherSnow2Tiles, sizeof(gWeatherSnow2Tiles)},
+};
+
+static const union AnimCmd gSpriteAnim_839AAEC[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AAF4[] =
+{
+ ANIMCMD_FRAME(1, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const gSpriteAnimTable_839AAFC[] =
+{
+ gSpriteAnim_839AAEC,
+ gSpriteAnim_839AAF4,
+};
+
+void sub_807ED48(struct Sprite *);
+static const struct SpriteTemplate sSnowflakeSpriteTemplate =
+{
+ .tileTag = 0xFFFF,
+ .paletteTag = 4608,
+ .oam = &gOamData_839AAD4,
+ .anims = gSpriteAnimTable_839AAFC,
+ .images = gSpriteImageTable_839AADC,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_807ED48,
+};
+
+// unused data
+static const u16 unusedData_839AB1C[] = {0, 6, 6, 12, 18, 42, 300, 300};
+
+static const struct OamData gOamData_839AB2C =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 1,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd gSpriteAnim_839AB34[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AB3C[] =
+{
+ ANIMCMD_FRAME(32, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AB44[] =
+{
+ ANIMCMD_FRAME(64, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AB4C[] =
+{
+ ANIMCMD_FRAME(96, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AB54[] =
+{
+ ANIMCMD_FRAME(128, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd gSpriteAnim_839AB5C[] =
+{
+ ANIMCMD_FRAME(160, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const gSpriteAnimTable_839AB64[] =
+{
+ gSpriteAnim_839AB34,
+ gSpriteAnim_839AB3C,
+ gSpriteAnim_839AB44,
+ gSpriteAnim_839AB4C,
+ gSpriteAnim_839AB54,
+ gSpriteAnim_839AB5C,
+};
+
+static const union AffineAnimCmd gSpriteAffineAnim_839AB7C[] =
+{
+ AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0),
+ AFFINEANIMCMD_END,
+};
+
+static const union AffineAnimCmd *const gSpriteAffineAnimTable_839AB8C[] =
+{
+ gSpriteAffineAnim_839AB7C,
+};
+
+static void Fog1SpriteCallback(struct Sprite *);
+static const struct SpriteTemplate sFog1SpriteTemplate =
+{
+ .tileTag = 4609,
+ .paletteTag = 4608,
+ .oam = &gOamData_839AB2C,
+ .anims = gSpriteAnimTable_839AB64,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_839AB8C,
+ .callback = Fog1SpriteCallback,
+};
+
+bool8 CreateRainSprite(void)
+{
+ u8 spriteNum;
+ u8 spriteId;
+
+ if (gWeatherPtr->rainSpriteCount == 24)
+ return FALSE;
+
+ spriteNum = gWeatherPtr->rainSpriteCount;
+ spriteId = CreateSpriteAtEnd(&sRainSpriteTemplate,
+ sRainSpriteCoords[spriteNum].x, sRainSpriteCoords[spriteNum].y, 78);
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].data[5] = 0;
+ gSprites[spriteId].data[1] = spriteNum * 145;
+ while (gSprites[spriteId].data[1] >= 600)
+ gSprites[spriteId].data[1] -= 600;
+ sub_807E4EC(&gSprites[spriteId]);
+ sub_807E6F0(&gSprites[spriteId], spriteNum * 9);
+ gSprites[spriteId].invisible = TRUE;
+ gWeatherPtr->sprites.s1.rainSprites[spriteNum] = &gSprites[spriteId];
+ }
+ else
+ {
+ gWeatherPtr->sprites.s1.rainSprites[spriteNum] = NULL;
+ }
+
+ if (++gWeatherPtr->rainSpriteCount == 24)
+ {
+ u16 i;
+
+ for (i = 0; i < 24; i++)
+ {
+ if (gWeatherPtr->sprites.s1.rainSprites[i] != NULL)
+ {
+ if (gWeatherPtr->sprites.s1.rainSprites[i]->data[6] == 0)
+ gWeatherPtr->sprites.s1.rainSprites[i]->callback = sub_807E5C0;
+ else
+ gWeatherPtr->sprites.s1.rainSprites[i]->callback = sub_807E6C4;
+ }
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool8 sub_807E8E8(void)
+{
+ if (gWeatherPtr->unknown_6D8 == gWeatherPtr->unknown_6D9)
+ return FALSE;
+
+ if (++gWeatherPtr->unknown_6D6 > gWeatherPtr->unknown_6DB)
+ {
+ gWeatherPtr->unknown_6D6 = 0;
+ if (gWeatherPtr->unknown_6D8 < gWeatherPtr->unknown_6D9)
+ {
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->unknown_6D8++]->data[5] = 1;
+ }
+ else
+ {
+ gWeatherPtr->unknown_6D8--;
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->unknown_6D8]->data[5] = 0;
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->unknown_6D8]->invisible = TRUE;
+ }
+ }
+ return TRUE;
+}
+
+void DestroyRainSprites(void)
+{
+ u16 i;
+
+ for (i = 0; i < gWeatherPtr->rainSpriteCount; i++)
+ {
+ if (gWeatherPtr->sprites.s1.rainSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s1.rainSprites[i]);
+ }
+ gWeatherPtr->rainSpriteCount = 0;
+ FreeSpriteTilesByTag(0x1206);
+}
+
+//------------------------------------------------------------------------------
+// Snow
+//------------------------------------------------------------------------------
+
+void Snow_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->unknown_6E5 = 16;
+ gWeatherPtr->unknown_6E0 = 0;
+}
+
+void Snow_Main(void);
+void sub_807ED48(struct Sprite *);
+
+void Snow_InitAll(void)
+{
+ Snow_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ {
+ u16 i;
+
+ Snow_Main();
+ for (i = 0; i < gWeatherPtr->snowflakeSpriteCount; i++)
+ {
+ sub_807ED48(gWeatherPtr->sprites.s1.snowflakeSprites[i]);
+ }
+ }
+}
+
+u8 snowflakes_progress(void);
+
+void Snow_Main(void)
+{
+ if (gWeatherPtr->initStep == 0 && snowflakes_progress() == FALSE)
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+}
+
+bool8 Snow_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ gWeatherPtr->unknown_6E5 = 0;
+ gWeatherPtr->unknown_6E0 = 0;
+ gWeatherPtr->finishStep++;
+ // fall through
+ case 1:
+ if (snowflakes_progress() == FALSE)
+ {
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 CreateSnowflakeSprite(void);
+bool8 RemoveSnowflakeSprite(void);
+
+bool8 snowflakes_progress(void)
+{
+ if (gWeatherPtr->snowflakeSpriteCount == gWeatherPtr->unknown_6E5)
+ return FALSE;
+
+ gWeatherPtr->unknown_6E0++;
+ if (gWeatherPtr->unknown_6E0 > 36)
+ {
+ gWeatherPtr->unknown_6E0 = 0;
+ if (gWeatherPtr->snowflakeSpriteCount < gWeatherPtr->unknown_6E5)
+ CreateSnowflakeSprite();
+ else
+ RemoveSnowflakeSprite();
+ }
+ return (gWeatherPtr->snowflakeSpriteCount != gWeatherPtr->unknown_6E5);
+}
+
+void sub_807EC40(struct Sprite *);
+
+bool8 CreateSnowflakeSprite(void)
+{
+ u8 spriteId = CreateSpriteAtEnd(&sSnowflakeSpriteTemplate, 0, 0, 78);
+
+ if (spriteId == MAX_SPRITES)
+ return FALSE;
+ gSprites[spriteId].data[4] = gWeatherPtr->snowflakeSpriteCount;
+ sub_807EC40(&gSprites[spriteId]);
+ gSprites[spriteId].coordOffsetEnabled = TRUE;
+ gWeatherPtr->sprites.s1.snowflakeSprites[gWeatherPtr->snowflakeSpriteCount++] = &gSprites[spriteId];
+ return TRUE;
+}
+
+bool8 RemoveSnowflakeSprite(void)
+{
+ if (gWeatherPtr->snowflakeSpriteCount != 0)
+ {
+ DestroySprite(gWeatherPtr->sprites.s1.snowflakeSprites[--gWeatherPtr->snowflakeSpriteCount]);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_807EC40(struct Sprite *sprite)
+{
+ u16 r4 = ((sprite->data[4] * 5) & 7) * 30 + (Random() % 30);
+ u16 r6;
+
+ sprite->pos1.y = -3 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->pos1.x = r4 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+ sprite->data[0] = sprite->pos1.y * 128;
+ sprite->pos2.x = 0;
+ r6 = Random();
+ sprite->data[1] = (r6 & 3) * 5 + 64;
+ sprite->data[7] = (r6 & 3) * 5 + 64;
+ StartSpriteAnim(sprite, (r6 & 1) ? 0 : 1);
+ sprite->data[3] = 0;
+ sprite->data[2] = ((r6 & 3) == 0) ? 2 : 1;
+ sprite->data[6] = (r6 & 0x1F) + 210;
+ sprite->data[5] = 0;
+}
+
+void sub_807ECEC(struct Sprite *sprite)
+{
+ if (gWeatherPtr->unknown_6E2 > 18)
+ {
+ sprite->invisible = FALSE;
+ sprite->callback = sub_807ED48;
+ sprite->pos1.y = 0xFA - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->data[0] = sprite->pos1.y * 128;
+ gWeatherPtr->unknown_6E2 = 0;
+ }
+}
+
+void sub_807ED48(struct Sprite *sprite)
+{
+ s16 r3;
+ s16 r2;
+
+ sprite->data[0] += sprite->data[1];
+ sprite->pos1.y = sprite->data[0] >> 7;
+ sprite->data[3] = (sprite->data[3] + sprite->data[2]) & 0xFF;
+ sprite->pos2.x = gSineTable[sprite->data[3]] / 64;
+
+ r3 = (sprite->pos1.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX) & 0x1FF;
+ if (r3 & 0x100)
+ r3 |= -0x100; // hmm... what is this?
+ if (r3 < -3)
+ sprite->pos1.x = 242 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+ else if (r3 > 242)
+ sprite->pos1.x = -3 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+
+ r2 = (sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY) & 0xFF;
+ if (r2 > 163 && r2 < 171)
+ {
+ sprite->pos1.y = 250 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->data[0] = sprite->pos1.y * 128;
+ sprite->data[5] = 0;
+ sprite->data[6] = 220;
+ }
+ else if (r2 > 242 && r2 < 250)
+ {
+ sprite->pos1.y = 163;
+ sprite->data[0] = sprite->pos1.y * 128;
+ sprite->data[5] = 0;
+ sprite->data[6] = 220;
+ sprite->invisible = TRUE;
+ sprite->callback = sub_807ECEC;
+ }
+
+ sprite->data[5]++;
+ if (sprite->data[5] == sprite->data[6])
+ {
+ sub_807EC40(sprite);
+ sprite->pos1.y = 250;
+ sprite->invisible = TRUE;
+ sprite->callback = sub_807ECEC;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Medium Rain
+//------------------------------------------------------------------------------
+
+void MedRain_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->unknown_6D6 = 0;
+ gWeatherPtr->unknown_6DB = 4;
+ gWeatherPtr->unknown_6DC = 0;
+ gWeatherPtr->unknown_6D9 = 16;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE; // duplicate assignment
+ gWeatherPtr->unknown_6ED = 0;
+ SetRainStrengthFromSoundEffect(SE_T_AME);
+}
+
+void Rain_Main(void);
+
+void MedRain_InitAll(void)
+{
+ MedRain_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Rain_Main();
+}
+
+//------------------------------------------------------------------------------
+// Heavy Rain
+//------------------------------------------------------------------------------
+
+void HeavyRain_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->unknown_6D6 = 0;
+ gWeatherPtr->unknown_6DB = 4;
+ gWeatherPtr->unknown_6DC = 1;
+ gWeatherPtr->unknown_6D9 = 24;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE; // duplicate assignment
+ SetRainStrengthFromSoundEffect(SE_T_OOAME);
+}
+
+void HeavyRain_InitAll(void)
+{
+ HeavyRain_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Rain_Main();
+}
+
+void UpdateThunderSound(void);
+void SetThunderCounter(u16);
+
+void Rain_Main(void)
+{
+ UpdateThunderSound();
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ LoadRainSpriteSheet();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (CreateRainSprite())
+ break;
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (sub_807E8E8())
+ break;
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ break;
+ case 3:
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_CHANGING_WEATHER)
+ break;
+ gWeatherPtr->initStep = 6;
+ break;
+ case 4:
+ gWeatherPtr->unknown_6EA = 1;
+ gWeatherPtr->unknown_6E6 = (Random() % 360) + 360;
+ gWeatherPtr->initStep++;
+ // fall through
+ case 5:
+ if (--gWeatherPtr->unknown_6E6 != 0)
+ break;
+ gWeatherPtr->initStep++;
+ break;
+ case 6:
+ gWeatherPtr->unknown_6EA = 1;
+ gWeatherPtr->unknown_6EB = Random() % 2;
+ gWeatherPtr->initStep++;
+ break;
+ case 7:
+ gWeatherPtr->unknown_6EC = (Random() & 1) + 1;
+ gWeatherPtr->initStep++;
+ // fall through
+ case 8:
+ sub_80ABC48(19);
+ if (gWeatherPtr->unknown_6EB == 0 && gWeatherPtr->unknown_6EC == 1)
+ SetThunderCounter(20);
+ gWeatherPtr->unknown_6E6 = (Random() % 3) + 6;
+ gWeatherPtr->initStep++;
+ break;
+ case 9:
+ if (--gWeatherPtr->unknown_6E6 != 0)
+ break;
+ sub_80ABC48(3);
+ gWeatherPtr->unknown_6EA = 1;
+ if (--gWeatherPtr->unknown_6EC != 0)
+ {
+ gWeatherPtr->unknown_6E6 = (Random() % 16) + 60;
+ gWeatherPtr->initStep = 10;
+ }
+ else if (gWeatherPtr->unknown_6EB == 0)
+ {
+ gWeatherPtr->initStep = 4;
+ }
+ else
+ {
+ gWeatherPtr->initStep = 11;
+ }
+ break;
+ case 10:
+ if (--gWeatherPtr->unknown_6E6 != 0)
+ break;
+ gWeatherPtr->initStep = 8;
+ break;
+ case 11:
+ gWeatherPtr->unknown_6E6 = (Random() % 16) + 60;
+ gWeatherPtr->initStep++;
+ break;
+ case 12:
+ if (--gWeatherPtr->unknown_6E6 != 0)
+ break;
+ SetThunderCounter(100);
+ sub_80ABC48(19);
+ // Why use "% 16" everywhere else and "& 0xF" here. So dumb.
+ gWeatherPtr->unknown_6E6 = (Random() & 0xF) + 30;
+ gWeatherPtr->initStep++;
+ break;
+ case 13:
+ if (--gWeatherPtr->unknown_6E6 != 0)
+ break;
+ sub_80ABC7C(19, 3, 5);
+ gWeatherPtr->initStep++;
+ break;
+ case 14:
+ if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_IDLE)
+ break;
+ gWeatherPtr->unknown_6EA = 1;
+ gWeatherPtr->initStep = 4;
+ break;
+ }
+}
+
+bool8 Rain_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ gWeatherPtr->unknown_6EA = 0;
+ gWeatherPtr->finishStep++;
+ // fall through
+ case 1:
+ Rain_Main();
+ if (gWeatherPtr->unknown_6EA != 0)
+ {
+ if (gWeatherPtr->nextWeather == WEATHER_RAIN_LIGHT
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_MED
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_HEAVY)
+ return FALSE;
+ gWeatherPtr->unknown_6D9 = 0;
+ gWeatherPtr->finishStep++;
+ }
+ break;
+ case 2:
+ if (sub_807E8E8())
+ break;
+ DestroyRainSprites();
+ gWeatherPtr->unknown_6ED = 0;
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void SetThunderCounter(u16 max)
+{
+ if (gWeatherPtr->unknown_6ED == 0)
+ {
+ gWeatherPtr->thunderCounter = Random() % max;
+ gWeatherPtr->unknown_6ED = 1;
+ }
+}
+
+void UpdateThunderSound(void)
+{
+ if (gWeatherPtr->unknown_6ED == 1)
+ {
+ if (gWeatherPtr->thunderCounter == 0)
+ {
+ if (IsSEPlaying())
+ return;
+ if (Random() & 1)
+ PlaySE(SE_T_KAMI);
+ else
+ PlaySE(SE_T_KAMI2);
+ gWeatherPtr->unknown_6ED = 0;
+ }
+ else
+ {
+ gWeatherPtr->thunderCounter--;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Fog 1
+//------------------------------------------------------------------------------
+
+void Fog1_Main(void);
+static void CreateFog1Sprites(void);
+static void DestroyFog1Sprites(void);
+
+void Fog1_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ if (gWeatherPtr->fog1SpritesCreated == 0)
+ {
+ gWeatherPtr->unknown_6F0 = 0;
+ gWeatherPtr->unknown_6F2 = 0;
+ gWeatherPtr->fog1ScrollPosX = 0;
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void Fog1_InitAll(void)
+{
+ Fog1_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Fog1_Main();
+}
+
+void Fog1_Main(void)
+{
+ gWeatherPtr->fog1ScrollPosX = (gSpriteCoordOffsetX - gWeatherPtr->unknown_6F2) & 0xFF;
+ if (++gWeatherPtr->unknown_6F0 > 3)
+ {
+ gWeatherPtr->unknown_6F0 = 0;
+ gWeatherPtr->unknown_6F2++;
+ }
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateFog1Sprites();
+ if (gWeatherPtr->currWeather == WEATHER_FOG_1)
+ Weather_SetTargetBlendCoeffs(12, 8, 3);
+ else
+ Weather_SetTargetBlendCoeffs(4, 16, 0);
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (Weather_UpdateBlend())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ }
+}
+
+bool8 Fog1_Finish(void)
+{
+ gWeatherPtr->fog1ScrollPosX = (gSpriteCoordOffsetX - gWeatherPtr->unknown_6F2) & 0xFF;
+ if (++gWeatherPtr->unknown_6F0 > 3)
+ {
+ gWeatherPtr->unknown_6F0 = 0;
+ gWeatherPtr->unknown_6F2++;
+ }
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 3);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ DestroyFog1Sprites();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#define sprColumn data[0]
+
+static void Fog1SpriteCallback(struct Sprite *sprite)
+{
+ sprite->pos2.y = (u8)gSpriteCoordOffsetY;
+ sprite->pos1.x = gWeatherPtr->fog1ScrollPosX + 32 + sprite->sprColumn * 64;
+ if (sprite->pos1.x > 0x10F)
+ {
+ sprite->pos1.x = 480 + gWeatherPtr->fog1ScrollPosX - (4 - sprite->sprColumn) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+static void CreateFog1Sprites(void)
+{
+ u16 i;
+
+ if (!gWeatherPtr->fog1SpritesCreated)
+ {
+ struct SpriteSheet fog1SpriteSheet = {gWeatherFog1Tiles, sizeof(gWeatherFog1Tiles), 0x1201};
+
+ LoadSpriteSheet(&fog1SpriteSheet);
+ for (i = 0; i < 20; i++)
+ {
+ u8 spriteId = CreateSpriteAtEnd(&sFog1SpriteTemplate, 0, 0, 0xFF);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ struct Sprite *sprite = &gSprites[spriteId];
+
+ sprite->sprColumn = i % 5;
+ sprite->pos1.x = (i % 5) * 64 + 32;
+ sprite->pos1.y = (i / 5) * 64 + 32;
+ gWeatherPtr->sprites.s2.fog1Sprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.fog1Sprites[i] = NULL;
+ }
+ }
+ gWeatherPtr->fog1SpritesCreated = TRUE;
+ }
+}
+
+#undef sprColumn
+
+static void DestroyFog1Sprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->fog1SpritesCreated)
+ {
+ for (i = 0; i < 20; i++)
+ {
+ if (gWeatherPtr->sprites.s2.fog1Sprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.fog1Sprites[i]);
+ }
+ FreeSpriteTilesByTag(0x1201);
+ gWeatherPtr->fog1SpritesCreated = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Volcanic ash
+//------------------------------------------------------------------------------
+
+void Ash_Main(void);
+void LoadAshSpriteSheet(void);
+void CreateAshSprites(void);
+void DestroyAshSprites(void);
+
+void Ash_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->unknown_6FE = 20;
+ if (!gWeatherPtr->ashSpritesCreated)
+ {
+ Weather_SetBlendCoeffs(0, 16);
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(64, 63)); // Those aren't even valid coefficients!
+ }
+}
+
+void Ash_InitAll(void)
+{
+ Ash_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Ash_Main();
+}
+
+void Ash_Main(void)
+{
+ gWeatherPtr->unknown_6FC = gSpriteCoordOffsetX & 0x1FF;
+ while (gWeatherPtr->unknown_6FC > 0xEF)
+ gWeatherPtr->unknown_6FC -= 0xF0;
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ LoadAshSpriteSheet();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (!gWeatherPtr->ashSpritesCreated)
+ CreateAshSprites();
+ Weather_SetTargetBlendCoeffs(16, 0, 1);
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ break;
+ default:
+ Weather_UpdateBlend();
+ break;
+ }
+}
+
+bool8 Ash_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 1);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (!Weather_UpdateBlend())
+ break;
+ DestroyAshSprites();
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static const struct SpriteSheet sAshSpriteSheet = {gWeatherAshTiles, sizeof(gWeatherAshTiles), 0x1202};
+
+void LoadAshSpriteSheet(void)
+{
+ LoadSpriteSheet(&sAshSpriteSheet);
+}
+
+const struct OamData gOamData_839ABB8 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 1,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 15,
+ .affineParam = 0,
+};
+
+const union AnimCmd gSpriteAnim_839ABC0[] =
+{
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(64, 60),
+ ANIMCMD_JUMP(0),
+};
+
+const union AnimCmd *const gSpriteAnimTable_839ABCC[] =
+{
+ gSpriteAnim_839ABC0,
+};
+
+void sub_807FAA8(struct Sprite *);
+static const struct SpriteTemplate sAshSpriteTemplate =
+{
+ .tileTag = 4610,
+ .paletteTag = 4608,
+ .oam = &gOamData_839ABB8,
+ .anims = gSpriteAnimTable_839ABCC,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_807FAA8,
+};
+
+void CreateAshSprites(void)
+{
+ u8 i;
+
+ if (!gWeatherPtr->ashSpritesCreated)
+ {
+ for (i = 0; i < 20; i++)
+ {
+ u8 spriteId = CreateSpriteAtEnd(&sAshSpriteTemplate, 0, 0, 0x4E);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ struct Sprite *sprite = &gSprites[spriteId];
+
+ sprite->data[1] = 0;
+ sprite->data[2] = (u8)(i % 5);
+ sprite->data[3] = (u8)(i / 5);
+ sprite->data[0] = sprite->data[3] * 64 + 32;
+ gWeatherPtr->sprites.s2.ashSprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.ashSprites[i] = NULL;
+ }
+ }
+ gWeatherPtr->ashSpritesCreated = TRUE;
+ }
+}
+
+void DestroyAshSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->ashSpritesCreated)
+ {
+ for (i = 0; i < 20; i++)
+ {
+ if (gWeatherPtr->sprites.s2.ashSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.ashSprites[i]);
+ }
+ FreeSpriteTilesByTag(0x1202);
+ gWeatherPtr->ashSpritesCreated = FALSE;
+ }
+}
+
+void sub_807FAA8(struct Sprite *sprite)
+{
+ sprite->data[1]++;
+ if (sprite->data[1] > 5)
+ {
+ sprite->data[1] = 0;
+ sprite->data[0]++;
+ }
+ sprite->pos1.y = gSpriteCoordOffsetY + sprite->data[0];
+ sprite->pos1.x = gWeatherPtr->unknown_6FC + 32 + sprite->data[2] * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->unknown_6FC + 0x1E0 - (4 - sprite->data[2]) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Fog 2
+//------------------------------------------------------------------------------
+
+void Fog2_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = 0;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->unknown_6F0 = 0;
+ gWeatherPtr->unknown_6F2 = 1;
+ if (gWeatherPtr->fog2SpritesCreated == 0)
+ {
+ gWeatherPtr->unknown_71C = 0;
+ gWeatherPtr->unknown_71E = 0;
+ gWeatherPtr->unknown_720 = 0;
+ gWeatherPtr->unknown_722 = 0;
+ gWeatherPtr->unknown_718 = 0;
+ gWeatherPtr->unknown_71A = 0;
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void Fog2_Main(void);
+
+void Fog2_InitAll(void)
+{
+ Fog2_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Fog2_Main();
+}
+
+void sub_807FC9C(void);
+void CreateFog2Sprites(void);
+
+void Fog2_Main(void)
+{
+ sub_807FC9C();
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateFog2Sprites();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ Weather_SetTargetBlendCoeffs(12, 8, 8);
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ break;
+ }
+}
+
+void DestroyFog2Sprites(void);
+
+bool8 Fog2_Finish(void)
+{
+ sub_807FC9C();
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 1);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ DestroyFog2Sprites();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void sub_807FC9C(void)
+{
+ if (++gWeatherPtr->unknown_71C > 2)
+ {
+ gWeatherPtr->unknown_720++;
+ gWeatherPtr->unknown_71C = 0;
+ }
+
+ if (++gWeatherPtr->unknown_71E > 4)
+ {
+ gWeatherPtr->unknown_722++;
+ gWeatherPtr->unknown_71E = 0;
+ }
+
+ gWeatherPtr->unknown_718 = (gSpriteCoordOffsetX - gWeatherPtr->unknown_720) & 0xFF;
+ gWeatherPtr->unknown_71A = gSpriteCoordOffsetY + gWeatherPtr->unknown_722;
+}
+
+extern const struct SpriteTemplate sFog2SpriteTemplate; // defined below
+
+void CreateFog2Sprites(void)
+{
+ u16 i;
+
+ if (!gWeatherPtr->fog2SpritesCreated)
+ {
+ struct SpriteSheet fog2SpriteSheet = {gWeatherFog2Tiles, sizeof(gWeatherFog2Tiles), 0x1203};
+
+ LoadSpriteSheet(&fog2SpriteSheet);
+ for (i = 0; i < 20; i++)
+ {
+ u8 spriteId = CreateSpriteAtEnd(&sFog2SpriteTemplate, 0, (i / 5) * 64, 0xFF);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ struct Sprite *sprite = &gSprites[spriteId];
+
+ sprite->data[0] = i % 5;
+ sprite->data[1] = i / 5;
+ gWeatherPtr->sprites.s2.fog2Sprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.fog2Sprites[i] = NULL;
+ }
+ }
+ gWeatherPtr->fog2SpritesCreated = TRUE;
+ }
+}
+
+const struct OamData gOamData_839ABF0 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 1,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+const union AnimCmd gSpriteAnim_839ABF8[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_839AC00[] =
+{
+ gSpriteAnim_839ABF8,
+};
+
+void Fog2SpriteCallback(struct Sprite *);
+const struct SpriteTemplate sFog2SpriteTemplate =
+{
+ .tileTag = 4611,
+ .paletteTag = 4608,
+ .oam = &gOamData_839ABF0,
+ .anims = gSpriteAnimTable_839AC00,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = Fog2SpriteCallback,
+};
+
+void DestroyFog2Sprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->fog2SpritesCreated)
+ {
+ for (i = 0; i < 20; i++)
+ {
+ if (gWeatherPtr->sprites.s2.fog2Sprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.fog2Sprites[i]);
+ }
+ FreeSpriteTilesByTag(0x1203);
+ gWeatherPtr->fog2SpritesCreated = FALSE;
+ }
+}
+
+void Fog2SpriteCallback(struct Sprite *sprite)
+{
+ sprite->pos2.y = gWeatherPtr->unknown_71A;
+ sprite->pos1.x = gWeatherPtr->unknown_718 + 32 + sprite->data[0] * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->unknown_718 + 0x1E0 - (4 - sprite->data[0]) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Sandstorm
+//------------------------------------------------------------------------------
+
+void Sandstorm_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = 0;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ if (gWeatherPtr->sandstormSprites1Created == 0)
+ {
+ gWeatherPtr->unknown_704 = gWeatherPtr->unknown_708 = 0;
+ gWeatherPtr->unknown_712 = 8;
+ gWeatherPtr->unknown_714 = 0;
+ // Dead code. How does the compiler not optimize this out?
+ if (gWeatherPtr->unknown_712 > 0x5F)
+ gWeatherPtr->unknown_712 = 0x80 - gWeatherPtr->unknown_712;
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void Sandstorm_Main(void);
+
+void Sandstorm_InitAll(void)
+{
+ Sandstorm_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Sandstorm_Main();
+}
+
+void sub_808002C(void);
+void sub_8080064(void);
+void CreateSandstormSprites_1(void);
+void CreateSandstormSprites_2(void);
+
+void Sandstorm_Main(void)
+{
+ sub_8080064();
+ sub_808002C();
+ if (gWeatherPtr->unknown_712 > 0x5F)
+ gWeatherPtr->unknown_712 = 32;
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateSandstormSprites_1();
+ CreateSandstormSprites_2();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ Weather_SetTargetBlendCoeffs(16, 0, 0);
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ break;
+ }
+}
+
+void sub_80800E4(void);
+
+bool8 Sandstorm_Finish(void)
+{
+ sub_8080064();
+ sub_808002C();
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 0);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ sub_80800E4();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void sub_808002C(void)
+{
+ if (gWeatherPtr->unknown_714++ > 4)
+ {
+ gWeatherPtr->unknown_712++;
+ gWeatherPtr->unknown_714 = 0;
+ }
+}
+
+void sub_8080064(void)
+{
+ gWeatherPtr->unknown_704 -= gSineTable[gWeatherPtr->unknown_712] * 4;
+ gWeatherPtr->unknown_708 -= gSineTable[gWeatherPtr->unknown_712];
+ gWeatherPtr->unknown_70E = (gSpriteCoordOffsetX + (gWeatherPtr->unknown_704 >> 8)) & 0xFF;
+ gWeatherPtr->unknown_710 = gSpriteCoordOffsetY + (gWeatherPtr->unknown_708 >> 8);
+}
+
+void sub_80800E4(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->sandstormSprites1Created)
+ {
+ for (i = 0; i < 20; i++)
+ {
+ if (gWeatherPtr->sprites.s2.sandstormSprites1[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.sandstormSprites1[i]);
+ }
+ gWeatherPtr->sandstormSprites1Created = FALSE;
+ FreeSpriteTilesByTag(0x1204);
+ }
+
+ if (gWeatherPtr->sandstormSprites2Created)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ if (gWeatherPtr->sprites.s2.sandstormSprites2[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.sandstormSprites2[i]);
+ }
+ gWeatherPtr->sandstormSprites2Created = FALSE;
+ }
+}
+
+const struct OamData gOamData_839AC1C =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 1,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+const union AnimCmd gSpriteAnim_839AC24[] =
+{
+ ANIMCMD_FRAME(0, 3),
+ ANIMCMD_END,
+};
+
+const union AnimCmd gSpriteAnim_839AC2C[] =
+{
+ ANIMCMD_FRAME(64, 3),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_839AC34[] =
+{
+ gSpriteAnim_839AC24,
+ gSpriteAnim_839AC2C,
+};
+
+void SandstormSpriteCallback1(struct Sprite *);
+const struct SpriteTemplate sSandstormSpriteTemplate =
+{
+ .tileTag = 4612,
+ .paletteTag = 4609,
+ .oam = &gOamData_839AC1C,
+ .anims = gSpriteAnimTable_839AC34,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SandstormSpriteCallback1,
+};
+
+static const struct SpriteSheet sSandstormSpriteSheet = {gWeatherSandstormTiles, sizeof(gWeatherSandstormTiles), 0x1204};
+
+void CreateSandstormSprites_1(void)
+{
+ u16 i;
+
+ if (!gWeatherPtr->sandstormSprites1Created)
+ {
+ LoadSpriteSheet(&sSandstormSpriteSheet);
+ LoadCustomWeatherSpritePalette(gUnknown_0854C2B0);
+ for (i = 0; i < 20; i++)
+ {
+ u8 spriteId = CreateSpriteAtEnd(&sSandstormSpriteTemplate, 0, (i / 5) * 64, 1);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites1[i] = &gSprites[spriteId];
+ gWeatherPtr->sprites.s2.sandstormSprites1[i]->data[0] = i % 5;
+ gWeatherPtr->sprites.s2.sandstormSprites1[i]->data[1] = i / 5;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites1[i] = NULL;
+ }
+ }
+ gWeatherPtr->sandstormSprites1Created = TRUE;
+ }
+}
+
+const u16 gUnknown_0839AC5C[] = {0, 120, 80, 160, 40, 0};
+
+void SandstormSpriteCallback2(struct Sprite *);
+
+void CreateSandstormSprites_2(void)
+{
+ u16 i;
+
+ if (!gWeatherPtr->sandstormSprites2Created)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ u8 spriteId = CreateSpriteAtEnd(&sSandstormSpriteTemplate, i * 48 + 24, 208, 1);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites2[i] = &gSprites[spriteId];
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->oam.size = 2;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[1] = i * 51;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[0] = 8;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[2] = 0;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[4] = 0x6730;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[3] = gUnknown_0839AC5C[i];
+ StartSpriteAnim(gWeatherPtr->sprites.s2.sandstormSprites2[i], 1);
+ CalcCenterToCornerVec(gWeatherPtr->sprites.s2.sandstormSprites2[i], 0, 2, 0);
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->callback = SandstormSpriteCallback2;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites2[i] = NULL;
+ }
+ gWeatherPtr->sandstormSprites2Created = TRUE;
+ }
+ }
+}
+
+void SandstormSpriteCallback1(struct Sprite *sprite)
+{
+ sprite->pos2.y = gWeatherPtr->unknown_710;
+ sprite->pos1.x = gWeatherPtr->unknown_70E + 32 + sprite->data[0] * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->unknown_70E + 0x1E0 - (4 - sprite->data[0]) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+void SandstormSpriteCallback3(struct Sprite *);
+
+void SandstormSpriteCallback2(struct Sprite *sprite)
+{
+ if (--sprite->data[3] == -1)
+ sprite->callback = SandstormSpriteCallback3;
+}
+
+void SandstormSpriteCallback3(struct Sprite *sprite)
+{
+ u32 x;
+ u32 y;
+
+ if (--sprite->pos1.y < -48)
+ {
+ sprite->pos1.y = 208;
+ sprite->data[0] = 4;
+ }
+ x = sprite->data[0] * gSineTable[sprite->data[1]];
+ y = sprite->data[0] * gSineTable[sprite->data[1] + 64];
+ sprite->pos2.x = x >> 8;
+ sprite->pos2.y = y >> 8;
+ sprite->data[1] = (sprite->data[1] + 10) & 0xFF;
+ if (++sprite->data[2] > 8)
+ {
+ sprite->data[2] = 0;
+ sprite->data[0]++;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Shade
+//------------------------------------------------------------------------------
+
+void Shade_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+}
+
+void Shade_InitAll(void)
+{
+ Shade_InitVars();
+}
+
+void Shade_Main(void)
+{
+}
+
+bool8 Shade_Finish(void)
+{
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+// Weather 14
+//------------------------------------------------------------------------------
+
+const u8 gUnknown_0839AC68[] = {40, 90, 60, 90, 2, 60, 40, 30};
+
+const struct SpriteSheet gWeatherBubbleSpriteSheet = {gWeatherBubbleTiles, sizeof(gWeatherBubbleTiles), 0x1205};
+
+void Bubbles_InitVars(void)
+{
+ Fog1_InitVars();
+ if (gWeatherPtr->unknown_72E == 0)
+ {
+ LoadSpriteSheet(&gWeatherBubbleSpriteSheet);
+ gWeatherPtr->unknown_728 = 0;
+ gWeatherPtr->unknown_726 = gUnknown_0839AC68[0];
+ gWeatherPtr->unknown_72A = 0;
+ gWeatherPtr->unknown_72C = 0;
+ }
+}
+
+void Bubbles_Main(void);
+
+void Bubbles_InitAll(void)
+{
+ Bubbles_InitVars();
+ while (gWeatherPtr->weatherGfxLoaded == FALSE)
+ Bubbles_Main();
+}
+
+void sub_8080588(u16);
+
+void Bubbles_Main(void)
+{
+ Fog1_Main();
+ if (++gWeatherPtr->unknown_726 > gUnknown_0839AC68[gWeatherPtr->unknown_728])
+ {
+ gWeatherPtr->unknown_726 = 0;
+ if (++gWeatherPtr->unknown_728 > 7)
+ gWeatherPtr->unknown_728 = 0;
+ sub_8080588(gWeatherPtr->unknown_72A);
+ if (++gWeatherPtr->unknown_72A > 12)
+ gWeatherPtr->unknown_72A = 0;
+ }
+}
+
+void sub_8080610(void);
+
+bool8 Bubbles_Finish(void)
+{
+ if (!Fog1_Finish())
+ {
+ sub_8080610();
+ return FALSE;
+ }
+ return TRUE;
+}
+
+const s16 gUnknown_0839AC78[][2] =
+{
+ {120, 160},
+ {376, 160},
+ { 40, 140},
+ {296, 140},
+ {180, 130},
+ {436, 130},
+ { 60, 160},
+ {436, 160},
+ {220, 180},
+ {476, 180},
+ { 10, 90},
+ {266, 90},
+ {256, 160},
+};
+
+const union AnimCmd gSpriteAnim_839ACAC[] =
+{
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_FRAME(1, 16),
+ ANIMCMD_END,
+};
+
+const union AnimCmd *const gSpriteAnimTable_839ACB8[] =
+{
+ gSpriteAnim_839ACAC,
+};
+
+extern const struct OamData gUnknown_08524904;
+
+void unc_0807DAB4(struct Sprite *);
+const struct SpriteTemplate gSpriteTemplate_839ACBC =
+{
+ .tileTag = 4613,
+ .paletteTag = 4608,
+ .oam = &gUnknown_08524904,
+ .anims = gSpriteAnimTable_839ACB8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = unc_0807DAB4,
+};
+
+void sub_8080588(u16 a)
+{
+ s16 x = gUnknown_0839AC78[a][0];
+ s16 y = gUnknown_0839AC78[a][1] - gSpriteCoordOffsetY;
+ u8 spriteId = CreateSpriteAtEnd(
+ &gSpriteTemplate_839ACBC,
+ x,
+ y,
+ 0);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].oam.priority = 1;
+ gSprites[spriteId].coordOffsetEnabled = TRUE;
+ gSprites[spriteId].data[0] = 0;
+ gSprites[spriteId].data[1] = 0;
+ gSprites[spriteId].data[2] = 0;
+ gWeatherPtr->unknown_72C++;
+ }
+}
+
+void sub_8080610(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->unknown_72C != 0)
+ {
+ for (i = 0; i < 64; i++)
+ {
+ if (gSprites[i].template == &gSpriteTemplate_839ACBC)
+ DestroySprite(&gSprites[i]);
+ }
+ FreeSpriteTilesByTag(0x1205);
+ gWeatherPtr->unknown_72C = 0;
+ }
+}
+
+void unc_0807DAB4(struct Sprite *sprite)
+{
+ ++sprite->data[0];
+ if (++sprite->data[0] > 8) // double increment
+ {
+ sprite->data[0] = 0;
+ if (sprite->data[1] == 0)
+ {
+ if (++sprite->pos2.x > 4)
+ sprite->data[1] = 1;
+ }
+ else
+ {
+ if (--sprite->pos2.x <= 0)
+ sprite->data[1] = 0;
+ }
+ }
+ sprite->pos1.y -= 3;
+ if (++sprite->data[2] > 0x77)
+ DestroySprite(sprite);
+}
+
+//------------------------------------------------------------------------------
+
+static void sub_80AEC94(u32 a0, u32 a1)
+{
+ gUnknown_02038BC4 = a0;
+ gUnknown_02038BC6 = a1;
+}
+
+static void sub_80AECA8(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ if (data[15]-- <= 0)
+ {
+ ChangeWeather(data[1]);
+ gUnknown_02038BC4 = data[1];
+ data[15] = 600;
+ data[0]++;
+ }
+ break;
+ case 1:
+ if (data[15]-- <= 0)
+ {
+ ChangeWeather(data[2]);
+ gUnknown_02038BC4 = data[2];
+ data[15] = 600;
+ data[0] = 0;
+ }
+ break;
+ }
+}
+
+static void sub_80AED28(void)
+{
+ u8 taskId = CreateTask(sub_80AECA8, 0);
+ s16 *data = gTasks[taskId].data;
+
+ data[15] = 600;
+ if (gUnknown_02038BC4 == WEATHER_RAIN_HEAVY)
+ {
+ data[1] = WEATHER_DROUGHT;
+ data[2] = WEATHER_RAIN_HEAVY;
+ }
+ else if (gUnknown_02038BC4 == WEATHER_DROUGHT)
+ {
+ data[1] = WEATHER_RAIN_HEAVY;
+ data[2] = WEATHER_DROUGHT;
+ }
+ else
+ {
+ gUnknown_02038BC4 = WEATHER_RAIN_HEAVY;
+ data[1] = WEATHER_DROUGHT;
+ data[2] = WEATHER_RAIN_HEAVY;
+ }
+}
+
+static u8 TranslateWeatherNum(u8);
+static void UpdateRainCounter(u8, u8);
+
+void SetSav1Weather(u32 weather)
+{
+ u8 oldWeather = gSaveBlock1Ptr->weather;
+ gSaveBlock1Ptr->weather = TranslateWeatherNum(weather);
+ UpdateRainCounter(gSaveBlock1Ptr->weather, oldWeather);
+}
+
+u8 GetSav1Weather(void)
+{
+ return gSaveBlock1Ptr->weather;
+}
+
+void SetSav1WeatherFromCurrMapHeader(void)
+{
+ u8 oldWeather = gSaveBlock1Ptr->weather;
+ gSaveBlock1Ptr->weather = TranslateWeatherNum(gMapHeader.weather);
+ UpdateRainCounter(gSaveBlock1Ptr->weather, oldWeather);
+}
+
+void SetWeather(u32 weather)
+{
+ SetSav1Weather(weather);
+ ChangeWeather(GetSav1Weather());
+}
+
+void SetWeather_Unused(u32 weather)
+{
+ SetSav1Weather(weather);
+ sub_80AB104(GetSav1Weather());
+}
+
+void DoCurrentWeather(void)
+{
+ u8 weather = GetSav1Weather();
+
+ if (weather == WEATHER_15)
+ {
+ if (!FuncIsActiveTask(sub_80AECA8))
+ sub_80AED28();
+ weather = gUnknown_02038BC4;
+ }
+ else
+ {
+ if (FuncIsActiveTask(sub_80AECA8))
+ DestroyTask(FindTaskIdByFunc(sub_80AECA8));
+ gUnknown_02038BC4 = WEATHER_RAIN_HEAVY;
+ }
+ ChangeWeather(weather);
+}
+
+void sub_80AEE84(void)
+{
+ u8 weather = GetSav1Weather();
+
+ if (weather == WEATHER_15)
+ {
+ if (!FuncIsActiveTask(sub_80AECA8))
+ sub_80AED28();
+ weather = gUnknown_02038BC4;
+ }
+ else
+ {
+ if (FuncIsActiveTask(sub_80AECA8))
+ DestroyTask(FindTaskIdByFunc(sub_80AECA8));
+ gUnknown_02038BC4 = WEATHER_RAIN_HEAVY;
+ }
+ sub_80AB104(weather);
+}
+
+static const u8 sWeatherCycleRoute119[] =
+{
+ WEATHER_SUNNY,
+ WEATHER_RAIN_LIGHT,
+ WEATHER_RAIN_MED,
+ WEATHER_RAIN_LIGHT,
+};
+static const u8 sWeatherCycleRoute123[] =
+{
+ WEATHER_SUNNY,
+ WEATHER_SUNNY,
+ WEATHER_RAIN_LIGHT,
+ WEATHER_SUNNY,
+};
+
+static u8 TranslateWeatherNum(u8 weather)
+{
+ switch (weather)
+ {
+ case WEATHER_NONE: return WEATHER_NONE;
+ case WEATHER_CLOUDS: return WEATHER_CLOUDS;
+ case WEATHER_SUNNY: return WEATHER_SUNNY;
+ case WEATHER_RAIN_LIGHT: return WEATHER_RAIN_LIGHT;
+ case WEATHER_SNOW: return WEATHER_SNOW;
+ case WEATHER_RAIN_MED: return WEATHER_RAIN_MED;
+ case WEATHER_FOG_1: return WEATHER_FOG_1;
+ case WEATHER_ASH: return WEATHER_ASH;
+ case WEATHER_SANDSTORM: return WEATHER_SANDSTORM;
+ case WEATHER_FOG_2: return WEATHER_FOG_2;
+ case WEATHER_FOG_3: return WEATHER_FOG_3;
+ case WEATHER_SHADE: return WEATHER_SHADE;
+ case WEATHER_DROUGHT: return WEATHER_DROUGHT;
+ case WEATHER_RAIN_HEAVY: return WEATHER_RAIN_HEAVY;
+ case WEATHER_BUBBLES: return WEATHER_BUBBLES;
+ case WEATHER_15: return WEATHER_15;
+ case WEATHER_ROUTE119_CYCLE: return sWeatherCycleRoute119[gSaveBlock1Ptr->weatherCycleStage];
+ case WEATHER_ROUTE123_CYCLE: return sWeatherCycleRoute123[gSaveBlock1Ptr->weatherCycleStage];
+ default: return WEATHER_NONE;
+ }
+}
+
+void UpdateWeatherPerDay(u16 increment)
+{
+ u16 weatherStage = gSaveBlock1Ptr->weatherCycleStage + increment;
+ weatherStage %= 4;
+ gSaveBlock1Ptr->weatherCycleStage = weatherStage;
+}
+
+static void UpdateRainCounter(u8 newWeather, u8 oldWeather)
+{
+ if (newWeather != oldWeather
+ && (newWeather == WEATHER_RAIN_LIGHT || newWeather == WEATHER_RAIN_MED))
+ IncrementGameStat(GAME_STAT_GOT_RAINED_ON);
+}
diff --git a/src/fldeff_flash.c b/src/fldeff_flash.c
index 9771232f2..8862caa9f 100644
--- a/src/fldeff_flash.c
+++ b/src/fldeff_flash.c
@@ -170,7 +170,7 @@ static bool8 sub_8137304(void)
return FALSE;
}
-bool8 sub_8137360(u8 a1, u8 a2)
+bool8 GetMapPairFadeToType(u8 a1, u8 a2)
{
u8 i;
u8 v0 = a1;
@@ -187,7 +187,7 @@ bool8 sub_8137360(u8 a1, u8 a2)
return FALSE;
}
-bool8 fade_type_for_given_maplight_pair(u8 a1, u8 a2)
+bool8 GetMapPairFadeFromType(u8 a1, u8 a2)
{
u8 i;
u8 v0 = a1;
diff --git a/src/fldeff_sweetscent.c b/src/fldeff_sweetscent.c
index 9951fe581..cd8fa400d 100644
--- a/src/fldeff_sweetscent.c
+++ b/src/fldeff_sweetscent.c
@@ -3,7 +3,8 @@
#include "event_scripts.h"
#include "field_effect.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
+#include "field_weather.h"
#include "palette.h"
#include "party_menu.h"
#include "rom6.h"
@@ -40,7 +41,7 @@ bool8 FldEff_SweetScent(void)
{
u8 taskId;
- sub_80AC3D0();
+ SetWeatherScreenFadeOut();
taskId = oei_task_add();
gTasks[taskId].data[8] = (u32)StartSweetScentFieldEffect >> 16;
gTasks[taskId].data[9] = (u32)StartSweetScentFieldEffect;
diff --git a/src/item_use.c b/src/item_use.c
index 4ab9f6e23..8399a1861 100755
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -10,7 +10,7 @@
#include "fieldmap.h"
#include "event_object_movement.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "item.h"
#include "item_menu.h"
diff --git a/src/learn_move.c b/src/learn_move.c
index 4e02cedd3..4db83861e 100644
--- a/src/learn_move.c
+++ b/src/learn_move.c
@@ -5,7 +5,7 @@
#include "contest_effect.h"
#include "data2.h"
#include "event_data.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "gpu_regs.h"
#include "learn_move.h"
#include "list_menu.h"
@@ -52,7 +52,7 @@ static EWRAM_DATA struct {
const u16 gUnknown_085CE9F8[] = INCBIN_U16("graphics/interface/ui_learn_move.gbapal");
const u8 gUnknown_085CEA18[] = INCBIN_U8("graphics/interface/ui_learn_move.4bpp");
-const struct OamData gUnknown_085CEB98 =
+const struct OamData gUnknown_085CEB98 =
{
.y = 0,
.affineMode = 0,
@@ -69,7 +69,7 @@ const struct OamData gUnknown_085CEB98 =
.affineParam = 0,
};
-const struct OamData gUnknown_085CEBA0 =
+const struct OamData gUnknown_085CEBA0 =
{
.y = 0,
.affineMode = 0,
@@ -86,7 +86,7 @@ const struct OamData gUnknown_085CEBA0 =
.affineParam = 0,
};
-const struct OamData gUnknown_085CEBA8 =
+const struct OamData gUnknown_085CEBA8 =
{
.y = 0,
.affineMode = 0,
@@ -103,20 +103,20 @@ const struct OamData gUnknown_085CEBA8 =
.affineParam = 0,
};
-const struct SpriteSheet gUnknown_085CEBB0 =
+const struct SpriteSheet gUnknown_085CEBB0 =
{
.data = gUnknown_085CEA18,
.size = 0x180,
.tag = 5525
};
-const struct SpritePalette gUnknown_085CEBB8 =
+const struct SpritePalette gUnknown_085CEBB8 =
{
.data = gUnknown_085CE9F8,
.tag = 5526
};
-const struct ScrollArrowsTemplate gUnknown_085CEBC0 =
+const struct ScrollArrowsTemplate gUnknown_085CEBC0 =
{
.firstArrowType = 0,
.firstX = 27,
@@ -131,7 +131,7 @@ const struct ScrollArrowsTemplate gUnknown_085CEBC0 =
.palNum = 0,
};
-const struct ScrollArrowsTemplate gUnknown_085CEBD0 =
+const struct ScrollArrowsTemplate gUnknown_085CEBD0 =
{
.firstArrowType = 2,
.firstX = 192,
@@ -146,31 +146,31 @@ const struct ScrollArrowsTemplate gUnknown_085CEBD0 =
.palNum = 0,
};
-const union AnimCmd gUnknown_085CEBE0[] =
+const union AnimCmd gUnknown_085CEBE0[] =
{
ANIMCMD_FRAME(8, 5, FALSE, FALSE),
ANIMCMD_END
};
-const union AnimCmd gUnknown_085CEBE8[] =
+const union AnimCmd gUnknown_085CEBE8[] =
{
ANIMCMD_FRAME(9, 5, FALSE, FALSE),
ANIMCMD_END
};
-const union AnimCmd gUnknown_085CEBF0[] =
+const union AnimCmd gUnknown_085CEBF0[] =
{
ANIMCMD_FRAME(10, 5, FALSE, FALSE),
ANIMCMD_END
};
-const union AnimCmd gUnknown_085CEBF8[] =
+const union AnimCmd gUnknown_085CEBF8[] =
{
ANIMCMD_FRAME(11, 5, FALSE, FALSE),
ANIMCMD_END
};
-const union AnimCmd *const gUnknown_085CEC00[] =
+const union AnimCmd *const gUnknown_085CEC00[] =
{
gUnknown_085CEBE0,
gUnknown_085CEBE8,
@@ -178,7 +178,7 @@ const union AnimCmd *const gUnknown_085CEC00[] =
gUnknown_085CEBF8,
};
-const struct SpriteTemplate gUnknown_085CEC10 =
+const struct SpriteTemplate gUnknown_085CEC10 =
{
.tileTag = 5525,
.paletteTag = 5526,
@@ -707,7 +707,7 @@ static void CreateHearts(void)
sLearnMoveStruct->scrollArrowTaskId2 = -1;
sLearnMoveStruct->scrollArrowTaskId1 = -1;
AddScrollArrows();
-
+
for (i = 0; i < 8; i++)
{
sLearnMoveStruct->spriteIds[i] = CreateSprite(&gUnknown_085CEC10, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 36, 0);
@@ -791,7 +791,7 @@ void ShowHideHearts(s32 item)
else
{
numHearts = (u8)(gContestEffects[gContestMoves[item].effect].appeal / 10);
-
+
if (numHearts == 0xFF)
{
numHearts = 0;
@@ -811,7 +811,7 @@ void ShowHideHearts(s32 item)
}
numHearts = (u8)(gContestEffects[gContestMoves[item].effect].jam / 10);
-
+
if (numHearts == 0xFF)
{
numHearts = 0;
diff --git a/src/overworld.c b/src/overworld.c
index 12e02a9b5..417c52a9e 100644
--- a/src/overworld.c
+++ b/src/overworld.c
@@ -4,18 +4,17 @@
#include "battle_setup.h"
#include "berry.h"
#include "bg.h"
-// #include "cable_club.h"
+#include "cable_club.h"
#include "clock.h"
#include "event_data.h"
#include "field_camera.h"
#include "field_control_avatar.h"
#include "field_effect.h"
-#include "field_fadetransition.h"
#include "event_object_movement.h"
#include "field_message_box.h"
#include "field_player_avatar.h"
#include "field_screen_effect.h"
-// #include "field_special_scene.h"
+#include "field_special_scene.h"
#include "field_specials.h"
#include "field_tasks.h"
#include "field_weather.h"
@@ -38,7 +37,7 @@
#include "play_time.h"
#include "random.h"
#include "roamer.h"
-// #include "rotating_gate.h"
+#include "rotating_gate.h"
#include "safari_zone.h"
#include "save.h"
#include "save_location.h"
@@ -129,7 +128,7 @@ extern void sub_80A0A38(void);
extern void trainer_hill_map_load_related(void);
extern void sub_8087D74(void);
extern void battle_pyramid_map_load_related(u8);
-extern void sub_80B00E8(u8);
+extern void WriteFlashScanlineEffectBuffer(u8);
extern void sub_80E9238(u8);
extern void sub_81AA2F8(void);
extern void sub_8195E10(void);
@@ -148,7 +147,7 @@ extern void ResetAllPicSprites(void);
extern void FieldEffectActiveListClear(void);
extern void SetUpFieldTasks(void);
extern void sub_81BE6B8(void);
-extern void sub_80AAFA4(void);
+extern void StartWeather(void);
extern void ShowStartMenu(void);
extern void sub_80AEE84(void);
extern void mapldr_default(void);
@@ -1277,7 +1276,7 @@ u8 GetMapMusicFadeoutSpeed(void)
return 4;
}
-void music_something(void)
+void TryFadeOutOldMapMusic(void)
{
u16 currentMusic = GetCurrentMapMusic();
u16 warpMusic = GetWarpDestinationMusic();
@@ -1855,7 +1854,7 @@ static void InitCurrentFlashLevelScanlineEffect(void)
}
else if ((flashLevel = Overworld_GetFlashLevel()))
{
- sub_80B00E8(flashLevel);
+ WriteFlashScanlineEffectBuffer(flashLevel);
ScanlineEffect_SetParams(sFlashEffectParams);
}
}
@@ -2196,7 +2195,7 @@ static void sub_8086988(u32 a1)
InitEventObjectPalettes(1);
FieldEffectActiveListClear();
- sub_80AAFA4();
+ StartWeather();
sub_80AEE84();
if (!a1)
SetUpFieldTasks();
diff --git a/src/player_pc.c b/src/player_pc.c
index f42d59147..c41dfa380 100644
--- a/src/player_pc.c
+++ b/src/player_pc.c
@@ -3,9 +3,8 @@
#include "bg.h"
#include "decoration.h"
#include "event_scripts.h"
-#include "field_fadetransition.h"
#include "event_object_movement.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "international_string_util.h"
#include "item.h"
diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c
index 465b97da2..ad56b1678 100644
--- a/src/pokemon_storage_system.c
+++ b/src/pokemon_storage_system.c
@@ -1,7 +1,7 @@
#include "global.h"
#include "bg.h"
#include "event_data.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "gpu_regs.h"
#include "international_string_util.h"
diff --git a/src/record_mixing.c b/src/record_mixing.c
index 975b51386..d37883e4d 100644
--- a/src/record_mixing.c
+++ b/src/record_mixing.c
@@ -22,7 +22,7 @@
#include "constants/songs.h"
#include "menu.h"
#include "overworld.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "fldeff_80F9BCC.h"
#include "script.h"
#include "event_data.h"
diff --git a/src/rom_8011DC0.c b/src/rom_8011DC0.c
index 0553b9cf4..deec55c9d 100644
--- a/src/rom_8011DC0.c
+++ b/src/rom_8011DC0.c
@@ -32,7 +32,7 @@
#include "decompress.h"
#include "start_menu.h"
#include "data2.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
extern void HealPlayerParty(void);
diff --git a/src/scrcmd.c b/src/scrcmd.c
index f486b93a6..e699bfeab 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -13,7 +13,6 @@
#include "event_data.h"
#include "field_door.h"
#include "field_effect.h"
-#include "field_fadetransition.h"
#include "event_object_movement.h"
#include "field_message_box.h"
#include "field_player_avatar.h"
diff --git a/src/secret_base.c b/src/secret_base.c
index 4bf1709d2..9b5685d8b 100644
--- a/src/secret_base.c
+++ b/src/secret_base.c
@@ -1,5 +1,3 @@
-
-// Includes
#include "global.h"
#include "constants/bg_event_constants.h"
#include "constants/decorations.h"
@@ -19,7 +17,7 @@
#include "fieldmap.h"
#include "field_camera.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "event_object_movement.h"
#include "field_effect.h"
diff --git a/src/shop.c b/src/shop.c
index b08d94545..c44cbca12 100755
--- a/src/shop.c
+++ b/src/shop.c
@@ -6,7 +6,7 @@
#include "decoration_inventory.h"
#include "event_object_movement.h"
#include "field_player_avatar.h"
-#include "field_screen.h"
+#include "field_screen_effect.h"
#include "field_weather.h"
#include "fieldmap.h"
#include "gpu_regs.h"
diff --git a/src/start_menu.c b/src/start_menu.c
index 079f05be0..0e52f05fb 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -88,7 +88,7 @@ extern void sub_80AF688(void);
extern void var_800D_set_xB(void);
extern void sub_808B864(void);
extern void CB2_Pokedex(void);
-extern void play_some_sound(void);
+extern void PlayRainSoundEffect(void);
extern void CB2_PartyMenuFromStartMenu(void);
extern void CB2_PokeNav(void);
extern void sub_80C4DDC(void (*)(void));
@@ -621,7 +621,7 @@ static bool8 StartMenuPokedexCallback(void)
if (!gPaletteFade.active)
{
IncrementGameStat(GAME_STAT_CHECKED_POKEDEX);
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_Pokedex);
@@ -636,7 +636,7 @@ static bool8 StartMenuPokemonCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_PartyMenuFromStartMenu); // Display party menu
@@ -651,7 +651,7 @@ static bool8 StartMenuBagCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_BagMenuFromStartMenu); // Display bag menu
@@ -666,7 +666,7 @@ static bool8 StartMenuPokeNavCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_PokeNav); // Display PokeNav
@@ -681,7 +681,7 @@ static bool8 StartMenuPlayerNameCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
@@ -720,7 +720,7 @@ static bool8 StartMenuOptionCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_InitOptionMenu); // Display option menu
@@ -753,7 +753,7 @@ static bool8 StartMenuLinkModePlayerNameCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
overworld_free_bg_tilemaps();
TrainerCard_ShowLinkCard(gUnknown_03005DB4, CB2_ReturnToFieldWithOpenMenu);
@@ -782,7 +782,7 @@ static bool8 StartMenuBattlePyramidBagCallback(void)
{
if (!gPaletteFade.active)
{
- play_some_sound();
+ PlayRainSoundEffect();
RemoveExtraStartMenuWindows();
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_PyramidBagMenuFromStartMenu);