summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/berry_pouch.c2
-rw-r--r--src/bg.c20
-rw-r--r--src/box_party_pokemon_dropdown.c180
-rw-r--r--src/credits.c4
-rw-r--r--src/field_specials.c10
-rw-r--r--src/field_weather.c1169
-rw-r--r--src/field_weather_effects.c2320
-rw-r--r--src/field_weather_util.c105
-rw-r--r--src/graphics.c4
-rw-r--r--src/hall_of_fame.c8
-rw-r--r--src/ice.c4
-rw-r--r--src/item_menu.c2
-rw-r--r--src/item_pc.c8
-rw-r--r--src/naming_screen.c2
-rw-r--r--src/pc_screen_effect.c154
-rw-r--r--src/pokemon.c4
-rw-r--r--src/pokemon_storage_system.c172
-rw-r--r--src/pokemon_storage_system_2.c653
-rw-r--r--src/pokemon_storage_system_3.c2779
-rw-r--r--src/pokemon_storage_system_4.c1489
-rw-r--r--src/pokemon_storage_system_5.c2036
-rw-r--r--src/pokemon_storage_system_6.c147
-rw-r--r--src/pokemon_storage_system_7.c582
-rw-r--r--src/pokemon_storage_system_8.c755
-rw-r--r--src/pokemon_storage_system_9.c87
-rw-r--r--src/quest_log.c8
-rw-r--r--src/string_util.c6
-rw-r--r--src/strings.c160
-rw-r--r--src/title_screen.c16
-rw-r--r--src/tm_case.c2
-rw-r--r--src/trade.c14
-rw-r--r--src/window_8bpp.c4
32 files changed, 12620 insertions, 286 deletions
diff --git a/src/berry_pouch.c b/src/berry_pouch.c
index a0b2c03a3..01a94c075 100644
--- a/src/berry_pouch.c
+++ b/src/berry_pouch.c
@@ -1258,7 +1258,7 @@ static void Task_ContextMenu_FromPartyGiveMenu(u8 taskId)
static void Task_ContextMenu_FromPokemonPC(u8 taskId)
{
- sResources->exitCallback = sub_808CE60;
+ sResources->exitCallback = Cb2_ReturnToPSS;
gTasks[taskId].func = BerryPouch_StartFadeToExitCallback;
}
diff --git a/src/bg.c b/src/bg.c
index 4ad2bebd6..2acba9d26 100644
--- a/src/bg.c
+++ b/src/bg.c
@@ -553,21 +553,21 @@ u16 GetBgAttribute(u8 bg, u8 attributeId)
{
switch (attributeId)
{
- case 1:
+ case BG_ATTR_CHARBASEINDEX:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_CHARBASEINDEX);
- case 2:
+ case BG_ATTR_MAPBASEINDEX:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_MAPBASEINDEX);
- case 3:
+ case BG_ATTR_SCREENSIZE:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_SCREENSIZE);
- case 4:
+ case BG_ATTR_PALETTEMODE:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_PALETTEMODE);
- case 7:
+ case BG_ATTR_PRIORITY:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_PRIORITY);
- case 5:
+ case BG_ATTR_MOSAIC:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_MOSAIC);
- case 6:
+ case BG_ATTR_WRAPAROUND:
return GetBgControlAttribute(bg, BG_CTRL_ATTR_WRAPAROUND);
- case 8:
+ case BG_ATTR_TEXTORAFFINEMODE:
switch (GetBgType(bg))
{
case 0:
@@ -577,9 +577,9 @@ u16 GetBgAttribute(u8 bg, u8 attributeId)
default:
return 0;
}
- case 9:
+ case BG_ATTR_BGTYPE:
return GetBgType(bg);
- case 10:
+ case BG_ATTR_BASETILE:
return sGpuBgConfigs2[bg].baseTile;
default:
return -1;
diff --git a/src/box_party_pokemon_dropdown.c b/src/box_party_pokemon_dropdown.c
index a74f1611c..b194777f3 100644
--- a/src/box_party_pokemon_dropdown.c
+++ b/src/box_party_pokemon_dropdown.c
@@ -3,7 +3,7 @@
#include "box_party_pokemon_dropdown.h"
#include "malloc.h"
-struct UnkStruct_203ABE4_Sub
+struct BPPD_MapRect
{
s16 destX;
s16 destY;
@@ -13,27 +13,27 @@ struct UnkStruct_203ABE4_Sub
s16 destY2;
};
-struct UnkStruct_203ABE4
+struct BPPD_Struct
{
- struct UnkStruct_203ABE4_Sub map1Rect;
- struct UnkStruct_203ABE4_Sub map2Rect;
+ struct BPPD_MapRect map1Rect;
+ struct BPPD_MapRect map2Rect;
const void * src1;
const void * src2;
u16 src1Height;
u16 src1Width;
+ u16 src2Width;
u16 src2Height;
- u16 unk_26;
- u16 unk_28;
+ u16 bytesPerRow;
u8 mapSize;
u8 bgId;
bool8 bgUpdateScheduled;
};
-static EWRAM_DATA struct UnkStruct_203ABE4 * sBoxPartyPokemonDropdownPtr = NULL;
+static EWRAM_DATA struct BPPD_Struct * sBoxPartyPokemonDropdownPtr = NULL;
static EWRAM_DATA u16 sBoxPartyPokemonDropdownCount = 0;
-static void PushMap1(u8 a0);
-static void PushMap2(u8 a0);
+static void PushMap1(u8 idx);
+static void PushMap2(u8 idx);
static const struct {
u16 height;
@@ -52,10 +52,10 @@ static const struct {
}
};
-void sub_80F7AD8(u8 num)
+void AllocBoxPartyPokemonDropdowns(u8 num)
{
u16 i;
- sBoxPartyPokemonDropdownPtr = Alloc(num * sizeof(struct UnkStruct_203ABE4));
+ sBoxPartyPokemonDropdownPtr = Alloc(num * sizeof(struct BPPD_Struct));
sBoxPartyPokemonDropdownCount = sBoxPartyPokemonDropdownPtr == NULL ? 0 : num;
for (i = 0; i < sBoxPartyPokemonDropdownCount; i++)
{
@@ -64,149 +64,149 @@ void sub_80F7AD8(u8 num)
}
}
-void sub_80F7B2C(void)
+void FreeBoxPartyPokemonDropdowns(void)
{
Free(sBoxPartyPokemonDropdownPtr);
}
-void sub_80F7B40(void)
+void CopyAllBoxPartyPokemonDropdownsToVram(void)
{
int i;
for (i = 0; i < sBoxPartyPokemonDropdownCount; i++)
{
if (sBoxPartyPokemonDropdownPtr[i].bgUpdateScheduled == TRUE)
- sub_80F7E54(i);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(i);
}
}
-void sub_80F7B80(u8 a0, u8 a1, const void * a2, u16 a3, u16 a4)
+void SetBoxPartyPokemonDropdownMap2(u8 idx, u8 bgId, const void * src, u16 width, u16 height)
{
u16 screenSize;
u16 bgType;
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- sBoxPartyPokemonDropdownPtr[a0].src1 = NULL;
- sBoxPartyPokemonDropdownPtr[a0].src2 = a2;
- sBoxPartyPokemonDropdownPtr[a0].bgId = a1;
- sBoxPartyPokemonDropdownPtr[a0].src2Height = a3;
- sBoxPartyPokemonDropdownPtr[a0].unk_26 = a4;
- screenSize = GetBgAttribute(a1, BG_ATTR_SCREENSIZE);
- bgType = GetBgAttribute(a1, BG_ATTR_BGTYPE);
- sBoxPartyPokemonDropdownPtr[a0].src1Height = sBGdims[bgType][screenSize].height;
- sBoxPartyPokemonDropdownPtr[a0].src1Width = sBGdims[bgType][screenSize].width;
+ sBoxPartyPokemonDropdownPtr[idx].src1 = NULL;
+ sBoxPartyPokemonDropdownPtr[idx].src2 = src;
+ sBoxPartyPokemonDropdownPtr[idx].bgId = bgId;
+ sBoxPartyPokemonDropdownPtr[idx].src2Width = width;
+ sBoxPartyPokemonDropdownPtr[idx].src2Height = height;
+ screenSize = GetBgAttribute(bgId, BG_ATTR_SCREENSIZE);
+ bgType = GetBgAttribute(bgId, BG_ATTR_BGTYPE);
+ sBoxPartyPokemonDropdownPtr[idx].src1Height = sBGdims[bgType][screenSize].height;
+ sBoxPartyPokemonDropdownPtr[idx].src1Width = sBGdims[bgType][screenSize].width;
if (bgType != 0)
- sBoxPartyPokemonDropdownPtr[a0].mapSize = 1;
+ sBoxPartyPokemonDropdownPtr[idx].mapSize = 1;
else
- sBoxPartyPokemonDropdownPtr[a0].mapSize = 2;
- sBoxPartyPokemonDropdownPtr[a0].unk_28 = a3 * sBoxPartyPokemonDropdownPtr[a0].mapSize;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.width = a3;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.height = a4;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX = 0;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY = 0;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX2 = 0;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY2 = 0;
- sBoxPartyPokemonDropdownPtr[a0].map1Rect = sBoxPartyPokemonDropdownPtr[a0].map2Rect;
- sBoxPartyPokemonDropdownPtr[a0].bgUpdateScheduled = TRUE;
+ sBoxPartyPokemonDropdownPtr[idx].mapSize = 2;
+ sBoxPartyPokemonDropdownPtr[idx].bytesPerRow = width * sBoxPartyPokemonDropdownPtr[idx].mapSize;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.width = width;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.height = height;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX = 0;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY = 0;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX2 = 0;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY2 = 0;
+ sBoxPartyPokemonDropdownPtr[idx].map1Rect = sBoxPartyPokemonDropdownPtr[idx].map2Rect;
+ sBoxPartyPokemonDropdownPtr[idx].bgUpdateScheduled = TRUE;
}
}
-void sub_80F7C7C(u8 a0, const void * a1)
+void SetBoxPartyPokemonDropdownMap1Tiles(u8 idx, const void * src)
{
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- sBoxPartyPokemonDropdownPtr[a0].src1 = a1;
- sBoxPartyPokemonDropdownPtr[a0].bgUpdateScheduled = TRUE;
+ sBoxPartyPokemonDropdownPtr[idx].src1 = src;
+ sBoxPartyPokemonDropdownPtr[idx].bgUpdateScheduled = TRUE;
}
}
-void sub_80F7CAC(u8 a0, u16 a1, u16 a2)
+void SetBoxPartyPokemonDropdownMap2Pos(u8 idx, u16 x, u16 y)
{
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX2 = a1;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY2 = a2;
- sBoxPartyPokemonDropdownPtr[a0].bgUpdateScheduled = TRUE;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX2 = x;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY2 = y;
+ sBoxPartyPokemonDropdownPtr[idx].bgUpdateScheduled = TRUE;
}
}
-void sub_80F7CE8(u8 a0, u16 a1, u16 a2, u16 a3, u16 a4)
+void SetBoxPartyPokemonDropdownMap2Rect(u8 idx, u16 x, u16 y, u16 width, u16 height)
{
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX = a1;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY = a2;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.width = a3;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.height = a4;
- sBoxPartyPokemonDropdownPtr[a0].bgUpdateScheduled = TRUE;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX = x;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY = y;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.width = width;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.height = height;
+ sBoxPartyPokemonDropdownPtr[idx].bgUpdateScheduled = TRUE;
}
}
-void sub_80F7D30(u8 a0, u8 a1, s8 a2)
+void AdjustBoxPartyPokemonDropdownPos(u8 idx, u8 op, s8 param)
{
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- switch (a1)
+ switch (op)
{
- case 0:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX2 += a2;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.width -= a2;
+ case BPPD_MOVE_INNER_LEFT:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX2 += param;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.width -= param;
break;
- case 1:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX += a2;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.width += a2;
+ case BPPD_MOVE_OUTER_LEFT:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX += param;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.width += param;
break;
- case 2:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY2 += a2;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.height -= a2;
+ case BPPD_MOVE_INNER_TOP:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY2 += param;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.height -= param;
break;
- case 3:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY -= a2;
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.height += a2;
+ case BPPD_MOVE_OUTER_TOP:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY -= param;
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.height += param;
break;
- case 4:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX2 += a2;
+ case BPPD_MOVE_INNER_X:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX2 += param;
break;
- case 5:
- sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY2 += a2;
+ case BPPD_MOVE_INNER_Y:
+ sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY2 += param;
break;
}
- sBoxPartyPokemonDropdownPtr[a0].bgUpdateScheduled = TRUE;
+ sBoxPartyPokemonDropdownPtr[idx].bgUpdateScheduled = TRUE;
}
}
-void sub_80F7E54(u8 a0)
+void CopyBoxPartyPokemonDropdownToBgTilemapBuffer(u8 idx)
{
- if (a0 < sBoxPartyPokemonDropdownCount)
+ if (idx < sBoxPartyPokemonDropdownCount)
{
- if (sBoxPartyPokemonDropdownPtr[a0].src1 != NULL)
- PushMap1(a0);
- PushMap2(a0);
- sBoxPartyPokemonDropdownPtr[a0].map1Rect = sBoxPartyPokemonDropdownPtr[a0].map2Rect;
+ if (sBoxPartyPokemonDropdownPtr[idx].src1 != NULL)
+ PushMap1(idx);
+ PushMap2(idx);
+ sBoxPartyPokemonDropdownPtr[idx].map1Rect = sBoxPartyPokemonDropdownPtr[idx].map2Rect;
}
}
-static void PushMap1(u8 a0)
+static void PushMap1(u8 idx)
{
int i;
- int r9 = sBoxPartyPokemonDropdownPtr[a0].mapSize * sBoxPartyPokemonDropdownPtr[a0].src1Height;
- const void * addr = sBoxPartyPokemonDropdownPtr[a0].src1 + r9 * sBoxPartyPokemonDropdownPtr[a0].map1Rect.destY2 + sBoxPartyPokemonDropdownPtr[a0].map1Rect.destX2 * sBoxPartyPokemonDropdownPtr[a0].mapSize;
- for (i = 0; i < sBoxPartyPokemonDropdownPtr[a0].map1Rect.height; i++)
+ int run = sBoxPartyPokemonDropdownPtr[idx].mapSize * sBoxPartyPokemonDropdownPtr[idx].src1Height;
+ const void * addr = sBoxPartyPokemonDropdownPtr[idx].src1 + run * sBoxPartyPokemonDropdownPtr[idx].map1Rect.destY2 + sBoxPartyPokemonDropdownPtr[idx].map1Rect.destX2 * sBoxPartyPokemonDropdownPtr[idx].mapSize;
+ for (i = 0; i < sBoxPartyPokemonDropdownPtr[idx].map1Rect.height; i++)
{
- CopyToBgTilemapBufferRect(sBoxPartyPokemonDropdownPtr[a0].bgId, addr, sBoxPartyPokemonDropdownPtr[a0].map1Rect.destX2, sBoxPartyPokemonDropdownPtr[a0].map1Rect.destY2 + i, sBoxPartyPokemonDropdownPtr[a0].map1Rect.width, 1);
- addr += r9;
+ CopyToBgTilemapBufferRect(sBoxPartyPokemonDropdownPtr[idx].bgId, addr, sBoxPartyPokemonDropdownPtr[idx].map1Rect.destX2, sBoxPartyPokemonDropdownPtr[idx].map1Rect.destY2 + i, sBoxPartyPokemonDropdownPtr[idx].map1Rect.width, 1);
+ addr += run;
}
}
-static void PushMap2(u8 a0)
+static void PushMap2(u8 idx)
{
int i;
- int r9 = sBoxPartyPokemonDropdownPtr[a0].mapSize * sBoxPartyPokemonDropdownPtr[a0].src2Height;
- const void * addr = sBoxPartyPokemonDropdownPtr[a0].src2 + r9 * sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY + sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX * sBoxPartyPokemonDropdownPtr[a0].mapSize;
- for (i = 0; i < sBoxPartyPokemonDropdownPtr[a0].map2Rect.height; i++)
+ int run = sBoxPartyPokemonDropdownPtr[idx].mapSize * sBoxPartyPokemonDropdownPtr[idx].src2Width;
+ const void * addr = sBoxPartyPokemonDropdownPtr[idx].src2 + run * sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY + sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX * sBoxPartyPokemonDropdownPtr[idx].mapSize;
+ for (i = 0; i < sBoxPartyPokemonDropdownPtr[idx].map2Rect.height; i++)
{
- CopyToBgTilemapBufferRect(sBoxPartyPokemonDropdownPtr[a0].bgId, addr, sBoxPartyPokemonDropdownPtr[a0].map2Rect.destX2, sBoxPartyPokemonDropdownPtr[a0].map2Rect.destY2 + i, sBoxPartyPokemonDropdownPtr[a0].map2Rect.width, 1);
- addr += r9;
+ CopyToBgTilemapBufferRect(sBoxPartyPokemonDropdownPtr[idx].bgId, addr, sBoxPartyPokemonDropdownPtr[idx].map2Rect.destX2, sBoxPartyPokemonDropdownPtr[idx].map2Rect.destY2 + i, sBoxPartyPokemonDropdownPtr[idx].map2Rect.width, 1);
+ addr += run;
}
}
diff --git a/src/credits.c b/src/credits.c
index e0d57a2a4..4d7bbd67b 100644
--- a/src/credits.c
+++ b/src/credits.c
@@ -910,7 +910,7 @@ static s32 RollCredits(void)
case CREDITSSCRCMD_MAPNEXT:
sCreditsMgr->mainseqno = CREDITSSCENE_MAPNEXT_DESTROYWINDOW;
sCreditsMgr->whichMon = sCreditsScript[sCreditsMgr->scrcmdidx].param;
- FieldWeather_StartFadingOutCreditsMap(1, 0, 0x3FFFFFFF);
+ FadeSelectedPals(1, 0, 0x3FFFFFFF);
break;
case CREDITSSCRCMD_MAP:
sCreditsMgr->mainseqno = CREDITSSCENE_MAP_LOADMAP_CREATESPRITES;
@@ -1305,7 +1305,7 @@ static s32 RollCredits(void)
"\tldr r2, _080F3E0C @ =0x3fffffff\n"
"\tmovs r0, 0x1\n"
"\tmovs r1, 0\n"
- "\tbl FieldWeather_StartFadingOutCreditsMap\n"
+ "\tbl FadeSelectedPals\n"
"\tb _080F3E94\n"
"\t.align 2, 0\n"
"_080F3E04: .4byte sCreditsMgr\n"
diff --git a/src/field_specials.c b/src/field_specials.c
index 5be7a4d1c..474fcd081 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -442,7 +442,7 @@ bool8 IsThereRoomInAnyBoxForMorePokemon(void)
{
for (j = 0; j < IN_BOX_COUNT; j++)
{
- if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
+ if (GetBoxMonDataAt(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
return TRUE;
}
}
@@ -1642,7 +1642,7 @@ void ChangeBoxPokemonNickname(void)
static void ChangeBoxPokemonNickname_CB(void)
{
- SetBoxMonNickFromAnyBox(gSpecialVar_MonBoxId, gSpecialVar_MonBoxPos, gStringVar2);
+ SetBoxMonNickAt(gSpecialVar_MonBoxId, gSpecialVar_MonBoxPos, gStringVar2);
CB2_ReturnToFieldContinueScriptPlayMapMusic();
}
@@ -1980,11 +1980,11 @@ u16 GetPCBoxToSendMon(void)
bool8 ShouldShowBoxWasFullMessage(void)
{
- if (FlagGet(FLAG_SYS_CHANGED_BOX_TO_STORE_MON))
+ if (FlagGet(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE))
return FALSE;
if (StorageGetCurrentBox() == VarGet(VAR_PC_BOX_TO_SEND_MON))
return FALSE;
- FlagSet(FLAG_SYS_CHANGED_BOX_TO_STORE_MON);
+ FlagSet(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE);
return TRUE;
}
@@ -2001,7 +2001,7 @@ bool8 IsDestinationBoxFull(void)
if (GetBoxMonData(GetBoxedMonPtr(i, j), MON_DATA_SPECIES, NULL) == SPECIES_NONE)
{
if (GetPCBoxToSendMon() != i)
- FlagClear(FLAG_SYS_CHANGED_BOX_TO_STORE_MON);
+ FlagClear(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE);
VarSet(VAR_PC_BOX_TO_SEND_MON, i);
return ShouldShowBoxWasFullMessage();
}
diff --git a/src/field_weather.c b/src/field_weather.c
new file mode 100644
index 000000000..1185f5763
--- /dev/null
+++ b/src/field_weather.c
@@ -0,0 +1,1169 @@
+#include "global.h"
+#include "gflib.h"
+#include "blend_palette.h"
+#include "field_effect.h"
+#include "field_weather.h"
+#include "field_weather_util.h"
+#include "field_weather_effects.h"
+#include "task.h"
+#include "trig.h"
+#include "constants/field_weather.h"
+#include "constants/weather.h"
+#include "constants/songs.h"
+
+#define DROUGHT_COLOR_INDEX(color) ((((color) >> 1) & 0xF) | (((color) >> 2) & 0xF0) | (((color) >> 3) & 0xF00))
+
+enum
+{
+ GAMMA_NONE,
+ GAMMA_NORMAL,
+ GAMMA_ALT,
+};
+
+struct RGBColor
+{
+ u16 r:5;
+ u16 g:5;
+ u16 b:5;
+};
+
+struct WeatherPaletteData
+{
+ u16 gammaShiftColors[8][0x1000]; // 0x1000 is the number of bytes that make up all palettes.
+};
+
+struct WeatherCallbacks
+{
+ void (*initVars)(void);
+ void (*main)(void);
+ void (*initAll)(void);
+ bool8 (*finish)(void);
+};
+
+static EWRAM_DATA struct Weather sWeather = {};
+static EWRAM_DATA u8 sFieldEffectPaletteGammaTypes[32] = {};
+static EWRAM_DATA const u8 *sPaletteGammaTypes = NULL;
+static EWRAM_DATA u16 gUnknown_20386A8 = 0;
+
+static void Task_WeatherMain(u8 taskId);
+static void Task_WeatherInit(u8 taskId);
+static void None_Init(void);
+static void None_Main(void);
+static bool8 None_Finish(void);
+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 FadeInScreenWithWeather(void);
+static bool8 FadeInScreen_RainShowShade(void);
+static bool8 FadeInScreen_Drought(void);
+static bool8 FadeInScreen_FogHorizontal(void);
+static void DoNothing(void);
+static void ApplyFogBlend(u8 blendCoeff, u16 blendColor);
+static bool8 LightenSpritePaletteInFog(u8 paletteIndex);
+
+struct Weather *const gWeatherPtr = &sWeather;
+
+static const struct WeatherCallbacks sWeatherFuncs[] = {
+ {None_Init, None_Main, None_Init, None_Finish},
+ {Clouds_InitVars, Clouds_Main, Clouds_InitAll, Clouds_Finish},
+ {Sunny_InitVars, Sunny_Main, Sunny_InitAll, Sunny_Finish},
+ {Rain_InitVars, Rain_Main, Rain_InitAll, Rain_Finish},
+ {Snow_InitVars, Snow_Main, Snow_InitAll, Snow_Finish},
+ {Thunderstorm_InitVars, Thunderstorm_Main, Thunderstorm_InitAll, Thunderstorm_Finish},
+ {FogHorizontal_InitVars, FogHorizontal_Main, FogHorizontal_InitAll, FogHorizontal_Finish},
+ {Ash_InitVars, Ash_Main, Ash_InitAll, Ash_Finish},
+ {Sandstorm_InitVars, Sandstorm_Main, Sandstorm_InitAll, Sandstorm_Finish},
+ {FogDiagonal_InitVars, FogDiagonal_Main, FogDiagonal_InitAll, FogDiagonal_Finish},
+ {FogHorizontal_InitVars, FogHorizontal_Main, FogHorizontal_InitAll, FogHorizontal_Finish},
+ {Shade_InitVars, Shade_Main, Shade_InitAll, Shade_Finish},
+ {Drought_InitVars, Drought_Main, Drought_InitAll, Drought_Finish},
+ {Downpour_InitVars, Thunderstorm_Main, Downpour_InitAll, Thunderstorm_Finish},
+ {Bubbles_InitVars, Bubbles_Main, Bubbles_InitAll, Bubbles_Finish},
+};
+
+static void (*const sWeatherPalStateFuncs[])(void) = {
+ UpdateWeatherGammaShift,
+ FadeInScreenWithWeather,
+ DoNothing,
+ DoNothing
+};
+
+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_NONE,
+ GAMMA_NONE,
+ GAMMA_NONE,
+ // sprite palettes
+ GAMMA_ALT,
+ GAMMA_NORMAL,
+ GAMMA_ALT,
+ GAMMA_ALT,
+ GAMMA_ALT,
+ GAMMA_ALT,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_ALT,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+ GAMMA_NORMAL,
+};
+
+const u16 gUnknown_83C2CE0[] = INCBIN_U16("graphics/field_effects/unk_83C2CE0.gbapal");
+const u16 gCloudsWeatherPalette[] = INCBIN_U16("graphics/weather/cloud.gbapal");
+const u16 gSandstormWeatherPalette[] = INCBIN_U16("graphics/weather/sandstorm.gbapal");
+const u8 gWeatherFogDiagonalTiles[] = INCBIN_U8("graphics/weather/fog_diagonal.4bpp");
+const u8 gWeatherFogHorizontalTiles[] = INCBIN_U8("graphics/weather/fog_horizontal.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");
+
+// code
+void StartWeather(void)
+{
+ if (!FuncIsActiveTask(Task_WeatherMain))
+ {
+ u8 index = AllocSpritePalette(0x1200);
+ CpuCopy32(gUnknown_83C2CE0, &gPlttBufferUnfaded[0x100 + index * 16], 32);
+ sub_8083598(index);
+ BuildGammaShiftTables();
+ gWeatherPtr->altGammaSpritePalIndex = index;
+ gWeatherPtr->weatherPicSpritePalIndex = index;
+ gWeatherPtr->rainSpriteCount = 0;
+ gWeatherPtr->curRainSpriteIndex = 0;
+ gWeatherPtr->cloudSpritesCreated = FALSE;
+ gWeatherPtr->snowflakeSpriteCount = 0;
+ gWeatherPtr->ashSpritesCreated = FALSE;
+ gWeatherPtr->fogHSpritesCreated = FALSE;
+ gWeatherPtr->fogDSpritesCreated = FALSE;
+ gWeatherPtr->sandstormSpritesCreated = FALSE;
+ gWeatherPtr->sandstormSwirlSpritesCreated = FALSE;
+ gWeatherPtr->bubblesSpritesCreated = FALSE;
+ gWeatherPtr->lightenedFogSpritePalsCount = 0;
+ Weather_SetBlendCoeffs(16, 0);
+ gWeatherPtr->currWeather = WEATHER_NONE;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ gWeatherPtr->readyForInit = FALSE;
+ gWeatherPtr->weatherChangeComplete = TRUE;
+ gWeatherPtr->taskId = CreateTask(Task_WeatherInit, 80);
+ }
+}
+
+void SetNextWeather(u8 weather)
+{
+ if (weather != WEATHER_RAIN && weather != WEATHER_RAIN_THUNDERSTORM && weather != WEATHER_DOWNPOUR)
+ {
+ PlayRainStoppingSoundEffect();
+ }
+
+ if (gWeatherPtr->nextWeather != weather && gWeatherPtr->currWeather == weather)
+ {
+ sWeatherFuncs[weather].initVars();
+ }
+
+ gWeatherPtr->weatherChangeComplete = FALSE;
+ gWeatherPtr->nextWeather = weather;
+ gWeatherPtr->finishStep = 0;
+}
+
+
+void SetCurrentAndNextWeather(u8 weather)
+{
+ PlayRainStoppingSoundEffect();
+ gWeatherPtr->currWeather = weather;
+ gWeatherPtr->nextWeather = weather;
+}
+
+static void SetCurrentAndNextWeatherNoDelay(u8 weather)
+{
+ PlayRainStoppingSoundEffect();
+ gWeatherPtr->currWeather = weather;
+ gWeatherPtr->nextWeather = weather;
+ // Overrides the normal delay during screen fading.
+ 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();
+ }
+
+ sWeatherPalStateFuncs[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->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:
+ case WEATHER_RAIN_THUNDERSTORM:
+ case WEATHER_DOWNPOUR:
+ case WEATHER_SNOW:
+ case WEATHER_SHADE:
+ if (FadeInScreen_RainShowShade() == FALSE)
+ {
+ gWeatherPtr->gammaIndex = 3;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ case WEATHER_DROUGHT:
+ if (FadeInScreen_Drought() == FALSE)
+ {
+ gWeatherPtr->gammaIndex = -6;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ case WEATHER_FOG_HORIZONTAL:
+ if (FadeInScreen_FogHorizontal() == FALSE)
+ {
+ gWeatherPtr->gammaIndex = 0;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ case WEATHER_VOLCANIC_ASH:
+ case WEATHER_SANDSTORM:
+ case WEATHER_FOG_DIAGONAL:
+ case WEATHER_UNDERWATER:
+ default:
+ if (!gPaletteFade.active)
+ {
+ gWeatherPtr->gammaIndex = gWeatherPtr->gammaTargetIndex;
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+ }
+ break;
+ }
+}
+
+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_FogHorizontal(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.
+ // Dummied out in FRLG
+
+ // gammaIndex = -gammaIndex - 1;
+ // palOffset = startPalIndex * 16;
+ // numPalettes += startPalIndex;
+ // curPalIndex = startPalIndex;
+ //
+ // CpuFastCopy(gPlttBufferUnfaded + palOffset, gPlttBufferFaded + palOffset, 16 * sizeof(u16));
+ // while (curPalIndex < numPalettes)
+ // {
+ // if (sPaletteGammaTypes[curPalIndex] == GAMMA_NONE)
+ // {
+ // // No palette change.
+ // palOffset += 16;
+ // }
+ // else
+ // {
+ //
+ // for (i = 0; i < 16; i++)
+ // {
+ // gPlttBufferFaded[palOffset] = sDroughtWeatherColors[gammaIndex][DROUGHT_COLOR_INDEX(gPlttBufferUnfaded[palOffset])];
+ // palOffset++;
+ // }
+ // }
+ //
+ // curPalIndex++;
+ // }
+ }
+ else
+ {
+ // No palette blending.
+ CpuFastCopy(gPlttBufferUnfaded + startPalIndex * 16, gPlttBufferFaded + startPalIndex * 16, numPalettes * 16 * sizeof(u16));
+ }
+}
+
+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;
+
+ r1 += ((rBlend - r1) * blendCoeff) >> 4;
+ g1 += ((gBlend - g1) * blendCoeff) >> 4;
+ b1 += ((bBlend - b1) * blendCoeff) >> 4;
+
+ gPlttBufferFaded[palOffset++] = (b1 << 10) | (g1 << 5) | r1;
+ }
+ }
+ }
+}
+
+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_807A790(s8 gammaIndex)
+{
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE)
+ {
+ ApplyGammaShift(0, 32, gammaIndex);
+ gWeatherPtr->gammaIndex = gammaIndex;
+ }
+}
+
+void sub_807A7C4(u8 gammaIndex, u8 gammaTargetIndex, u8 gammaStepDelay)
+{
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE)
+ {
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_CHANGING_WEATHER;
+ gWeatherPtr->gammaIndex = gammaIndex;
+ gWeatherPtr->gammaTargetIndex = gammaTargetIndex;
+ gWeatherPtr->gammaStepFrameCounter = 0;
+ gWeatherPtr->gammaStepDelay = gammaStepDelay;
+ sub_807A790(gammaIndex);
+ }
+}
+
+void FadeScreen(u8 mode, s8 delay)
+{
+ u32 fadeColor;
+ bool8 fadeOut;
+ bool8 useWeatherPal;
+
+ switch (mode)
+ {
+ case FADE_FROM_BLACK:
+ fadeColor = RGB_BLACK;
+ fadeOut = FALSE;
+ break;
+ case FADE_FROM_WHITE:
+ fadeColor = RGB_WHITEALPHA;
+ fadeOut = FALSE;
+ break;
+ case FADE_TO_BLACK:
+ fadeColor = RGB_BLACK;
+ fadeOut = TRUE;
+ break;
+ case FADE_TO_WHITE:
+ fadeColor = RGB_WHITEALPHA;
+ fadeOut = TRUE;
+ break;
+ default:
+ return;
+ }
+
+ switch (gWeatherPtr->currWeather)
+ {
+ case WEATHER_RAIN:
+ case WEATHER_RAIN_THUNDERSTORM:
+ case WEATHER_DOWNPOUR:
+ case WEATHER_SNOW:
+ case WEATHER_FOG_HORIZONTAL:
+ case WEATHER_SHADE:
+ case WEATHER_DROUGHT:
+ useWeatherPal = TRUE;
+ break;
+ default:
+ useWeatherPal = FALSE;
+ break;
+ }
+
+ if (fadeOut)
+ {
+ if (useWeatherPal)
+ CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
+
+ BeginNormalPaletteFade(0xFFFFFFFF, delay, 0, 16, fadeColor);
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT;
+ }
+ else
+ {
+ gWeatherPtr->fadeDestColor = fadeColor;
+ if (useWeatherPal)
+ gWeatherPtr->fadeScreenCounter = 0;
+ else
+ BeginNormalPaletteFade(0xFFFFFFFF, delay, 16, 0, fadeColor);
+
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_IN;
+ gWeatherPtr->unknown_6CA = 1;
+ gWeatherPtr->unknown_6CB = 0;
+ Weather_SetBlendCoeffs(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB);
+ gWeatherPtr->readyForInit = TRUE;
+ }
+}
+
+void FadeSelectedPals(u8 mode, s8 delay, u32 selectedPalettes)
+{
+ u32 fadeColor;
+ bool8 fadeOut;
+ bool8 useWeatherPal;
+
+ switch (mode)
+ {
+ case FADE_FROM_BLACK:
+ fadeColor = RGB_BLACK;
+ fadeOut = FALSE;
+ break;
+ case FADE_FROM_WHITE:
+ fadeColor = RGB_WHITEALPHA;
+ fadeOut = FALSE;
+ break;
+ case FADE_TO_BLACK:
+ fadeColor = RGB_BLACK;
+ fadeOut = TRUE;
+ break;
+ case FADE_TO_WHITE:
+ fadeColor = RGB_WHITEALPHA;
+ fadeOut = TRUE;
+ break;
+ default:
+ return;
+ }
+
+ switch (gWeatherPtr->currWeather)
+ {
+ case WEATHER_RAIN:
+ case WEATHER_RAIN_THUNDERSTORM:
+ case WEATHER_DOWNPOUR:
+ case WEATHER_SNOW:
+ case WEATHER_FOG_HORIZONTAL:
+ case WEATHER_SHADE:
+ case WEATHER_DROUGHT:
+ useWeatherPal = TRUE;
+ break;
+ default:
+ useWeatherPal = FALSE;
+ break;
+ }
+
+ if (fadeOut)
+ {
+ if (useWeatherPal)
+ CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
+
+ BeginNormalPaletteFade(selectedPalettes, delay, 0, 16, fadeColor);
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT;
+ }
+ else
+ {
+ gWeatherPtr->fadeDestColor = fadeColor;
+ if (useWeatherPal)
+ gWeatherPtr->fadeScreenCounter = 0;
+ else
+ BeginNormalPaletteFade(selectedPalettes, delay, 16, 0, fadeColor);
+
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_IN;
+ gWeatherPtr->unknown_6CA = 1;
+ gWeatherPtr->unknown_6CB = 0;
+ Weather_SetBlendCoeffs(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB);
+ gWeatherPtr->readyForInit = TRUE;
+ }
+}
+
+
+bool8 IsWeatherNotFadingIn(void)
+{
+ return (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_IN);
+}
+
+void UpdateSpritePaletteWithWeather(u8 spritePaletteIndex)
+{
+ u16 paletteIndex = 16 + spritePaletteIndex;
+ u16 i;
+
+ switch (gWeatherPtr->palProcessingState)
+ {
+ case WEATHER_PAL_STATE_SCREEN_FADING_IN:
+ if (gWeatherPtr->unknown_6CA != 0)
+ {
+ if (gWeatherPtr->currWeather == WEATHER_FOG_HORIZONTAL)
+ MarkFogSpritePalToLighten(paletteIndex);
+ paletteIndex *= 16;
+ for (i = 0; i < 16; i++)
+ gPlttBufferFaded[paletteIndex + i] = gWeatherPtr->fadeDestColor;
+ }
+ break;
+ case WEATHER_PAL_STATE_SCREEN_FADING_OUT:
+ paletteIndex *= 16;
+ CpuFastCopy(gPlttBufferFaded + paletteIndex, gPlttBufferUnfaded + paletteIndex, 32);
+ BlendPalette(paletteIndex, 16, gPaletteFade.y, gPaletteFade.blendColor);
+ break;
+ // WEATHER_PAL_STATE_CHANGING_WEATHER
+ // WEATHER_PAL_STATE_CHANGING_IDLE
+ default:
+ if (gWeatherPtr->currWeather != WEATHER_FOG_HORIZONTAL)
+ {
+ ApplyGammaShift(paletteIndex, 1, gWeatherPtr->gammaIndex);
+ }
+ else
+ {
+ paletteIndex *= 16;
+ BlendPalette(paletteIndex, 16, 12, RGB(28, 31, 28));
+ }
+ break;
+ }
+}
+
+void ApplyWeatherGammaShiftToPal(u8 paletteIndex)
+{
+ ApplyGammaShift(paletteIndex, 1, gWeatherPtr->gammaIndex);
+}
+
+static u8 sub_80ABF20(void)
+{
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_SCREEN_FADING_IN)
+ return gWeatherPtr->unknown_6CA;
+ else
+ return 0;
+}
+
+void LoadCustomWeatherSpritePalette(const u16 *palette)
+{
+ LoadPalette(palette, 0x100 + gWeatherPtr->weatherPicSpritePalIndex * 16, 32);
+ UpdateSpritePaletteWithWeather(gWeatherPtr->weatherPicSpritePalIndex);
+}
+
+static void LoadDroughtWeatherPalette(u8 *gammaIndexPtr, u8 *a1)
+{
+ // Dummied out in FRLG
+ // *gammaIndexPtr = 0x20;
+ // *a1 = 0x20;
+}
+
+void ResetDroughtWeatherPaletteLoading(void)
+{
+ gWeatherPtr->loadDroughtPalsIndex = 1;
+ gWeatherPtr->loadDroughtPalsOffset = 1;
+}
+
+bool8 LoadDroughtWeatherPalettes(void)
+{
+ if (gWeatherPtr->loadDroughtPalsIndex < 32)
+ {
+ LoadDroughtWeatherPalette(&gWeatherPtr->loadDroughtPalsIndex, &gWeatherPtr->loadDroughtPalsOffset);
+ if (gWeatherPtr->loadDroughtPalsIndex < 32)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_807AC50(s8 gammaIndex)
+{
+ sub_807A790(-gammaIndex - 1);
+}
+
+void sub_807AC60(void)
+{
+ gWeatherPtr->unknown_73C = 0;
+ gWeatherPtr->unknown_740 = 0;
+ gWeatherPtr->unknown_742 = 0;
+ gWeatherPtr->unknown_73E = 0;
+ gUnknown_20386A8 = 5;
+}
+
+void sub_807AC98(void)
+{
+ switch (gWeatherPtr->unknown_742)
+ {
+ case 0:
+ if (++gWeatherPtr->unknown_740 > gUnknown_20386A8)
+ {
+ gWeatherPtr->unknown_740 = 0;
+ sub_807AC50(gWeatherPtr->unknown_73C++);
+ if (gWeatherPtr->unknown_73C > 5)
+ {
+ gWeatherPtr->unknown_73E = gWeatherPtr->unknown_73C;
+ gWeatherPtr->unknown_742 = 1;
+ gWeatherPtr->unknown_740 = 0x3C;
+ }
+ }
+ break;
+ case 1:
+ gWeatherPtr->unknown_740 = (gWeatherPtr->unknown_740 + 3) & 0x7F;
+ gWeatherPtr->unknown_73C = ((gSineTable[gWeatherPtr->unknown_740] - 1) >> 6) + 2;
+ if (gWeatherPtr->unknown_73C != gWeatherPtr->unknown_73E)
+ sub_807AC50(gWeatherPtr->unknown_73C);
+ gWeatherPtr->unknown_73E = gWeatherPtr->unknown_73C;
+ break;
+ case 2:
+ if (++gWeatherPtr->unknown_740 > gUnknown_20386A8)
+ {
+ gWeatherPtr->unknown_740 = 0;
+ sub_807AC50(--gWeatherPtr->unknown_73C);
+ if (gWeatherPtr->unknown_73C == 3)
+ gWeatherPtr->unknown_742 = 0;
+ }
+ break;
+ }
+}
+
+void Weather_SetBlendCoeffs(u8 eva, u8 evb)
+{
+ gWeatherPtr->currBlendEVA = eva;
+ gWeatherPtr->currBlendEVB = evb;
+ gWeatherPtr->targetBlendEVA = eva;
+ gWeatherPtr->targetBlendEVB = evb;
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(eva, evb));
+}
+
+void Weather_SetTargetBlendCoeffs(u8 eva, u8 evb, int delay)
+{
+ gWeatherPtr->targetBlendEVA = eva;
+ gWeatherPtr->targetBlendEVB = evb;
+ gWeatherPtr->blendDelay = delay;
+ gWeatherPtr->blendFrameCounter = 0;
+ gWeatherPtr->blendUpdateCounter = 0;
+}
+
+bool8 Weather_UpdateBlend(void)
+{
+ if (gWeatherPtr->currBlendEVA == gWeatherPtr->targetBlendEVA
+ && gWeatherPtr->currBlendEVB == gWeatherPtr->targetBlendEVB)
+ return TRUE;
+
+ if (++gWeatherPtr->blendFrameCounter > gWeatherPtr->blendDelay)
+ {
+ gWeatherPtr->blendFrameCounter = 0;
+ gWeatherPtr->blendUpdateCounter++;
+
+ // Update currBlendEVA and currBlendEVB on alternate frames
+ if (gWeatherPtr->blendUpdateCounter & 1)
+ {
+ if (gWeatherPtr->currBlendEVA < gWeatherPtr->targetBlendEVA)
+ gWeatherPtr->currBlendEVA++;
+ else if (gWeatherPtr->currBlendEVA > gWeatherPtr->targetBlendEVA)
+ gWeatherPtr->currBlendEVA--;
+ }
+ else
+ {
+ if (gWeatherPtr->currBlendEVB < gWeatherPtr->targetBlendEVB)
+ gWeatherPtr->currBlendEVB++;
+ else if (gWeatherPtr->currBlendEVB > gWeatherPtr->targetBlendEVB)
+ gWeatherPtr->currBlendEVB--;
+ }
+ }
+
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB));
+
+ if (gWeatherPtr->currBlendEVA == gWeatherPtr->targetBlendEVA
+ && gWeatherPtr->currBlendEVB == gWeatherPtr->targetBlendEVB)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void sub_807AF00(u8 a)
+{
+ switch (a)
+ {
+ case 1:
+ SetWeather(WEATHER_SUNNY_CLOUDS);
+ break;
+ case 2:
+ SetWeather(WEATHER_SUNNY);
+ break;
+ case 3:
+ SetWeather(WEATHER_RAIN);
+ break;
+ case 4:
+ SetWeather(WEATHER_SNOW);
+ break;
+ case 5:
+ SetWeather(WEATHER_RAIN_THUNDERSTORM);
+ break;
+ case 6:
+ SetWeather(WEATHER_FOG_HORIZONTAL);
+ break;
+ case 7:
+ SetWeather(WEATHER_FOG_DIAGONAL);
+ break;
+ case 8:
+ SetWeather(WEATHER_VOLCANIC_ASH);
+ break;
+ case 9:
+ SetWeather(WEATHER_SANDSTORM);
+ break;
+ case 10:
+ SetWeather(WEATHER_SHADE);
+ break;
+ }
+}
+
+u8 GetCurrentWeather(void)
+{
+ return gWeatherPtr->currWeather;
+}
+
+void SetRainStrengthFromSoundEffect(u16 soundEffect)
+{
+ if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_SCREEN_FADING_OUT)
+ {
+ switch (soundEffect)
+ {
+ case SE_T_KOAME:
+ gWeatherPtr->rainStrength = 0;
+ break;
+ case SE_T_OOAME:
+ gWeatherPtr->rainStrength = 1;
+ break;
+ case SE_T_AME:
+ gWeatherPtr->rainStrength = 2;
+ break;
+ default:
+ return;
+ }
+
+ PlaySE(soundEffect);
+ }
+}
+
+void PlayRainStoppingSoundEffect(void)
+{
+ if (IsSpecialSEPlaying())
+ {
+ switch (gWeatherPtr->rainStrength)
+ {
+ case 0:
+ PlaySE(SE_T_KOAME_E);
+ break;
+ case 1:
+ PlaySE(SE_T_OOAME_E);
+ break;
+ case 2:
+ default:
+ PlaySE(SE_T_AME_E);
+ break;
+ }
+ }
+}
+
+u8 IsWeatherChangeComplete(void)
+{
+ return gWeatherPtr->weatherChangeComplete;
+}
+
+void SetWeatherScreenFadeOut(void)
+{
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_SCREEN_FADING_OUT;
+}
+
+void sub_807B070(void)
+{
+ gWeatherPtr->palProcessingState = WEATHER_PAL_STATE_IDLE;
+}
+
+void PreservePaletteInWeather(u8 preservedPalIndex)
+{
+ CpuCopy16(sBasePaletteGammaTypes, sFieldEffectPaletteGammaTypes, 32);
+ sFieldEffectPaletteGammaTypes[preservedPalIndex] = GAMMA_NONE;
+ sPaletteGammaTypes = sFieldEffectPaletteGammaTypes;
+}
+
+void ResetPreservedPalettesInWeather(void)
+{
+ sPaletteGammaTypes = sBasePaletteGammaTypes;
+}
+
+void sub_807B0C4(u16 *palbuf, u16 *unused, u32 size)
+{
+ switch (gWeatherPtr->currWeather)
+ {
+ case WEATHER_RAIN:
+ case WEATHER_SNOW:
+ case WEATHER_RAIN_THUNDERSTORM:
+ case WEATHER_SHADE:
+ case WEATHER_DOWNPOUR:
+ sub_8045314(palbuf, RGB_BLACK, 3, size);
+ break;
+ }
+}
diff --git a/src/field_weather_effects.c b/src/field_weather_effects.c
new file mode 100644
index 000000000..e6f4bfacf
--- /dev/null
+++ b/src/field_weather_effects.c
@@ -0,0 +1,2320 @@
+#include "global.h"
+#include "gflib.h"
+#include "battle_anim.h"
+#include "event_object_movement.h"
+#include "field_weather.h"
+#include "field_weather_effects.h"
+#include "overworld.h"
+#include "random.h"
+#include "script.h"
+#include "constants/weather.h"
+#include "constants/songs.h"
+#include "task.h"
+#include "trig.h"
+
+//------------------------------------------------------------------------------
+// WEATHER_SUNNY_CLOUDS
+//------------------------------------------------------------------------------
+
+static void CreateCloudSprites(void);
+static void DestroyCloudSprites(void);
+static void UpdateCloudSprite(struct Sprite *);
+
+// The clouds are positioned on the map's grid.
+// These coordinates are for the lower half of Route 120.
+static const struct Coords16 sCloudSpriteMapCoords[] = {
+ { 0, 66},
+ { 5, 73},
+ {10, 78},
+};
+
+static const struct SpriteSheet sCloudSpriteSheet = {
+ .data = gWeatherCloudTiles,
+ .size = 0x0800,
+ .tag = 0x1200
+};
+
+static const struct OamData sCloudSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sCloudSpriteAnimCmd[] = {
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sCloudSpriteAnimCmds[] = {
+ sCloudSpriteAnimCmd,
+};
+
+static const struct SpriteTemplate sCloudSpriteTemplate = {
+ .tileTag = 0x1200,
+ .paletteTag = 0x1200,
+ .oam = &sCloudSpriteOamData,
+ .anims = sCloudSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateCloudSprite,
+};
+
+void Clouds_InitVars(void)
+{
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->initStep = 0;
+ if (!gWeatherPtr->cloudSpritesCreated)
+ Weather_SetBlendCoeffs(0, 16);
+}
+
+void Clouds_InitAll(void)
+{
+ Clouds_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Clouds_Main();
+}
+
+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;
+ }
+}
+
+bool8 Clouds_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 1);
+ gWeatherPtr->finishStep++;
+ return TRUE;
+ case 1:
+ if (Weather_UpdateBlend())
+ {
+ DestroyCloudSprites();
+ gWeatherPtr->finishStep++;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void Sunny_InitVars(void)
+{
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+}
+
+void Sunny_InitAll(void)
+{
+ Sunny_InitVars();
+}
+
+void Sunny_Main(void)
+{
+}
+
+bool8 Sunny_Finish(void)
+{
+ return FALSE;
+}
+
+static void CreateCloudSprites(void)
+{
+ u16 i;
+ u8 spriteId;
+ struct Sprite *sprite;
+
+ if (gWeatherPtr->cloudSpritesCreated == TRUE)
+ return;
+
+ LoadSpriteSheet(&sCloudSpriteSheet);
+ LoadCustomWeatherSpritePalette(gCloudsWeatherPalette);
+ for (i = 0; i < NUM_CLOUD_SPRITES; i++)
+ {
+ spriteId = CreateSprite(&sCloudSpriteTemplate, 0, 0, 0xFF);
+ if (spriteId != MAX_SPRITES)
+ {
+ gWeatherPtr->sprites.s1.cloudSprites[i] = &gSprites[spriteId];
+ sprite = gWeatherPtr->sprites.s1.cloudSprites[i];
+ SetSpritePosToMapCoords(sCloudSpriteMapCoords[i].x + 7, sCloudSpriteMapCoords[i].y + 7, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->coordOffsetEnabled = TRUE;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s1.cloudSprites[i] = NULL;
+ }
+ }
+
+ gWeatherPtr->cloudSpritesCreated = TRUE;
+}
+
+static void DestroyCloudSprites(void)
+{
+ u16 i;
+
+ if (!gWeatherPtr->cloudSpritesCreated)
+ return;
+
+ for (i = 0; i < NUM_CLOUD_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s1.cloudSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s1.cloudSprites[i]);
+ }
+
+ FreeSpriteTilesByTag(0x1200);
+ gWeatherPtr->cloudSpritesCreated = FALSE;
+}
+
+static void UpdateCloudSprite(struct Sprite *sprite)
+{
+ // Move 1 pixel left every 2 frames.
+ sprite->data[0] = (sprite->data[0] + 1) & 1;
+ if (sprite->data[0])
+ sprite->pos1.x--;
+}
+
+//------------------------------------------------------------------------------
+// WEATHER_DROUGHT
+//------------------------------------------------------------------------------
+
+static void UpdateDroughtBlend(u8);
+
+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)
+ 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())
+ gWeatherPtr->initStep++;
+ break;
+ case 3:
+ sub_807AC60();
+ gWeatherPtr->initStep++;
+ break;
+ case 4:
+ sub_807AC98();
+ if (gWeatherPtr->unknown_73C == 6)
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ default:
+ sub_807AC98();
+ break;
+ }
+}
+
+bool8 Drought_Finish(void)
+{
+ return FALSE;
+}
+
+void StartDroughtWeatherBlend(void)
+{
+ CreateTask(UpdateDroughtBlend, 0x50);
+}
+
+#define tState data[0]
+#define tBlendY data[1]
+#define tBlendDelay data[2]
+#define tWinRange data[3]
+
+static void UpdateDroughtBlend(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->tState)
+ {
+ case 0:
+ task->tBlendY = 0;
+ task->tBlendDelay = 0;
+ task->tWinRange = GetGpuReg(REG_OFFSET_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
+
+//------------------------------------------------------------------------------
+// WEATHER_RAIN
+//------------------------------------------------------------------------------
+
+static void LoadRainSpriteSheet(void);
+static bool8 CreateRainSprite(void);
+static void UpdateRainSprite(struct Sprite *sprite);
+static bool8 UpdateVisibleRainSprites(void);
+static void DestroyRainSprites(void);
+
+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 sRainSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(16x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(16x32),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 2,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sRainSpriteFallAnimCmd[] = {
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd sRainSpriteSplashAnimCmd[] = {
+ ANIMCMD_FRAME(8, 3),
+ ANIMCMD_FRAME(32, 2),
+ ANIMCMD_FRAME(40, 2),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sRainSpriteHeavySplashAnimCmd[] = {
+ ANIMCMD_FRAME(8, 3),
+ ANIMCMD_FRAME(16, 3),
+ ANIMCMD_FRAME(24, 4),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sRainSpriteAnimCmds[] = {
+ sRainSpriteFallAnimCmd,
+ sRainSpriteSplashAnimCmd,
+ sRainSpriteHeavySplashAnimCmd,
+};
+
+static const struct SpriteTemplate sRainSpriteTemplate = {
+ .tileTag = 0x1206,
+ .paletteTag = 0x1200,
+ .oam = &sRainSpriteOamData,
+ .anims = sRainSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateRainSprite,
+};
+
+// Q28.4 fixed-point format values
+static const s16 sRainSpriteMovement[][2] = {
+ {-0x68, 0xD0},
+ {-0xA0, 0x140},
+};
+
+// First byte is the number of frames a raindrop falls before it splashes.
+// Second byte is the maximum number of frames a raindrop can "wait" before
+// it appears and starts falling. (This is only for the initial raindrop spawn.)
+static const u16 sRainSpriteFallingDurations[][2] = {
+ {18, 7},
+ {12, 10},
+};
+
+static const struct SpriteSheet sRainSpriteSheet = {
+ .data = gWeatherRainTiles,
+ .size = 0x0600,
+ .tag = 0x1206,
+};
+
+void Rain_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->rainSpriteVisibleCounter = 0;
+ gWeatherPtr->rainSpriteVisibleDelay = 8;
+ gWeatherPtr->isDownpour = FALSE;
+ gWeatherPtr->targetRainSpriteCount = 10;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ SetRainStrengthFromSoundEffect(SE_T_KOAME);
+}
+
+void Rain_InitAll(void)
+{
+ Rain_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Rain_Main();
+}
+
+void Rain_Main(void)
+{
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ LoadRainSpriteSheet();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (!CreateRainSprite())
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (!UpdateVisibleRainSprites())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ }
+}
+
+bool8 Rain_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ if (gWeatherPtr->nextWeather == WEATHER_RAIN
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_THUNDERSTORM
+ || gWeatherPtr->nextWeather == WEATHER_DOWNPOUR)
+ {
+ gWeatherPtr->finishStep = 0xFF;
+ return FALSE;
+ }
+ else
+ {
+ gWeatherPtr->targetRainSpriteCount = 0;
+ gWeatherPtr->finishStep++;
+ }
+ // fall through
+ case 1:
+ if (!UpdateVisibleRainSprites())
+ {
+ DestroyRainSprites();
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#define tCounter data[0]
+#define tRandom data[1]
+#define tPosX data[2]
+#define tPosY data[3]
+#define tState data[4]
+#define tActive data[5]
+#define tWaiting data[6]
+
+static void StartRainSpriteFall(struct Sprite *sprite)
+{
+ u32 rand;
+ u16 numFallingFrames;
+ int tileX;
+ int tileY;
+
+ if (sprite->tRandom == 0)
+ sprite->tRandom = 361;
+
+ // Standard RNG sequence.
+ rand = sprite->tRandom * 1103515245 + 12345;
+ sprite->tRandom = ((rand & 0x7FFF0000) >> 16) % 600;
+
+ numFallingFrames = sRainSpriteFallingDurations[gWeatherPtr->isDownpour][0];
+
+ tileX = sprite->tRandom % 30;
+ sprite->tPosX = tileX * 8; // Useless assignment, leftover from before fixed-point values were used
+
+ tileY = sprite->tRandom / 30;
+ sprite->tPosY = tileY * 8; // Useless assignment, leftover from before fixed-point values were used
+
+ sprite->tPosX = tileX;
+ sprite->tPosX <<= 7; // This is tileX * 8, using a fixed-point value with 4 decimal places
+
+ sprite->tPosY = tileY;
+ sprite->tPosY <<= 7; // This is tileX * 8, using a fixed-point value with 4 decimal places
+
+ // "Rewind" the rain sprites, from their ending position.
+ sprite->tPosX -= sRainSpriteMovement[gWeatherPtr->isDownpour][0] * numFallingFrames;
+ sprite->tPosY -= sRainSpriteMovement[gWeatherPtr->isDownpour][1] * numFallingFrames;
+
+ StartSpriteAnim(sprite, 0);
+ sprite->tState = 0;
+ sprite->coordOffsetEnabled = FALSE;
+ sprite->tCounter = numFallingFrames;
+}
+
+static void UpdateRainSprite(struct Sprite *sprite)
+{
+ if (sprite->tState == 0)
+ {
+ // Raindrop is in its "falling" motion.
+ sprite->tPosX += sRainSpriteMovement[gWeatherPtr->isDownpour][0];
+ sprite->tPosY += sRainSpriteMovement[gWeatherPtr->isDownpour][1];
+ sprite->pos1.x = sprite->tPosX >> 4;
+ sprite->pos1.y = sprite->tPosY >> 4;
+
+ if (sprite->tActive
+ && (sprite->pos1.x >= -8 && sprite->pos1.x <= 248)
+ && sprite->pos1.y >= -16 && sprite->pos1.y <= 176)
+ sprite->invisible = FALSE;
+ else
+ sprite->invisible = TRUE;
+
+ if (--sprite->tCounter == 0)
+ {
+ // Make raindrop splash on the ground
+ StartSpriteAnim(sprite, gWeatherPtr->isDownpour + 1);
+ sprite->tState = 1;
+ sprite->pos1.x -= gSpriteCoordOffsetX;
+ sprite->pos1.y -= gSpriteCoordOffsetY;
+ sprite->coordOffsetEnabled = TRUE;
+ }
+ }
+ else if (sprite->animEnded)
+ {
+ // The splashing animation ended.
+ sprite->invisible = TRUE;
+ StartRainSpriteFall(sprite);
+ }
+}
+
+static void WaitRainSprite(struct Sprite *sprite)
+{
+ if (sprite->tCounter == 0)
+ {
+ StartRainSpriteFall(sprite);
+ sprite->callback = UpdateRainSprite;
+ }
+ else
+ {
+ sprite->tCounter--;
+ }
+}
+
+static void InitRainSpriteMovement(struct Sprite *sprite, u16 val)
+{
+ u16 numFallingFrames = sRainSpriteFallingDurations[gWeatherPtr->isDownpour][0];
+ u16 numAdvanceRng = val / (sRainSpriteFallingDurations[gWeatherPtr->isDownpour][1] + numFallingFrames);
+ u16 frameVal = val % (sRainSpriteFallingDurations[gWeatherPtr->isDownpour][1] + numFallingFrames);
+
+ while (--numAdvanceRng != 0xFFFF)
+ StartRainSpriteFall(sprite);
+
+ if (frameVal < numFallingFrames)
+ {
+ while (--frameVal != 0xFFFF)
+ UpdateRainSprite(sprite);
+
+ sprite->tWaiting = FALSE;
+ }
+ else
+ {
+ sprite->tCounter = frameVal - numFallingFrames;
+ sprite->invisible = TRUE;
+ sprite->tWaiting = TRUE;
+ }
+}
+
+static void LoadRainSpriteSheet(void)
+{
+ LoadSpriteSheet(&sRainSpriteSheet);
+}
+
+static bool8 CreateRainSprite(void)
+{
+ u8 spriteIndex;
+ u8 spriteId;
+
+ if (gWeatherPtr->rainSpriteCount == MAX_RAIN_SPRITES)
+ return FALSE;
+
+ spriteIndex = gWeatherPtr->rainSpriteCount;
+ spriteId = CreateSpriteAtEnd(&sRainSpriteTemplate,
+ sRainSpriteCoords[spriteIndex].x, sRainSpriteCoords[spriteIndex].y, 78);
+
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].tActive = 0;
+ gSprites[spriteId].tRandom = spriteIndex * 145;
+ while (gSprites[spriteId].tRandom >= 600)
+ gSprites[spriteId].tRandom -= 600;
+
+ StartRainSpriteFall(&gSprites[spriteId]);
+ InitRainSpriteMovement(&gSprites[spriteId], spriteIndex * 9);
+ gSprites[spriteId].invisible = TRUE;
+ gWeatherPtr->sprites.s1.rainSprites[spriteIndex] = &gSprites[spriteId];
+ }
+ else
+ {
+ gWeatherPtr->sprites.s1.rainSprites[spriteIndex] = NULL;
+ }
+
+ if (++gWeatherPtr->rainSpriteCount == MAX_RAIN_SPRITES)
+ {
+ u16 i;
+ for (i = 0; i < MAX_RAIN_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s1.rainSprites[i])
+ {
+ if (!gWeatherPtr->sprites.s1.rainSprites[i]->tWaiting)
+ gWeatherPtr->sprites.s1.rainSprites[i]->callback = UpdateRainSprite;
+ else
+ gWeatherPtr->sprites.s1.rainSprites[i]->callback = WaitRainSprite;
+ }
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool8 UpdateVisibleRainSprites(void)
+{
+ if (gWeatherPtr->curRainSpriteIndex == gWeatherPtr->targetRainSpriteCount)
+ return FALSE;
+
+ if (++gWeatherPtr->rainSpriteVisibleCounter > gWeatherPtr->rainSpriteVisibleDelay)
+ {
+ gWeatherPtr->rainSpriteVisibleCounter = 0;
+ if (gWeatherPtr->curRainSpriteIndex < gWeatherPtr->targetRainSpriteCount)
+ {
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->curRainSpriteIndex++]->tActive = 1;
+ }
+ else
+ {
+ gWeatherPtr->curRainSpriteIndex--;
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->curRainSpriteIndex]->tActive = 0;
+ gWeatherPtr->sprites.s1.rainSprites[gWeatherPtr->curRainSpriteIndex]->invisible = TRUE;
+ }
+ }
+ return TRUE;
+}
+
+static 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);
+}
+
+#undef tCounter
+#undef tRandom
+#undef tPosX
+#undef tPosY
+#undef tState
+#undef tActive
+#undef tWaiting
+
+//------------------------------------------------------------------------------
+// Snow
+//------------------------------------------------------------------------------
+
+static void UpdateSnowflakeSprite(struct Sprite *);
+static bool8 UpdateVisibleSnowflakeSprites(void);
+static bool8 CreateSnowflakeSprite(void);
+static bool8 DestroySnowflakeSprite(void);
+static void InitSnowflakeSpriteMovement(struct Sprite *);
+
+void Snow_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->targetSnowflakeSpriteCount = 16;
+ gWeatherPtr->snowflakeVisibleCounter = 0;
+}
+
+void Snow_InitAll(void)
+{
+ u16 i;
+
+ Snow_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ {
+ Snow_Main();
+ for (i = 0; i < gWeatherPtr->snowflakeSpriteCount; i++)
+ UpdateSnowflakeSprite(gWeatherPtr->sprites.s1.snowflakeSprites[i]);
+ }
+}
+
+void Snow_Main(void)
+{
+ if (gWeatherPtr->initStep == 0 && !UpdateVisibleSnowflakeSprites())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+}
+
+bool8 Snow_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ gWeatherPtr->targetSnowflakeSpriteCount = 0;
+ gWeatherPtr->snowflakeVisibleCounter = 0;
+ gWeatherPtr->finishStep++;
+ // fall through
+ case 1:
+ if (!UpdateVisibleSnowflakeSprites())
+ {
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool8 UpdateVisibleSnowflakeSprites(void)
+{
+ if (gWeatherPtr->snowflakeSpriteCount == gWeatherPtr->targetSnowflakeSpriteCount)
+ return FALSE;
+
+ if (++gWeatherPtr->snowflakeVisibleCounter > 36)
+ {
+ gWeatherPtr->snowflakeVisibleCounter = 0;
+ if (gWeatherPtr->snowflakeSpriteCount < gWeatherPtr->targetSnowflakeSpriteCount)
+ CreateSnowflakeSprite();
+ else
+ DestroySnowflakeSprite();
+ }
+
+ return gWeatherPtr->snowflakeSpriteCount != gWeatherPtr->targetSnowflakeSpriteCount;
+}
+
+static const struct OamData sSnowflakeSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(8x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x8),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteFrameImage sSnowflakeSpriteImages[] = {
+ {gWeatherSnow1Tiles, 0x20},
+ {gWeatherSnow2Tiles, 0x20},
+};
+
+static const union AnimCmd sSnowflakeAnimCmd0[] = {
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sSnowflakeAnimCmd1[] = {
+ ANIMCMD_FRAME(1, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSnowflakeAnimCmds[] = {
+ sSnowflakeAnimCmd0,
+ sSnowflakeAnimCmd1,
+};
+
+static const struct SpriteTemplate sSnowflakeSpriteTemplate = {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0x1200,
+ .oam = &sSnowflakeSpriteOamData,
+ .anims = sSnowflakeAnimCmds,
+ .images = sSnowflakeSpriteImages,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateSnowflakeSprite,
+};
+
+#define tPosY data[0]
+#define tDeltaY data[1]
+#define tWaveDelta data[2]
+#define tWaveIndex data[3]
+#define tSnowflakeId data[4]
+#define tFallCounter data[5]
+#define tFallDuration data[6]
+#define tDeltaY2 data[7]
+
+static bool8 CreateSnowflakeSprite(void)
+{
+ u8 spriteId = CreateSpriteAtEnd(&sSnowflakeSpriteTemplate, 0, 0, 78);
+ if (spriteId == MAX_SPRITES)
+ return FALSE;
+
+ gSprites[spriteId].tSnowflakeId = gWeatherPtr->snowflakeSpriteCount;
+ InitSnowflakeSpriteMovement(&gSprites[spriteId]);
+ gSprites[spriteId].coordOffsetEnabled = TRUE;
+ gWeatherPtr->sprites.s1.snowflakeSprites[gWeatherPtr->snowflakeSpriteCount++] = &gSprites[spriteId];
+ return TRUE;
+}
+
+static bool8 DestroySnowflakeSprite(void)
+{
+ if (gWeatherPtr->snowflakeSpriteCount)
+ {
+ DestroySprite(gWeatherPtr->sprites.s1.snowflakeSprites[--gWeatherPtr->snowflakeSpriteCount]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void InitSnowflakeSpriteMovement(struct Sprite *sprite)
+{
+ u16 rand;
+ u16 x = ((sprite->tSnowflakeId * 5) & 7) * 30 + (Random() % 30);
+
+ sprite->pos1.y = -3 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->pos1.x = x - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+ sprite->tPosY = sprite->pos1.y * 128;
+ sprite->pos2.x = 0;
+ rand = Random();
+ sprite->tDeltaY = (rand & 3) * 5 + 64;
+ sprite->tDeltaY2 = sprite->tDeltaY;
+ StartSpriteAnim(sprite, (rand & 1) ? 0 : 1);
+ sprite->tWaveIndex = 0;
+ sprite->tWaveDelta = ((rand & 3) == 0) ? 2 : 1;
+ sprite->tFallDuration = (rand & 0x1F) + 210;
+ sprite->tFallCounter = 0;
+}
+
+static void WaitSnowflakeSprite(struct Sprite *sprite)
+{
+ if (gWeatherPtr->unknown_6E2 > 18)
+ {
+ sprite->invisible = FALSE;
+ sprite->callback = UpdateSnowflakeSprite;
+ sprite->pos1.y = 250 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->tPosY = sprite->pos1.y * 128;
+ gWeatherPtr->unknown_6E2 = 0;
+ }
+}
+
+static void UpdateSnowflakeSprite(struct Sprite *sprite)
+{
+ s16 x;
+ s16 y;
+
+ sprite->tPosY += sprite->tDeltaY;
+ sprite->pos1.y = sprite->tPosY >> 7;
+ sprite->tWaveIndex += sprite->tWaveDelta;
+ sprite->tWaveIndex &= 0xFF;
+ sprite->pos2.x = gSineTable[sprite->tWaveIndex] / 64;
+
+ x = (sprite->pos1.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX) & 0x1FF;
+ if (x & 0x100)
+ x |= -0x100;
+
+ if (x < -3)
+ sprite->pos1.x = 242 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+ else if (x > 242)
+ sprite->pos1.x = -3 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
+
+ y = (sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY) & 0xFF;
+ if (y > 163 && y < 171)
+ {
+ sprite->pos1.y = 250 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
+ sprite->tPosY = sprite->pos1.y * 128;
+ sprite->tFallCounter = 0;
+ sprite->tFallDuration = 220;
+ }
+ else if (y > 242 && y < 250)
+ {
+ sprite->pos1.y = 163;
+ sprite->tPosY = sprite->pos1.y * 128;
+ sprite->tFallCounter = 0;
+ sprite->tFallDuration = 220;
+ sprite->invisible = TRUE;
+ sprite->callback = WaitSnowflakeSprite;
+ }
+
+ if (++sprite->tFallCounter == sprite->tFallDuration)
+ {
+ InitSnowflakeSpriteMovement(sprite);
+ sprite->pos1.y = 250;
+ sprite->invisible = TRUE;
+ sprite->callback = WaitSnowflakeSprite;
+ }
+}
+
+#undef tPosY
+#undef tDeltaY
+#undef tWaveDelta
+#undef tWaveIndex
+#undef tSnowflakeId
+#undef tFallCounter
+#undef tFallDuration
+#undef tDeltaY2
+
+//------------------------------------------------------------------------------
+// WEATHER_RAIN_THUNDERSTORM
+//------------------------------------------------------------------------------
+
+void Thunderstorm_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->rainSpriteVisibleCounter = 0;
+ gWeatherPtr->rainSpriteVisibleDelay = 4;
+ gWeatherPtr->isDownpour = FALSE;
+ gWeatherPtr->targetRainSpriteCount = 16;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE; // duplicate assignment
+ gWeatherPtr->thunderTriggered = FALSE;
+ SetRainStrengthFromSoundEffect(SE_T_AME);
+}
+
+void Thunderstorm_InitAll(void)
+{
+ Thunderstorm_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Thunderstorm_Main();
+}
+
+//------------------------------------------------------------------------------
+// WEATHER_DOWNPOUR
+//------------------------------------------------------------------------------
+
+static void UpdateThunderSound(void);
+static void SetThunderCounter(u16);
+
+void Downpour_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->rainSpriteVisibleCounter = 0;
+ gWeatherPtr->rainSpriteVisibleDelay = 4;
+ gWeatherPtr->isDownpour = TRUE;
+ gWeatherPtr->targetRainSpriteCount = 24;
+ gWeatherPtr->gammaTargetIndex = 3;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->weatherGfxLoaded = FALSE; // duplicate assignment
+ SetRainStrengthFromSoundEffect(SE_T_OOAME);
+}
+
+void Downpour_InitAll(void)
+{
+ Downpour_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Thunderstorm_Main();
+}
+
+void Thunderstorm_Main(void)
+{
+ UpdateThunderSound();
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ LoadRainSpriteSheet();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ if (!CreateRainSprite())
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (!UpdateVisibleRainSprites())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ case 3:
+ if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_CHANGING_WEATHER)
+ 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)
+ 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_807A790(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)
+ {
+ sub_807A790(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)
+ gWeatherPtr->initStep = 8;
+ break;
+ case 11:
+ gWeatherPtr->unknown_6E6 = (Random() % 16) + 60;
+ gWeatherPtr->initStep++;
+ break;
+ case 12:
+ if (--gWeatherPtr->unknown_6E6 == 0)
+ {
+ SetThunderCounter(100);
+ sub_807A790(19);
+ gWeatherPtr->unknown_6E6 = (Random() & 0xF) + 30;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ case 13:
+ if (--gWeatherPtr->unknown_6E6 == 0)
+ {
+ sub_807A7C4(19, 3, 5);
+ gWeatherPtr->initStep++;
+ }
+ break;
+ case 14:
+ if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE)
+ {
+ gWeatherPtr->unknown_6EA = 1;
+ gWeatherPtr->initStep = 4;
+ }
+ break;
+ }
+}
+
+bool8 Thunderstorm_Finish(void)
+{
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ gWeatherPtr->unknown_6EA = 0;
+ gWeatherPtr->finishStep++;
+ // fall through
+ case 1:
+ Thunderstorm_Main();
+ if (gWeatherPtr->unknown_6EA)
+ {
+ if (gWeatherPtr->nextWeather == WEATHER_RAIN
+ || gWeatherPtr->nextWeather == WEATHER_RAIN_THUNDERSTORM
+ || gWeatherPtr->nextWeather == WEATHER_DOWNPOUR)
+ return FALSE;
+
+ gWeatherPtr->targetRainSpriteCount = 0;
+ gWeatherPtr->finishStep++;
+ }
+ break;
+ case 2:
+ if (!UpdateVisibleRainSprites())
+ {
+ DestroyRainSprites();
+ gWeatherPtr->thunderTriggered = FALSE;
+ gWeatherPtr->finishStep++;
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void SetThunderCounter(u16 max)
+{
+ if (!gWeatherPtr->thunderTriggered)
+ {
+ gWeatherPtr->thunderCounter = Random() % max;
+ gWeatherPtr->thunderTriggered = TRUE;
+ }
+}
+
+static void UpdateThunderSound(void)
+{
+ if (gWeatherPtr->thunderTriggered == TRUE)
+ {
+ if (gWeatherPtr->thunderCounter == 0)
+ {
+ if (IsSEPlaying())
+ return;
+
+ if (Random() & 1)
+ PlaySE(SE_T_KAMI);
+ else
+ PlaySE(SE_T_KAMI2);
+
+ gWeatherPtr->thunderTriggered = FALSE;
+ }
+ else
+ {
+ gWeatherPtr->thunderCounter--;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// WEATHER_FOG_HORIZONTAL and WEATHER_UNDERWATER
+//------------------------------------------------------------------------------
+
+// unused data
+static const u16 unusedData_839AB1C[] = {0, 6, 6, 12, 18, 42, 300, 300};
+
+static const struct OamData gOamData_839AB2C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .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 FogHorizontalSpriteCallback(struct Sprite *);
+static const struct SpriteTemplate sFogHorizontalSpriteTemplate = {
+ .tileTag = 0x1201,
+ .paletteTag = 0x1200,
+ .oam = &gOamData_839AB2C,
+ .anims = gSpriteAnimTable_839AB64,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_839AB8C,
+ .callback = FogHorizontalSpriteCallback,
+};
+
+static void CreateFogHorizontalSprites(void);
+static void DestroyFogHorizontalSprites(void);
+
+void FogHorizontal_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = FALSE;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ if (!gWeatherPtr->fogHSpritesCreated)
+ {
+ gWeatherPtr->fogHScrollCounter = 0;
+ gWeatherPtr->fogHScrollOffset = 0;
+ gWeatherPtr->fogHScrollPosX = 0;
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void FogHorizontal_InitAll(void)
+{
+ FogHorizontal_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ FogHorizontal_Main();
+}
+
+void FogHorizontal_Main(void)
+{
+ gWeatherPtr->fogHScrollPosX = (gSpriteCoordOffsetX - gWeatherPtr->fogHScrollOffset) & 0xFF;
+ if (++gWeatherPtr->fogHScrollCounter > 3)
+ {
+ gWeatherPtr->fogHScrollCounter = 0;
+ gWeatherPtr->fogHScrollOffset++;
+ }
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateFogHorizontalSprites();
+ if (gWeatherPtr->currWeather == WEATHER_FOG_HORIZONTAL)
+ 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 FogHorizontal_Finish(void)
+{
+ gWeatherPtr->fogHScrollPosX = (gSpriteCoordOffsetX - gWeatherPtr->fogHScrollOffset) & 0xFF;
+ if (++gWeatherPtr->fogHScrollCounter > 3)
+ {
+ gWeatherPtr->fogHScrollCounter = 0;
+ gWeatherPtr->fogHScrollOffset++;
+ }
+
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 3);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (Weather_UpdateBlend())
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ DestroyFogHorizontalSprites();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#define tSpriteColumn data[0]
+
+static void FogHorizontalSpriteCallback(struct Sprite *sprite)
+{
+ sprite->pos2.y = (u8)gSpriteCoordOffsetY;
+ sprite->pos1.x = gWeatherPtr->fogHScrollPosX + 32 + sprite->tSpriteColumn * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = 480 + gWeatherPtr->fogHScrollPosX - (4 - sprite->tSpriteColumn) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+static void CreateFogHorizontalSprites(void)
+{
+ u16 i;
+ u8 spriteId;
+ struct Sprite *sprite;
+
+ if (!gWeatherPtr->fogHSpritesCreated)
+ {
+ struct SpriteSheet fogHorizontalSpriteSheet = {
+ .data = gWeatherFogHorizontalTiles,
+ .size = 0x0800,
+ .tag = 0x1201,
+ };
+ LoadSpriteSheet(&fogHorizontalSpriteSheet);
+ for (i = 0; i < NUM_FOG_HORIZONTAL_SPRITES; i++)
+ {
+ spriteId = CreateSpriteAtEnd(&sFogHorizontalSpriteTemplate, 0, 0, 0xFF);
+ if (spriteId != MAX_SPRITES)
+ {
+ sprite = &gSprites[spriteId];
+ sprite->tSpriteColumn = i % 5;
+ sprite->pos1.x = (i % 5) * 64 + 32;
+ sprite->pos1.y = (i / 5) * 64 + 32;
+ gWeatherPtr->sprites.s2.fogHSprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.fogHSprites[i] = NULL;
+ }
+ }
+
+ gWeatherPtr->fogHSpritesCreated = TRUE;
+ }
+}
+
+static void DestroyFogHorizontalSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->fogHSpritesCreated)
+ {
+ for (i = 0; i < NUM_FOG_HORIZONTAL_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s2.fogHSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.fogHSprites[i]);
+ }
+
+ FreeSpriteTilesByTag(0x1201);
+ gWeatherPtr->fogHSpritesCreated = FALSE;
+ }
+}
+
+#undef tSpriteColumn
+
+//------------------------------------------------------------------------------
+// WEATHER_VOLCANIC_ASH
+//------------------------------------------------------------------------------
+
+static void LoadAshSpriteSheet(void);
+static void CreateAshSprites(void);
+static void DestroyAshSprites(void);
+static void UpdateAshSprite(struct Sprite *);
+
+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)); // These aren't valid blend coefficients!
+ }
+}
+
+void Ash_InitAll(void)
+{
+ Ash_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Ash_Main();
+}
+
+void Ash_Main(void)
+{
+ gWeatherPtr->ashBaseSpritesX = gSpriteCoordOffsetX & 0x1FF;
+ while (gWeatherPtr->ashBaseSpritesX >= 240)
+ gWeatherPtr->ashBaseSpritesX -= 240;
+
+ 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())
+ {
+ 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())
+ {
+ 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 = {
+ .data = gWeatherAshTiles,
+ .size = 0x1000,
+ .tag = 0x1202,
+};
+
+static void LoadAshSpriteSheet(void)
+{
+ LoadSpriteSheet(&sAshSpriteSheet);
+}
+
+static const struct OamData sAshSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 15,
+};
+
+static const union AnimCmd sAshSpriteAnimCmd0[] = {
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(64, 60),
+ ANIMCMD_JUMP(0),
+};
+
+static const union AnimCmd *const sAshSpriteAnimCmds[] = {
+ sAshSpriteAnimCmd0,
+};
+
+static const struct SpriteTemplate sAshSpriteTemplate = {
+ .tileTag = 0x1202,
+ .paletteTag = 0x1200,
+ .oam = &sAshSpriteOamData,
+ .anims = sAshSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateAshSprite,
+};
+
+#define tOffsetY data[0]
+#define tCounterY data[1]
+#define tSpriteColumn data[2]
+#define tSpriteRow data[3]
+
+static void CreateAshSprites(void)
+{
+ u8 i;
+ u8 spriteId;
+ struct Sprite *sprite;
+
+ if (!gWeatherPtr->ashSpritesCreated)
+ {
+ for (i = 0; i < NUM_ASH_SPRITES; i++)
+ {
+ spriteId = CreateSpriteAtEnd(&sAshSpriteTemplate, 0, 0, 0x4E);
+ if (spriteId != MAX_SPRITES)
+ {
+ sprite = &gSprites[spriteId];
+ sprite->tCounterY = 0;
+ sprite->tSpriteColumn = (u8)(i % 5);
+ sprite->tSpriteRow = (u8)(i / 5);
+ sprite->tOffsetY = sprite->tSpriteRow * 64 + 32;
+ gWeatherPtr->sprites.s2.ashSprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.ashSprites[i] = NULL;
+ }
+ }
+
+ gWeatherPtr->ashSpritesCreated = TRUE;
+ }
+}
+
+static void DestroyAshSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->ashSpritesCreated)
+ {
+ for (i = 0; i < NUM_ASH_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s2.ashSprites[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.ashSprites[i]);
+ }
+
+ FreeSpriteTilesByTag(0x1202);
+ gWeatherPtr->ashSpritesCreated = FALSE;
+ }
+}
+
+static void UpdateAshSprite(struct Sprite *sprite)
+{
+ if (++sprite->tCounterY > 5)
+ {
+ sprite->tCounterY = 0;
+ sprite->tOffsetY++;
+ }
+
+ sprite->pos1.y = gSpriteCoordOffsetY + sprite->tOffsetY;
+ sprite->pos1.x = gWeatherPtr->ashBaseSpritesX + 32 + sprite->tSpriteColumn * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->ashBaseSpritesX + 480 - (4 - sprite->tSpriteColumn) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+#undef tOffsetY
+#undef tCounterY
+#undef tSpriteColumn
+#undef tSpriteRow
+
+//------------------------------------------------------------------------------
+// WEATHER_FOG_DIAGONAL
+//------------------------------------------------------------------------------
+
+static void UpdateFogDiagonalMovement(void);
+static void CreateFogDiagonalSprites(void);
+static void DestroyFogDiagonalSprites(void);
+static void UpdateFogDiagonalSprite(struct Sprite *);
+
+void FogDiagonal_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = 0;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ gWeatherPtr->fogHScrollCounter = 0;
+ gWeatherPtr->fogHScrollOffset = 1;
+ if (!gWeatherPtr->fogDSpritesCreated)
+ {
+ gWeatherPtr->fogDScrollXCounter = 0;
+ gWeatherPtr->fogDScrollYCounter = 0;
+ gWeatherPtr->fogDXOffset = 0;
+ gWeatherPtr->fogDYOffset = 0;
+ gWeatherPtr->fogDBaseSpritesX = 0;
+ gWeatherPtr->fogDPosY = 0;
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void FogDiagonal_InitAll(void)
+{
+ FogDiagonal_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ FogDiagonal_Main();
+}
+
+void FogDiagonal_Main(void)
+{
+ UpdateFogDiagonalMovement();
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateFogDiagonalSprites();
+ 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;
+ }
+}
+
+bool8 FogDiagonal_Finish(void)
+{
+ UpdateFogDiagonalMovement();
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 1);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (!Weather_UpdateBlend())
+ break;
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ DestroyFogDiagonalSprites();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void UpdateFogDiagonalMovement(void)
+{
+ if (++gWeatherPtr->fogDScrollXCounter > 2)
+ {
+ gWeatherPtr->fogDXOffset++;
+ gWeatherPtr->fogDScrollXCounter = 0;
+ }
+
+ if (++gWeatherPtr->fogDScrollYCounter > 4)
+ {
+ gWeatherPtr->fogDYOffset++;
+ gWeatherPtr->fogDScrollYCounter = 0;
+ }
+
+ gWeatherPtr->fogDBaseSpritesX = (gSpriteCoordOffsetX - gWeatherPtr->fogDXOffset) & 0xFF;
+ gWeatherPtr->fogDPosY = gSpriteCoordOffsetY + gWeatherPtr->fogDYOffset;
+}
+
+static const struct SpriteSheet gFogDiagonalSpriteSheet = {
+ .data = gWeatherFogDiagonalTiles,
+ .size = 0x0800,
+ .tag = 0x1203,
+};
+
+static const struct OamData sFogDiagonalSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+};
+
+static const union AnimCmd sFogDiagonalSpriteAnimCmd0[] = {
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sFogDiagonalSpriteAnimCmds[] = {
+ sFogDiagonalSpriteAnimCmd0,
+};
+
+static const struct SpriteTemplate sFogDiagonalSpriteTemplate = {
+ .tileTag = 0x1203,
+ .paletteTag = 0x1200,
+ .oam = &sFogDiagonalSpriteOamData,
+ .anims = sFogDiagonalSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateFogDiagonalSprite,
+};
+
+#define tSpriteColumn data[0]
+#define tSpriteRow data[1]
+
+static void CreateFogDiagonalSprites(void)
+{
+ u16 i;
+ struct SpriteSheet fogDiagonalSpriteSheet;
+ u8 spriteId;
+ struct Sprite *sprite;
+
+ if (!gWeatherPtr->fogDSpritesCreated)
+ {
+ fogDiagonalSpriteSheet = gFogDiagonalSpriteSheet;
+ LoadSpriteSheet(&fogDiagonalSpriteSheet);
+ for (i = 0; i < NUM_FOG_DIAGONAL_SPRITES; i++)
+ {
+ spriteId = CreateSpriteAtEnd(&sFogDiagonalSpriteTemplate, 0, (i / 5) * 64, 0xFF);
+ if (spriteId != MAX_SPRITES)
+ {
+ sprite = &gSprites[spriteId];
+ sprite->tSpriteColumn = i % 5;
+ sprite->tSpriteRow = i / 5;
+ gWeatherPtr->sprites.s2.fogDSprites[i] = sprite;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.fogDSprites[i] = NULL;
+ }
+ }
+
+ gWeatherPtr->fogDSpritesCreated = TRUE;
+ }
+}
+
+static void DestroyFogDiagonalSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->fogDSpritesCreated)
+ {
+ for (i = 0; i < NUM_FOG_DIAGONAL_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s2.fogDSprites[i])
+ DestroySprite(gWeatherPtr->sprites.s2.fogDSprites[i]);
+ }
+
+ FreeSpriteTilesByTag(0x1203);
+ gWeatherPtr->fogDSpritesCreated = FALSE;
+ }
+}
+
+static void UpdateFogDiagonalSprite(struct Sprite *sprite)
+{
+ sprite->pos2.y = gWeatherPtr->fogDPosY;
+ sprite->pos1.x = gWeatherPtr->fogDBaseSpritesX + 32 + sprite->tSpriteColumn * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->fogDBaseSpritesX + 480 - (4 - sprite->tSpriteColumn) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+#undef tSpriteColumn
+#undef tSpriteRow
+
+//------------------------------------------------------------------------------
+// WEATHER_SANDSTORM
+//------------------------------------------------------------------------------
+
+static void UpdateSandstormWaveIndex(void);
+static void UpdateSandstormMovement(void);
+static void CreateSandstormSprites(void);
+static void CreateSwirlSandstormSprites(void);
+static void DestroySandstormSprites(void);
+static void UpdateSandstormSprite(struct Sprite *);
+static void WaitSandSwirlSpriteEntrance(struct Sprite *);
+static void UpdateSandstormSwirlSprite(struct Sprite *);
+
+#define MIN_SANDSTORM_WAVE_INDEX 0x20
+
+void Sandstorm_InitVars(void)
+{
+ gWeatherPtr->initStep = 0;
+ gWeatherPtr->weatherGfxLoaded = 0;
+ gWeatherPtr->gammaTargetIndex = 0;
+ gWeatherPtr->gammaStepDelay = 20;
+ if (!gWeatherPtr->sandstormSpritesCreated)
+ {
+ gWeatherPtr->sandstormXOffset = gWeatherPtr->sandstormYOffset = 0;
+ gWeatherPtr->sandstormWaveIndex = 8;
+ gWeatherPtr->sandstormWaveCounter = 0;
+ // Dead code. How does the compiler not optimize this out?
+ if (gWeatherPtr->sandstormWaveIndex >= 0x80 - MIN_SANDSTORM_WAVE_INDEX)
+ gWeatherPtr->sandstormWaveIndex = 0x80 - gWeatherPtr->sandstormWaveIndex;
+
+ Weather_SetBlendCoeffs(0, 16);
+ }
+}
+
+void Sandstorm_InitAll(void)
+{
+ Sandstorm_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Sandstorm_Main();
+}
+
+void Sandstorm_Main(void)
+{
+ UpdateSandstormMovement();
+ UpdateSandstormWaveIndex();
+ if (gWeatherPtr->sandstormWaveIndex >= 0x80 - MIN_SANDSTORM_WAVE_INDEX)
+ gWeatherPtr->sandstormWaveIndex = MIN_SANDSTORM_WAVE_INDEX;
+
+ switch (gWeatherPtr->initStep)
+ {
+ case 0:
+ CreateSandstormSprites();
+ CreateSwirlSandstormSprites();
+ gWeatherPtr->initStep++;
+ break;
+ case 1:
+ Weather_SetTargetBlendCoeffs(16, 0, 0);
+ gWeatherPtr->initStep++;
+ break;
+ case 2:
+ if (Weather_UpdateBlend())
+ {
+ gWeatherPtr->weatherGfxLoaded = TRUE;
+ gWeatherPtr->initStep++;
+ }
+ break;
+ }
+}
+
+bool8 Sandstorm_Finish(void)
+{
+ UpdateSandstormMovement();
+ UpdateSandstormWaveIndex();
+ switch (gWeatherPtr->finishStep)
+ {
+ case 0:
+ Weather_SetTargetBlendCoeffs(0, 16, 0);
+ gWeatherPtr->finishStep++;
+ break;
+ case 1:
+ if (Weather_UpdateBlend())
+ gWeatherPtr->finishStep++;
+ break;
+ case 2:
+ DestroySandstormSprites();
+ gWeatherPtr->finishStep++;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void UpdateSandstormWaveIndex(void)
+{
+ if (gWeatherPtr->sandstormWaveCounter++ > 4)
+ {
+ gWeatherPtr->sandstormWaveIndex++;
+ gWeatherPtr->sandstormWaveCounter = 0;
+ }
+}
+
+static void UpdateSandstormMovement(void)
+{
+ gWeatherPtr->sandstormXOffset -= gSineTable[gWeatherPtr->sandstormWaveIndex] * 4;
+ gWeatherPtr->sandstormYOffset -= gSineTable[gWeatherPtr->sandstormWaveIndex];
+ gWeatherPtr->sandstormBaseSpritesX = (gSpriteCoordOffsetX + (gWeatherPtr->sandstormXOffset >> 8)) & 0xFF;
+ gWeatherPtr->sandstormPosY = gSpriteCoordOffsetY + (gWeatherPtr->sandstormYOffset >> 8);
+}
+
+static void DestroySandstormSprites(void)
+{
+ u16 i;
+
+ if (gWeatherPtr->sandstormSpritesCreated)
+ {
+ for (i = 0; i < NUM_SANDSTORM_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s2.sandstormSprites1[i])
+ DestroySprite(gWeatherPtr->sprites.s2.sandstormSprites1[i]);
+ }
+
+ gWeatherPtr->sandstormSpritesCreated = FALSE;
+ FreeSpriteTilesByTag(0x1204);
+ }
+
+ if (gWeatherPtr->sandstormSwirlSpritesCreated)
+ {
+ for (i = 0; i < NUM_SWIRL_SANDSTORM_SPRITES; i++)
+ {
+ if (gWeatherPtr->sprites.s2.sandstormSprites2[i] != NULL)
+ DestroySprite(gWeatherPtr->sprites.s2.sandstormSprites2[i]);
+ }
+
+ gWeatherPtr->sandstormSwirlSpritesCreated = FALSE;
+ }
+}
+
+static const struct OamData sSandstormSpriteOamData = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+};
+
+static const union AnimCmd sSandstormSpriteAnimCmd0[] = {
+ ANIMCMD_FRAME(0, 3),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sSandstormSpriteAnimCmd1[] = {
+ ANIMCMD_FRAME(64, 3),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSandstormSpriteAnimCmds[] = {
+ sSandstormSpriteAnimCmd0,
+ sSandstormSpriteAnimCmd1,
+};
+
+static const struct SpriteTemplate sSandstormSpriteTemplate = {
+ .tileTag = 0x1204,
+ .paletteTag = 0x1200,
+ .oam = &sSandstormSpriteOamData,
+ .anims = sSandstormSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateSandstormSprite,
+};
+
+static const struct SpriteSheet sSandstormSpriteSheet = {
+ .data = gWeatherSandstormTiles,
+ .size = 0x0a00,
+ .tag = 0x1204,
+};
+
+// Regular sandstorm sprites
+#define tSpriteColumn data[0]
+#define tSpriteRow data[1]
+
+// Swirly sandstorm sprites
+#define tRadius data[0]
+#define tWaveIndex data[1]
+#define tRadiusCounter data[2]
+#define tEntranceDelay data[3]
+
+static void CreateSandstormSprites(void)
+{
+ u16 i;
+ u8 spriteId;
+
+ if (!gWeatherPtr->sandstormSpritesCreated)
+ {
+ LoadSpriteSheet(&sSandstormSpriteSheet);
+ LoadCustomWeatherSpritePalette(gSandstormWeatherPalette);
+ for (i = 0; i < NUM_SANDSTORM_SPRITES; i++)
+ {
+ spriteId = CreateSpriteAtEnd(&sSandstormSpriteTemplate, 0, (i / 5) * 64, 1);
+ if (spriteId != MAX_SPRITES)
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites1[i] = &gSprites[spriteId];
+ gWeatherPtr->sprites.s2.sandstormSprites1[i]->tSpriteColumn = i % 5;
+ gWeatherPtr->sprites.s2.sandstormSprites1[i]->tSpriteRow = i / 5;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites1[i] = NULL;
+ }
+ }
+
+ gWeatherPtr->sandstormSpritesCreated = TRUE;
+ }
+}
+
+static const u16 sSwirlEntranceDelays[] = {0, 120, 80, 160, 40, 0};
+
+static void CreateSwirlSandstormSprites(void)
+{
+ u16 i;
+ u8 spriteId;
+
+ if (!gWeatherPtr->sandstormSwirlSpritesCreated)
+ {
+ for (i = 0; i < NUM_SWIRL_SANDSTORM_SPRITES; i++)
+ {
+ 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 = ST_OAM_SIZE_2;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->tSpriteRow = i * 51;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->tRadius = 8;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->tRadiusCounter = 0;
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->data[4] = 0x6730; // unused value
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->tEntranceDelay = sSwirlEntranceDelays[i];
+ StartSpriteAnim(gWeatherPtr->sprites.s2.sandstormSprites2[i], 1);
+ CalcCenterToCornerVec(gWeatherPtr->sprites.s2.sandstormSprites2[i], SPRITE_SHAPE(32x32), SPRITE_SIZE(32x32), ST_OAM_AFFINE_OFF);
+ gWeatherPtr->sprites.s2.sandstormSprites2[i]->callback = WaitSandSwirlSpriteEntrance;
+ }
+ else
+ {
+ gWeatherPtr->sprites.s2.sandstormSprites2[i] = NULL;
+ }
+
+ gWeatherPtr->sandstormSwirlSpritesCreated = TRUE;
+ }
+ }
+}
+
+static void UpdateSandstormSprite(struct Sprite *sprite)
+{
+ sprite->pos2.y = gWeatherPtr->sandstormPosY;
+ sprite->pos1.x = gWeatherPtr->sandstormBaseSpritesX + 32 + sprite->tSpriteColumn * 64;
+ if (sprite->pos1.x > 271)
+ {
+ sprite->pos1.x = gWeatherPtr->sandstormBaseSpritesX + 480 - (4 - sprite->tSpriteColumn) * 64;
+ sprite->pos1.x &= 0x1FF;
+ }
+}
+
+static void WaitSandSwirlSpriteEntrance(struct Sprite *sprite)
+{
+ if (--sprite->tEntranceDelay == -1)
+ sprite->callback = UpdateSandstormSwirlSprite;
+}
+
+static void UpdateSandstormSwirlSprite(struct Sprite *sprite)
+{
+ u32 x, y;
+
+ if (--sprite->pos1.y < -48)
+ {
+ sprite->pos1.y = 208;
+ sprite->tRadius = 4;
+ }
+
+ x = sprite->tRadius * gSineTable[sprite->tWaveIndex];
+ y = sprite->tRadius * gSineTable[sprite->tWaveIndex + 0x40];
+ sprite->pos2.x = x >> 8;
+ sprite->pos2.y = y >> 8;
+ sprite->tWaveIndex = (sprite->tWaveIndex + 10) & 0xFF;
+ if (++sprite->tRadiusCounter > 8)
+ {
+ sprite->tRadiusCounter = 0;
+ sprite->tRadius++;
+ }
+}
+
+#undef tSpriteColumn
+#undef tSpriteRow
+
+#undef tRadius
+#undef tWaveIndex
+#undef tRadiusCounter
+#undef tEntranceDelay
+
+//------------------------------------------------------------------------------
+// WEATHER_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_UNDERWATER_BUBBLES
+//------------------------------------------------------------------------------
+
+static void CreateBubbleSprite(u16);
+static void DestroyBubbleSprites(void);
+static void UpdateBubbleSprite(struct Sprite *);
+
+static const u8 sBubbleStartDelays[] = {40, 90, 60, 90, 2, 60, 40, 30};
+
+static const struct SpriteSheet sWeatherBubbleSpriteSheet = {
+ .data = gWeatherBubbleTiles,
+ .size = 0x0040,
+ .tag = 0x1205,
+};
+
+static const s16 sBubbleStartCoords[][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},
+};
+
+void Bubbles_InitVars(void)
+{
+ FogHorizontal_InitVars();
+ if (!gWeatherPtr->bubblesSpritesCreated)
+ {
+ LoadSpriteSheet(&sWeatherBubbleSpriteSheet);
+ gWeatherPtr->bubblesDelayIndex = 0;
+ gWeatherPtr->bubblesDelayCounter = sBubbleStartDelays[0];
+ gWeatherPtr->bubblesCoordsIndex = 0;
+ gWeatherPtr->bubblesSpriteCount = 0;
+ }
+}
+
+void Bubbles_InitAll(void)
+{
+ Bubbles_InitVars();
+ while (!gWeatherPtr->weatherGfxLoaded)
+ Bubbles_Main();
+}
+
+void Bubbles_Main(void)
+{
+ FogHorizontal_Main();
+ if (++gWeatherPtr->bubblesDelayCounter > sBubbleStartDelays[gWeatherPtr->bubblesDelayIndex])
+ {
+ gWeatherPtr->bubblesDelayCounter = 0;
+ if (++gWeatherPtr->bubblesDelayIndex > NELEMS(sBubbleStartDelays) - 1)
+ gWeatherPtr->bubblesDelayIndex = 0;
+
+ CreateBubbleSprite(gWeatherPtr->bubblesCoordsIndex);
+ if (++gWeatherPtr->bubblesCoordsIndex > NELEMS(sBubbleStartCoords) - 1)
+ gWeatherPtr->bubblesCoordsIndex = 0;
+ }
+}
+
+bool8 Bubbles_Finish(void)
+{
+ if (!FogHorizontal_Finish())
+ {
+ DestroyBubbleSprites();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static const union AnimCmd sBubbleSpriteAnimCmd0[] = {
+ ANIMCMD_FRAME(0, 16),
+ ANIMCMD_FRAME(1, 16),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sBubbleSpriteAnimCmds[] = {
+ sBubbleSpriteAnimCmd0,
+};
+
+static const struct SpriteTemplate sBubbleSpriteTemplate = {
+ .tileTag = 0x1205,
+ .paletteTag = 0x1200,
+ .oam = &gOamData_AffineOff_ObjNormal_8x8,
+ .anims = sBubbleSpriteAnimCmds,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = UpdateBubbleSprite,
+};
+
+#define tScrollXCounter data[0]
+#define tScrollXDir data[1]
+#define tCounter data[2]
+
+static void CreateBubbleSprite(u16 coordsIndex)
+{
+ s16 x = sBubbleStartCoords[coordsIndex][0];
+ s16 y = sBubbleStartCoords[coordsIndex][1] - gSpriteCoordOffsetY;
+ u8 spriteId = CreateSpriteAtEnd(&sBubbleSpriteTemplate, x, y, 0);
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].oam.priority = 1;
+ gSprites[spriteId].coordOffsetEnabled = TRUE;
+ gSprites[spriteId].tScrollXCounter = 0;
+ gSprites[spriteId].tScrollXDir = 0;
+ gSprites[spriteId].tCounter = 0;
+ gWeatherPtr->bubblesSpriteCount++;
+ }
+}
+
+static void DestroyBubbleSprites(void)
+{
+ u16 i;
+
+ for (i = 0; i < MAX_SPRITES; i++)
+ {
+ if (gSprites[i].template == &sBubbleSpriteTemplate)
+ DestroySprite(&gSprites[i]);
+ }
+
+ FreeSpriteTilesByTag(0x1205);
+}
+
+static void UpdateBubbleSprite(struct Sprite *sprite)
+{
+ ++sprite->tScrollXCounter;
+ if (++sprite->tScrollXCounter > 8) // double increment
+ {
+ sprite->tScrollXCounter = 0;
+ if (sprite->tScrollXDir == 0)
+ {
+ if (++sprite->pos2.x > 4)
+ sprite->tScrollXDir = 1;
+ }
+ else
+ {
+ if (--sprite->pos2.x <= 0)
+ sprite->tScrollXDir = 0;
+ }
+ }
+
+ sprite->pos1.y -= 3;
+ if (++sprite->tCounter >= 120)
+ DestroySprite(sprite);
+}
+
+#undef tScrollXCounter
+#undef tScrollXDir
+#undef tCounter
diff --git a/src/field_weather_util.c b/src/field_weather_util.c
new file mode 100644
index 000000000..459071736
--- /dev/null
+++ b/src/field_weather_util.c
@@ -0,0 +1,105 @@
+#include "global.h"
+#include "field_weather.h"
+#include "overworld.h"
+#include "constants/weather.h"
+
+static u8 TranslateWeatherNum(u8 weather);
+static void UpdateRainCounter(u8 newWeather, u8 oldWeather);
+
+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);
+ SetNextWeather(GetSav1Weather());
+}
+
+void SetWeather_Unused(u32 weather)
+{
+ SetSav1Weather(weather);
+ SetCurrentAndNextWeather(GetSav1Weather());
+}
+
+void DoCurrentWeather(void)
+{
+ u8 weather = GetSav1Weather();
+
+ SetNextWeather(weather);
+}
+
+void ResumePausedWeather(void)
+{
+ u8 weather = GetSav1Weather();
+
+ SetCurrentAndNextWeather(weather);
+}
+
+static const u8 sWeatherCycleRoute119[] = {
+ WEATHER_SUNNY,
+ WEATHER_RAIN,
+ WEATHER_RAIN_THUNDERSTORM,
+ WEATHER_RAIN,
+};
+
+static const u8 sWeatherCycleRoute123[] = {
+ WEATHER_SUNNY,
+ WEATHER_SUNNY,
+ WEATHER_RAIN,
+ WEATHER_SUNNY,
+};
+
+static u8 TranslateWeatherNum(u8 weather)
+{
+ switch (weather)
+ {
+ case WEATHER_NONE: return WEATHER_NONE;
+ case WEATHER_SUNNY_CLOUDS: return WEATHER_SUNNY_CLOUDS;
+ case WEATHER_SUNNY: return WEATHER_SUNNY;
+ case WEATHER_RAIN: return WEATHER_RAIN;
+ case WEATHER_SNOW: return WEATHER_SNOW;
+ case WEATHER_RAIN_THUNDERSTORM: return WEATHER_RAIN_THUNDERSTORM;
+ case WEATHER_FOG_HORIZONTAL: return WEATHER_FOG_HORIZONTAL;
+ case WEATHER_VOLCANIC_ASH: return WEATHER_VOLCANIC_ASH;
+ case WEATHER_SANDSTORM: return WEATHER_SANDSTORM;
+ case WEATHER_FOG_DIAGONAL: return WEATHER_FOG_DIAGONAL;
+ case WEATHER_UNDERWATER: return WEATHER_UNDERWATER;
+ case WEATHER_SHADE: return WEATHER_SHADE;
+ case WEATHER_DROUGHT: return WEATHER_DROUGHT;
+ case WEATHER_DOWNPOUR: return WEATHER_DOWNPOUR;
+ case WEATHER_UNDERWATER_BUBBLES: return WEATHER_UNDERWATER_BUBBLES;
+ 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 || newWeather == WEATHER_RAIN_THUNDERSTORM))
+ IncrementGameStat(GAME_STAT_GOT_RAINED_ON);
+}
diff --git a/src/graphics.c b/src/graphics.c
index 69e804fd9..5a802cd35 100644
--- a/src/graphics.c
+++ b/src/graphics.c
@@ -1247,10 +1247,10 @@ const u32 gUnknown_8E9BF48[] = INCBIN_U32("graphics/interface/link_rfu_status.4b
const u16 gUnknown_8E9C14C[] = INCBIN_U16("graphics/interface/pokedex_abc.gbapal");
const u32 gUnknown_8E9C16C[] = INCBIN_U32("graphics/interface/pokedex_abc.4bpp.lz");
-const u16 gUnknown_8E9C3D8[] = INCBIN_U16("graphics/interface/box_tiles_pal1.gbapal");
+const u16 gPSSMenu_Pal[] = INCBIN_U16("graphics/interface/box_tiles_pal1.gbapal");
const u16 gUnknown_8E9C3F8[] = INCBIN_U16("graphics/interface/box_tiles_pal2.gbapal");
const u16 gUnknown_8E9C418[] = INCBIN_U16("graphics/interface/box_tiles_pal3.gbapal");
-const u32 gUnknown_8E9C438[] = INCBIN_U32("graphics/interface/box_tiles.4bpp.lz");
+const u32 gPSSMenu_Gfx[] = INCBIN_U32("graphics/interface/box_tiles.4bpp.lz");
const u32 gUnknown_8E9CAEC[] = INCBIN_U32("graphics/unknown/unknown_E9CAEC.bin.lz");
diff --git a/src/hall_of_fame.c b/src/hall_of_fame.c
index 4ed0d3f04..2284cbc3f 100644
--- a/src/hall_of_fame.c
+++ b/src/hall_of_fame.c
@@ -738,7 +738,7 @@ void CB2_InitHofPC(void)
case 3:
if (!DrawHofBackground())
{
- sub_80A0A48(0, 0, 0);
+ BeginPCScreenEffect_TurnOn(0, 0, 0);
SetVBlankCallback(VBlankCB_HofIdle);
gMain.state++;
}
@@ -748,7 +748,7 @@ void CB2_InitHofPC(void)
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
- if (!sub_80A0A98())
+ if (!IsPCScreenEffectRunning_TurnOn())
gMain.state++;
break;
case 5:
@@ -946,13 +946,13 @@ static void Task_HofPC_HandlePaletteOnExit(u8 taskId)
struct HallofFameTeam* fameTeam;
CpuCopy16(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
- sub_80A0A70(0, 0, 0);
+ BeginPCScreenEffect_TurnOff(0, 0, 0);
gTasks[taskId].func = Task_HofPC_HandleExit;
}
static void Task_HofPC_HandleExit(u8 taskId)
{
- if (!sub_80A0AAC())
+ if (!IsPCScreenEffectRunning_TurnOff())
{
HideBg(0);
HideBg(1);
diff --git a/src/ice.c b/src/ice.c
index 6843538f9..8b4269a95 100644
--- a/src/ice.c
+++ b/src/ice.c
@@ -944,7 +944,7 @@ void AnimTask_Haze1(u8 taskId)
SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X);
SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
sub_80752A0(&animBg);
- LoadBgTiles(animBg.bgId, gWeatherFog1Tiles, 0x800, animBg.tilesOffset);
+ LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset);
AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimFogTilemap);
LoadPalette(&gUnknown_83C2CE0, animBg.paletteId * 16, 32);
if (IsContest())
@@ -1042,7 +1042,7 @@ void AnimTask_LoadMistTiles(u8 taskId)
SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X);
SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
sub_80752A0(&animBg);
- LoadBgTiles(animBg.bgId, gWeatherFog1Tiles, 0x800, animBg.tilesOffset);
+ LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset);
AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimFogTilemap);
LoadPalette(&gUnknown_83C2CE0, animBg.paletteId * 16, 32);
if (IsContest())
diff --git a/src/item_menu.c b/src/item_menu.c
index 4131e7fd5..e048b4b78 100644
--- a/src/item_menu.c
+++ b/src/item_menu.c
@@ -1784,7 +1784,7 @@ static void GoToBerryPouch_PCBox(void)
static void ReturnToBagMenuFromSubmenu_PCBox(void)
{
- GoToBagMenu(ITEMMENULOCATION_PCBOX, OPEN_BAG_LAST, sub_808CE60);
+ GoToBagMenu(ITEMMENULOCATION_PCBOX, OPEN_BAG_LAST, Cb2_ReturnToPSS);
}
static void Task_ItemContext_Sell(u8 taskId)
diff --git a/src/item_pc.c b/src/item_pc.c
index 46419f2f3..af57d9f03 100644
--- a/src/item_pc.c
+++ b/src/item_pc.c
@@ -378,7 +378,7 @@ static bool8 ItemPc_DoGfxSetup(void)
}
else
{
- sub_80A0A48(0, 0, 0);
+ BeginPCScreenEffect_TurnOn(0, 0, 0);
ItemPc_SetInitializedFlag(1);
PlaySE(SE_PC_LOGIN);
}
@@ -642,7 +642,7 @@ static void Task_ItemPcTurnOff1(u8 taskId)
}
else
{
- sub_80A0A70(0, 0, 0);
+ BeginPCScreenEffect_TurnOff(0, 0, 0);
PlaySE(SE_PC_OFF);
}
gTasks[taskId].func = Task_ItemPcTurnOff2;
@@ -652,7 +652,7 @@ static void Task_ItemPcTurnOff2(u8 taskId)
{
s16 * data = gTasks[taskId].data;
- if (!gPaletteFade.active && !sub_80A0AAC())
+ if (!gPaletteFade.active && !IsPCScreenEffectRunning_TurnOff())
{
DestroyListMenuTask(data[0], &sListMenuState.scroll, &sListMenuState.row);
if (sStateDataPtr->savedCallback != NULL)
@@ -726,7 +726,7 @@ static void Task_ItemPcMain(u8 taskId)
u16 row;
s32 input;
- if (!gPaletteFade.active && !sub_80A0A98())
+ if (!gPaletteFade.active && !IsPCScreenEffectRunning_TurnOn())
{
if (JOY_NEW(SELECT_BUTTON))
{
diff --git a/src/naming_screen.c b/src/naming_screen.c
index 364fc3fe6..b8b121535 100644
--- a/src/naming_screen.c
+++ b/src/naming_screen.c
@@ -1986,7 +1986,7 @@ static const struct NamingScreenTemplate sPlayerNamingScreenTemplate = {
static const struct NamingScreenTemplate sPcBoxNamingScreenTemplate = {
.copyExistingString = FALSE,
- .maxChars = 8/*BOX_NAME_LENGTH*/,
+ .maxChars = BOX_NAME_LENGTH,
.iconFunction = 2,
.addGenderIcon = 0,
.initialPage = KBPAGE_LETTERS_UPPER,
diff --git a/src/pc_screen_effect.c b/src/pc_screen_effect.c
index 5cc09df71..5ee8e2b7b 100644
--- a/src/pc_screen_effect.c
+++ b/src/pc_screen_effect.c
@@ -3,146 +3,160 @@
#include "gpu_regs.h"
#include "palette.h"
-static void sub_80A0AC0(TaskFunc func, u16 a2, UNUSED u16 a3, u8 priority);
-static void sub_80A0B0C(u8 taskId);
-static void sub_80A0C78(u8 taskId);
+/*
+ * Animates the screen as though it was a CRT monitor turning on or off.
+ */
-void sub_80A0A48(u16 a1, u16 a2, u8 a3)
+#define tState data[0]
+#define tXSpeed data[1]
+#define tYSpeed data[2]
+#define tWin0Left data[3]
+#define tWin0Right data[4]
+#define tWin0Top data[5]
+#define tWin0Bottom data[6]
+#define tBldCntBak data[7]
+#define tBldYBak data[8]
+
+static void BeginPCScreenEffect(TaskFunc func, u16 a2, UNUSED u16 a3, u8 priority);
+static void Task_PCScreenEffect_TurnOn(u8 taskId);
+static void Task_PCScreenEffect_TurnOff(u8 taskId);
+
+void BeginPCScreenEffect_TurnOn(u16 xspeed, u16 yspeed, u8 priority)
{
- sub_80A0AC0(sub_80A0B0C, a1, a2, a3);
+ BeginPCScreenEffect(Task_PCScreenEffect_TurnOn, xspeed, yspeed, priority);
}
-void sub_80A0A70(u16 a1, u16 a2, u8 a3)
+void BeginPCScreenEffect_TurnOff(u16 xspeed, u16 yspeed, u8 priority)
{
- sub_80A0AC0(sub_80A0C78, a1, a2, a3);
+ BeginPCScreenEffect(Task_PCScreenEffect_TurnOff, xspeed, yspeed, priority);
}
-bool8 sub_80A0A98(void)
+bool8 IsPCScreenEffectRunning_TurnOn(void)
{
- return FuncIsActiveTask(sub_80A0B0C);
+ return FuncIsActiveTask(Task_PCScreenEffect_TurnOn);
}
-bool8 sub_80A0AAC(void)
+bool8 IsPCScreenEffectRunning_TurnOff(void)
{
- return FuncIsActiveTask(sub_80A0C78);
+ return FuncIsActiveTask(Task_PCScreenEffect_TurnOff);
}
-static void sub_80A0AC0(TaskFunc func, u16 a2, UNUSED u16 a3, u8 priority)
+static void BeginPCScreenEffect(TaskFunc func, u16 speed, UNUSED u16 unused, u8 priority)
{
u8 taskId = CreateTask(func, priority);
- gTasks[taskId].data[0] = 0;
- gTasks[taskId].data[1] = a2 == 0 ? 16 : a2;
- gTasks[taskId].data[2] = a2 == 0 ? 20 : a2;
+ gTasks[taskId].tState = 0;
+ gTasks[taskId].tXSpeed = speed == 0 ? 16 : speed;
+ gTasks[taskId].tYSpeed = speed == 0 ? 20 : speed; // Bug? should be the unused param, not speed
gTasks[taskId].func(taskId);
}
-static void sub_80A0B0C(u8 taskId)
+static void Task_PCScreenEffect_TurnOn(u8 taskId)
{
struct Task *task = &gTasks[taskId];
- switch (task->data[0])
+ switch (task->tState)
{
case 0:
- task->data[3] = 120;
- task->data[4] = 120;
- task->data[5] = 80;
- task->data[6] = 81;
+ task->tWin0Left = 120;
+ task->tWin0Right = 120;
+ task->tWin0Top = 80;
+ task->tWin0Bottom = 81;
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
- SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->data[3], task->data[4]));
- SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->data[5], task->data[6]));
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->tWin0Left, task->tWin0Right));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->tWin0Top, task->tWin0Bottom));
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
SetGpuReg(REG_OFFSET_WINOUT, 0);
break;
case 1:
- task->data[7] = GetGpuReg(REG_OFFSET_BLDCNT);
- task->data[8] = GetGpuReg(REG_OFFSET_BLDY);
+ task->tBldCntBak = GetGpuReg(REG_OFFSET_BLDCNT);
+ task->tBldYBak = GetGpuReg(REG_OFFSET_BLDY);
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_LIGHTEN);
SetGpuReg(REG_OFFSET_BLDY, 16);
break;
case 2:
- task->data[3] -= task->data[1];
- task->data[4] += task->data[1];
- if (task->data[3] <= 0 || task->data[4] >= DISPLAY_WIDTH)
+ task->tWin0Left -= task->tXSpeed;
+ task->tWin0Right += task->tXSpeed;
+ if (task->tWin0Left <= 0 || task->tWin0Right >= DISPLAY_WIDTH)
{
- task->data[3] = 0;
- task->data[4] = DISPLAY_WIDTH;
+ task->tWin0Left = 0;
+ task->tWin0Right = DISPLAY_WIDTH;
SetGpuReg(REG_OFFSET_BLDY, 0);
- SetGpuReg(REG_OFFSET_BLDCNT, task->data[7]);
+ SetGpuReg(REG_OFFSET_BLDCNT, task->tBldCntBak);
BlendPalettes(0xFFFFFFFF, 0, RGB_BLACK);
gPlttBufferFaded[0] = 0;
}
- SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->data[3], task->data[4]));
- if (task->data[3])
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->tWin0Left, task->tWin0Right));
+ if (task->tWin0Left)
return;
break;
case 3:
- task->data[5] -= task->data[2];
- task->data[6] += task->data[2];
- if (task->data[5] <= 0 || task->data[6] >= DISPLAY_HEIGHT)
+ task->tWin0Top -= task->tYSpeed;
+ task->tWin0Bottom += task->tYSpeed;
+ if (task->tWin0Top <= 0 || task->tWin0Bottom >= DISPLAY_HEIGHT)
{
- task->data[5] = 0;
- task->data[6] = DISPLAY_HEIGHT;
+ task->tWin0Top = 0;
+ task->tWin0Bottom = DISPLAY_HEIGHT;
ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
}
- SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->data[5], task->data[6]));
- if (task->data[5])
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->tWin0Top, task->tWin0Bottom));
+ if (task->tWin0Top)
return;
break;
default:
- SetGpuReg(REG_OFFSET_BLDCNT, task->data[7]);
+ SetGpuReg(REG_OFFSET_BLDCNT, task->tBldCntBak);
DestroyTask(taskId);
return;
}
- ++task->data[0];
+ ++task->tState;
}
-static void sub_80A0C78(u8 taskId)
+static void Task_PCScreenEffect_TurnOff(u8 taskId)
{
struct Task *task = &gTasks[taskId];
- switch (task->data[0])
+ switch (task->tState)
{
case 0:
gPlttBufferFaded[0] = 0;
break;
case 1:
- task->data[3] = 0;
- task->data[4] = DISPLAY_WIDTH;
- task->data[5] = 0;
- task->data[6] = DISPLAY_HEIGHT;
+ task->tWin0Left = 0;
+ task->tWin0Right = DISPLAY_WIDTH;
+ task->tWin0Top = 0;
+ task->tWin0Bottom = DISPLAY_HEIGHT;
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
- SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->data[3], task->data[4]));
- SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->data[5], task->data[6]));
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->tWin0Left, task->tWin0Right));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->tWin0Top, task->tWin0Bottom));
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
SetGpuReg(REG_OFFSET_WINOUT, 0);
break;
case 2:
- task->data[5] += task->data[2];
- task->data[6] -= task->data[2];
- if (task->data[5] >= 80 || task->data[6] <= 81)
+ task->tWin0Top += task->tYSpeed;
+ task->tWin0Bottom -= task->tYSpeed;
+ if (task->tWin0Top >= 80 || task->tWin0Bottom <= 81)
{
- task->data[5] = 80;
- task->data[6] = 81;
+ task->tWin0Top = 80;
+ task->tWin0Bottom = 81;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_LIGHTEN);
SetGpuReg(REG_OFFSET_BLDY, 16);
}
- SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->data[5], task->data[6]));
- if (task->data[5] != 80)
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(task->tWin0Top, task->tWin0Bottom));
+ if (task->tWin0Top != 80)
return;
break;
case 3:
- task->data[3] += task->data[1];
- task->data[4] -= task->data[1];
- if (task->data[3] >= 120 || task->data[4] <= 120)
+ task->tWin0Left += task->tXSpeed;
+ task->tWin0Right -= task->tXSpeed;
+ if (task->tWin0Left >= 120 || task->tWin0Right <= 120)
{
- task->data[3] = 120;
- task->data[4] = 120;
+ task->tWin0Left = 120;
+ task->tWin0Right = 120;
BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
gPlttBufferFaded[0] = 0;
}
- SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->data[3], task->data[4]));
- if (task->data[3] != 120)
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(task->tWin0Left, task->tWin0Right));
+ if (task->tWin0Left != 120)
return;
break;
default:
@@ -152,5 +166,15 @@ static void sub_80A0C78(u8 taskId)
DestroyTask(taskId);
return;
}
- ++task->data[0];
+ ++task->tState;
}
+
+#undef tBldYBak
+#undef tBldCntBak
+#undef tWin0Bottom
+#undef tWin0Top
+#undef tWin0Right
+#undef tWin0Left
+#undef tYSpeed
+#undef tXSpeed
+#undef tState
diff --git a/src/pokemon.c b/src/pokemon.c
index f1f7834b1..b9e62502d 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -3661,7 +3661,7 @@ static u8 SendMonToPC(struct Pokemon* mon)
gSpecialVar_MonBoxId = boxNo;
gSpecialVar_MonBoxPos = boxPos;
if (GetPCBoxToSendMon() != boxNo)
- FlagClear(FLAG_SYS_CHANGED_BOX_TO_STORE_MON);
+ FlagClear(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE);
VarSet(VAR_PC_BOX_TO_SEND_MON, boxNo);
return MON_GIVEN_TO_PC;
}
@@ -3806,7 +3806,7 @@ static bool8 IsPokemonStorageFull(void)
for (i = 0; i < 14; i++)
for (j = 0; j < 30; j++)
- if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
+ if (GetBoxMonDataAt(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
return FALSE;
return TRUE;
diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c
new file mode 100644
index 000000000..b69fe7de4
--- /dev/null
+++ b/src/pokemon_storage_system.c
@@ -0,0 +1,172 @@
+#include "global.h"
+#include "gflib.h"
+#include "pokemon_storage_system_internal.h"
+#include "constants/species.h"
+
+void BackupPokemonStorage(struct PokemonStorage * dest)
+{
+ *dest = *gPokemonStoragePtr;
+}
+
+void RestorePokemonStorage(struct PokemonStorage * src)
+{
+ *gPokemonStoragePtr = *src;
+}
+
+// Functions here are general utility functions.
+u8 StorageGetCurrentBox(void)
+{
+ return gPokemonStoragePtr->currentBox;
+}
+
+void SetCurrentBox(u8 boxId)
+{
+ if (boxId < TOTAL_BOXES_COUNT)
+ gPokemonStoragePtr->currentBox = boxId;
+}
+
+u32 GetBoxMonDataAt(u8 boxId, u8 boxPosition, s32 request)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ return GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], request);
+ else
+ return 0;
+}
+
+void SetBoxMonDataAt(u8 boxId, u8 boxPosition, s32 request, const void *value)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ SetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], request, value);
+}
+
+u32 GetCurrentBoxMonData(u8 boxPosition, s32 request)
+{
+ return GetBoxMonDataAt(gPokemonStoragePtr->currentBox, boxPosition, request);
+}
+
+void SetCurrentBoxMonData(u8 boxPosition, s32 request, const void *value)
+{
+ SetBoxMonDataAt(gPokemonStoragePtr->currentBox, boxPosition, request, value);
+}
+
+void GetBoxMonNickAt(u8 boxId, u8 boxPosition, u8 *dst)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_NICKNAME, dst);
+ else
+ *dst = EOS;
+}
+
+void SetBoxMonNickAt(u8 boxId, u8 boxPosition, const u8 *nick)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ SetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_NICKNAME, nick);
+}
+
+u32 GetAndCopyBoxMonDataAt(u8 boxId, u8 boxPosition, s32 request, void *dst)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ return GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], request, dst);
+ else
+ return 0;
+}
+
+void SetBoxMonAt(u8 boxId, u8 boxPosition, struct BoxPokemon * src)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ gPokemonStoragePtr->boxes[boxId][boxPosition] = *src;
+}
+
+void CopyBoxMonAt(u8 boxId, u8 boxPosition, struct BoxPokemon * dst)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ *dst = gPokemonStoragePtr->boxes[boxId][boxPosition];
+}
+
+void CreateBoxMonAt(u8 boxId, u8 boxPosition, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 personality, u8 otIDType, u32 otID)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ {
+ CreateBoxMon(&gPokemonStoragePtr->boxes[boxId][boxPosition],
+ species,
+ level,
+ fixedIV,
+ hasFixedPersonality, personality,
+ otIDType, otID);
+ }
+}
+
+void ZeroBoxMonAt(u8 boxId, u8 boxPosition)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ ZeroBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition]);
+}
+
+void BoxMonAtToMon(u8 boxId, u8 boxPosition, struct Pokemon * dst)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ BoxMonToMon(&gPokemonStoragePtr->boxes[boxId][boxPosition], dst);
+}
+
+struct BoxPokemon * GetBoxedMonPtr(u8 boxId, u8 boxPosition)
+{
+ if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT)
+ return &gPokemonStoragePtr->boxes[boxId][boxPosition];
+ else
+ return NULL;
+}
+
+u8 *GetBoxNamePtr(u8 boxId)
+{
+ if (boxId < TOTAL_BOXES_COUNT)
+ return gPokemonStoragePtr->boxNames[boxId];
+ else
+ return NULL;
+}
+
+u8 GetBoxWallpaper(u8 boxId)
+{
+ if (boxId < TOTAL_BOXES_COUNT)
+ return gPokemonStoragePtr->boxWallpapers[boxId];
+ else
+ return 0;
+}
+
+void SetBoxWallpaper(u8 boxId, u8 wallpaperId)
+{
+ if (boxId < TOTAL_BOXES_COUNT && wallpaperId < WALLPAPER_COUNT)
+ gPokemonStoragePtr->boxWallpapers[boxId] = wallpaperId;
+}
+
+s16 SeekToNextMonInBox(struct BoxPokemon * boxMons, s8 currIndex, u8 maxIndex, u8 flags)
+{
+ // flags:
+ // bit 0: Allow eggs
+ // bit 1: Search backwards
+ s16 i;
+ s16 adder;
+ if (flags == 0 || flags == 1)
+ adder = 1;
+ else
+ adder = -1;
+
+ if (flags == 1 || flags == 3)
+ {
+ for (i = currIndex + adder; i >= 0 && i <= maxIndex; i += adder)
+ {
+ if (GetBoxMonData(&boxMons[i], MON_DATA_SPECIES) != SPECIES_NONE)
+ return i;
+ }
+ }
+ else
+ {
+ for (i = currIndex + adder; i >= 0 && i <= maxIndex; i += adder)
+ {
+ if (GetBoxMonData(&boxMons[i], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetBoxMonData(&boxMons[i], MON_DATA_IS_EGG))
+ return i;
+ }
+ }
+
+ return -1;
+}
diff --git a/src/pokemon_storage_system_2.c b/src/pokemon_storage_system_2.c
new file mode 100644
index 000000000..b806e7afa
--- /dev/null
+++ b/src/pokemon_storage_system_2.c
@@ -0,0 +1,653 @@
+#include "global.h"
+#include "gflib.h"
+#include "event_data.h"
+#include "field_fadetransition.h"
+#include "field_weather.h"
+#include "help_system.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "overworld.h"
+#include "pokemon_storage_system_internal.h"
+#include "script.h"
+#include "strings.h"
+#include "task.h"
+#include "constants/species.h"
+#include "constants/songs.h"
+#include "constants/field_weather.h"
+#include "constants/help_system.h"
+
+struct PSS_MenuStringPtrs
+{
+ const u8 *text;
+ const u8 *desc;
+};
+
+static EWRAM_DATA u8 sPreviousBoxOption = 0;
+static EWRAM_DATA struct UnkPSSStruct_2002370 *sBoxSelectionPopupSpriteManager = NULL;
+
+static void PSS_CreatePCMenu(u8 whichMenu, s16 *windowIdPtr);
+static void sub_808C9C4(u8 curBox);
+static void sub_808CBA4(void);
+static void UpdateBoxNameAndCountSprite_WraparoundRight(void);
+static void UpdateBoxNameAndCountSprite_WraparoundLeft(void);
+static void PrintBoxNameAndCountToSprite(void);
+static void PrintToSpriteWithTagUnk0240(const u8 *a0, u16 x, u16 y);
+static void sub_808CD64(struct Sprite * sprite);
+
+// Forward declarations
+
+static const u16 sBoxSelectionPopupPalette[];
+static const u16 sBoxSelectionPopupCenterTiles[];
+static const u16 sBoxSelectionPopupSidesTiles[];
+
+static const struct PSS_MenuStringPtrs sUnknown_83CDA20[] = {
+ {gText_WithdrawPokemon, gText_WithdrawMonDescription},
+ {gText_DepositPokemon, gText_DepositMonDescription },
+ {gText_MovePokemon, gText_MoveMonDescription },
+ {gText_MoveItems, gText_MoveItemsDescription },
+ {gText_SeeYa, gText_SeeYaDescription }
+};
+
+void DrawTextWindowAndBufferTiles(const u8 *string, void *dst, u8 zero1, u8 zero2, u8 *buffer, s32 bytesToBuffer)
+{
+ s32 i, tileBytesToBuffer, remainingBytes;
+ u16 windowId;
+ u8 txtColor[3];
+ u8 *tileData1, *tileData2;
+ struct WindowTemplate winTemplate = {0};
+
+ winTemplate.width = 24;
+ winTemplate.height = 2;
+ windowId = AddWindow(&winTemplate);
+ FillWindowPixelBuffer(windowId, PIXEL_FILL(zero2));
+ tileData1 = (u8*)GetWindowAttribute(windowId, WINDOW_TILE_DATA);
+ tileData2 = (winTemplate.width * 32) + tileData1;
+
+ if (!zero1)
+ txtColor[0] = TEXT_COLOR_TRANSPARENT;
+ else
+ txtColor[0] = zero2;
+ txtColor[1] = TEXT_DYNAMIC_COLOR_6;
+ txtColor[2] = TEXT_DYNAMIC_COLOR_5;
+ AddTextPrinterParameterized4(windowId, 1, 0, 2, 0, 0, txtColor, -1, string);
+
+ tileBytesToBuffer = bytesToBuffer;
+ if (tileBytesToBuffer > 6)
+ tileBytesToBuffer = 6;
+ remainingBytes = bytesToBuffer - 6;
+ if (tileBytesToBuffer > 0)
+ {
+ for (i = tileBytesToBuffer; i != 0; i--)
+ {
+ CpuCopy16(tileData1, dst, 0x80);
+ CpuCopy16(tileData2, dst + 0x80, 0x80);
+ tileData1 += 0x80;
+ tileData2 += 0x80;
+ dst += 0x100;
+ }
+ }
+
+ // Never used. bytesToBuffer is always passed <= 6, so remainingBytes is always <= 0 here
+ if (remainingBytes > 0)
+ CpuFill16((zero2 << 4) | zero2, dst, (u32)(remainingBytes) * 0x100);
+
+ RemoveWindow(windowId);
+}
+
+static void PrintStringToBufferCopyNow(const u8 *string, void *dst, u16 rise, u8 bgClr, u8 fgClr, u8 shClr, u8 *buffer)
+{
+ u32 var;
+ u8 windowId;
+ u8 txtColor[3];
+ u8 *tileData1, *tileData2;
+ struct WindowTemplate winTemplate = {0};
+
+ winTemplate.width = StringLength_Multibyte(string);
+ winTemplate.height = 2;
+ var = winTemplate.width * 32;
+ windowId = AddWindow(&winTemplate);
+ FillWindowPixelBuffer(windowId, PIXEL_FILL(bgClr));
+ tileData1 = (u8*)GetWindowAttribute(windowId, WINDOW_TILE_DATA);
+ tileData2 = (winTemplate.width * 32) + tileData1;
+ txtColor[0] = bgClr;
+ txtColor[1] = fgClr;
+ txtColor[2] = shClr;
+ AddTextPrinterParameterized4(windowId, 1, 0, 2, 0, 0, txtColor, -1, string);
+ CpuCopy16(tileData1, dst, var);
+ CpuCopy16(tileData2, dst + rise, var);
+ RemoveWindow(windowId);
+}
+
+static u8 CountMonsInBox(u8 boxId)
+{
+ u16 i, count;
+
+ for (i = 0, count = 0; i < IN_BOX_COUNT; i++)
+ {
+ if (GetBoxMonDataAt(boxId, i, MON_DATA_SPECIES) != SPECIES_NONE)
+ count++;
+ }
+
+ return count;
+}
+
+s16 GetFirstFreeBoxSpot(u8 boxId)
+{
+ u16 i;
+
+ for (i = 0; i < IN_BOX_COUNT; i++)
+ {
+ if (GetBoxMonDataAt(boxId, i, MON_DATA_SPECIES) == SPECIES_NONE)
+ return i;
+ }
+
+ return -1; // all spots are taken
+}
+
+u8 CountPartyNonEggMons(void)
+{
+ u16 i, count;
+
+ for (i = 0, count = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+u8 CountPartyAliveNonEggMonsExcept(u8 slotToIgnore)
+{
+ u16 i, count;
+
+ for (i = 0, count = 0; i < PARTY_SIZE; i++)
+ {
+ if (i != slotToIgnore
+ && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)
+ && GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0)
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+u16 CountPartyAliveNonEggMons_IgnoreVar0x8004Slot(void)
+{
+ return CountPartyAliveNonEggMonsExcept(gSpecialVar_0x8004);
+}
+
+u8 CountPartyMons(void)
+{
+ u16 i, count;
+
+ for (i = 0, count = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static u8 *StringCopyAndFillWithSpaces(u8 *dst, const u8 *src, u16 n)
+{
+ u8 *str;
+
+ for (str = StringCopy(dst, src); str < dst + n; str++)
+ *str = CHAR_SPACE;
+
+ *str = EOS;
+ return str;
+}
+
+static void sub_808C25C(u16 *dest, u16 dest_left, u16 dest_top, const u16 *src, u16 src_left, u16 src_top, u16 dest_width, u16 dest_height, u16 src_width)
+{
+ u16 i;
+
+ dest_width *= 2;
+ dest += dest_top * 0x20 + dest_left;
+ src += src_top * src_width + src_left;
+ for (i = 0; i < dest_height; i++)
+ {
+ CpuCopy16(src, dest, dest_width);
+ dest += 0x20;
+ src += src_width;
+ }
+}
+
+static void sub_808C2D8(u16 *dest, u16 dest_left, u16 dest_top, u16 width, u16 height)
+{
+ u16 i;
+
+ dest += dest_top * 0x20 + dest_left;
+ width *= 2;
+ for (i = 0; i < height; dest += 0x20, i++)
+ Dma3FillLarge16_(0, dest, width);
+}
+
+static void Task_PokemonStorageSystemPC(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ SetHelpContext(HELPCONTEXT_BILLS_PC);
+ PSS_CreatePCMenu(task->data[1], &task->data[15]);
+ LoadStdWindowFrameGfx();
+ DrawDialogueFrame(0, 0);
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, sUnknown_83CDA20[task->data[1]].desc, TEXT_SPEED_FF, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ CopyWindowToVram(0, 3);
+ CopyWindowToVram(task->data[15], 3);
+ task->data[0]++;
+ break;
+ case 1:
+ if (IsWeatherNotFadingIn())
+ {
+ task->data[0]++;
+ }
+ break;
+ case 2:
+ task->data[2] = Menu_ProcessInput();
+ switch(task->data[2])
+ {
+ case MENU_NOTHING_CHOSEN:
+ task->data[3] = task->data[1];
+ if (JOY_NEW(DPAD_UP) && --task->data[3] < 0)
+ task->data[3] = 4;
+
+ if (JOY_NEW(DPAD_DOWN) && ++task->data[3] > 4)
+ task->data[3] = 0;
+ if (task->data[1] != task->data[3])
+ {
+ task->data[1] = task->data[3];
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, sUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ }
+ break;
+ case MENU_B_PRESSED:
+ case 4:
+ ClearStdWindowAndFrame(0, TRUE);
+ ClearStdWindowAndFrame(task->data[15], TRUE);
+ ScriptContext2_Disable();
+ EnableBothScriptContexts();
+ DestroyTask(taskId);
+ break;
+ default:
+ if (task->data[2] == 0 && CountPartyMons() == PARTY_SIZE)
+ {
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, gText_PartyFull, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ task->data[0] = 3;
+ }
+ else if (task->data[2] == 1 && CountPartyMons() == 1)
+ {
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, gText_JustOnePkmn, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ task->data[0] = 3;
+ }
+ else
+ {
+ FadeScreen(FADE_TO_BLACK, 0);
+ task->data[0] = 4;
+ }
+ break;
+ }
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, sUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ task->data[0] = 2;
+ }
+ else if (JOY_NEW(DPAD_UP))
+ {
+ if (--task->data[1] < 0)
+ task->data[1] = 4;
+ Menu_MoveCursor(-1);
+ task->data[1] = Menu_GetCursorPos();
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, sUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ task->data[0] = 2;
+ }
+ else if (JOY_NEW(DPAD_DOWN))
+ {
+ if (++task->data[1] > 3)
+ task->data[1] = 0;
+ Menu_MoveCursor(1);
+ task->data[1] = Menu_GetCursorPos();
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ AddTextPrinterParameterized2(0, 2, sUnknown_83CDA20[task->data[1]].desc, 0, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GREY);
+ task->data[0] = 2;
+ }
+ break;
+ case 4:
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ Cb2_EnterPSS(task->data[2]);
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void ShowPokemonStorageSystemPC(void)
+{
+ u8 taskId = CreateTask(Task_PokemonStorageSystemPC, 80);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 0;
+ ScriptContext2_Enable();
+}
+
+static void FieldCb_ReturnToPcMenu(void)
+{
+ u8 taskId;
+ MainCallback vblankCb = gMain.vblankCallback;
+
+ SetVBlankCallback(NULL);
+ taskId = CreateTask(Task_PokemonStorageSystemPC, 80);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = sPreviousBoxOption;
+ Task_PokemonStorageSystemPC(taskId);
+ SetVBlankCallback(vblankCb);
+ FadeInFromBlack();
+}
+
+static const struct WindowTemplate sUnknown_83CDA48 = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 1,
+ .width = 17,
+ .height = 10,
+ .paletteNum = 15,
+ .baseBlock = 0x001
+};
+
+static void PSS_CreatePCMenu(u8 whichMenu, s16 *windowIdPtr)
+{
+ s16 windowId;
+ windowId = AddWindow(&sUnknown_83CDA48);
+
+ DrawStdWindowFrame(windowId, FALSE);
+ PrintTextArray(windowId, 2, GetMenuCursorDimensionByFont(2, 0), 2, 16, NELEMS(sUnknown_83CDA20), (void *)sUnknown_83CDA20);
+ Menu_InitCursor(windowId, 2, 0, 2, 16, NELEMS(sUnknown_83CDA20), whichMenu);
+ *windowIdPtr = windowId;
+}
+
+void Cb2_ExitPSS(void)
+{
+ sPreviousBoxOption = GetCurrentBoxOption();
+ gFieldCallback = FieldCb_ReturnToPcMenu;
+ SetMainCallback2(CB2_ReturnToField);
+}
+
+void ResetPokemonStorageSystem(void)
+{
+ u16 boxId, boxPosition;
+
+ SetCurrentBox(0);
+ for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
+ {
+ for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++)
+ ZeroBoxMonAt(boxId, boxPosition);
+ }
+ for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
+ {
+ u8 *dest = StringCopy(GetBoxNamePtr(boxId), gText_Box);
+ ConvertIntToDecimalStringN(dest, boxId + 1, STR_CONV_MODE_LEFT_ALIGN, 2);
+ }
+ for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
+ {
+ SetBoxWallpaper(boxId, boxId % 4);
+ }
+}
+
+void LoadBoxSelectionPopupSpriteGfx(struct UnkPSSStruct_2002370 *a0, u16 tileTag, u16 palTag, u8 a3, bool32 loadPal)
+{
+ struct SpritePalette palette = {
+ sBoxSelectionPopupPalette, palTag
+ };
+ struct SpriteSheet sheets[] = {
+ {sBoxSelectionPopupCenterTiles, 0x800, tileTag},
+ {sBoxSelectionPopupSidesTiles, 0x180, tileTag + 1},
+ {}
+ };
+
+ if (loadPal)
+ LoadSpritePalette(&palette);
+
+ LoadSpriteSheets(sheets);
+ sBoxSelectionPopupSpriteManager = a0;
+ a0->tilesTag = tileTag;
+ a0->paletteTag = palTag;
+ a0->subpriority = a3;
+ a0->loadPal = loadPal;
+}
+
+void FreeBoxSelectionPopupSpriteGfx(void)
+{
+ if (sBoxSelectionPopupSpriteManager->loadPal)
+ FreeSpritePaletteByTag(sBoxSelectionPopupSpriteManager->paletteTag);
+ FreeSpriteTilesByTag(sBoxSelectionPopupSpriteManager->tilesTag);
+ FreeSpriteTilesByTag(sBoxSelectionPopupSpriteManager->tilesTag + 1);
+}
+
+void sub_808C940(u8 curBox)
+{
+ sub_808C9C4(curBox);
+}
+
+void sub_808C950(void)
+{
+ sub_808CBA4();
+}
+
+u8 HandleBoxChooseSelectionInput(void)
+{
+ if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ return 201;
+ }
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ return sBoxSelectionPopupSpriteManager->curBox;
+ }
+ if (JOY_NEW(DPAD_LEFT))
+ {
+ PlaySE(SE_SELECT);
+ UpdateBoxNameAndCountSprite_WraparoundLeft();
+ }
+ else if (JOY_NEW(DPAD_RIGHT))
+ {
+ PlaySE(SE_SELECT);
+ UpdateBoxNameAndCountSprite_WraparoundRight();
+ }
+ return 200;
+}
+
+static const union AnimCmd gUnknown_83CDA50[] = {
+ ANIMCMD_FRAME( 0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83CDA58[] = {
+ ANIMCMD_FRAME( 4, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83CDA60[] = {
+ ANIMCMD_FRAME( 6, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83CDA68[] = {
+ ANIMCMD_FRAME(10, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83CDA70[] = {
+ gUnknown_83CDA50,
+ gUnknown_83CDA58,
+ gUnknown_83CDA60,
+ gUnknown_83CDA68
+};
+
+static const union AffineAnimCmd gUnknown_83CDA80[] = {
+ AFFINEANIMCMD_FRAME(224, 224, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const gUnknown_83CDA90[] = {
+ gUnknown_83CDA80
+};
+
+static void sub_808C9C4(u8 curBox)
+{
+ u16 i;
+ u8 spriteId;
+ struct SpriteTemplate template;
+ struct OamData oamData = {};
+ oamData.size = SPRITE_SIZE(64x64);
+ oamData.paletteNum = 1;
+ template = (struct SpriteTemplate){
+ 0, 0, &oamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
+ };
+ {
+ const u8 gUnknown_83CDA94[] = _("/30");
+
+ sBoxSelectionPopupSpriteManager->curBox = curBox;
+ template.tileTag = sBoxSelectionPopupSpriteManager->tilesTag;
+ template.paletteTag = sBoxSelectionPopupSpriteManager->paletteTag;
+
+ spriteId = CreateSprite(&template, 160, 96, 0);
+ sBoxSelectionPopupSpriteManager->unk_0000 = gSprites + spriteId;
+
+ // Manual subsprites
+ oamData.shape = SPRITE_SHAPE(8x32);
+ oamData.size = SPRITE_SIZE(8x32);
+ template.tileTag = sBoxSelectionPopupSpriteManager->tilesTag + 1;
+ template.anims = gUnknown_83CDA70;
+ for (i = 0; i < 4; i++)
+ {
+ u16 r5;
+ spriteId = CreateSprite(&template, 124, 80, sBoxSelectionPopupSpriteManager->subpriority);
+ sBoxSelectionPopupSpriteManager->unk_0004[i] = gSprites + spriteId;
+ r5 = 0;
+ if (i & 2)
+ {
+ sBoxSelectionPopupSpriteManager->unk_0004[i]->pos1.x = 196;
+ r5 = 2;
+ }
+ if (i & 1)
+ {
+ sBoxSelectionPopupSpriteManager->unk_0004[i]->pos1.y = 112;
+ sBoxSelectionPopupSpriteManager->unk_0004[i]->oam.size = SPRITE_SIZE(8x16);
+ r5++;
+ }
+ StartSpriteAnim(sBoxSelectionPopupSpriteManager->unk_0004[i], r5);
+ }
+ for (i = 0; i < 2; i++)
+ {
+ sBoxSelectionPopupSpriteManager->unk_0020[i] = sub_809223C(72 * i + 0x7c, 0x58, i, 0, sBoxSelectionPopupSpriteManager->subpriority);
+ if (sBoxSelectionPopupSpriteManager->unk_0020[i])
+ {
+ sBoxSelectionPopupSpriteManager->unk_0020[i]->data[0] = (i == 0 ? -1 : 1);
+ sBoxSelectionPopupSpriteManager->unk_0020[i]->callback = sub_808CD64;
+ }
+ }
+ PrintBoxNameAndCountToSprite();
+ PrintToSpriteWithTagUnk0240(gUnknown_83CDA94, 5, 3);
+ }
+}
+
+static void sub_808CBA4(void)
+{
+ u16 i;
+ if (sBoxSelectionPopupSpriteManager->unk_0000)
+ {
+ DestroySprite(sBoxSelectionPopupSpriteManager->unk_0000);
+ sBoxSelectionPopupSpriteManager->unk_0000 = NULL;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (sBoxSelectionPopupSpriteManager->unk_0004[i])
+ {
+ DestroySprite(sBoxSelectionPopupSpriteManager->unk_0004[i]);
+ sBoxSelectionPopupSpriteManager->unk_0004[i] = NULL;
+ }
+ }
+ for (i = 0; i < 2; i++)
+ {
+ if (sBoxSelectionPopupSpriteManager->unk_0020[i])
+ DestroySprite(sBoxSelectionPopupSpriteManager->unk_0020[i]);
+ }
+}
+
+static void UpdateBoxNameAndCountSprite_WraparoundRight(void)
+{
+ if (++sBoxSelectionPopupSpriteManager->curBox >= TOTAL_BOXES_COUNT)
+ sBoxSelectionPopupSpriteManager->curBox = 0;
+ PrintBoxNameAndCountToSprite();
+}
+
+static void UpdateBoxNameAndCountSprite_WraparoundLeft(void)
+{
+ sBoxSelectionPopupSpriteManager->curBox = (sBoxSelectionPopupSpriteManager->curBox == 0 ? TOTAL_BOXES_COUNT - 1 : sBoxSelectionPopupSpriteManager->curBox - 1);
+ PrintBoxNameAndCountToSprite();
+}
+
+static void PrintBoxNameAndCountToSprite(void)
+{
+ u8 nPokemonInBox = CountMonsInBox(sBoxSelectionPopupSpriteManager->curBox);
+ u8 *boxName = StringCopy(sBoxSelectionPopupSpriteManager->strbuf, GetBoxNamePtr(sBoxSelectionPopupSpriteManager->curBox));
+
+ while (boxName < sBoxSelectionPopupSpriteManager->strbuf + BOX_NAME_LENGTH)
+ *boxName++ = CHAR_SPACE;
+ *boxName = EOS;
+
+ PrintToSpriteWithTagUnk0240(sBoxSelectionPopupSpriteManager->strbuf, 0, 1);
+
+ ConvertIntToDecimalStringN(sBoxSelectionPopupSpriteManager->strbuf, nPokemonInBox, STR_CONV_MODE_RIGHT_ALIGN, 2);
+
+ PrintToSpriteWithTagUnk0240(sBoxSelectionPopupSpriteManager->strbuf, 3, 3);
+}
+
+static void PrintToSpriteWithTagUnk0240(const u8 *str, u16 x, u16 y)
+{
+ u16 tileStart = GetSpriteTileStartByTag(sBoxSelectionPopupSpriteManager->tilesTag);
+ PrintStringToBufferCopyNow(str, (void *)(OBJ_VRAM0 + tileStart * 32 + 256 * y + 32 * x), 0x100, TEXT_COLOR_RED, TEXT_DYNAMIC_COLOR_6, TEXT_DYNAMIC_COLOR_5, sBoxSelectionPopupSpriteManager->buffer);
+}
+
+static void sub_808CD64(struct Sprite *sprite)
+{
+ if (++sprite->data[1] > 3)
+ {
+ sprite->data[1] = 0;
+ sprite->pos2.x += sprite->data[0];
+ if (++sprite->data[2] > 5)
+ {
+ sprite->data[2] = 0;
+ sprite->pos2.x = 0;
+ }
+ }
+}
+
+// Forward-declared rodata
+
+static const u16 sBoxSelectionPopupPalette[] = INCBIN_U16("graphics/interface/pss_unk_83CDA98.gbapal");
+static const u16 sBoxSelectionPopupCenterTiles[] = INCBIN_U16("graphics/interface/pss_unk_83CDAB8.4bpp");
+static const u16 sBoxSelectionPopupSidesTiles[] = INCBIN_U16("graphics/interface/pss_unk_83CE2B8.4bpp");
diff --git a/src/pokemon_storage_system_3.c b/src/pokemon_storage_system_3.c
new file mode 100644
index 000000000..7ae451b69
--- /dev/null
+++ b/src/pokemon_storage_system_3.c
@@ -0,0 +1,2779 @@
+#include "global.h"
+#include "gflib.h"
+#include "box_party_pokemon_dropdown.h"
+#include "data.h"
+#include "decompress.h"
+#include "dynamic_placeholder_text_util.h"
+#include "event_data.h"
+#include "graphics.h"
+#include "help_system.h"
+#include "item.h"
+#include "item_menu.h"
+#include "mail_data.h"
+#include "menu.h"
+#include "naming_screen.h"
+#include "new_menu_helpers.h"
+#include "pc_screen_effect.h"
+#include "pokemon_icon.h"
+#include "pokemon_storage_system_internal.h"
+#include "pokemon_summary_screen.h"
+#include "quest_log.h"
+#include "strings.h"
+#include "task.h"
+#include "text_window.h"
+#include "trig.h"
+#include "constants/items.h"
+#include "constants/help_system.h"
+#include "constants/songs.h"
+#include "constants/flags.h"
+#include "constants/vars.h"
+
+EWRAM_DATA struct PokemonStorageSystemData *gPSSData = NULL;
+static EWRAM_DATA bool8 sInPartyMenu = 0;
+static EWRAM_DATA u8 sCurrentBoxOption = 0;
+static EWRAM_DATA u8 gUnknown_20397B6 = 0;
+static EWRAM_DATA u8 sWhichToReshow = 0;
+static EWRAM_DATA u8 sLastUsedBox = 0;
+static EWRAM_DATA u16 gUnknown_20397BA = ITEM_NONE;
+
+static void Cb_InitPSS(u8 taskId);
+static void Cb_ShowPSS(u8 taskId);
+static void Cb_ReshowPSS(u8 taskId);
+static void Cb_MainPSS(u8 taskId);
+static void Cb_ShowPartyPokemon(u8 taskId);
+static void Cb_HidePartyPokemon(u8 taskId);
+static void Cb_OnSelectedMon(u8 taskId);
+static void Cb_MoveMon(u8 taskId);
+static void Cb_PlaceMon(u8 taskId);
+static void Cb_ShiftMon(u8 taskId);
+static void Cb_WithdrawMon(u8 taskId);
+static void Cb_DepositMenu(u8 taskId);
+static void Cb_ReleaseMon(u8 taskId);
+static void Cb_ShowMarkMenu(u8 taskId);
+static void Cb_TakeItemForMoving(u8 taskId);
+static void Cb_GiveMovingItemToMon(u8 taskId);
+static void Cb_ItemToBag(u8 taskId);
+static void Cb_SwitchSelectedItem(u8 taskId);
+static void Cb_ShowItemInfo(u8 taskId);
+static void Cb_HandleMovingMonFromParty(u8 taskId);
+static void Cb_PrintCantStoreMail(u8 taskId);
+static void Cb_HandleBoxOptions(u8 taskId);
+static void Cb_HandleWallpapers(u8 taskId);
+static void Cb_JumpBox(u8 taskId);
+static void Cb_NameBox(u8 taskId);
+static void Cb_ShowMonSummary(u8 taskId);
+static void Cb_GiveItemFromBag(u8 taskId);
+static void Cb_OnCloseBoxPressed(u8 taskId);
+static void Cb_OnBPressed(u8 taskId);
+static void Cb_ChangeScreen(u8 taskId);
+static void GiveChosenBagItem(void);
+static void FreePSSData(void);
+static void SetScrollingBackground(void);
+static void ScrollBackground(void);
+static void LoadPSSMenuGfx(void);
+static bool8 InitPSSWindows(void);
+static void LoadWaveformSpritePalette(void);
+static void sub_808F078(void);
+static void sub_808F0F4(void);
+static void sub_808F164(void);
+static void RefreshCursorMonData(void);
+static void BoxSetMosaic(void);
+static void SpriteCB_CursorMon_Mosaic(struct Sprite * sprite);
+static bool8 BoxGetMosaic(void);
+static void LoadCursorMonSprite(void);
+static void LoadCursorMonGfx(u16 species, u32 pid);
+static void PrintCursorMonInfo(void);
+static void sub_808F5E8(void);
+static void sub_808F68C(void);
+static void SetUpHidePartyMenu(void);
+static bool8 HidePartyMenu(void);
+static void sub_808F90C(bool8 species);
+static void sub_808F948(void);
+static void sub_808F974(void);
+static void sub_808F99C(void);
+static void sub_808F9FC(void);
+static void sub_808FA30(u8 pos, bool8 isPartyMon);
+static void sub_808FAA8(void);
+static void SetUpDoShowPartyMenu(void);
+static bool8 DoShowPartyMenu(void);
+static void sub_808FB68(void);
+static void PrintStorageActionText(u8 textId);
+static void ShowYesNoWindow(s8 species);
+static void ClearBottomWindow(void);
+static void AddWallpaperSetsMenu(void);
+static void AddWallpapersMenu(u8 wallpaperSet);
+static void sub_808FDFC(void);
+static void sub_808FE54(u8 species);
+static void sub_808FF70(void);
+
+static const u32 sPokemonStorageScrollingBGTileset[] = INCBIN_U32("graphics/interface/pss_unk_83CE438.4bpp.lz");
+static const u32 sPokemonStorageScrollingBGTilemap[] = INCBIN_U32("graphics/interface/pss_unk_83CE4D0.bin.lz");
+static const u16 sPokemonStorageScrollingBGPalette[] = INCBIN_U16("graphics/interface/pss_unk_83CE5DC.gbapal");
+static const u32 gUnknown_83CE5FC[] = INCBIN_U32("graphics/interface/pss_unk_83CE5FC.bin.lz");
+
+static const u16 gUnknown_83CE6F8[] = {
+ 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108,
+ 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118,
+ 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, 0x2108,
+ 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, 0x2118,
+};
+
+static const u16 gUnknown_83CE738[] = INCBIN_U16("graphics/interface/pss_unk_83CE738.gbapal");
+static const u16 gUnknown_83CE758[] = INCBIN_U16("graphics/interface/pss_unk_83CE758.gbapal");
+
+static const u16 gUnknown_83CE778[] = {
+ 0x014c, 0x014d, 0x014e, 0x014f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174,
+ 0x015c, 0x015d, 0x015e, 0x015f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184,
+ 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x0185, 0x0186, 0x0187, 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d,
+};
+
+static const u16 gUnknown_83CE7C0[] = {
+ 0x1140, 0x1141, 0x1141, 0x1142,
+ 0x1150, 0x1151, 0x1151, 0x1152,
+ 0x1160, 0x1161, 0x1161, 0x1162,
+};
+
+static const u16 gUnknown_83CE7D8[] = {
+ 0x1143, 0x1144, 0x1144, 0x1145,
+ 0x1153, 0x1154, 0x1154, 0x1155,
+ 0x1163, 0x1164, 0x1164, 0x1165,
+};
+
+static const u16 gUnknown_83CE7F0[] = INCBIN_U16("graphics/interface/pss_unk_83CE810.gbapal");
+static const u16 gUnknown_83CE810[] = INCBIN_U16("graphics/interface/pss_unk_83CE810.4bpp");
+static const u16 gUnknown_83CE9D0[] = INCBIN_U16("graphics/interface/pss_unk_83CE9D0.gbapal");
+static const u16 gUnknown_83CEA10[] = INCBIN_U16("graphics/interface/pss_unk_83CEA10.gbapal");
+
+static const struct WindowTemplate gUnknown_83CEA30[] = {
+ {
+ .bg = 1,
+ .tilemapLeft = 0,
+ .tilemapTop = 11,
+ .width = 9,
+ .height = 7,
+ .paletteNum = 3,
+ .baseBlock = 0x0c0
+ }, {
+ .bg = 0,
+ .tilemapLeft = 11,
+ .tilemapTop = 17,
+ .width = 18,
+ .height = 2,
+ .paletteNum = 13,
+ .baseBlock = 0x014
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 12,
+ .width = 25,
+ .height = 8,
+ .paletteNum = 15,
+ .baseBlock = 0x014
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct BgTemplate gUnknown_83CEA50[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x100
+ }, {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 27,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+static const struct SpritePalette sWaveformSpritePalette = {
+ gUnknown_83CE7F0, TAG_PAL_WAVEFORM
+};
+
+static const struct SpriteSheet sWaveformSpriteSheet = {
+ gUnknown_83CE810, 0x01c0, TAG_TILE_WAVEFORM
+};
+
+static const struct OamData gUnknown_83CEB88;
+
+static const struct SpriteTemplate sSpriteTemplate_CursorMon = {
+ .tileTag = TAG_TILE_2,
+ .paletteTag = TAG_PAL_DAC6,
+ .oam = &gUnknown_83CEB88,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct StorageAction sPCStorageActionTexts[] = {
+ [PC_TEXT_EXIT_BOX] = {gText_ExitFromBox, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_WHAT_YOU_DO] = {gText_WhatDoYouWantToDo, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PICK_A_THEME] = {gText_PleasePickATheme, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PICK_A_WALLPAPER] = {gText_PickTheWallpaper, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_IS_SELECTED] = {gText_PkmnIsSelected, PC_TEXT_FMT_MON_NAME_1},
+ [PC_TEXT_JUMP_TO_WHICH_BOX] = {gText_JumpToWhichBox, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_DEPOSIT_IN_WHICH_BOX] = {gText_DepositInWhichBox, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_WAS_DEPOSITED] = {gText_PkmnWasDeposited, PC_TEXT_FMT_MON_NAME_1},
+ [PC_TEXT_BOX_IS_FULL] = {gText_BoxIsFull2, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_RELEASE_POKE] = {gText_ReleaseThisPokemon, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_WAS_RELEASED] = {gText_PkmnWasReleased, PC_TEXT_FMT_MON_NAME_4},
+ [PC_TEXT_BYE_BYE] = {gText_ByeByePkmn, PC_TEXT_FMT_MON_NAME_6},
+ [PC_TEXT_MARK_POKE] = {gText_MarkYourPkmn, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_LAST_POKE] = {gText_ThatsYourLastPkmn, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PARTY_FULL] = {gText_YourPartysFull, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_HOLDING_POKE] = {gText_YoureHoldingAPkmn, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_WHICH_ONE_WILL_TAKE] = {gText_WhichOneWillYouTake, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_CANT_RELEASE_EGG] = {gText_YouCantReleaseAnEgg, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_CONTINUE_BOX] = {gText_ContinueBoxOperations, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_CAME_BACK] = {gText_PkmnCameBack, PC_TEXT_FMT_MON_NAME_1},
+ [PC_TEXT_WORRIED] = {gText_WasItWorriedAboutYou, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_SURPRISE] = {gText_FourEllipsesExclamation, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PLEASE_REMOVE_MAIL] = {gText_PleaseRemoveTheMail, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_IS_SELECTED2] = {gText_PkmnIsSelected, PC_TEXT_FMT_ITEM_NAME},
+ [PC_TEXT_GIVE_TO_MON] = {gText_GiveToAPkmn, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PLACED_IN_BAG] = {gText_PlacedItemInBag, PC_TEXT_FMT_ITEM_NAME},
+ [PC_TEXT_BAG_FULL] = {gText_BagIsFull2, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_PUT_IN_BAG] = {gText_PutItemInBag, PC_TEXT_FMT_NORMAL},
+ [PC_TEXT_ITEM_IS_HELD] = {gText_ItemIsNowHeld, PC_TEXT_FMT_ITEM_NAME},
+ [PC_TEXT_CHANGED_TO_ITEM] = {gText_ChangedToNewItem, PC_TEXT_FMT_ITEM_NAME},
+ [PC_TEXT_CANT_STORE_MAIL] = {gText_MailCantBeStored, PC_TEXT_FMT_NORMAL},
+};
+
+// Yes/No menu
+static const struct WindowTemplate sYesNoWindowTemplate = {
+ .bg = 0,
+ .tilemapLeft = 24,
+ .tilemapTop = 11,
+ .width = 5,
+ .height = 4,
+ .paletteNum = 15,
+ .baseBlock = 0x05c
+};
+
+static const struct OamData gUnknown_83CEB88 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0x000,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+// Waveform
+
+static const struct OamData gUnknown_83CEB90 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(16x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(16x8),
+ .tileNum = 0x000,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const union AnimCmd gUnknown_83CEB98[] = {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83CEBA0[] = {
+ ANIMCMD_FRAME(2, 8),
+ ANIMCMD_FRAME(4, 8),
+ ANIMCMD_FRAME(6, 8),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd gUnknown_83CEBB0[] = {
+ ANIMCMD_FRAME(8, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83CEBB8[] = {
+ ANIMCMD_FRAME(10, 8),
+ ANIMCMD_FRAME(4, 8),
+ ANIMCMD_FRAME(12, 8),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd *const gUnknown_83CEBC8[] = {
+ gUnknown_83CEB98,
+ gUnknown_83CEBA0,
+ gUnknown_83CEBB0,
+ gUnknown_83CEBB8
+};
+
+static const struct SpriteTemplate sSpriteTemplate_Waveform = {
+ .tileTag = TAG_TILE_WAVEFORM,
+ .paletteTag = TAG_PAL_WAVEFORM,
+ .oam = &gUnknown_83CEB90,
+ .anims = gUnknown_83CEBC8,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+static void VblankCb_PSS(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ sub_8096BF8();
+ TransferPlttBuffer();
+ SetGpuReg(REG_OFFSET_BG2HOFS, gPSSData->bg2_X);
+}
+
+static void Cb2_PSS(void)
+{
+ RunTasks();
+ DoScheduledBgTilemapCopiesToVram();
+ ScrollBackground();
+ sub_808F99C();
+ AnimateSprites();
+ BuildOamBuffer();
+}
+
+void Cb2_EnterPSS(u8 boxOption)
+{
+ ResetTasks();
+ sCurrentBoxOption = boxOption;
+ gPSSData = Alloc(sizeof(struct PokemonStorageSystemData));
+ if (gPSSData == NULL)
+ SetMainCallback2(Cb2_ExitPSS);
+ else
+ {
+ gPSSData->boxOption = boxOption;
+ gPSSData->isReshowingPSS = FALSE;
+ gUnknown_20397BA = 0;
+ gPSSData->state = 0;
+ gPSSData->taskId = CreateTask(Cb_InitPSS, 3);
+ SetHelpContext(HELPCONTEXT_BILLS_PC);
+ sLastUsedBox = StorageGetCurrentBox();
+ SetMainCallback2(Cb2_PSS);
+ }
+}
+
+void Cb2_ReturnToPSS(void)
+{
+ ResetTasks();
+ gPSSData = Alloc(sizeof(struct PokemonStorageSystemData));
+ if (gPSSData == NULL)
+ SetMainCallback2(Cb2_ExitPSS);
+ else
+ {
+ gPSSData->boxOption = sCurrentBoxOption;
+ gPSSData->isReshowingPSS = TRUE;
+ gPSSData->state = 0;
+ gPSSData->taskId = CreateTask(Cb_InitPSS, 3);
+ SetHelpContext(HELPCONTEXT_BILLS_PC);
+ SetMainCallback2(Cb2_PSS);
+ }
+}
+
+static void ResetAllBgCoords(void)
+{
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+}
+
+static void sub_808CF10(void)
+{
+ ResetPaletteFade();
+ ResetSpriteData();
+ FreeSpriteTileRanges();
+ FreeAllSpritePalettes();
+ ClearDma3Requests();
+ gReservedSpriteTileCount = 0x280;
+ sub_8096BE4(&gPSSData->unk_0020, gPSSData->unk_0028, 8);
+ gKeyRepeatStartDelay = 20;
+ ClearScheduledBgCopiesToVram();
+ AllocBoxPartyPokemonDropdowns(3);
+ SetBoxPartyPokemonDropdownMap2(0, 1, gUnknown_83CE6F8, 8, 4);
+ SetBoxPartyPokemonDropdownMap2Pos(0, 1, 0);
+ gPSSData->unk_02C7 = FALSE;
+}
+
+static void sub_808CF94(void)
+{
+ sub_8092B50();
+ sInPartyMenu = gPSSData->boxOption == BOX_OPTION_DEPOSIT;
+ gUnknown_20397B6 = 0;
+}
+
+static void sub_808CFC4(void)
+{
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL);
+ SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(7, 11));
+ }
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_1D_MAP);
+}
+
+static void SetPSSCallback(TaskFunc newFunc)
+{
+ gTasks[gPSSData->taskId].func = newFunc;
+ gPSSData->state = 0;
+}
+
+static void Cb_InitPSS(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ sub_808CF10();
+ if (gPSSData->isReshowingPSS)
+ {
+ switch (sWhichToReshow)
+ {
+ case 1:
+ sub_8093660();
+ break;
+ case 0:
+ sub_80937B4();
+ break;
+ case 2:
+ GiveChosenBagItem();
+ break;
+ }
+ }
+ LoadPSSMenuGfx();
+ LoadWaveformSpritePalette();
+ break;
+ case 1:
+ if (!InitPSSWindows())
+ {
+ SetPSSCallback(Cb_ChangeScreen);
+ return;
+ }
+ break;
+ case 2:
+ PutWindowTilemap(0);
+ ClearWindowTilemap(1);
+ CpuFill32(0, (void *)VRAM, 0x200);
+ TextWindow_SetUserSelectedFrame(1, 0xB, 0xE0);
+ break;
+ case 3:
+ ResetAllBgCoords();
+ if (!gPSSData->isReshowingPSS)
+ sub_808CF94();
+ break;
+ case 4:
+ sub_808FFAC();
+ if (!gPSSData->isReshowingPSS)
+ sub_80922C0();
+ else
+ sub_8092340();
+ break;
+ case 5:
+ if (!sub_8095050())
+ {
+ SetPSSCallback(Cb_ChangeScreen);
+ return;
+ }
+ else
+ {
+ SetScrollingBackground();
+ sub_808FB68();
+ }
+ break;
+ case 6:
+ sub_808F078();
+ break;
+ case 7:
+ sub_808F68C();
+ break;
+ case 8:
+ sub_80913DC(StorageGetCurrentBox());
+ break;
+ case 9:
+ if (sub_809140C())
+ return;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ gPSSData->field_DA4.baseTileTag = TAG_TILE_D;
+ gPSSData->field_DA4.basePaletteTag = TAG_PAL_DACE;
+ SetMonMarkingsMenuPointer(&gPSSData->field_DA4);
+ LoadMonMarkingsFrameGfx();
+ }
+ else
+ {
+ sub_8095B5C();
+ sub_808FDFC();
+ }
+ break;
+ case 10:
+ sub_808CFC4();
+ if (!gPSSData->isReshowingPSS)
+ {
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
+ SetPSSCallback(Cb_ShowPSS);
+ }
+ else
+ {
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
+ SetPSSCallback(Cb_ReshowPSS);
+ }
+ SetVBlankCallback(VblankCb_PSS);
+ return;
+ default:
+ return;
+ }
+
+ gPSSData->state++;
+}
+
+static void Cb_ShowPSS(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PlaySE(SE_PC_LOGIN);
+ BeginPCScreenEffect_TurnOn(20, 0, 1);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!IsPCScreenEffectRunning_TurnOn())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_ReshowPSS(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0x10, 0, RGB_BLACK);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_MainPSS(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ switch (HandleInput())
+ {
+ case 1:
+ PlaySE(SE_SELECT);
+ gPSSData->state = 1;
+ break;
+ case 5:
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_MONS && gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ PrintStorageActionText(PC_TEXT_WHICH_ONE_WILL_TAKE);
+ gPSSData->state = 3;
+ }
+ else
+ {
+ sub_8092B50();
+ SetPSSCallback(Cb_ShowPartyPokemon);
+ }
+ break;
+ case 6:
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_MONS)
+ {
+ if (IsMonBeingMoved() && ItemIsMail(gPSSData->cursorMonItem))
+ gPSSData->state = 5;
+ else
+ SetPSSCallback(Cb_HidePartyPokemon);
+ }
+ else if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ SetPSSCallback(Cb_HidePartyPokemon);
+ }
+ break;
+ case 4:
+ SetPSSCallback(Cb_OnCloseBoxPressed);
+ break;
+ case 19:
+ SetPSSCallback(Cb_OnBPressed);
+ break;
+ case 7:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_HandleBoxOptions);
+ break;
+ case 8:
+ SetPSSCallback(Cb_OnSelectedMon);
+ break;
+ case 9:
+ PlaySE(SE_SELECT);
+ gPSSData->newCurrBoxId = StorageGetCurrentBox() + 1;
+ if (gPSSData->newCurrBoxId >= TOTAL_BOXES_COUNT)
+ gPSSData->newCurrBoxId = 0;
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ SetUpScrollToBox(gPSSData->newCurrBoxId);
+ gPSSData->state = 2;
+ }
+ else
+ {
+ sub_8094D60();
+ gPSSData->state = 10;
+ }
+ break;
+ case 10:
+ PlaySE(SE_SELECT);
+ gPSSData->newCurrBoxId = StorageGetCurrentBox() - 1;
+ if (gPSSData->newCurrBoxId < 0)
+ gPSSData->newCurrBoxId = TOTAL_BOXES_COUNT - 1;
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ SetUpScrollToBox(gPSSData->newCurrBoxId);
+ gPSSData->state = 2;
+ }
+ else
+ {
+ sub_8094D60();
+ gPSSData->state = 10;
+ }
+ break;
+ case 11:
+ if (!CanMovePartyMon())
+ {
+ if (ItemIsMail(gPSSData->cursorMonItem))
+ {
+ gPSSData->state = 5;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_DepositMenu);
+ }
+ }
+ else
+ {
+ gPSSData->state = 4;
+ }
+ break;
+ case 13:
+ if (CanMovePartyMon())
+ {
+ gPSSData->state = 4;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_MoveMon);
+ }
+ break;
+ case 14:
+ if (!CanShiftMon())
+ {
+ gPSSData->state = 4;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_ShiftMon);
+ }
+ break;
+ case 12:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_WithdrawMon);
+ break;
+ case 15:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_PlaceMon);
+ break;
+ case 16:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_TakeItemForMoving);
+ break;
+ case 17:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_GiveMovingItemToMon);
+ break;
+ case 18:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_SwitchSelectedItem);
+ break;
+ case 20:
+ PlaySE(SE_SELECT);
+ sub_80950BC(0);
+ gPSSData->state = 7;
+ break;
+ case 22:
+ sub_80950BC(1);
+ gPSSData->state = 8;
+ break;
+ case 21:
+ PlaySE(SE_SELECT);
+ sub_80950BC(2);
+ gPSSData->state = 9;
+ break;
+ case 23:
+ sub_80950BC(3);
+ gPSSData->state = 7;
+ break;
+ case 25:
+ PlaySE(SE_SELECT);
+ sub_80950BC(4);
+ gPSSData->state = 9;
+ break;
+ case 26:
+ PlaySE(SE_SELECT);
+ sub_808FE54(3);
+ sub_80950BC(5);
+ gPSSData->state = 7;
+ break;
+ case 24:
+ PlaySE(SE_HAZURE);
+ break;
+ }
+ break;
+ case 1:
+ if (!sub_80924A8())
+ {
+ if (IsCursorOnCloseBox())
+ sub_808F948();
+ else
+ sub_808F974();
+
+ if (gPSSData->setMosaic)
+ BoxSetMosaic();
+ gPSSData->state = 0;
+ }
+ break;
+ case 2:
+ if (!ScrollToBox())
+ {
+ SetCurrentBox(gPSSData->newCurrBoxId);
+ if (!sInPartyMenu && !IsMonBeingMoved())
+ {
+ sub_8092F54();
+ BoxSetMosaic();
+ }
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ sub_8094D84();
+ gPSSData->state = 11;
+ }
+ else
+ {
+ gPSSData->state = 0;
+ }
+ }
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ gPSSData->state = 0;
+ }
+ break;
+ case 4:
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_LAST_POKE);
+ gPSSData->state = 6;
+ break;
+ case 5:
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_PLEASE_REMOVE_MAIL);
+ gPSSData->state = 6;
+ break;
+ case 6:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 7:
+ if (!sub_80950D0())
+ gPSSData->state = 0;
+ break;
+ case 8:
+ if (!sub_80950D0())
+ SetPSSCallback(Cb_MoveMon);
+ break;
+ case 9:
+ if (!sub_80950D0())
+ {
+ if (gPSSData->setMosaic)
+ BoxSetMosaic();
+ gPSSData->state = 0;
+ }
+ break;
+ case 10:
+ if (!sub_809610C())
+ {
+ SetUpScrollToBox(gPSSData->newCurrBoxId);
+ gPSSData->state = 2;
+ }
+ break;
+ case 11:
+ if (!sub_809610C())
+ gPSSData->state = 0;
+ break;
+ }
+}
+
+static void Cb_ShowPartyPokemon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ SetUpDoShowPartyMenu();
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!DoShowPartyMenu())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_HidePartyPokemon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ SetUpHidePartyMenu();
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!HidePartyMenu())
+ {
+ sub_8092B3C(sub_8092B70());
+ gPSSData->state++;
+ }
+ break;
+ case 2:
+ if (!sub_80924A8())
+ {
+ if (gPSSData->setMosaic)
+ BoxSetMosaic();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_OnSelectedMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (!BoxGetMosaic())
+ {
+ PlaySE(SE_SELECT);
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ PrintStorageActionText(PC_TEXT_IS_SELECTED);
+ else if (IsActiveItemMoving() || gPSSData->cursorMonItem != 0)
+ PrintStorageActionText(PC_TEXT_IS_SELECTED2);
+ else
+ PrintStorageActionText(PC_TEXT_GIVE_TO_MON);
+
+ AddMenu();
+ gPSSData->state = 1;
+ }
+ break;
+ case 1: // debug?
+ if (!sub_8094F90())
+ gPSSData->state = 2;
+ break;
+ case 2:
+ switch (sub_8094F94())
+ {
+ case -1:
+ case 0:
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 3:
+ if (CanMovePartyMon())
+ {
+ gPSSData->state = 3;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MoveMon);
+ }
+ break;
+ case 5:
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_PlaceMon);
+ break;
+ case 4:
+ if (!CanShiftMon())
+ {
+ gPSSData->state = 3;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_ShiftMon);
+ }
+ break;
+ case 2:
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_WithdrawMon);
+ break;
+ case 1:
+ if (CanMovePartyMon())
+ {
+ gPSSData->state = 3;
+ }
+ else if (ItemIsMail(gPSSData->cursorMonItem))
+ {
+ gPSSData->state = 4;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_DepositMenu);
+ }
+ break;
+ case 7:
+ if (CanMovePartyMon())
+ {
+ gPSSData->state = 3;
+ }
+ else if (gPSSData->cursorMonIsEgg)
+ {
+ gPSSData->state = 5; // Cannot release an Egg.
+ }
+ else if (ItemIsMail(gPSSData->cursorMonItem))
+ {
+ gPSSData->state = 4;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_ReleaseMon);
+ }
+ break;
+ case 6:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_ShowMonSummary);
+ break;
+ case 8:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_ShowMarkMenu);
+ break;
+ case 12:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_TakeItemForMoving);
+ break;
+ case 13:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_GiveMovingItemToMon);
+ break;
+ case 16:
+ SetPSSCallback(Cb_ItemToBag);
+ break;
+ case 15:
+ SetPSSCallback(Cb_SwitchSelectedItem);
+ break;
+ case 14:
+ SetPSSCallback(Cb_GiveItemFromBag);
+ break;
+ case 17:
+ SetPSSCallback(Cb_ShowItemInfo);
+ break;
+ }
+ break;
+ case 3:
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_LAST_POKE);
+ gPSSData->state = 6;
+ break;
+ case 5:
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_CANT_RELEASE_EGG);
+ gPSSData->state = 6;
+ break;
+ case 4:
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_PLEASE_REMOVE_MAIL);
+ gPSSData->state = 6;
+ break;
+ case 6:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_MoveMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ InitMonPlaceChange(0);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!DoMonPlaceChange())
+ {
+ if (sInPartyMenu)
+ SetPSSCallback(Cb_HandleMovingMonFromParty);
+ else
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_PlaceMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ sub_808FE54(1);
+ InitMonPlaceChange(1);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!DoMonPlaceChange())
+ {
+ if (sInPartyMenu)
+ SetPSSCallback(Cb_HandleMovingMonFromParty);
+ else
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_ShiftMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ sub_808FE54(0);
+ InitMonPlaceChange(2);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!DoMonPlaceChange())
+ {
+ BoxSetMosaic();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_WithdrawMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (CalculatePlayerPartyCount() == PARTY_SIZE)
+ {
+ PrintStorageActionText(PC_TEXT_PARTY_FULL);
+ gPSSData->state = 1;
+ }
+ else
+ {
+ sub_8092B5C();
+ InitMonPlaceChange(0);
+ gPSSData->state = 2;
+ }
+ break;
+ case 1:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 2:
+ if (!DoMonPlaceChange())
+ {
+ SetMovingMonPriority(1);
+ SetUpDoShowPartyMenu();
+ gPSSData->state++;
+ }
+ break;
+ case 3:
+ if (!DoShowPartyMenu())
+ {
+ sub_808FE54(1);
+ InitMonPlaceChange(1);
+ gPSSData->state++;
+ }
+ break;
+ case 4:
+ if (!DoMonPlaceChange())
+ {
+ sub_808FAA8();
+ gPSSData->state++;
+ }
+ break;
+ case 5:
+ SetPSSCallback(Cb_HidePartyPokemon);
+ break;
+ }
+}
+
+static void Cb_DepositMenu(u8 taskId)
+{
+ u8 boxId;
+
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_DEPOSIT_IN_WHICH_BOX);
+ LoadBoxSelectionPopupSpriteGfx(&gPSSData->field_1E5C, TAG_TILE_A, TAG_PAL_DAC7, 3, FALSE);
+ sub_808C940(gUnknown_20397B6);
+ gPSSData->state++;
+ break;
+ case 1:
+ boxId = HandleBoxChooseSelectionInput();
+ if (boxId == 200)
+ {
+ // no box chosen yet
+ }
+ else if (boxId == 201)
+ {
+ ClearBottomWindow();
+ sub_808C950();
+ FreeBoxSelectionPopupSpriteGfx();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ else
+ {
+ if (TryStorePartyMonInBox(boxId))
+ {
+ gUnknown_20397B6 = boxId;
+ sub_808FE54(2);
+ ClearBottomWindow();
+ sub_808C950();
+ FreeBoxSelectionPopupSpriteGfx();
+ gPSSData->state = 2;
+ }
+ else
+ {
+ PrintStorageActionText(PC_TEXT_BOX_IS_FULL);
+ gPSSData->state = 4;
+ }
+ }
+ break;
+ case 2:
+ CompactPartySlots();
+ sub_80909F4();
+ gPSSData->state++;
+ break;
+ case 3:
+ if (!sub_8090A60())
+ {
+ sub_8093174();
+ BoxSetMosaic();
+ sub_808FAA8();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 4:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ PrintStorageActionText(PC_TEXT_DEPOSIT_IN_WHICH_BOX);
+ gPSSData->state = 1;
+ }
+ break;
+ }
+}
+
+static void Cb_ReleaseMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_RELEASE_POKE);
+ ShowYesNoWindow(1);
+ gPSSData->state++;
+ // fallthrough
+ case 1:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case MENU_B_PRESSED:
+ case 1:
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 0:
+ ClearBottomWindow();
+ InitCanReleaseMonVars();
+ sub_8093194();
+ gPSSData->state++;
+ break;
+ }
+ break;
+ case 2:
+ RunCanReleaseMon();
+ if (!sub_80931EC())
+ {
+ while (1)
+ {
+ s8 r0 = RunCanReleaseMon();
+ if (r0 == 1)
+ {
+ gPSSData->state++;
+ break;
+ }
+ else if (r0 == 0)
+ {
+ gPSSData->state = 8; // Can't release the mon.
+ break;
+ }
+ }
+ }
+ break;
+ case 3:
+ ReleaseMon();
+ RefreshCursorMonData();
+ PrintStorageActionText(PC_TEXT_WAS_RELEASED);
+ gPSSData->state++;
+ break;
+ case 4:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ PrintStorageActionText(PC_TEXT_BYE_BYE);
+ gPSSData->state++;
+ }
+ break;
+ case 5:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ if (sInPartyMenu)
+ {
+ CompactPartySlots();
+ sub_80909F4();
+ gPSSData->state++;
+ }
+ else
+ {
+ gPSSData->state = 7;
+ }
+ }
+ break;
+ case 6:
+ if (!sub_8090A60())
+ {
+ sub_8092F54();
+ BoxSetMosaic();
+ sub_808FAA8();
+ gPSSData->state++;
+ }
+ break;
+ case 7:
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 8:
+ PrintStorageActionText(PC_TEXT_WAS_RELEASED);
+ gPSSData->state++;
+ break;
+ case 9:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ PrintStorageActionText(PC_TEXT_SURPRISE);
+ gPSSData->state++;
+ }
+ break;
+ case 10:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ sub_8091114();
+ gPSSData->state++;
+ }
+ break;
+ case 11:
+ if (!sub_8091150())
+ {
+ sub_8093264();
+ PrintStorageActionText(PC_TEXT_CAME_BACK);
+ gPSSData->state++;
+ }
+ break;
+ case 12:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ PrintStorageActionText(PC_TEXT_WORRIED);
+ gPSSData->state++;
+ }
+ break;
+ case 13:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_ShowMarkMenu(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_MARK_POKE);
+ gPSSData->field_DA4.markings = gPSSData->cursorMonMarkings;
+ DrawMonMarkingsMenu(gPSSData->cursorMonMarkings, 0xb0, 0x10);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!MonMarkingsHandleInput())
+ {
+ TeardownMonMarkingsMenu();
+ ClearBottomWindow();
+ SetMonMarkings(gPSSData->field_DA4.markings);
+ RefreshCursorMonData();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_TakeItemForMoving(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (!ItemIsMail(gPSSData->cursorMonItem))
+ {
+ ClearBottomWindow();
+ gPSSData->state++;
+ }
+ else
+ {
+ SetPSSCallback(Cb_PrintCantStoreMail);
+ }
+ break;
+ case 1:
+ sub_8094D14(2);
+ Item_FromMonToMoving(sInPartyMenu ? CURSOR_AREA_IN_PARTY : CURSOR_AREA_IN_BOX, GetBoxCursorPosition());
+ gPSSData->state++;
+ break;
+ case 2:
+ if (!sub_809610C())
+ {
+ sub_8094D14(3);
+ ClearBottomWindow();
+ sub_8092F54();
+ PrintCursorMonInfo();
+ gPSSData->state++;
+ }
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_GiveMovingItemToMon(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ ClearBottomWindow();
+ gPSSData->state++;
+ break;
+ case 1:
+ sub_8094D14(2);
+ Item_GiveMovingToMon(sInPartyMenu ? CURSOR_AREA_IN_PARTY : CURSOR_AREA_IN_BOX, GetBoxCursorPosition());
+ gPSSData->state++;
+ break;
+ case 2:
+ if (!sub_809610C())
+ {
+ sub_8094D14(0);
+ sub_8092F54();
+ PrintCursorMonInfo();
+ PrintStorageActionText(PC_TEXT_ITEM_IS_HELD);
+ gPSSData->state++;
+ }
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ gPSSData->state++;
+ }
+ break;
+ case 4:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_ItemToBag(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (!AddBagItem(gPSSData->cursorMonItem, 1))
+ {
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_BAG_FULL);
+ gPSSData->state = 3;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ Item_TakeMons(sInPartyMenu ? CURSOR_AREA_IN_PARTY : CURSOR_AREA_IN_BOX, GetBoxCursorPosition());
+ gPSSData->state = 1;
+ }
+ break;
+ case 1:
+ if (!sub_809610C())
+ {
+ PrintStorageActionText(PC_TEXT_PLACED_IN_BAG);
+ gPSSData->state = 2;
+ }
+ break;
+ case 2:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ sub_8092F54();
+ PrintCursorMonInfo();
+ gPSSData->state = 4;
+ }
+ break;
+ case 4:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_SwitchSelectedItem(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (!ItemIsMail(gPSSData->cursorMonItem))
+ {
+ ClearBottomWindow();
+ gPSSData->state++;
+ }
+ else
+ {
+ SetPSSCallback(Cb_PrintCantStoreMail);
+ }
+ break;
+ case 1:
+ sub_8094D14(2);
+ Item_SwitchMonsWithMoving(sInPartyMenu ? CURSOR_AREA_IN_PARTY : CURSOR_AREA_IN_BOX, GetBoxCursorPosition());
+ gPSSData->state++;
+ break;
+ case 2:
+ if (!sub_809610C())
+ {
+ sub_8094D14(3);
+ sub_8092F54();
+ PrintCursorMonInfo();
+ PrintStorageActionText(PC_TEXT_CHANGED_TO_ITEM);
+ gPSSData->state++;
+ }
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ gPSSData->state++;
+ }
+ break;
+ case 4:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_ShowItemInfo(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ ClearBottomWindow();
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ PlaySE(SE_WIN_OPEN);
+ PrintItemDescription();
+ sub_80966F4();
+ gPSSData->state++;
+ }
+ break;
+ case 2:
+ if (!sub_8096728())
+ gPSSData->state++;
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ gPSSData->state++;
+ break;
+ case 4:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ PlaySE(SE_WIN_OPEN);
+ gPSSData->state++;
+ }
+ break;
+ case 5:
+ if (!sub_80967C0())
+ gPSSData->state++;
+ break;
+ case 6:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_CloseBoxWhileHoldingItem(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ PrintStorageActionText(PC_TEXT_PUT_IN_BAG);
+ ShowYesNoWindow(0);
+ gPSSData->state = 1;
+ break;
+ case 1:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case MENU_B_PRESSED:
+ case 1:
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 0:
+ if (AddBagItem(gPSSData->movingItem, 1) == TRUE)
+ {
+ ClearBottomWindow();
+ gPSSData->state = 3;
+ }
+ else
+ {
+ PrintStorageActionText(PC_TEXT_BAG_FULL);
+ gPSSData->state = 2;
+ }
+ break;
+ }
+ break;
+ case 2:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ gPSSData->state = 5;
+ }
+ break;
+ case 3:
+ sub_8096088();
+ gPSSData->state = 4;
+ break;
+ case 4:
+ if (!sub_809610C())
+ {
+ sub_8094D14(0);
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 5:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_HandleMovingMonFromParty(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ CompactPartySlots();
+ sub_80909F4();
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!sub_8090A60())
+ {
+ sub_808FAA8();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_PrintCantStoreMail(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_CANT_STORE_MAIL);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ gPSSData->state++;
+ break;
+ case 2:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ gPSSData->state++;
+ }
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ }
+}
+
+static void Cb_HandleBoxOptions(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_WHAT_YOU_DO);
+ AddMenu();
+ gPSSData->state++;
+ break;
+ case 1:
+ if (sub_8094F90())
+ return;
+ gPSSData->state++;
+ case 2:
+ switch (sub_8094F94())
+ {
+ case -1:
+ case 0:
+ sub_80920FC(TRUE);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 11:
+ PlaySE(SE_SELECT);
+ SetPSSCallback(Cb_NameBox);
+ break;
+ case 10:
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_HandleWallpapers);
+ break;
+ case 9:
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_JumpBox);
+ break;
+ }
+ break;
+ }
+}
+
+static void Cb_HandleWallpapers(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ AddWallpaperSetsMenu();
+ PrintStorageActionText(PC_TEXT_PICK_A_THEME);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!sub_8094F90())
+ gPSSData->state++;
+ break;
+ case 2:
+ gPSSData->wallpaperSetId = sub_8094F94();
+ switch (gPSSData->wallpaperSetId)
+ {
+ case -1:
+ sub_80920FC(TRUE);
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 18 ... 21:
+ PlaySE(SE_SELECT);
+ sub_8095024();
+ gPSSData->wallpaperSetId -= 18;
+ gPSSData->state++;
+ break;
+ }
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ AddWallpapersMenu(gPSSData->wallpaperSetId);
+ PrintStorageActionText(PC_TEXT_PICK_A_WALLPAPER);
+ gPSSData->state++;
+ }
+ break;
+ case 4:
+ gPSSData->wallpaperId = sub_8094F94();
+ switch (gPSSData->wallpaperId)
+ {
+ case MENU_NOTHING_CHOSEN:
+ break;
+ case MENU_B_PRESSED:
+ ClearBottomWindow();
+ gPSSData->state = 0;
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ ClearBottomWindow();
+ gPSSData->wallpaperId -= 22;
+ SetWallpaperForCurrentBox(gPSSData->wallpaperId);
+ gPSSData->state++;
+ break;
+ }
+ break;
+ case 5:
+ if (!DoWallpaperGfxChange())
+ {
+ sub_80920FC(TRUE);
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_JumpBox(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ PrintStorageActionText(PC_TEXT_JUMP_TO_WHICH_BOX);
+ LoadBoxSelectionPopupSpriteGfx(&gPSSData->field_1E5C, TAG_TILE_A, TAG_PAL_DAC7, 3, FALSE);
+ sub_808C940(StorageGetCurrentBox());
+ gPSSData->state++;
+ break;
+ case 1:
+ gPSSData->newCurrBoxId = HandleBoxChooseSelectionInput();
+ switch (gPSSData->newCurrBoxId)
+ {
+ case 200:
+ break;
+ default:
+ ClearBottomWindow();
+ sub_808C950();
+ FreeBoxSelectionPopupSpriteGfx();
+ if (gPSSData->newCurrBoxId == 201 || gPSSData->newCurrBoxId == StorageGetCurrentBox())
+ {
+ sub_80920FC(TRUE);
+ SetPSSCallback(Cb_MainPSS);
+ }
+ else
+ {
+ gPSSData->state++;
+ }
+ break;
+ }
+ break;
+ case 2:
+ SetUpScrollToBox(gPSSData->newCurrBoxId);
+ gPSSData->state++;
+ break;
+ case 3:
+ if (!ScrollToBox())
+ {
+ SetCurrentBox(gPSSData->newCurrBoxId);
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ }
+}
+
+static void Cb_NameBox(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ sub_8093630();
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ sWhichToReshow = 1;
+ gPSSData->screenChangeType = SCREEN_CHANGE_NAME_BOX;
+ SetPSSCallback(Cb_ChangeScreen);
+ }
+ break;
+ }
+}
+
+static void Cb_ShowMonSummary(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ sub_80936B8();
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ sWhichToReshow = 0;
+ gPSSData->screenChangeType = SCREEN_CHANGE_SUMMARY_SCREEN;
+ SetPSSCallback(Cb_ChangeScreen);
+ }
+ break;
+ }
+}
+
+static void Cb_GiveItemFromBag(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ gPSSData->state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ sWhichToReshow = 2;
+ gPSSData->screenChangeType = SCREEN_CHANGE_ITEM_FROM_BAG;
+ SetPSSCallback(Cb_ChangeScreen);
+ }
+ break;
+ }
+}
+
+static void Cb_OnCloseBoxPressed(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (IsMonBeingMoved())
+ {
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_HOLDING_POKE);
+ gPSSData->state = 1;
+ }
+ else if (IsActiveItemMoving())
+ {
+ SetPSSCallback(Cb_CloseBoxWhileHoldingItem);
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ PrintStorageActionText(PC_TEXT_EXIT_BOX);
+ ShowYesNoWindow(0);
+ gPSSData->state = 2;
+ }
+ break;
+ case 1:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 2:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case MENU_B_PRESSED:
+ case 1:
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 0:
+ PlaySE(SE_PC_OFF);
+ ClearBottomWindow();
+ gPSSData->state++;
+ break;
+ }
+ break;
+ case 3:
+ BeginPCScreenEffect_TurnOff(20, 0, 1);
+ gPSSData->state++;
+ break;
+ case 4:
+ if (!IsPCScreenEffectRunning_TurnOff())
+ {
+ sub_808FF70();
+ gPlayerPartyCount = CalculatePlayerPartyCount();
+ gPSSData->screenChangeType = SCREEN_CHANGE_EXIT_BOX;
+ SetPSSCallback(Cb_ChangeScreen);
+ }
+ break;
+ }
+}
+
+static void Cb_OnBPressed(u8 taskId)
+{
+ switch (gPSSData->state)
+ {
+ case 0:
+ if (IsMonBeingMoved())
+ {
+ PlaySE(SE_HAZURE);
+ PrintStorageActionText(PC_TEXT_HOLDING_POKE);
+ gPSSData->state = 1;
+ }
+ else if (IsActiveItemMoving())
+ {
+ SetPSSCallback(Cb_CloseBoxWhileHoldingItem);
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ PrintStorageActionText(PC_TEXT_CONTINUE_BOX);
+ ShowYesNoWindow(0);
+ gPSSData->state = 2;
+ }
+ break;
+ case 1:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ {
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ }
+ break;
+ case 2:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ ClearBottomWindow();
+ SetPSSCallback(Cb_MainPSS);
+ break;
+ case 1:
+ case MENU_B_PRESSED:
+ PlaySE(SE_PC_OFF);
+ ClearBottomWindow();
+ gPSSData->state++;
+ break;
+ }
+ break;
+ case 3:
+ BeginPCScreenEffect_TurnOff(20, 0, 0);
+ gPSSData->state++;
+ break;
+ case 4:
+ if (!IsPCScreenEffectRunning_TurnOff())
+ {
+ sub_808FF70();
+ gPlayerPartyCount = CalculatePlayerPartyCount();
+ gPSSData->screenChangeType = SCREEN_CHANGE_EXIT_BOX;
+ SetPSSCallback(Cb_ChangeScreen);
+ }
+ break;
+ }
+}
+
+static void Cb_ChangeScreen(u8 taskId)
+{
+ struct Pokemon * partyMon;
+ u8 mode, monIndex, maxMonIndex;
+ u8 screenChangeType = gPSSData->screenChangeType;
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS && IsActiveItemMoving() == TRUE)
+ gUnknown_20397BA = GetMovingItem();
+ else
+ gUnknown_20397BA = ITEM_NONE;
+
+ switch (screenChangeType)
+ {
+ case SCREEN_CHANGE_EXIT_BOX:
+ default:
+ FreePSSData();
+ SetMainCallback2(Cb2_ExitPSS);
+ break;
+ case SCREEN_CHANGE_SUMMARY_SCREEN:
+ partyMon = gPSSData->field_218C.mon;
+ monIndex = gPSSData->field_2187;
+ maxMonIndex = gPSSData->field_2186;
+ mode = gPSSData->field_2188;
+ FreePSSData();
+ ShowPokemonSummaryScreen(partyMon, monIndex, maxMonIndex, Cb2_ReturnToPSS, mode);
+ break;
+ case SCREEN_CHANGE_NAME_BOX:
+ FreePSSData();
+ DoNamingScreen(NAMING_SCREEN_BOX, GetBoxNamePtr(StorageGetCurrentBox()), 0, 0, 0, Cb2_ReturnToPSS);
+ break;
+ case SCREEN_CHANGE_ITEM_FROM_BAG:
+ FreePSSData();
+ GoToBagMenu(ITEMMENULOCATION_PCBOX, OPEN_BAG_ITEMS, Cb2_ReturnToPSS);
+ break;
+ }
+
+ DestroyTask(taskId);
+}
+
+static void GiveChosenBagItem(void)
+{
+ u16 item = gSpecialVar_ItemId;
+
+ if (item != ITEM_NONE)
+ {
+ u8 id = GetBoxCursorPosition();
+
+ if (sInPartyMenu)
+ SetMonData(&gPlayerParty[id], MON_DATA_HELD_ITEM, &item);
+ else
+ SetCurrentBoxMonData(id, MON_DATA_HELD_ITEM, &item);
+
+ RemoveBagItem(item, 1);
+ }
+}
+
+static void FreePSSData(void)
+{
+ FreeBoxPartyPokemonDropdowns();
+ sub_80950A4();
+ FREE_AND_SET_NULL(gPSSData);
+ FreeAllWindowBuffers();
+}
+
+// ******************************************************************
+// Graphics util
+// ******************************************************************
+
+static void SetScrollingBackground(void)
+{
+ SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(3) | BGCNT_16COLOR | BGCNT_SCREENBASE(31));
+ DecompressAndLoadBgGfxUsingHeap(3, sPokemonStorageScrollingBGTileset, 0, 0, 0);
+ LZ77UnCompVram(sPokemonStorageScrollingBGTilemap, (void *)BG_SCREEN_ADDR(31));
+}
+
+static void ScrollBackground(void)
+{
+ ChangeBgX(3, 128, 1);
+ ChangeBgY(3, 128, 2);
+}
+
+static void LoadPSSMenuGfx(void)
+{
+ InitBgsFromTemplates(0, gUnknown_83CEA50, NELEMS(gUnknown_83CEA50));
+ DecompressAndLoadBgGfxUsingHeap(1, gPSSMenu_Gfx, 0, 0, 0);
+ LZ77UnCompWram(gUnknown_83CE5FC, gPSSData->field_5AC4);
+ SetBgTilemapBuffer(1, gPSSData->field_5AC4);
+ ShowBg(1);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+static bool8 InitPSSWindows(void)
+{
+ if (!InitWindows(gUnknown_83CEA30))
+ {
+ return FALSE;
+ }
+ else
+ {
+ DeactivateAllTextPrinters();
+ return TRUE;
+ }
+}
+
+static void LoadWaveformSpritePalette(void)
+{
+ LoadSpritePalette(&sWaveformSpritePalette);
+}
+
+static void sub_808F078(void)
+{
+ LoadPalette(gUnknown_8E9C3F8, 0, 0x20);
+ LoadPalette(gUnknown_8E9C418, 0x20, 0x20);
+ LoadPalette(gUnknown_83CEA10, 0xF0, 0x20);
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ LoadPalette(gUnknown_83CE738, 0x30, 0x20);
+ else
+ LoadPalette(gUnknown_83CE758, 0x30, 0x20);
+
+ SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) | BGCNT_CHARBASE(1) | BGCNT_16COLOR | BGCNT_SCREENBASE(30));
+ LoadCursorMonSprite();
+ sub_808F0F4();
+ sub_808F164();
+ RefreshCursorMonData();
+}
+
+static void sub_808F0F4(void)
+{
+ gPSSData->field_D94 = CreateMonMarkingSprite_AllOff(TAG_TILE_10, TAG_PAL_DAC8, NULL);
+ gPSSData->field_D94->oam.priority = 1;
+ gPSSData->field_D94->subpriority = 1;
+ gPSSData->field_D94->pos1.x = 40;
+ gPSSData->field_D94->pos1.y = 150;
+ gPSSData->field_DA0 = (void *)OBJ_VRAM0 + 32 * GetSpriteTileStartByTag(TAG_TILE_10);
+}
+
+static void sub_808F164(void)
+{
+ u16 i;
+ struct SpriteSheet sheet = sWaveformSpriteSheet;
+
+ LoadSpriteSheet(&sheet);
+ for (i = 0; i < 2; i++)
+ {
+ u8 spriteId = CreateSprite(&sSpriteTemplate_Waveform, i * 63 + 8, 9, 2);
+ gPSSData->field_D98[i] = &gSprites[spriteId];
+ }
+}
+
+static void RefreshCursorMonData(void)
+{
+ LoadCursorMonGfx(gPSSData->cursorMonSpecies, gPSSData->cursorMonPersonality);
+ PrintCursorMonInfo();
+ sub_808F5E8();
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void BoxSetMosaic(void)
+{
+ RefreshCursorMonData();
+ if (gPSSData->cursorMonSprite)
+ {
+ gPSSData->cursorMonSprite->oam.mosaic = TRUE;
+ gPSSData->cursorMonSprite->data[0] = 10;
+ gPSSData->cursorMonSprite->data[1] = 1;
+ gPSSData->cursorMonSprite->callback = SpriteCB_CursorMon_Mosaic;
+ SetGpuReg(REG_OFFSET_MOSAIC, (gPSSData->cursorMonSprite->data[0] << 12) | (gPSSData->cursorMonSprite->data[0] << 8));
+ }
+}
+
+static u8 BoxGetMosaic(void)
+{
+ return gPSSData->cursorMonSprite->oam.mosaic;
+}
+
+static void SpriteCB_CursorMon_Mosaic(struct Sprite *sprite)
+{
+ sprite->data[0] -= sprite->data[1];
+ if (sprite->data[0] < 0)
+ sprite->data[0] = 0;
+ SetGpuReg(REG_OFFSET_MOSAIC, (sprite->data[0] << 12) | (sprite->data[0] << 8));
+ if (sprite->data[0] == 0)
+ {
+ sprite->oam.mosaic = FALSE;
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void LoadCursorMonSprite(void)
+{
+ u16 i;
+ u16 tileStart;
+ u8 palSlot;
+ u8 spriteId;
+ struct SpriteSheet sheet = {gPSSData->field_22C4, 0x800, TAG_TILE_2};
+ struct SpritePalette palette = {gPSSData->field_2244, TAG_PAL_DAC6};
+ struct SpriteTemplate template = sSpriteTemplate_CursorMon;
+
+ for (i = 0; i < 0x800; i++)
+ gPSSData->field_22C4[i] = 0;
+ for (i = 0; i < 0x10; i++)
+ gPSSData->field_2244[i] = 0;
+
+ gPSSData->cursorMonSprite = NULL;
+
+ do
+ {
+ tileStart = LoadSpriteSheet(&sheet);
+ if (tileStart == 0)
+ break;
+
+ palSlot = LoadSpritePalette(&palette);
+ if (palSlot == 0xFF)
+ break;
+
+ spriteId = CreateSprite(&template, 40, 48, 0);
+ if (spriteId == MAX_SPRITES)
+ break;
+
+ gPSSData->cursorMonSprite = &gSprites[spriteId];
+ gPSSData->field_223A = palSlot * 16 + 0x100;
+ gPSSData->field_223C = (void *)OBJ_VRAM0 + tileStart * 32;
+ } while (0);
+
+ if (gPSSData->cursorMonSprite == NULL)
+ {
+ FreeSpriteTilesByTag(TAG_TILE_2);
+ FreeSpritePaletteByTag(TAG_PAL_DAC6);
+ }
+}
+
+static void LoadCursorMonGfx(u16 species, u32 pid)
+{
+ if (gPSSData->cursorMonSprite == NULL)
+ return;
+
+ if (species != SPECIES_NONE)
+ {
+ HandleLoadSpecialPokePic(&gMonFrontPicTable[species], gPSSData->field_22C4, species, pid);
+ LZ77UnCompWram(gPSSData->cursorMonPalette, gPSSData->field_2244);
+ CpuCopy32(gPSSData->field_22C4, gPSSData->field_223C, 0x800);
+ LoadPalette(gPSSData->field_2244, gPSSData->field_223A, 0x20);
+ gPSSData->cursorMonSprite->invisible = FALSE;
+ }
+ else
+ {
+ gPSSData->cursorMonSprite->invisible = TRUE;
+ }
+}
+
+static void PrintCursorMonInfo(void)
+{
+ u16 i;
+ u16 y;
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ for (i = 0, y = 0; i < 3; i++, y += 14)
+ {
+ AddTextPrinterParameterized(0, 2, gPSSData->cursorMonTexts[i], i == 2 ? 10 : 6, y, TEXT_SPEED_FF, NULL);
+ }
+ AddTextPrinterParameterized(0, 0, gPSSData->cursorMonTexts[3], 6, y + 2, TEXT_SPEED_FF, NULL);
+ }
+ else
+ {
+ AddTextPrinterParameterized(0, 0, gPSSData->cursorMonTexts[3], 6, 0, TEXT_SPEED_FF, NULL);
+ for (i = 0, y = 15; i < 3; i++, y += 14)
+ {
+ AddTextPrinterParameterized(0, 2, gPSSData->cursorMonTexts[i], i == 2 ? 10 : 6, y, TEXT_SPEED_FF, NULL);
+ }
+ }
+
+ CopyWindowToVram(0, 2);
+ if (gPSSData->cursorMonSpecies != SPECIES_NONE)
+ {
+ sub_80BEBD0(gPSSData->cursorMonMarkings, gPSSData->field_DA0);
+ gPSSData->field_D94->invisible = FALSE;
+ }
+ else
+ {
+ gPSSData->field_D94->invisible = TRUE;
+ }
+}
+
+static void sub_808F5E8(void)
+{
+ u16 i;
+
+ if (gPSSData->cursorMonSpecies != SPECIES_NONE)
+ {
+ SetBoxPartyPokemonDropdownMap2Rect(0, 0, 0, 8, 2);
+ for (i = 0; i < 2; i++)
+ StartSpriteAnimIfDifferent(gPSSData->field_D98[i], i * 2 + 1);
+ }
+ else
+ {
+ SetBoxPartyPokemonDropdownMap2Rect(0, 0, 2, 8, 2);
+ for (i = 0; i < 2; i++)
+ StartSpriteAnim(gPSSData->field_D98[i], i * 2);
+ }
+
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(0);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+static void sub_808F68C(void)
+{
+ LZ77UnCompWram(gUnknown_8E9CAEC, gPSSData->field_B0);
+ LoadPalette(gPSSMenu_Pal, 0x10, 0x20);
+ SetBoxPartyPokemonDropdownMap2(1, 1, gPSSData->field_B0, 12, 22);
+ SetBoxPartyPokemonDropdownMap2(2, 1, gUnknown_83CE778, 9, 4);
+ SetBoxPartyPokemonDropdownMap2Pos(1, 10, 0);
+ SetBoxPartyPokemonDropdownMap2Pos(2, 21, 0);
+ sub_808F9FC();
+ if (sInPartyMenu)
+ {
+ sub_808F90C(TRUE);
+ CreatePartyMonsSprites(TRUE);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(2);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(1);
+ }
+ else
+ {
+ SetBoxPartyPokemonDropdownMap2Rect(1, 0, 20, 12, 2);
+ sub_808F90C(TRUE);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(1);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(2);
+ }
+
+ ScheduleBgCopyTilemapToVram(1);
+ gPSSData->unk_02C7 = FALSE;
+}
+
+static void SetUpShowPartyMenu(void)
+{
+ gPSSData->field_2C0 = 20;
+ gPSSData->field_2C2 = 2;
+ gPSSData->field_2C5 = 0;
+ CreatePartyMonsSprites(FALSE);
+}
+
+static bool8 ShowPartyMenu(void)
+{
+ if (gPSSData->field_2C5 == 20)
+ return FALSE;
+
+ gPSSData->field_2C0--;
+ gPSSData->field_2C2++;
+ AdjustBoxPartyPokemonDropdownPos(1, 3, 1);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(1);
+ ScheduleBgCopyTilemapToVram(1);
+ sub_8090B98(8);
+ if (++gPSSData->field_2C5 == 20)
+ {
+ sInPartyMenu = TRUE;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+static void SetUpHidePartyMenu(void)
+{
+ gPSSData->field_2C0 = 0;
+ gPSSData->field_2C2 = 22;
+ gPSSData->field_2C5 = 0;
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ sub_80960C0();
+}
+
+static bool8 HidePartyMenu(void)
+{
+ if (gPSSData->field_2C5 != 20)
+ {
+ gPSSData->field_2C0++;
+ gPSSData->field_2C2--;
+ AdjustBoxPartyPokemonDropdownPos(1, 3, -1);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(1);
+ FillBgTilemapBufferRect_Palette0(1, 0x100, 10, gPSSData->field_2C2, 12, 1);
+ sub_8090B98(-8);
+ if (++gPSSData->field_2C5 != 20)
+ {
+ ScheduleBgCopyTilemapToVram(1);
+ return TRUE;
+ }
+ else
+ {
+ sInPartyMenu = FALSE;
+ DestroyAllPartyMonIcons();
+ CompactPartySlots();
+ SetBoxPartyPokemonDropdownMap2Rect(2, 0, 0, 9, 2);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(2);
+ ScheduleBgCopyTilemapToVram(1);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void sub_808F90C(bool8 arg0)
+{
+ if (arg0)
+ SetBoxPartyPokemonDropdownMap2Rect(2, 0, 0, 9, 2);
+ else
+ SetBoxPartyPokemonDropdownMap2Rect(2, 0, 2, 9, 2);
+
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(2);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+static void sub_808F948(void)
+{
+ gPSSData->unk_02C7 = TRUE;
+ gPSSData->unk_02C8 = 30;
+ gPSSData->unk_02C9 = TRUE;
+}
+
+static void sub_808F974(void)
+{
+ if (gPSSData->unk_02C7)
+ {
+ gPSSData->unk_02C7 = FALSE;
+ sub_808F90C(TRUE);
+ }
+}
+
+static void sub_808F99C(void)
+{
+ if (gPSSData->unk_02C7 && ++gPSSData->unk_02C8 > 30)
+ {
+ gPSSData->unk_02C8 = 0;
+ gPSSData->unk_02C9 = (gPSSData->unk_02C9 == FALSE);
+ sub_808F90C(gPSSData->unk_02C9);
+ }
+}
+
+static void sub_808F9FC(void)
+{
+ u8 i;
+
+ for (i = 1; i < PARTY_SIZE; i++)
+ {
+ s32 species = GetMonData(gPlayerParty + i, MON_DATA_SPECIES);
+ sub_808FA30(i, (species != SPECIES_NONE));
+ }
+}
+
+static void sub_808FA30(u8 pos, bool8 isPartyMon)
+{
+ u16 i, j, index;
+ const u16 *data;
+
+ if (isPartyMon)
+ data = gUnknown_83CE7C0;
+ else
+ data = gUnknown_83CE7D8;
+
+ index = 3 * (3 * (pos - 1) + 1);
+ index *= 4;
+ index += 7;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ gPSSData->field_B0[index + j] = data[j];
+ }
+ data += 4;
+ index += 12;
+ }
+}
+
+static void sub_808FAA8(void)
+{
+ sub_808F9FC();
+ SetBoxPartyPokemonDropdownMap2Rect(1, 0, 0, 12, 22);
+ CopyBoxPartyPokemonDropdownToBgTilemapBuffer(1);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+static void SetUpDoShowPartyMenu(void)
+{
+ gPSSData->showPartyMenuState = 0;
+ PlaySE(SE_WIN_OPEN);
+ SetUpShowPartyMenu();
+}
+
+static bool8 DoShowPartyMenu(void)
+{
+ switch (gPSSData->showPartyMenuState)
+ {
+ case 0:
+ if (!ShowPartyMenu())
+ {
+ sub_8092AE4();
+ gPSSData->showPartyMenuState++;
+ }
+ break;
+ case 1:
+ if (!sub_80924A8())
+ {
+ if (gPSSData->setMosaic)
+ BoxSetMosaic();
+ gPSSData->showPartyMenuState++;
+ }
+ break;
+ case 2:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void sub_808FB68(void)
+{
+ SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(29));
+ TextWindow_SetStdFrame0_WithPal(1, 2, 208);
+ FillBgTilemapBufferRect(0, 0, 0, 0, 32, 20, 17);
+ CopyBgTilemapBufferToVram(0);
+}
+
+static void PrintStorageActionText(u8 id)
+{
+ u8 *txtPtr;
+
+ DynamicPlaceholderTextUtil_Reset();
+ switch (sPCStorageActionTexts[id].format)
+ {
+ case PC_TEXT_FMT_NORMAL:
+ break;
+ case PC_TEXT_FMT_MON_NAME_1:
+ case PC_TEXT_FMT_MON_NAME_2:
+ case PC_TEXT_FMT_MON_NAME_3:
+ DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gPSSData->cursorMonNick);
+ break;
+ case PC_TEXT_FMT_MON_NAME_4:
+ case PC_TEXT_FMT_MON_NAME_5:
+ case PC_TEXT_FMT_MON_NAME_6:
+ DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gPSSData->field_21E0);
+ break;
+ case PC_TEXT_FMT_ITEM_NAME:
+ if (IsActiveItemMoving())
+ txtPtr = StringCopy(gPSSData->itemName, GetMovingItemName());
+ else
+ txtPtr = StringCopy(gPSSData->itemName, gPSSData->cursorMonTexts[3]);
+
+ while (*(txtPtr - 1) == CHAR_SPACE)
+ txtPtr--;
+
+ *txtPtr = EOS;
+ DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gPSSData->itemName);
+ break;
+ }
+
+ DynamicPlaceholderTextUtil_ExpandPlaceholders(gPSSData->field_2190, sPCStorageActionTexts[id].text);
+ FillWindowPixelBuffer(1, PIXEL_FILL(1));
+ AddTextPrinterParameterized(1, 1, gPSSData->field_2190, 0, 2, TEXT_SPEED_FF, NULL);
+ DrawTextBorderOuter(1, 2, 13);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 2);
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void ShowYesNoWindow(s8 cursorPos)
+{
+ CreateYesNoMenu(&sYesNoWindowTemplate, 1, 0, 2, 0x00b, 14, 1);
+ Menu_MoveCursorNoWrapAround(cursorPos);
+}
+
+static void ClearBottomWindow(void)
+{
+ ClearStdWindowAndFrameToTransparent(1, FALSE);
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void AddWallpaperSetsMenu(void)
+{
+ InitMenu();
+ SetMenuText(PC_TEXT_SCENERY1);
+ SetMenuText(PC_TEXT_SCENERY2);
+ SetMenuText(PC_TEXT_SCENERY3);
+ SetMenuText(PC_TEXT_ETCETERA);
+ AddMenu();
+}
+
+static void AddWallpapersMenu(u8 wallpaperSet)
+{
+ InitMenu();
+ switch (wallpaperSet)
+ {
+ case 0:
+ SetMenuText(PC_TEXT_FOREST);
+ SetMenuText(PC_TEXT_CITY);
+ SetMenuText(PC_TEXT_DESERT);
+ SetMenuText(PC_TEXT_SAVANNA);
+ break;
+ case 1:
+ SetMenuText(PC_TEXT_CRAG);
+ SetMenuText(PC_TEXT_VOLCANO);
+ SetMenuText(PC_TEXT_SNOW);
+ SetMenuText(PC_TEXT_CAVE);
+ break;
+ case 2:
+ SetMenuText(PC_TEXT_BEACH);
+ SetMenuText(PC_TEXT_SEAFLOOR);
+ SetMenuText(PC_TEXT_RIVER);
+ SetMenuText(PC_TEXT_SKY);
+ break;
+ case 3:
+ SetMenuText(PC_TEXT_POLKADOT);
+ SetMenuText(PC_TEXT_POKECENTER);
+ SetMenuText(PC_TEXT_MACHINE);
+ SetMenuText(PC_TEXT_SIMPLE);
+ break;
+ }
+ AddMenu();
+}
+
+u8 GetCurrentBoxOption(void)
+{
+ return sCurrentBoxOption;
+}
+
+static void sub_808FDFC(void)
+{
+ if (!IsCursorOnBox())
+ {
+ if (sInPartyMenu)
+ sub_8095C84(CURSOR_AREA_IN_PARTY, GetBoxCursorPosition());
+ else
+ sub_8095C84(CURSOR_AREA_IN_BOX, GetBoxCursorPosition());
+ }
+
+ if (gUnknown_20397BA != ITEM_NONE)
+ {
+ sub_8095E2C(gUnknown_20397BA);
+ sub_8094D14(3);
+ }
+}
+
+static void sub_808FE54(u8 action)
+{
+ u16 event;
+ u8 fromBox = sub_8094D34();
+ u16 species = gPSSData->cursorMonSpecies;
+ u16 species2;
+ u8 toBox;
+ struct PssQuestLogBuffer * qlogBuffer;
+ if (sInPartyMenu)
+ {
+ toBox = TOTAL_BOXES_COUNT;
+ species2 = GetMonData(&gPlayerParty[GetBoxCursorPosition()], MON_DATA_SPECIES2);
+ }
+ else
+ {
+ toBox = StorageGetCurrentBox();
+ species2 = GetCurrentBoxMonData(GetBoxCursorPosition(), MON_DATA_SPECIES2);
+ }
+ qlogBuffer = &gPSSData->qlogBuffer;
+
+ switch (action)
+ {
+ default:
+ return;
+ case 0:
+ if (sInPartyMenu)
+ {
+ if (fromBox == TOTAL_BOXES_COUNT)
+ return;
+ else
+ event = QL_EVENT_SWITCHED_PARTY_MON_FOR_PC_MON;
+ }
+ else
+ {
+ if (fromBox == TOTAL_BOXES_COUNT)
+ // Should upmerge but doesn't
+ event = QL_EVENT_SWITCHED_PARTY_MON_FOR_PC_MON;
+ else
+ event = fromBox != toBox ? QL_EVENT_SWITCHED_MONS_BETWEEN_BOXES : QL_EVENT_SWITCHED_MONS_WITHIN_BOX;
+ }
+ qlogBuffer->species = species;
+ qlogBuffer->species2 = species2;
+ qlogBuffer->fromBox = fromBox;
+ qlogBuffer->toBox = toBox;
+ break;
+ case 1:
+ qlogBuffer->species = species;
+ qlogBuffer->species2 = SPECIES_NONE;
+ qlogBuffer->fromBox = fromBox;
+ qlogBuffer->toBox = 0xFF;
+ if (sInPartyMenu)
+ {
+ if (fromBox == TOTAL_BOXES_COUNT)
+ return;
+ else
+ event = QL_EVENT_WITHDREW_MON_PC;
+ }
+ else
+ {
+ if (fromBox == TOTAL_BOXES_COUNT)
+ {
+ event = QL_EVENT_DEPOSITED_MON_PC;
+ qlogBuffer->fromBox = toBox;
+ }
+ else if (fromBox != toBox)
+ {
+ event = QL_EVENT_MOVED_MON_BETWEEN_BOXES;
+ qlogBuffer->toBox = toBox;
+ }
+ else
+ event = QL_EVENT_MOVED_MON_WITHIN_BOX;
+ }
+ break;
+ case 2:
+ event = QL_EVENT_DEPOSITED_MON_PC;
+ qlogBuffer->species = species;
+ qlogBuffer->species2 = SPECIES_NONE;
+ qlogBuffer->fromBox = gUnknown_20397B6;
+ qlogBuffer->toBox = 0xFF;
+ break;
+ case 3:
+ event = QL_EVENT_SWITCHED_MULTIPLE_MONS;
+ qlogBuffer->species = SPECIES_NONE;
+ qlogBuffer->species2 = SPECIES_NONE;
+ qlogBuffer->fromBox = fromBox;
+ qlogBuffer->toBox = toBox;
+ break;
+ }
+ SetQuestLogEvent(event, (const void *)qlogBuffer);
+}
+
+static void sub_808FF70(void)
+{
+ if (sLastUsedBox != StorageGetCurrentBox())
+ {
+ FlagClear(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE);
+ VarSet(VAR_PC_BOX_TO_SEND_MON, StorageGetCurrentBox());
+ }
+}
diff --git a/src/pokemon_storage_system_4.c b/src/pokemon_storage_system_4.c
new file mode 100644
index 000000000..392d17574
--- /dev/null
+++ b/src/pokemon_storage_system_4.c
@@ -0,0 +1,1489 @@
+#include "global.h"
+#include "gflib.h"
+#include "event_data.h"
+#include "graphics.h"
+#include "new_menu_helpers.h"
+#include "pokemon_icon.h"
+#include "pokemon_storage_system_internal.h"
+#include "strings.h"
+#include "task.h"
+#include "trig.h"
+#include "constants/species.h"
+#include "constants/vars.h"
+#include "constants/flags.h"
+
+static void sub_8090324(struct Sprite * sprite);
+static void SetBoxSpeciesAndPersonalities(u8 boxId);
+static void sub_8090A74(struct Sprite * sprite, u16 idx);
+static void sub_8090AE0(struct Sprite * sprite);
+static void DestroyBoxMonIcon(struct Sprite * sprite);
+static void sub_80911B0(struct Sprite * sprite);
+static void sub_8091420(u8 taskId);
+static s8 sub_80916F4(u8 boxId);
+static void LoadWallpaperGfx(u8 wallpaperId, s8 direction);
+static bool32 WaitForWallpaperGfxLoad(void);
+static void sub_8091984(void *buffer, const void *buffer2, s8 direction, u8 baseBlock);
+static void sub_8091A24(void *buffer);
+static void sub_8091A94(u8 wallpaperId);
+static void sub_8091C48(u8 wallpaperId, s8 direction);
+static void sub_8091E84(struct Sprite * sprite);
+static void sub_8091EB8(struct Sprite * sprite);
+static s16 sub_8091F60(const u8 *boxName);
+static void sub_8091E34(void);
+static void sub_8091EF0(void);
+static void sub_8091F80(void);
+static void sub_809200C(s8 direction);
+static void sub_80920AC(void);
+static void sub_8092164(struct Sprite * sprite);
+
+static const struct OamData gUnknown_83CEC08;
+
+static const struct SpriteTemplate gUnknown_83CEBF0 = {
+ .tileTag = TAG_TILE_12,
+ .paletteTag = TAG_PAL_DAC0,
+ .oam = &gUnknown_83CEC08,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_83CEC08 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(32x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x32),
+ .tileNum = 0x000,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const union AffineAnimCmd gUnknown_83CEC10[] = {
+ AFFINEANIMCMD_FRAME(-2, -2, 0, 120),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83CEC20[] = {
+ AFFINEANIMCMD_FRAME(16, 16, 0, 0),
+ AFFINEANIMCMD_FRAME(16, 16, 0, 15),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const gUnknown_83CEC38[] = {
+ gUnknown_83CEC10,
+ gUnknown_83CEC20
+};
+
+static const u16 gUnknown_83CEC40[] = INCBIN_U16("graphics/interface/pss_unk_83CEC40.gbapal");
+static const u32 gUnknown_83CEC80[] = INCBIN_U32("graphics/interface/pss_unk_83CEC80.4bpp.lz");
+static const u32 gUnknown_83CF050[] = INCBIN_U32("graphics/interface/pss_unk_83CF050.bin.lz");
+static const u16 gUnknown_83CF12C[] = INCBIN_U16("graphics/interface/pss_unk_83CF12C.gbapal");
+static const u32 gUnknown_83CF16C[] = INCBIN_U32("graphics/interface/pss_unk_83CF16C.4bpp.lz");
+static const u32 gUnknown_83CF374[] = INCBIN_U32("graphics/interface/pss_unk_83CF374.bin.lz");
+static const u16 gUnknown_83CF424[] = INCBIN_U16("graphics/interface/pss_unk_83CF424.gbapal");
+static const u32 gUnknown_83CF464[] = INCBIN_U32("graphics/interface/pss_unk_83CF464.4bpp.lz");
+static const u32 gUnknown_83CF750[] = INCBIN_U32("graphics/interface/pss_unk_83CF750.bin.lz");
+static const u16 gUnknown_83CF834[] = INCBIN_U16("graphics/interface/pss_unk_83CF834.gbapal");
+static const u32 gUnknown_83CF874[] = INCBIN_U32("graphics/interface/pss_unk_83CF874.4bpp.lz");
+static const u32 gUnknown_83CFA94[] = INCBIN_U32("graphics/interface/pss_unk_83CFA94.bin.lz");
+static const u16 gUnknown_83CFB60[] = INCBIN_U16("graphics/interface/pss_unk_83CFB60.gbapal");
+static const u32 gUnknown_83CFBA0[] = INCBIN_U32("graphics/interface/pss_unk_83CFBA0.4bpp.lz");
+static const u32 gUnknown_83CFEF0[] = INCBIN_U32("graphics/interface/pss_unk_83CFEF0.bin.lz");
+static const u16 gUnknown_83CFFC8[] = INCBIN_U16("graphics/interface/pss_unk_83CFFC8.gbapal");
+static const u32 gUnknown_83D0008[] = INCBIN_U32("graphics/interface/pss_unk_83D0008.4bpp.lz");
+static const u8 sSpace_83D0338[4] = {};
+static const u32 gUnknown_83D033C[] = INCBIN_U32("graphics/interface/pss_unk_83D033C.bin.lz");
+static const u16 gUnknown_83D0414[] = INCBIN_U16("graphics/interface/pss_unk_83D0414.gbapal");
+static const u32 gUnknown_83D0454[] = INCBIN_U32("graphics/interface/pss_unk_83D0454.4bpp.lz");
+static const u32 gUnknown_83D070C[] = INCBIN_U32("graphics/interface/pss_unk_83D070C.bin.lz");
+static const u16 gUnknown_83D07D8[] = INCBIN_U16("graphics/interface/pss_unk_83D07D8.gbapal");
+static const u32 gUnknown_83D0818[] = INCBIN_U32("graphics/interface/pss_unk_83D0818.4bpp.lz");
+static const u32 gUnknown_83D0B5C[] = INCBIN_U32("graphics/interface/pss_unk_83D0B5C.bin.lz");
+static const u16 gUnknown_83D0C38[] = INCBIN_U16("graphics/interface/pss_unk_83D0C38.gbapal");
+static const u32 gUnknown_83D0C78[] = INCBIN_U32("graphics/interface/pss_unk_83D0C78.4bpp.lz");
+static const u32 gUnknown_83D0FFC[] = INCBIN_U32("graphics/interface/pss_unk_83D0FFC.bin.lz");
+static const u16 gUnknown_83D10E4[] = INCBIN_U16("graphics/interface/pss_unk_83D10E4.gbapal");
+static const u32 gUnknown_83D1124[] = INCBIN_U32("graphics/interface/pss_unk_83D1124.4bpp.lz");
+static const u32 gUnknown_83D13D8[] = INCBIN_U32("graphics/interface/pss_unk_83D13D8.bin.lz");
+static const u16 gUnknown_83D14B4[] = INCBIN_U16("graphics/interface/pss_unk_83D14B4.gbapal");
+static const u32 gUnknown_83D14F4[] = INCBIN_U32("graphics/interface/pss_unk_83D14F4.4bpp.lz");
+static const u32 gUnknown_83D1788[] = INCBIN_U32("graphics/interface/pss_unk_83D1788.bin.lz");
+static const u16 gUnknown_83D1874[] = INCBIN_U16("graphics/interface/pss_unk_83D1874.gbapal");
+static const u32 gUnknown_83D18B4[] = INCBIN_U32("graphics/interface/pss_unk_83D18B4.4bpp.lz");
+static const u32 gUnknown_83D1B4C[] = INCBIN_U32("graphics/interface/pss_unk_83D1B4C.bin.lz");
+static const u16 gUnknown_83D1C2C[] = INCBIN_U16("graphics/interface/pss_unk_83D1C2C.gbapal");
+static const u8 sSpace_83D1C6C[32] = {};
+static const u32 gUnknown_83D1C8C[] = INCBIN_U32("graphics/interface/pss_unk_83D1C8C.4bpp.lz");
+static const u32 gUnknown_83D1EC4[] = INCBIN_U32("graphics/interface/pss_unk_83D1EC4.bin.lz");
+static const u16 gUnknown_83D1F94[] = INCBIN_U16("graphics/interface/pss_unk_83D1F94.gbapal");
+static const u32 gUnknown_83D1FD4[] = INCBIN_U32("graphics/interface/pss_unk_83D1FD4.4bpp.lz");
+static const u32 gUnknown_83D22B8[] = INCBIN_U32("graphics/interface/pss_unk_83D22B8.bin.lz");
+static const u16 gUnknown_83D239C[] = INCBIN_U16("graphics/interface/pss_unk_83D239C.gbapal");
+static const u32 gUnknown_83D23DC[] = INCBIN_U32("graphics/interface/pss_unk_83D23DC.4bpp.lz");
+static const u32 gUnknown_83D256C[] = INCBIN_U32("graphics/interface/pss_unk_83D256C.bin.lz");
+static const u16 gUnknown_83D2614[] = INCBIN_U16("graphics/interface/pss_unk_83D2614.gbapal");
+static const u32 gUnknown_83D2654[] = INCBIN_U32("graphics/interface/pss_unk_83D2654.4bpp.lz");
+static const u32 gUnknown_83D277C[] = INCBIN_U32("graphics/interface/pss_unk_83D277C.bin.lz");
+static const u16 gUnknown_83D2820[] = INCBIN_U16("graphics/interface/pss_unk_83D2820.bin");
+
+static const u16 gUnknown_83D29D0[][2] = {
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)},
+ {RGB( 7, 7, 7), RGB(31, 31, 31)}
+};
+
+static const struct WallpaperTable sWallpaperTable[] = {
+ {gUnknown_83CEC80, gUnknown_83CF050, gUnknown_83CEC40},
+ {gUnknown_83CF16C, gUnknown_83CF374, gUnknown_83CF12C},
+ {gUnknown_83CF464, gUnknown_83CF750, gUnknown_83CF424},
+ {gUnknown_83CF874, gUnknown_83CFA94, gUnknown_83CF834},
+ {gUnknown_83CFBA0, gUnknown_83CFEF0, gUnknown_83CFB60},
+ {gUnknown_83D0008, gUnknown_83D033C, gUnknown_83CFFC8},
+ {gUnknown_83D0454, gUnknown_83D070C, gUnknown_83D0414},
+ {gUnknown_83D0818, gUnknown_83D0B5C, gUnknown_83D07D8},
+ {gUnknown_83D0C78, gUnknown_83D0FFC, gUnknown_83D0C38},
+ {gUnknown_83D1124, gUnknown_83D13D8, gUnknown_83D10E4},
+ {gUnknown_83D14F4, gUnknown_83D1788, gUnknown_83D14B4},
+ {gUnknown_83D18B4, gUnknown_83D1B4C, gUnknown_83D1874},
+ {gUnknown_83D1C8C, gUnknown_83D1EC4, gUnknown_83D1C2C},
+ {gUnknown_83D1FD4, gUnknown_83D22B8, gUnknown_83D1F94},
+ {gUnknown_83D23DC, gUnknown_83D256C, gUnknown_83D239C},
+ {gUnknown_83D2654, gUnknown_83D277C, gUnknown_83D2614},
+};
+
+static const u16 gUnknown_83D2AD0[] = INCBIN_U16("graphics/interface/pss_unk_83D2AD0.4bpp");
+static const u8 sUnref_83D2B50[] = {0xba, 0x23};
+
+static const struct SpriteSheet gUnknown_83D2B54 = {
+ gUnknown_83D2AD0, 0x0080, TAG_TILE_6
+};
+
+static const struct OamData gUnknown_83D2B5C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(32x16),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x16),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0
+};
+
+static const union AnimCmd gUnknown_83D2B64[] = {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D2B6C[] = {
+ ANIMCMD_FRAME(8, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83D2B74[] = {
+ gUnknown_83D2B64,
+ gUnknown_83D2B6C
+};
+
+static const struct SpriteTemplate gUnknown_83D2B7C = {
+ .tileTag = TAG_TILE_3,
+ .paletteTag = TAG_PAL_DAC9,
+ .oam = &gUnknown_83D2B5C,
+ .anims = gUnknown_83D2B74,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_83D2B94 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(8x16),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x16),
+ .tileNum = 0x000,
+ .priority = 2,
+ .paletteNum = 0
+};
+
+static const union AnimCmd gUnknown_83D2B9C[] = {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D2BA4[] = {
+ ANIMCMD_FRAME(2, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83D2BAC[] = {
+ gUnknown_83D2B9C,
+ gUnknown_83D2BA4
+};
+
+static const struct SpriteTemplate gUnknown_83D2BB4 = {
+ .tileTag = TAG_TILE_6,
+ .paletteTag = TAG_PAL_WAVEFORM,
+ .oam = &gUnknown_83D2B94,
+ .anims = gUnknown_83D2BAC,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_8092164
+};
+
+void sub_808FFAC(void)
+{
+ u16 i;
+
+ LoadMonIconPalettes();
+ for (i = 0; i < MAX_MON_ICONS; i++)
+ gPSSData->field_B08[i] = 0;
+ for (i = 0; i < MAX_MON_ICONS; i++)
+ gPSSData->field_B58[i] = 0;
+ for (i = 0; i < PARTY_SIZE; i++)
+ gPSSData->partySprites[i] = NULL;
+ for (i = 0; i < IN_BOX_COUNT; i++)
+ gPSSData->boxMonsSprites[i] = NULL;
+
+ gPSSData->movingMonSprite = NULL;
+ gPSSData->field_78C = 0;
+}
+
+static u8 sub_8090058(void)
+{
+ return (IsCursorInBox() ? 2 : 1);
+}
+
+void CreateMovingMonIcon(void)
+{
+ u32 personality = GetMonData(&gPSSData->movingMon, MON_DATA_PERSONALITY);
+ u16 species = GetMonData(&gPSSData->movingMon, MON_DATA_SPECIES2);
+ u8 priority = sub_8090058();
+
+ gPSSData->movingMonSprite = CreateMonIconSprite(species, personality, 0, 0, priority, 7);
+ gPSSData->movingMonSprite->callback = sub_80911B0;
+}
+
+static void sub_80900D4(u8 boxId)
+{
+ u8 boxPosition;
+ u16 i, j, count;
+ u16 species;
+ u32 personality;
+
+ count = 0;
+ boxPosition = 0;
+ for (i = 0; i < IN_BOX_COLUMNS; i++)
+ {
+ for (j = 0; j < IN_BOX_ROWS; j++)
+ {
+ species = GetBoxMonDataAt(boxId, boxPosition, MON_DATA_SPECIES2);
+ if (species != SPECIES_NONE)
+ {
+ personality = GetBoxMonDataAt(boxId, boxPosition, MON_DATA_PERSONALITY);
+ gPSSData->boxMonsSprites[count] = CreateMonIconSprite(species, personality, 8 * (3 * j) + 100, 8 * (3 * i) + 44, 2, 19 - j);
+ }
+ else
+ {
+ gPSSData->boxMonsSprites[count] = NULL;
+ }
+ boxPosition++;
+ count++;
+ }
+ }
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++)
+ {
+ if (GetBoxMonDataAt(boxId, boxPosition, MON_DATA_HELD_ITEM) == 0)
+ gPSSData->boxMonsSprites[boxPosition]->oam.objMode = ST_OAM_OBJ_BLEND;
+ }
+ }
+}
+
+void sub_80901EC(u8 boxPosition)
+{
+ u16 species = GetCurrentBoxMonData(boxPosition, MON_DATA_SPECIES2);
+
+ if (species != SPECIES_NONE)
+ {
+ s16 x = 8 * (3 * (boxPosition % IN_BOX_ROWS)) + 100;
+ s16 y = 8 * (3 * (boxPosition / IN_BOX_ROWS)) + 44;
+ u32 personality = GetCurrentBoxMonData(boxPosition, MON_DATA_PERSONALITY);
+
+ gPSSData->boxMonsSprites[boxPosition] = CreateMonIconSprite(species, personality, x, y, 2, 19 - (boxPosition % IN_BOX_ROWS));
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ gPSSData->boxMonsSprites[boxPosition]->oam.objMode = ST_OAM_OBJ_BLEND;
+ }
+}
+
+static void sub_809029C(s16 arg0)
+{
+ u16 i;
+
+ for (i = 0; i < IN_BOX_COUNT; i++)
+ {
+ if (gPSSData->boxMonsSprites[i] != NULL)
+ {
+ gPSSData->boxMonsSprites[i]->data[2] = arg0;
+ gPSSData->boxMonsSprites[i]->data[4] = 1;
+ gPSSData->boxMonsSprites[i]->callback = sub_8090324;
+ }
+ }
+}
+
+static void sub_80902E0(struct Sprite *sprite)
+{
+ if (sprite->data[1] != 0)
+ {
+ sprite->data[1]--;
+ sprite->pos1.x += sprite->data[2];
+ }
+ else
+ {
+ gPSSData->field_C66--;
+ sprite->pos1.x = sprite->data[3];
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void sub_8090324(struct Sprite *sprite)
+{
+ if (sprite->data[4] != 0)
+ {
+ sprite->data[4]--;
+ }
+ else
+ {
+ sprite->pos1.x += sprite->data[2];
+ sprite->data[5] = sprite->pos1.x + sprite->pos2.x;
+ if (sprite->data[5] <= 68 || sprite->data[5] >= 252)
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void DestroyAllIconsInRow(u8 row)
+{
+ u16 column;
+ u8 boxPosition = row;
+
+ for (column = 0; column < IN_BOX_COLUMNS; column++)
+ {
+ if (gPSSData->boxMonsSprites[boxPosition] != NULL)
+ {
+ DestroyBoxMonIcon(gPSSData->boxMonsSprites[boxPosition]);
+ gPSSData->boxMonsSprites[boxPosition] = NULL;
+ }
+ boxPosition += IN_BOX_ROWS;
+ }
+}
+
+static u8 sub_80903A4(u8 row, u16 times, s16 xDelta)
+{
+ s32 i;
+ u16 y = 44;
+ s16 xDest = 8 * (3 * row) + 100;
+ u16 x = xDest - ((times + 1) * xDelta);
+ u8 subpriority = 19 - row;
+ u8 count = 0;
+ u8 boxPosition = row;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ for (i = 0; i < IN_BOX_COLUMNS; i++)
+ {
+ if (gPSSData->boxSpecies[boxPosition] != SPECIES_NONE)
+ {
+ gPSSData->boxMonsSprites[boxPosition] = CreateMonIconSprite(gPSSData->boxSpecies[boxPosition],
+ gPSSData->boxPersonalities[boxPosition],
+ x, y, 2, subpriority);
+ if (gPSSData->boxMonsSprites[boxPosition] != NULL)
+ {
+ gPSSData->boxMonsSprites[boxPosition]->data[1] = times;
+ gPSSData->boxMonsSprites[boxPosition]->data[2] = xDelta;
+ gPSSData->boxMonsSprites[boxPosition]->data[3] = xDest;
+ gPSSData->boxMonsSprites[boxPosition]->callback = sub_80902E0;
+ count++;
+ }
+ }
+ boxPosition += IN_BOX_ROWS;
+ y += 24;
+ }
+ }
+ else
+ {
+ for (i = 0; i < IN_BOX_COLUMNS; i++)
+ {
+ if (gPSSData->boxSpecies[boxPosition] != SPECIES_NONE)
+ {
+ gPSSData->boxMonsSprites[boxPosition] = CreateMonIconSprite(gPSSData->boxSpecies[boxPosition],
+ gPSSData->boxPersonalities[boxPosition],
+ x, y, 2, subpriority);
+ if (gPSSData->boxMonsSprites[boxPosition] != NULL)
+ {
+ gPSSData->boxMonsSprites[boxPosition]->data[1] = times;
+ gPSSData->boxMonsSprites[boxPosition]->data[2] = xDelta;
+ gPSSData->boxMonsSprites[boxPosition]->data[3] = xDest;
+ gPSSData->boxMonsSprites[boxPosition]->callback = sub_80902E0;
+ if (GetBoxMonDataAt(gPSSData->field_C5C, boxPosition, MON_DATA_HELD_ITEM) == 0)
+ gPSSData->boxMonsSprites[boxPosition]->oam.objMode = ST_OAM_OBJ_BLEND;
+ count++;
+ }
+ }
+ boxPosition += IN_BOX_ROWS;
+ y += 24;
+ }
+ }
+
+ return count;
+}
+
+static void sub_8090574(u8 boxId, s8 direction)
+{
+ gPSSData->field_C6A = 0;
+ gPSSData->field_C6B = boxId;
+ gPSSData->field_C69 = direction;
+ gPSSData->field_C60 = 32;
+ gPSSData->field_C64 = -(6 * direction);
+ gPSSData->field_C66 = 0;
+ SetBoxSpeciesAndPersonalities(boxId);
+ if (direction > 0)
+ gPSSData->field_C68 = 0;
+ else
+ gPSSData->field_C68 = IN_BOX_ROWS - 1;
+
+ gPSSData->field_C62 = (24 * gPSSData->field_C68) + 100;
+ sub_809029C(gPSSData->field_C64);
+}
+
+static bool8 sub_809062C(void)
+{
+ if (gPSSData->field_C60 != 0)
+ gPSSData->field_C60--;
+
+ switch (gPSSData->field_C6A)
+ {
+ case 0:
+ gPSSData->field_C62 += gPSSData->field_C64;
+ if (gPSSData->field_C62 <= 64 || gPSSData->field_C62 >= 252)
+ {
+ DestroyAllIconsInRow(gPSSData->field_C68);
+ gPSSData->field_C62 += gPSSData->field_C69 * 24;
+ gPSSData->field_C6A++;
+ }
+ break;
+ case 1:
+ gPSSData->field_C62 += gPSSData->field_C64;
+ gPSSData->field_C66 += sub_80903A4(gPSSData->field_C68, gPSSData->field_C60, gPSSData->field_C64);
+ if ((gPSSData->field_C69 > 0 && gPSSData->field_C68 == IN_BOX_ROWS - 1)
+ || (gPSSData->field_C69 < 0 && gPSSData->field_C68 == 0))
+ {
+ gPSSData->field_C6A++;
+ }
+ else
+ {
+ gPSSData->field_C68 += gPSSData->field_C69;
+ gPSSData->field_C6A = 0;
+ }
+ break;
+ case 2:
+ if (gPSSData->field_C66 == 0)
+ {
+ gPSSData->field_C60++;
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void SetBoxSpeciesAndPersonalities(u8 boxId)
+{
+ s32 i, j, boxPosition;
+
+ boxPosition = 0;
+ for (i = 0; i < IN_BOX_COLUMNS; i++)
+ {
+ for (j = 0; j < IN_BOX_ROWS; j++)
+ {
+ gPSSData->boxSpecies[boxPosition] = GetBoxMonDataAt(boxId, boxPosition, MON_DATA_SPECIES2);
+ if (gPSSData->boxSpecies[boxPosition] != SPECIES_NONE)
+ gPSSData->boxPersonalities[boxPosition] = GetBoxMonDataAt(boxId, boxPosition, MON_DATA_PERSONALITY);
+ boxPosition++;
+ }
+ }
+
+ gPSSData->field_C5C = boxId;
+}
+
+void DestroyBoxMonIconAtPosition(u8 boxPosition)
+{
+ if (gPSSData->boxMonsSprites[boxPosition] != NULL)
+ {
+ DestroyBoxMonIcon(gPSSData->boxMonsSprites[boxPosition]);
+ gPSSData->boxMonsSprites[boxPosition] = NULL;
+ }
+}
+
+void SetBoxMonIconObjMode(u8 boxPosition, u8 objMode)
+{
+ if (gPSSData->boxMonsSprites[boxPosition] != NULL)
+ {
+ gPSSData->boxMonsSprites[boxPosition]->oam.objMode = objMode;
+ }
+}
+
+void CreatePartyMonsSprites(bool8 arg0)
+{
+ u16 i, count;
+ u16 species = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES2);
+ u32 personality = GetMonData(&gPlayerParty[0], MON_DATA_PERSONALITY);
+
+ gPSSData->partySprites[0] = CreateMonIconSprite(species, personality, 104, 64, 1, 12);
+ count = 1;
+ for (i = 1; i < PARTY_SIZE; i++)
+ {
+ species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ if (species != SPECIES_NONE)
+ {
+ personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY);
+ gPSSData->partySprites[i] = CreateMonIconSprite(species, personality, 152, 8 * (3 * (i - 1)) + 16, 1, 12);
+ count++;
+ }
+ else
+ {
+ gPSSData->partySprites[i] = NULL;
+ }
+ }
+
+ if (!arg0)
+ {
+ for (i = 0; i < count; i++)
+ {
+ gPSSData->partySprites[i]->pos1.y -= 160;
+ gPSSData->partySprites[i]->invisible = TRUE;
+ }
+ }
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (gPSSData->partySprites[i] != NULL && GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM) == 0)
+ gPSSData->partySprites[i]->oam.objMode = ST_OAM_OBJ_BLEND;
+ }
+ }
+}
+
+void sub_80909F4(void)
+{
+ u16 i, count;
+
+ gPSSData->field_C5E = 0;
+ for (i = 0, count = 0; i < PARTY_SIZE; i++)
+ {
+ if (gPSSData->partySprites[i] != NULL)
+ {
+ if (i != count)
+ {
+ sub_8090A74(gPSSData->partySprites[i], count);
+ gPSSData->partySprites[i] = NULL;
+ gPSSData->field_C5E++;
+ }
+ count++;
+ }
+ }
+}
+
+u8 sub_8090A60(void)
+{
+ return gPSSData->field_C5E;
+}
+
+static void sub_8090A74(struct Sprite *sprite, u16 partyId)
+{
+ s16 x, y;
+
+ sprite->data[1] = partyId;
+ if (partyId == 0)
+ x = 104, y = 64;
+ else
+ x = 152, y = 8 * (3 * (partyId - 1)) + 16;
+
+ sprite->data[2] = (u16)(sprite->pos1.x) * 8;
+ sprite->data[3] = (u16)(sprite->pos1.y) * 8;
+ sprite->data[4] = ((x * 8) - sprite->data[2]) / 8;
+ sprite->data[5] = ((y * 8) - sprite->data[3]) / 8;
+ sprite->data[6] = 8;
+ sprite->callback = sub_8090AE0;
+}
+
+static void sub_8090AE0(struct Sprite *sprite)
+{
+ if (sprite->data[6] != 0)
+ {
+ s16 x = sprite->data[2] += sprite->data[4];
+ s16 y = sprite->data[3] += sprite->data[5];
+ sprite->pos1.x = x / 8u;
+ sprite->pos1.y = y / 8u;
+ sprite->data[6]--;
+ }
+ else
+ {
+ if (sprite->data[1] == 0)
+ {
+ sprite->pos1.x = 104;
+ sprite->pos1.y = 64;
+ }
+ else
+ {
+ sprite->pos1.x = 152;
+ sprite->pos1.y = 8 * (3 * (sprite->data[1] - 1)) + 16;
+ }
+ sprite->callback = SpriteCallbackDummy;
+ gPSSData->partySprites[sprite->data[1]] = sprite;
+ gPSSData->field_C5E--;
+ }
+}
+
+void DestroyMovingMonIcon(void)
+{
+ if (gPSSData->movingMonSprite != NULL)
+ {
+ DestroyBoxMonIcon(gPSSData->movingMonSprite);
+ gPSSData->movingMonSprite = NULL;
+ }
+}
+
+void sub_8090B98(s16 yDelta)
+{
+ u16 i, posY;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (gPSSData->partySprites[i] != NULL)
+ {
+ gPSSData->partySprites[i]->pos1.y += yDelta;
+ posY = gPSSData->partySprites[i]->pos1.y + gPSSData->partySprites[i]->pos2.y + gPSSData->partySprites[i]->centerToCornerVecY;
+ posY += 16;
+ if (posY > 192)
+ gPSSData->partySprites[i]->invisible = TRUE;
+ else
+ gPSSData->partySprites[i]->invisible = FALSE;
+ }
+ }
+}
+
+void DestroyPartyMonIcon(u8 partyId)
+{
+ if (gPSSData->partySprites[partyId] != NULL)
+ {
+ DestroyBoxMonIcon(gPSSData->partySprites[partyId]);
+ gPSSData->partySprites[partyId] = NULL;
+ }
+}
+
+void DestroyAllPartyMonIcons(void)
+{
+ u16 i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (gPSSData->partySprites[i] != NULL)
+ {
+ DestroyBoxMonIcon(gPSSData->partySprites[i]);
+ gPSSData->partySprites[i] = NULL;
+ }
+ }
+}
+
+void SetPartyMonIconObjMode(u8 partyId, u8 objMode)
+{
+ if (gPSSData->partySprites[partyId] != NULL)
+ {
+ gPSSData->partySprites[partyId]->oam.objMode = objMode;
+ }
+}
+
+void sub_8090CC0(u8 mode, u8 id)
+{
+ if (mode == MODE_PARTY)
+ {
+ gPSSData->movingMonSprite = gPSSData->partySprites[id];
+ gPSSData->partySprites[id] = NULL;
+ }
+ else if (mode == MODE_BOX)
+ {
+ gPSSData->movingMonSprite = gPSSData->boxMonsSprites[id];
+ gPSSData->boxMonsSprites[id] = NULL;
+ }
+ else
+ {
+ return;
+ }
+
+ gPSSData->movingMonSprite->callback = sub_80911B0;
+ gPSSData->movingMonSprite->oam.priority = sub_8090058();
+ gPSSData->movingMonSprite->subpriority = 7;
+}
+
+void sub_8090D58(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT) // party mon
+ {
+ gPSSData->partySprites[position] = gPSSData->movingMonSprite;
+ gPSSData->partySprites[position]->oam.priority = 1;
+ gPSSData->partySprites[position]->subpriority = 12;
+ }
+ else
+ {
+ gPSSData->boxMonsSprites[position] = gPSSData->movingMonSprite;
+ gPSSData->boxMonsSprites[position]->oam.priority = 2;
+ gPSSData->boxMonsSprites[position]->subpriority = 19 - (position % IN_BOX_ROWS);
+ }
+ gPSSData->movingMonSprite->callback = SpriteCallbackDummy;
+ gPSSData->movingMonSprite = NULL;
+}
+
+void sub_8090E08(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT) // party mon
+ gPSSData->field_B00 = &gPSSData->partySprites[position];
+ else
+ gPSSData->field_B00 = &gPSSData->boxMonsSprites[position];
+
+ gPSSData->movingMonSprite->callback = SpriteCallbackDummy;
+ gPSSData->field_C5D = 0;
+}
+
+bool8 sub_8090E74(void)
+{
+ if (gPSSData->field_C5D == 16)
+ return FALSE;
+
+ gPSSData->field_C5D++;
+ if (gPSSData->field_C5D & 1)
+ {
+ (*gPSSData->field_B00)->pos1.y--;
+ gPSSData->movingMonSprite->pos1.y++;
+ }
+
+ (*gPSSData->field_B00)->pos2.x = gSineTable[gPSSData->field_C5D * 8] / 16;
+ gPSSData->movingMonSprite->pos2.x = -(gSineTable[gPSSData->field_C5D * 8] / 16);
+ if (gPSSData->field_C5D == 8)
+ {
+ gPSSData->movingMonSprite->oam.priority = (*gPSSData->field_B00)->oam.priority;
+ gPSSData->movingMonSprite->subpriority = (*gPSSData->field_B00)->subpriority;
+ (*gPSSData->field_B00)->oam.priority = sub_8090058();
+ (*gPSSData->field_B00)->subpriority = 7;
+ }
+
+ if (gPSSData->field_C5D == 16)
+ {
+ struct Sprite *sprite = gPSSData->movingMonSprite;
+ gPSSData->movingMonSprite = (*gPSSData->field_B00);
+ *gPSSData->field_B00 = sprite;
+
+ gPSSData->movingMonSprite->callback = sub_80911B0;
+ (*gPSSData->field_B00)->callback = SpriteCallbackDummy;
+ }
+
+ return TRUE;
+}
+
+void sub_8090FC4(u8 mode, u8 position)
+{
+ switch (mode)
+ {
+ case MODE_PARTY:
+ gPSSData->field_B04 = &gPSSData->partySprites[position];
+ break;
+ case MODE_BOX:
+ gPSSData->field_B04 = &gPSSData->boxMonsSprites[position];
+ break;
+ case MODE_2:
+ gPSSData->field_B04 = &gPSSData->movingMonSprite;
+ break;
+ default:
+ return;
+ }
+
+ if (*gPSSData->field_B04 != NULL)
+ {
+ InitSpriteAffineAnim(*gPSSData->field_B04);
+ (*gPSSData->field_B04)->oam.affineMode = ST_OAM_AFFINE_NORMAL;
+ (*gPSSData->field_B04)->affineAnims = gUnknown_83CEC38;
+ StartSpriteAffineAnim(*gPSSData->field_B04, 0);
+ }
+}
+
+bool8 sub_8091084(void)
+{
+ if (*gPSSData->field_B04 == NULL || (*gPSSData->field_B04)->invisible)
+ return FALSE;
+
+ if ((*gPSSData->field_B04)->affineAnimEnded)
+ (*gPSSData->field_B04)->invisible = TRUE;
+
+ return TRUE;
+}
+
+void sub_80910CC(void)
+{
+ if (*gPSSData->field_B04 != NULL)
+ {
+ FreeOamMatrix((*gPSSData->field_B04)->oam.matrixNum);
+ DestroyBoxMonIcon(*gPSSData->field_B04);
+ *gPSSData->field_B04 = NULL;
+ }
+}
+
+void sub_8091114(void)
+{
+ if (*gPSSData->field_B04 != NULL)
+ {
+ (*gPSSData->field_B04)->invisible = FALSE;
+ StartSpriteAffineAnim(*gPSSData->field_B04, 1);
+ }
+}
+
+bool8 sub_8091150(void)
+{
+ if (gPSSData->field_B04 == NULL)
+ return FALSE;
+
+ if ((*gPSSData->field_B04)->affineAnimEnded)
+ gPSSData->field_B04 = NULL;
+
+ return TRUE;
+}
+
+void SetMovingMonPriority(u8 priority)
+{
+ gPSSData->movingMonSprite->oam.priority = priority;
+}
+
+static void sub_80911B0(struct Sprite *sprite)
+{
+ sprite->pos1.x = gPSSData->field_CB4->pos1.x;
+ sprite->pos1.y = gPSSData->field_CB4->pos1.y + gPSSData->field_CB4->pos2.y + 4;
+}
+
+static u16 sub_80911D4(u16 species)
+{
+ u16 i, var;
+
+ // Find the currently-allocated slot
+ for (i = 0; i < MAX_MON_ICONS; i++)
+ {
+ if (gPSSData->field_B58[i] == species)
+ break;
+ }
+
+ if (i == MAX_MON_ICONS)
+ {
+ // Find the first empty slot
+ for (i = 0; i < MAX_MON_ICONS; i++)
+ {
+ if (gPSSData->field_B58[i] == SPECIES_NONE)
+ break;
+ }
+ if (i == MAX_MON_ICONS)
+ return 0xFFFF;
+ }
+
+ gPSSData->field_B58[i] = species;
+ gPSSData->field_B08[i]++;
+ var = 16 * i;
+ CpuCopy32(GetMonIconTiles(species, TRUE), (void*)(OBJ_VRAM0) + var * 32, 0x200);
+
+ return var;
+}
+
+static void sub_8091290(u16 species)
+{
+ u16 i;
+
+ for (i = 0; i < MAX_MON_ICONS; i++)
+ {
+ if (gPSSData->field_B58[i] == species)
+ {
+ if (--gPSSData->field_B08[i] == 0)
+ gPSSData->field_B58[i] = 0;
+ break;
+ }
+ }
+}
+
+struct Sprite *CreateMonIconSprite(u16 species, u32 personality, s16 x, s16 y, u8 oamPriority, u8 subpriority)
+{
+ u16 tileNum;
+ u8 spriteId;
+ struct SpriteTemplate template = gUnknown_83CEBF0;
+
+ species = GetIconSpecies(species, personality);
+ template.paletteTag = 0xDAC0 + gMonIconPaletteIndices[species];
+ tileNum = sub_80911D4(species);
+ if (tileNum == 0xFFFF)
+ return NULL;
+
+ spriteId = CreateSprite(&template, x, y, subpriority);
+ if (spriteId == MAX_SPRITES)
+ {
+ sub_8091290(species);
+ return NULL;
+ }
+
+ gSprites[spriteId].oam.tileNum = tileNum;
+ gSprites[spriteId].oam.priority = oamPriority;
+ gSprites[spriteId].data[0] = species;
+ return &gSprites[spriteId];
+}
+
+static void DestroyBoxMonIcon(struct Sprite *sprite)
+{
+ sub_8091290(sprite->data[0]);
+ DestroySprite(sprite);
+}
+
+void sub_80913DC(u8 boxId)
+{
+ u8 taskId = CreateTask(sub_8091420, 2);
+
+ gTasks[taskId].data[2] = boxId;
+}
+
+bool8 sub_809140C(void)
+{
+ return FuncIsActiveTask(sub_8091420);
+}
+
+static void sub_8091420(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ gPSSData->field_2D2 = 0;
+ gPSSData->bg2_X = 0;
+ task->data[1] = RequestDma3Fill(0, gPSSData->field_4AC4, 0x1000, 1);
+ break;
+ case 1:
+ if (CheckForSpaceForDma3Request(task->data[1]) == -1)
+ return;
+
+ SetBgTilemapBuffer(2, gPSSData->field_4AC4);
+ ShowBg(2);
+ break;
+ case 2:
+ LoadWallpaperGfx(task->data[2], 0);
+ break;
+ case 3:
+ if (!WaitForWallpaperGfxLoad())
+ return;
+
+ sub_8091A94(task->data[2]);
+ sub_8091F80();
+ sub_80900D4(task->data[2]);
+ SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(27) | BGCNT_TXT512x256);
+ break;
+ case 4:
+ DestroyTask(taskId);
+ break;
+ default:
+ task->data[0] = 0;
+ return;
+ }
+
+ task->data[0]++;
+}
+
+void SetUpScrollToBox(u8 boxId)
+{
+ s8 direction = sub_80916F4(boxId);
+
+ gPSSData->field_2CE = (direction > 0) ? 6 : -6;
+ gPSSData->field_2D3 = (direction > 0) ? 1 : 2;
+ gPSSData->field_2D0 = 32;
+ gPSSData->field_2D4 = boxId;
+ gPSSData->field_2D6 = (direction <= 0) ? 5 : 0;
+ gPSSData->field_2D8 = direction;
+ gPSSData->field_2DA = (direction > 0) ? 264 : 56;
+ gPSSData->field_2DC = (direction <= 0) ? 5 : 0;
+ gPSSData->field_2DE = 0;
+ gPSSData->field_2E0 = 2;
+ gPSSData->field_A64 = boxId;
+ gPSSData->field_A65 = direction;
+ gPSSData->field_A63 = 0;
+}
+
+bool8 ScrollToBox(void)
+{
+ bool8 var;
+
+ switch (gPSSData->field_A63)
+ {
+ case 0:
+ LoadWallpaperGfx(gPSSData->field_A64, gPSSData->field_A65);
+ gPSSData->field_A63++;
+ case 1:
+ if (!WaitForWallpaperGfxLoad())
+ return TRUE;
+
+ sub_8090574(gPSSData->field_A64, gPSSData->field_A65);
+ sub_8091C48(gPSSData->field_A64, gPSSData->field_A65);
+ sub_809200C(gPSSData->field_A65);
+ break;
+ case 2:
+ var = sub_809062C();
+ if (gPSSData->field_2D0 != 0)
+ {
+ gPSSData->bg2_X += gPSSData->field_2CE;
+ if (--gPSSData->field_2D0 != 0)
+ return TRUE;
+ sub_8091E34();
+ sub_80920AC();
+ }
+ return var;
+ }
+
+ gPSSData->field_A63++;
+ return TRUE;
+}
+
+static s8 sub_80916F4(u8 boxId)
+{
+ u8 i;
+ u8 currentBox = StorageGetCurrentBox();
+
+ for (i = 0; currentBox != boxId; i++)
+ {
+ currentBox++;
+ if (currentBox >= TOTAL_BOXES_COUNT)
+ currentBox = 0;
+ }
+
+ return (i < TOTAL_BOXES_COUNT / 2) ? 1 : -1;
+}
+
+void SetWallpaperForCurrentBox(u8 wallpaperId)
+{
+ u8 boxId = StorageGetCurrentBox();
+ SetBoxWallpaper(boxId, wallpaperId);
+ gPSSData->wallpaperChangeState = 0;
+}
+
+bool8 DoWallpaperGfxChange(void)
+{
+ switch (gPSSData->wallpaperChangeState)
+ {
+ case 0:
+ BeginNormalPaletteFade(gPSSData->field_738, 1, 0, 16, RGB_WHITEALPHA);
+ gPSSData->wallpaperChangeState++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ u8 curBox = StorageGetCurrentBox();
+ LoadWallpaperGfx(curBox, 0);
+ gPSSData->wallpaperChangeState++;
+ }
+ break;
+ case 2:
+ if (WaitForWallpaperGfxLoad() == TRUE)
+ {
+ sub_8091EF0();
+ BeginNormalPaletteFade(gPSSData->field_738, 1, 16, 0, RGB_WHITEALPHA);
+ gPSSData->wallpaperChangeState++;
+ }
+ break;
+ case 3:
+ if (!UpdatePaletteFade())
+ gPSSData->wallpaperChangeState++;
+ break;
+ case 4:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void LoadWallpaperGfx(u8 boxId, s8 direction)
+{
+ u8 wallpaperId;
+ const struct WallpaperTable *wallpaperGfx;
+ void *iconGfx;
+ u32 size1, size2;
+
+ gPSSData->field_6F9 = 0;
+ gPSSData->field_6FA = boxId;
+ gPSSData->field_6FB = direction;
+ if (gPSSData->field_6FB != 0)
+ {
+ gPSSData->field_2D2 = (gPSSData->field_2D2 == 0);
+ sub_8091A24(gPSSData->field_4AC4);
+ }
+
+ wallpaperId = GetBoxWallpaper(gPSSData->field_6FA);
+ wallpaperGfx = &sWallpaperTable[wallpaperId];
+ LZ77UnCompWram(wallpaperGfx->tileMap, gPSSData->field_792);
+ sub_8091984(gPSSData->field_4AC4, gPSSData->field_792, gPSSData->field_6FB, gPSSData->field_2D2);
+
+ if (gPSSData->field_6FB != 0)
+ LoadPalette(wallpaperGfx->palettes, (gPSSData->field_2D2 * 32) + 0x40, 0x40);
+ else
+ CpuCopy16(wallpaperGfx->palettes, &gPlttBufferUnfaded[(gPSSData->field_2D2 * 32) + 0x40], 0x40);
+
+ DecompressAndLoadBgGfxUsingHeap(2, wallpaperGfx->tiles, 0, 256 * gPSSData->field_2D2, 0);
+
+ CopyBgTilemapBufferToVram(2);
+}
+
+static bool32 WaitForWallpaperGfxLoad(void)
+{
+ if (IsDma3ManagerBusyWithBgCopy() == TRUE)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void sub_8091984(void *buffer, const void *tilemap, s8 direction, u8 arg2)
+{
+ s16 var = (arg2 * 2) + 3;
+ s16 x = ((gPSSData->bg2_X / 8 + 10) + (direction * 24)) & 0x3F;
+
+ CopyRectToBgTilemapBufferRect(2, tilemap, 0, 0, 0x14, 0x12, x, 2, 0x14, 0x12, 0x11, arg2 << 8, var);
+
+ if (direction == 0)
+ return;
+ else if (direction > 0)
+ x *= 1, x += 0x14; // x * 1 is needed to match, but can be safely removed as it makes no functional difference
+ else
+ x -= 4;
+
+ FillBgTilemapBufferRect(2, 0, x, 2, 4, 0x12, 0x11);
+}
+
+static void sub_8091A24(void *arg0)
+{
+ u16 i;
+ u16 *dest = arg0;
+ s16 r3 = ((gPSSData->bg2_X / 8) + 30) & 0x3F;
+
+ if (r3 <= 31)
+ dest += r3 + 0x260;
+ else
+ dest += r3 + 0x640;
+
+ for (i = 0; i < 0x2C; i++)
+ {
+ *dest++ = 0;
+ r3 = (r3 + 1) & 0x3F;
+ if (r3 == 0)
+ dest -= 0x420;
+ if (r3 == 0x20)
+ dest += 0x3e0;
+ }
+}
+
+static void sub_8091A94(u8 boxId)
+{
+ u8 tagIndex;
+ s16 r6;
+ u16 i;
+
+ struct SpriteSheet spriteSheet = {gPSSData->field_2F8, 0x200, TAG_TILE_3};
+ struct SpritePalette palettes[] = {
+ {gPSSData->field_6FC, TAG_PAL_DAC9},
+ {}
+ };
+
+ u16 wallpaperId = GetBoxWallpaper(boxId);
+
+ gPSSData->field_6FC[14] = gUnknown_83D29D0[wallpaperId][0];
+ gPSSData->field_6FC[15] = gUnknown_83D29D0[wallpaperId][1];
+ LoadSpritePalettes(palettes);
+ gPSSData->field_738 = 0x3f0;
+
+ tagIndex = IndexOfSpritePaletteTag(TAG_PAL_DAC9);
+ gPSSData->field_71C = 0x10e + 16 * tagIndex;
+ gPSSData->field_738 |= 0x10000 << tagIndex;
+
+ tagIndex = IndexOfSpritePaletteTag(TAG_PAL_DAC9);
+ gPSSData->field_71E = 0x10e + 16 * tagIndex;
+ gPSSData->field_738 |= 0x10000 << tagIndex;
+
+ StringCopyPadded(gPSSData->field_21B8, GetBoxNamePtr(boxId), 0, 8);
+ DrawTextWindowAndBufferTiles(gPSSData->field_21B8, gPSSData->field_2F8, 0, 0, gPSSData->field_4F8, 2);
+ LoadSpriteSheet(&spriteSheet);
+ r6 = sub_8091F60(GetBoxNamePtr(boxId));
+
+ for (i = 0; i < 2; i++)
+ {
+ u8 spriteId = CreateSprite(&gUnknown_83D2B7C, r6 + i * 32, 28, 24);
+ gPSSData->field_720[i] = &gSprites[spriteId];
+ StartSpriteAnim(gPSSData->field_720[i], i);
+ }
+ gPSSData->field_6F8 = 0;
+}
+
+static void sub_8091C48(u8 boxId, s8 direction)
+{
+ u16 r8;
+ s16 x, x2;
+ u16 i;
+ struct SpriteSheet spriteSheet = {gPSSData->field_2F8, 0x200, TAG_TILE_3};
+ struct SpriteTemplate template = gUnknown_83D2B7C;
+
+ gPSSData->field_6F8 = (gPSSData->field_6F8 == 0);
+ if (gPSSData->field_6F8 == 0)
+ {
+ spriteSheet.tag = TAG_TILE_3;
+ r8 = gPSSData->field_71C;
+ }
+ else
+ {
+ spriteSheet.tag = TAG_TILE_4;
+ r8 = gPSSData->field_71C;
+ template.tileTag = TAG_TILE_4;
+ template.paletteTag = TAG_PAL_DAC9;
+ }
+
+ StringCopyPadded(gPSSData->field_21B8, GetBoxNamePtr(boxId), 0, 8);
+ DrawTextWindowAndBufferTiles(gPSSData->field_21B8, gPSSData->field_2F8, 0, 0, gPSSData->field_4F8, 2);
+ LoadSpriteSheet(&spriteSheet);
+ LoadPalette(gUnknown_83D29D0[GetBoxWallpaper(boxId)], r8, 4);
+ x = sub_8091F60(GetBoxNamePtr(boxId));
+ x2 = x;
+ x2 += direction * 192;
+
+ for (i = 0; i < 2; i++)
+ {
+ u8 spriteId = CreateSprite(&template, i * 32 + x2, 28, 24);
+
+ gPSSData->field_728[i] = &gSprites[spriteId];
+ gPSSData->field_728[i]->data[0] = (-direction) * 6;
+ gPSSData->field_728[i]->data[1] = i * 32 + x;
+ gPSSData->field_728[i]->data[2] = 0;
+ gPSSData->field_728[i]->callback = sub_8091E84;
+ StartSpriteAnim(gPSSData->field_728[i], i);
+
+ gPSSData->field_720[i]->data[0] = (-direction) * 6;
+ gPSSData->field_720[i]->data[1] = 1;
+ gPSSData->field_720[i]->callback = sub_8091EB8;
+ }
+}
+
+static void sub_8091E34(void)
+{
+ if (gPSSData->field_6F8 == 0)
+ FreeSpriteTilesByTag(TAG_TILE_4);
+ else
+ FreeSpriteTilesByTag(TAG_TILE_3);
+
+ gPSSData->field_720[0] = gPSSData->field_728[0];
+ gPSSData->field_720[1] = gPSSData->field_728[1];
+}
+
+static void sub_8091E84(struct Sprite *sprite)
+{
+ if (sprite->data[2] != 0)
+ sprite->data[2]--;
+ else if ((sprite->pos1.x += sprite->data[0]) == sprite->data[1])
+ sprite->callback = SpriteCallbackDummy;
+}
+
+static void sub_8091EB8(struct Sprite *sprite)
+{
+ if (sprite->data[1] != 0)
+ {
+ sprite->data[1]--;
+ }
+ else
+ {
+ sprite->pos1.x += sprite->data[0];
+ sprite->data[2] = sprite->pos1.x + sprite->pos2.x;
+ if (sprite->data[2] < 0x40 || sprite->data[2] > 0x100)
+ DestroySprite(sprite);
+ }
+}
+
+static void sub_8091EF0(void)
+{
+ u8 boxId = StorageGetCurrentBox();
+ u8 wallpaperId = GetBoxWallpaper(boxId);
+ if (gPSSData->field_6F8 == 0)
+ CpuCopy16(gUnknown_83D29D0[wallpaperId], gPlttBufferUnfaded + gPSSData->field_71C, 4);
+ else
+ CpuCopy16(gUnknown_83D29D0[wallpaperId], gPlttBufferUnfaded + gPSSData->field_71E, 4);
+}
+
+static s16 sub_8091F60(const u8 *string)
+{
+ return 0xB0 - GetStringWidth(1, string, 0) / 2;
+}
+
+static void sub_8091F80(void)
+{
+ u16 i;
+
+ LoadSpriteSheet(&gUnknown_83D2B54);
+ for (i = 0; i < 2; i++)
+ {
+ u8 spriteId = CreateSprite(&gUnknown_83D2BB4, 0x5c + i * 0x88, 28, 22);
+ if (spriteId != MAX_SPRITES)
+ {
+ struct Sprite *sprite = &gSprites[spriteId];
+ StartSpriteAnim(sprite, i);
+ sprite->data[3] = (i == 0) ? -1 : 1;
+ gPSSData->field_730[i] = sprite;
+ }
+ }
+ if (IsCursorOnBox())
+ sub_80920FC(TRUE);
+}
+
+static void sub_809200C(s8 direction)
+{
+ u16 i;
+
+ for (i = 0; i < 2; i++)
+ {
+ gPSSData->field_730[i]->pos2.x = 0;
+ gPSSData->field_730[i]->data[0] = 2;
+ }
+ if (direction < 0)
+ {
+ gPSSData->field_730[0]->data[1] = 29;
+ gPSSData->field_730[1]->data[1] = 5;
+ gPSSData->field_730[0]->data[2] = 0x48;
+ gPSSData->field_730[1]->data[2] = 0x48;
+ }
+ else
+ {
+ gPSSData->field_730[0]->data[1] = 5;
+ gPSSData->field_730[1]->data[1] = 29;
+ gPSSData->field_730[0]->data[2] = 0xF8;
+ gPSSData->field_730[1]->data[2] = 0xF8;
+ }
+ gPSSData->field_730[0]->data[7] = 0;
+ gPSSData->field_730[1]->data[7] = 1;
+}
+
+static void sub_80920AC(void)
+{
+ u16 i;
+
+ for (i = 0; i < 2; i++)
+ {
+ gPSSData->field_730[i]->pos1.x = 0x88 * i + 0x5c;
+ gPSSData->field_730[i]->pos2.x = 0;
+ gPSSData->field_730[i]->invisible = FALSE;
+ }
+ sub_80920FC(TRUE);
+}
+
+void sub_80920FC(bool8 a0)
+{
+ u16 i;
+
+ if (a0)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ gPSSData->field_730[i]->data[0] = 1;
+ gPSSData->field_730[i]->data[1] = 0;
+ gPSSData->field_730[i]->data[2] = 0;
+ gPSSData->field_730[i]->data[4] = 0;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 2; i++)
+ {
+ gPSSData->field_730[i]->data[0] = 0;
+ }
+ }
+}
+
+static void sub_8092164(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->pos2.x = 0;
+ break;
+ case 1:
+ if (++sprite->data[1] > 3)
+ {
+ sprite->data[1] = 0;
+ sprite->pos2.x += sprite->data[3];
+ if (++sprite->data[2] > 5)
+ {
+ sprite->data[2] = 0;
+ sprite->pos2.x = 0;
+ }
+ }
+ break;
+ case 2:
+ sprite->data[0] = 3;
+ break;
+ case 3:
+ sprite->pos1.x -= gPSSData->field_2CE;
+ if (sprite->pos1.x < 73 || sprite->pos1.x > 247)
+ sprite->invisible = TRUE;
+ if (--sprite->data[1] == 0)
+ {
+ sprite->pos1.x = sprite->data[2];
+ sprite->invisible = FALSE;
+ sprite->data[0] = 4;
+ }
+ break;
+ case 4:
+ sprite->pos1.x -= gPSSData->field_2CE;
+ break;
+ }
+}
+
+struct Sprite *sub_809223C(u16 x, u16 y, u8 animId, u8 priority, u8 subpriority)
+{
+ u8 spriteId = CreateSprite(&gUnknown_83D2BB4, x, y, subpriority);
+ if (spriteId == MAX_SPRITES)
+ return NULL;
+
+ animId %= 2;
+ StartSpriteAnim(&gSprites[spriteId], animId);
+ gSprites[spriteId].oam.priority = priority;
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ return &gSprites[spriteId];
+}
diff --git a/src/pokemon_storage_system_5.c b/src/pokemon_storage_system_5.c
new file mode 100644
index 000000000..a977d0118
--- /dev/null
+++ b/src/pokemon_storage_system_5.c
@@ -0,0 +1,2036 @@
+#include "global.h"
+#include "gflib.h"
+#include "data.h"
+#include "item.h"
+#include "mail_data.h"
+#include "pokemon_storage_system_internal.h"
+#include "pokemon_summary_screen.h"
+#include "strings.h"
+#include "constants/items.h"
+#include "constants/moves.h"
+
+static EWRAM_DATA struct Pokemon gUnknown_20397BC = {};
+static EWRAM_DATA s8 sBoxCursorArea = 0;
+static EWRAM_DATA s8 sBoxCursorPosition = 0;
+static EWRAM_DATA bool8 sIsMonBeingMoved = FALSE;
+static EWRAM_DATA u8 sMovingMonOrigBoxId = 0;
+static EWRAM_DATA u8 sMovingMonOrigBoxPos = 0;
+static EWRAM_DATA bool8 sCanOnlyMove = FALSE;
+static EWRAM_DATA u8 gUnknown_2039826 = 0;
+
+static void sub_80929B0(void);
+static bool8 MonPlaceChange_Move(void);
+static bool8 MonPlaceChange_Place(void);
+static bool8 MonPlaceChange_Shift(void);
+static bool8 sub_8092E00(void);
+static bool8 sub_8092E10(void);
+static bool8 sub_8092E20(void);
+static bool8 sub_8092E54(void);
+static void MoveMon(void);
+static void PlaceMon(void);
+static void SetMovedMonData(u8 boxId, u8 cursorPos);
+static void SetPlacedMonData(u8 boxId, u8 cursorPos);
+static void PurgeMonOrBoxMon(u8 boxId, u8 cursorPos);
+static void SetShiftedMonData(u8 boxId, u8 cursorPos);
+static void sub_8093A10(void);
+static void SetCursorMonData(void * cursorMon, u8 mode);
+static void sub_8093AAC(void);
+static u8 InBoxInput_Normal(void);
+static u8 InBoxInput_GrabbingMultiple(void);
+static u8 InBoxInput_MovingMultiple(void);
+static void AddBoxMenu(void);
+static bool8 sub_8094924(void);
+static bool8 sub_809494C(void);
+static bool8 sub_8094A0C(void);
+static void sub_8094AD8(void);
+static void sub_8094C84(void);
+
+static const u16 sHandCursorPalette[] = INCBIN_U16("graphics/interface/pss_unk_83D2BCC.gbapal");
+static const u16 sHandCursorTiles[] = INCBIN_U16("graphics/interface/pss_unk_83D2BEC.4bpp");
+static const u16 sHandCursorShadowTiles[] = INCBIN_U16("graphics/interface/pss_unk_83D33EC.4bpp");
+
+void sub_80922C0(void)
+{
+ if (gPSSData->boxOption != BOX_OPTION_DEPOSIT)
+ sBoxCursorArea = CURSOR_AREA_IN_BOX;
+ else
+ sBoxCursorArea = CURSOR_AREA_IN_PARTY;
+
+ sBoxCursorPosition = 0;
+ sIsMonBeingMoved = FALSE;
+ sMovingMonOrigBoxId = 0;
+ sMovingMonOrigBoxPos = 0;
+ sCanOnlyMove = FALSE;
+ sub_8092B50();
+ sub_8094AD8();
+ gPSSData->field_CD6 = 1;
+ gPSSData->inBoxMovingMode = 0;
+ sub_8093A10();
+}
+
+void sub_8092340(void)
+{
+ sub_8094AD8();
+ sub_8093AAC();
+ gPSSData->field_CD6 = 1;
+ gPSSData->inBoxMovingMode = 0;
+ if (sIsMonBeingMoved)
+ {
+ gPSSData->movingMon = gUnknown_20397BC;
+ CreateMovingMonIcon();
+ }
+}
+
+static void sub_8092398(u8 cursorArea, u8 cursorPosition, u16 *x, u16 *y)
+{
+ switch (cursorArea)
+ {
+ case CURSOR_AREA_IN_BOX:
+ *x = (cursorPosition % IN_BOX_ROWS) * 24 + 100;
+ *y = (cursorPosition / IN_BOX_ROWS) * 24 + 32;
+ break;
+ case CURSOR_AREA_IN_PARTY:
+ if (cursorPosition == 0)
+ {
+ *x = 0x68;
+ *y = 0x34;
+ }
+ else if (cursorPosition == PARTY_SIZE)
+ {
+ *x = 0x98;
+ *y = 0x84;
+ }
+ else
+ {
+ *x = 0x98;
+ *y = (cursorPosition - 1) * 24 + 4;
+ }
+ break;
+ case CURSOR_AREA_BOX:
+ *x = 0xa2;
+ *y = 0x0c;
+ break;
+ case CURSOR_AREA_BUTTONS:
+ *y = sIsMonBeingMoved ? 8 : 14;
+ *x = cursorPosition * 0x58 + 0x78;
+ break;
+ case 4:
+ *x = 0xa0;
+ *y = 0x60;
+ break;
+ }
+}
+
+static u16 sub_8092458(void)
+{
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ return GetMonData(&gPlayerParty[sBoxCursorPosition], MON_DATA_SPECIES);
+ case CURSOR_AREA_IN_BOX:
+ return GetCurrentBoxMonData(sBoxCursorPosition, MON_DATA_SPECIES);
+ default:
+ return SPECIES_NONE;
+ }
+}
+
+bool8 sub_80924A8(void)
+{
+ s16 tmp;
+
+ if (gPSSData->field_CD0 == 0)
+ {
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return FALSE;
+ else
+ return sub_809610C();
+ }
+ else if (--gPSSData->field_CD0 != 0)
+ {
+ gPSSData->field_CBC += gPSSData->field_CC4;
+ gPSSData->field_CC0 += gPSSData->field_CC8;
+ gPSSData->field_CB4->pos1.x = gPSSData->field_CBC >> 8;
+ gPSSData->field_CB4->pos1.y = gPSSData->field_CC0 >> 8;
+ if (gPSSData->field_CB4->pos1.x > 0x100)
+ {
+ tmp = gPSSData->field_CB4->pos1.x - 0x100;
+ gPSSData->field_CB4->pos1.x = tmp + 0x40;
+ }
+ if (gPSSData->field_CB4->pos1.x < 0x40)
+ {
+ tmp = 0x40 - gPSSData->field_CB4->pos1.x;
+ gPSSData->field_CB4->pos1.x = 0x100 - tmp;
+ }
+ if (gPSSData->field_CB4->pos1.y > 0xb0)
+ {
+ tmp = gPSSData->field_CB4->pos1.y - 0xb0;
+ gPSSData->field_CB4->pos1.y = tmp - 0x10;
+ }
+ if (gPSSData->field_CB4->pos1.y < -0x10)
+ {
+ tmp = -0x10 - gPSSData->field_CB4->pos1.y;
+ gPSSData->field_CB4->pos1.y = 0xb0 - tmp;
+ }
+ if (gPSSData->field_CD7 && --gPSSData->field_CD7 == 0)
+ gPSSData->field_CB4->vFlip = (gPSSData->field_CB4->vFlip == FALSE);
+ }
+ else
+ {
+ gPSSData->field_CB4->pos1.x = gPSSData->field_CCC;
+ gPSSData->field_CB4->pos1.y = gPSSData->field_CCE;
+ sub_80929B0();
+ }
+
+ return TRUE;
+}
+
+static void sub_8092604(u8 newCurosrArea, u8 newCursorPosition)
+{
+ u16 x, y;
+
+ sub_8092398(newCurosrArea, newCursorPosition, &x, &y);
+ gPSSData->field_CD4 = newCurosrArea;
+ gPSSData->field_CD5 = newCursorPosition;
+ gPSSData->field_CCC = x;
+ gPSSData->field_CCE = y;
+}
+
+static void sub_8092660(void)
+{
+ int r7, r0;
+
+ if (gPSSData->field_CD2 != 0 || gPSSData->field_CD3 != 0)
+ gPSSData->field_CD0 = 12;
+ else
+ gPSSData->field_CD0 = 6;
+
+ if (gPSSData->field_CD7)
+ gPSSData->field_CD7 = gPSSData->field_CD0 >> 1;
+
+ switch (gPSSData->field_CD2)
+ {
+ default:
+ r7 = gPSSData->field_CCE - gPSSData->field_CB4->pos1.y;
+ break;
+ case -1:
+ r7 = gPSSData->field_CCE - 0xc0 - gPSSData->field_CB4->pos1.y;
+ break;
+ case 1:
+ r7 = gPSSData->field_CCE + 0xc0 - gPSSData->field_CB4->pos1.y;
+ break;
+ }
+
+ switch (gPSSData->field_CD3)
+ {
+ default:
+ r0 = gPSSData->field_CCC - gPSSData->field_CB4->pos1.x;
+ break;
+ case -1:
+ r0 = gPSSData->field_CCC - 0xc0 - gPSSData->field_CB4->pos1.x;
+ break;
+ case 1:
+ r0 = gPSSData->field_CCC + 0xc0 - gPSSData->field_CB4->pos1.x;
+ break;
+ }
+
+ r7 <<= 8;
+ r0 <<= 8;
+ gPSSData->field_CC4 = r0 / gPSSData->field_CD0;
+ gPSSData->field_CC8 = r7 / gPSSData->field_CD0;
+ gPSSData->field_CBC = gPSSData->field_CB4->pos1.x << 8;
+ gPSSData->field_CC0 = gPSSData->field_CB4->pos1.y << 8;
+}
+
+static void sub_80927E8(u8 newCurosrArea, u8 newCursorPosition)
+{
+ sub_8092604(newCurosrArea, newCursorPosition);
+ sub_8092660();
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ if (gPSSData->inBoxMovingMode == 0 && !sIsMonBeingMoved)
+ StartSpriteAnim(gPSSData->field_CB4, 1);
+ }
+ else
+ {
+ if (!IsActiveItemMoving())
+ StartSpriteAnim(gPSSData->field_CB4, 1);
+ }
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX)
+ sub_8095D44(CURSOR_AREA_IN_BOX, sBoxCursorPosition);
+ else if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ sub_8095D44(CURSOR_AREA_IN_PARTY, sBoxCursorPosition);
+
+ if (newCurosrArea == CURSOR_AREA_IN_BOX)
+ sub_8095C84(newCurosrArea, newCursorPosition);
+ else if (newCurosrArea == CURSOR_AREA_IN_PARTY)
+ sub_8095C84(newCurosrArea, newCursorPosition);
+ }
+
+ if (newCurosrArea == CURSOR_AREA_IN_PARTY && sBoxCursorArea != CURSOR_AREA_IN_PARTY)
+ {
+ gPSSData->field_CD6 = newCurosrArea;
+ gPSSData->field_CB8->invisible = TRUE;
+ }
+
+ switch (newCurosrArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ case CURSOR_AREA_BOX:
+ case CURSOR_AREA_BUTTONS:
+ gPSSData->field_CB4->oam.priority = 1;
+ gPSSData->field_CB8->invisible = TRUE;
+ gPSSData->field_CB8->oam.priority = 1;
+ break;
+ case CURSOR_AREA_IN_BOX:
+ if (gPSSData->inBoxMovingMode != 0)
+ {
+ gPSSData->field_CB4->oam.priority = 0;
+ gPSSData->field_CB8->invisible = TRUE;
+ }
+ else
+ {
+ gPSSData->field_CB4->oam.priority = 2;
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX && sIsMonBeingMoved)
+ SetMovingMonPriority(2);
+ }
+ break;
+ }
+}
+
+static void sub_80929B0(void)
+{
+ sBoxCursorArea = gPSSData->field_CD4;
+ sBoxCursorPosition = gPSSData->field_CD5;
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ {
+ if (gPSSData->inBoxMovingMode == 0 && !sIsMonBeingMoved)
+ StartSpriteAnim(gPSSData->field_CB4, 1);
+ }
+ else
+ {
+ if (!IsActiveItemMoving())
+ StartSpriteAnim(gPSSData->field_CB4, 1);
+ }
+
+ sub_8093A10();
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_BUTTONS:
+ SetMovingMonPriority(1);
+ break;
+ case CURSOR_AREA_BOX:
+ sub_80920FC(TRUE);
+ break;
+ case CURSOR_AREA_IN_PARTY:
+ gPSSData->field_CB8->subpriority = 13;
+ SetMovingMonPriority(1);
+ break;
+ case CURSOR_AREA_IN_BOX:
+ if (gPSSData->inBoxMovingMode == 0)
+ {
+ gPSSData->field_CB4->oam.priority = 1;
+ gPSSData->field_CB8->oam.priority = 2;
+ gPSSData->field_CB8->subpriority = 21;
+ gPSSData->field_CB8->invisible = FALSE;
+ SetMovingMonPriority(2);
+ }
+ break;
+ }
+}
+
+void sub_8092AE4(void)
+{
+ u8 partyCount;
+
+ if (!sIsMonBeingMoved)
+ {
+ partyCount = 0;
+ }
+ else
+ {
+ partyCount = CalculatePlayerPartyCount();
+ if (partyCount >= PARTY_SIZE)
+ partyCount = PARTY_SIZE - 1;
+ }
+ if (gPSSData->field_CB4->vFlip)
+ gPSSData->field_CD7 = 1;
+ sub_80927E8(CURSOR_AREA_IN_PARTY, partyCount);
+}
+
+void sub_8092B3C(u8 cursorBoxPosition)
+{
+ sub_80927E8(CURSOR_AREA_IN_BOX, cursorBoxPosition);
+}
+
+void sub_8092B50(void)
+{
+ gUnknown_2039826 = 0;
+}
+
+void sub_8092B5C(void)
+{
+ gUnknown_2039826 = sBoxCursorPosition;
+}
+
+u8 sub_8092B70(void)
+{
+ return gUnknown_2039826;
+}
+
+void InitMonPlaceChange(u8 a0)
+{
+ static bool8 (*const placeChangeFuncs[])(void) = {
+ MonPlaceChange_Move,
+ MonPlaceChange_Place,
+ MonPlaceChange_Shift,
+ };
+
+ gPSSData->monPlaceChangeFunc = placeChangeFuncs[a0];
+ gPSSData->monPlaceChangeState = 0;
+}
+
+void sub_8092BAC(bool8 arg0)
+{
+ if (!arg0)
+ gPSSData->monPlaceChangeFunc = sub_8092E00;
+ else
+ gPSSData->monPlaceChangeFunc = sub_8092E10;
+
+ gPSSData->monPlaceChangeState = 0;
+}
+
+bool8 DoMonPlaceChange(void)
+{
+ return gPSSData->monPlaceChangeFunc();
+}
+
+static bool8 MonPlaceChange_Move(void)
+{
+ switch (gPSSData->monPlaceChangeState)
+ {
+ case 0:
+ if (sIsMonBeingMoved)
+ return FALSE;
+ StartSpriteAnim(gPSSData->field_CB4, 2);
+ gPSSData->monPlaceChangeState++;
+ break;
+ case 1:
+ if (!sub_8092E20())
+ {
+ StartSpriteAnim(gPSSData->field_CB4, 3);
+ MoveMon();
+ gPSSData->monPlaceChangeState++;
+ }
+ break;
+ case 2:
+ if (!sub_8092E54())
+ gPSSData->monPlaceChangeState++;
+ break;
+ case 3:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool8 MonPlaceChange_Place(void)
+{
+ switch (gPSSData->monPlaceChangeState)
+ {
+ case 0:
+ if (!sub_8092E20())
+ {
+ StartSpriteAnim(gPSSData->field_CB4, 2);
+ PlaceMon();
+ gPSSData->monPlaceChangeState++;
+ }
+ break;
+ case 1:
+ if (!sub_8092E54())
+ {
+ StartSpriteAnim(gPSSData->field_CB4, 0);
+ gPSSData->monPlaceChangeState++;
+ }
+ break;
+ case 2:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool8 MonPlaceChange_Shift(void)
+{
+ switch (gPSSData->monPlaceChangeState)
+ {
+ case 0:
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ gPSSData->field_D91 = TOTAL_BOXES_COUNT;
+ break;
+ case CURSOR_AREA_IN_BOX:
+ gPSSData->field_D91 = StorageGetCurrentBox();
+ break;
+ default:
+ return FALSE;
+ }
+ StartSpriteAnim(gPSSData->field_CB4, 2);
+ sub_8090E08(gPSSData->field_D91, sBoxCursorPosition);
+ gPSSData->monPlaceChangeState++;
+ break;
+ case 1:
+ if (!sub_8090E74())
+ {
+ StartSpriteAnim(gPSSData->field_CB4, 3);
+ SetShiftedMonData(gPSSData->field_D91, sBoxCursorPosition);
+ gPSSData->monPlaceChangeState++;
+ }
+ break;
+ case 2:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_8092E00(void)
+{
+ return sub_8092E20();
+}
+
+static bool8 sub_8092E10(void)
+{
+ return sub_8092E54();
+}
+
+static bool8 sub_8092E20(void)
+{
+ switch (gPSSData->field_CB4->pos2.y)
+ {
+ default:
+ gPSSData->field_CB4->pos2.y++;
+ break;
+ case 0:
+ gPSSData->field_CB4->pos2.y++;
+ break;
+ case 8:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_8092E54(void)
+{
+ switch (gPSSData->field_CB4->pos2.y)
+ {
+ case 0:
+ return FALSE;
+ default:
+ gPSSData->field_CB4->pos2.y--;
+ break;
+ }
+
+ return TRUE;
+}
+
+static void MoveMon(void)
+{
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ SetMovedMonData(TOTAL_BOXES_COUNT, sBoxCursorPosition);
+ sub_8090CC0(MODE_PARTY, sBoxCursorPosition);
+ break;
+ case CURSOR_AREA_IN_BOX:
+ if (gPSSData->inBoxMovingMode == 0)
+ {
+ SetMovedMonData(StorageGetCurrentBox(), sBoxCursorPosition);
+ sub_8090CC0(MODE_BOX, sBoxCursorPosition);
+ }
+ break;
+ default:
+ return;
+ }
+
+ sIsMonBeingMoved = TRUE;
+}
+
+static void PlaceMon(void)
+{
+ u8 boxId;
+
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ SetPlacedMonData(TOTAL_BOXES_COUNT, sBoxCursorPosition);
+ sub_8090D58(TOTAL_BOXES_COUNT, sBoxCursorPosition);
+ break;
+ case CURSOR_AREA_IN_BOX:
+ boxId = StorageGetCurrentBox();
+ SetPlacedMonData(boxId, sBoxCursorPosition);
+ sub_8090D58(boxId, sBoxCursorPosition);
+ break;
+ default:
+ return;
+ }
+
+ sIsMonBeingMoved = FALSE;
+}
+
+void sub_8092F54(void)
+{
+ sub_8093A10();
+}
+
+static void SetMovedMonData(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT)
+ gPSSData->movingMon = gPlayerParty[sBoxCursorPosition];
+ else
+ BoxMonAtToMon(boxId, position, &gPSSData->movingMon);
+
+ PurgeMonOrBoxMon(boxId, position);
+ sMovingMonOrigBoxId = boxId;
+ sMovingMonOrigBoxPos = position;
+}
+
+static void SetPlacedMonData(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT)
+ {
+ gPlayerParty[position] = gPSSData->movingMon;
+ }
+ else
+ {
+ BoxMonRestorePP(&gPSSData->movingMon.box);
+ SetBoxMonAt(boxId, position, &gPSSData->movingMon.box);
+ }
+}
+
+static void PurgeMonOrBoxMon(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT)
+ ZeroMonData(&gPlayerParty[position]);
+ else
+ ZeroBoxMonAt(boxId, position);
+}
+
+static void SetShiftedMonData(u8 boxId, u8 position)
+{
+ if (boxId == TOTAL_BOXES_COUNT)
+ gPSSData->field_2108 = gPlayerParty[position];
+ else
+ BoxMonAtToMon(boxId, position, &gPSSData->field_2108);
+
+ SetPlacedMonData(boxId, position);
+ gPSSData->movingMon = gPSSData->field_2108;
+ SetCursorMonData(&gPSSData->movingMon, MODE_PARTY);
+ sMovingMonOrigBoxId = boxId;
+ sMovingMonOrigBoxPos = position;
+}
+
+bool8 TryStorePartyMonInBox(u8 boxId)
+{
+ s16 boxPosition = GetFirstFreeBoxSpot(boxId);
+ if (boxPosition == -1)
+ return FALSE;
+
+ if (sIsMonBeingMoved)
+ {
+ SetPlacedMonData(boxId, boxPosition);
+ DestroyMovingMonIcon();
+ sIsMonBeingMoved = FALSE;
+ }
+ else
+ {
+ SetMovedMonData(TOTAL_BOXES_COUNT, sBoxCursorPosition);
+ SetPlacedMonData(boxId, boxPosition);
+ DestroyPartyMonIcon(sBoxCursorPosition);
+ }
+
+ if (boxId == StorageGetCurrentBox())
+ sub_80901EC(boxPosition);
+
+ StartSpriteAnim(gPSSData->field_CB4, 1);
+ return TRUE;
+}
+
+void sub_8093174(void)
+{
+ StartSpriteAnim(gPSSData->field_CB4, 0);
+ sub_8093A10();
+}
+
+void sub_8093194(void)
+{
+ u8 mode;
+
+ if (sIsMonBeingMoved)
+ mode = MODE_2;
+ else if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ mode = MODE_PARTY;
+ else
+ mode = MODE_BOX;
+
+ sub_8090FC4(mode, sBoxCursorPosition);
+ StringCopy(gPSSData->field_21E0, gPSSData->cursorMonNick);
+}
+
+bool8 sub_80931EC(void)
+{
+ if (!sub_8091084())
+ {
+ StartSpriteAnim(gPSSData->field_CB4, 0);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void ReleaseMon(void)
+{
+ u8 boxId;
+
+ sub_80910CC();
+ if (sIsMonBeingMoved)
+ {
+ sIsMonBeingMoved = FALSE;
+ }
+ else
+ {
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ boxId = TOTAL_BOXES_COUNT;
+ else
+ boxId = StorageGetCurrentBox();
+
+ PurgeMonOrBoxMon(boxId, sBoxCursorPosition);
+ }
+ sub_8093A10();
+}
+
+void sub_8093264(void)
+{
+ if (sIsMonBeingMoved)
+ StartSpriteAnim(gPSSData->field_CB4, 3);
+}
+
+void InitCanReleaseMonVars(void)
+{
+ u16 knownIdx;
+ if (sIsMonBeingMoved)
+ {
+ gPSSData->field_2108 = gPSSData->movingMon;
+ gPSSData->field_2170 = -1;
+ gPSSData->field_2171 = -1;
+ }
+ else
+ {
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ {
+ gPSSData->field_2108 = gPlayerParty[sBoxCursorPosition];
+ gPSSData->field_2170 = TOTAL_BOXES_COUNT;
+ }
+ else
+ {
+ BoxMonAtToMon(StorageGetCurrentBox(), sBoxCursorPosition, &gPSSData->field_2108);
+ gPSSData->field_2170 = StorageGetCurrentBox();
+ }
+ gPSSData->field_2171 = sBoxCursorPosition;
+ }
+
+ gPSSData->isSurfMon = FALSE;
+ gPSSData->isDiveMon = FALSE;
+ gPSSData->field_2176[0] = MOVE_SURF;
+ gPSSData->field_2176[1] = MOVE_DIVE;
+ gPSSData->field_2176[2] = MOVES_COUNT;
+ knownIdx = GetMonData(&gPSSData->field_2108, MON_DATA_KNOWN_MOVES, (u8*)gPSSData->field_2176);
+ gPSSData->isSurfMon = knownIdx & 1;
+ gPSSData->isDiveMon = (knownIdx >> 1) & 1;
+ if (gPSSData->isSurfMon || gPSSData->isDiveMon)
+ {
+ gPSSData->field_216D = 0;
+ }
+ else
+ {
+ gPSSData->field_216D = 1;
+ gPSSData->field_216C = 1;
+ }
+
+ gPSSData->field_2172 = 0;
+}
+
+s8 RunCanReleaseMon(void)
+{
+ u16 i;
+ u16 knownMoves;
+
+ if (gPSSData->field_216D)
+ return gPSSData->field_216C;
+
+ switch (gPSSData->field_2172)
+ {
+ case 0:
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (gPSSData->field_2170 != TOTAL_BOXES_COUNT || gPSSData->field_2171 != i)
+ {
+ knownMoves = GetMonData(gPlayerParty + i, MON_DATA_KNOWN_MOVES, (u8*)gPSSData->field_2176);
+ if (knownMoves & 1)
+ gPSSData->isSurfMon = FALSE;
+ if (knownMoves & 2)
+ gPSSData->isDiveMon = FALSE;
+ }
+ }
+ if (!(gPSSData->isSurfMon || gPSSData->isDiveMon))
+ {
+ gPSSData->field_216D = 1;
+ gPSSData->field_216C = 1;
+ }
+ else
+ {
+ gPSSData->field_216E = 0;
+ gPSSData->field_216F = 0;
+ gPSSData->field_2172++;
+ }
+ break;
+ case 1:
+ for (i = 0; i < 5; i++)
+ {
+ knownMoves = GetAndCopyBoxMonDataAt(gPSSData->field_216E, gPSSData->field_216F, MON_DATA_KNOWN_MOVES, (u8*)gPSSData->field_2176);
+ if (knownMoves != 0
+ && !(gPSSData->field_2170 == gPSSData->field_216E && gPSSData->field_2171 == gPSSData->field_216F))
+ {
+ if (knownMoves & 1)
+ gPSSData->isSurfMon = FALSE;
+ if (knownMoves & 2)
+ gPSSData->isDiveMon = FALSE;
+ }
+ if (++gPSSData->field_216F >= IN_BOX_COUNT)
+ {
+ gPSSData->field_216F = 0;
+ if (++gPSSData->field_216E >= TOTAL_BOXES_COUNT)
+ {
+ gPSSData->field_216D = 1;
+ gPSSData->field_216C = 0;
+ break;
+ }
+ }
+ }
+ if (!(gPSSData->isSurfMon || gPSSData->isDiveMon))
+ {
+ gPSSData->field_216D = 1;
+ gPSSData->field_216C = 1;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+void sub_8093630(void)
+{
+ if (sIsMonBeingMoved)
+ gUnknown_20397BC = gPSSData->movingMon;
+}
+
+void sub_8093660(void)
+{
+ if (sIsMonBeingMoved)
+ {
+ if (sMovingMonOrigBoxId == TOTAL_BOXES_COUNT)
+ gPSSData->movingMon = gUnknown_20397BC;
+ else
+ gPSSData->movingMon.box = gUnknown_20397BC.box;
+ }
+}
+
+void sub_80936B8(void)
+{
+ if (sIsMonBeingMoved)
+ {
+ sub_8093630();
+ gPSSData->field_218C.mon = &gUnknown_20397BC;
+ gPSSData->field_2187 = 0;
+ gPSSData->field_2186 = 0;
+ gPSSData->field_2188 = 0;
+ }
+ else if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ {
+ gPSSData->field_218C.mon = gPlayerParty;
+ gPSSData->field_2187 = sBoxCursorPosition;
+ gPSSData->field_2186 = CountPartyMons() - 1;
+ gPSSData->field_2188 = 0;
+ }
+ else
+ {
+ gPSSData->field_218C.box = GetBoxedMonPtr(StorageGetCurrentBox(), 0);
+ gPSSData->field_2187 = sBoxCursorPosition;
+ gPSSData->field_2186 = IN_BOX_COUNT - 1;
+ gPSSData->field_2188 = 5;
+ }
+}
+
+void sub_80937B4(void)
+{
+ if (sIsMonBeingMoved)
+ sub_8093660();
+ else
+ sBoxCursorPosition = GetLastViewedMonIndex();
+}
+
+// file boundary maybe?
+
+s16 CompactPartySlots(void)
+{
+ s16 retVal = -1;
+ u16 i, last;
+
+ for (i = 0, last = 0; i < PARTY_SIZE; i++)
+ {
+ u16 species = GetMonData(gPlayerParty + i, MON_DATA_SPECIES);
+ if (species != SPECIES_NONE)
+ {
+ if (i != last)
+ gPlayerParty[last] = gPlayerParty[i];
+ last++;
+ }
+ else if (retVal == -1)
+ {
+ retVal = i;
+ }
+ }
+ for (; last < PARTY_SIZE; last++)
+ ZeroMonData(gPlayerParty + last);
+
+ return retVal;
+}
+
+void SetMonMarkings(u8 markings)
+{
+ gPSSData->cursorMonMarkings = markings;
+ if (sIsMonBeingMoved)
+ {
+ SetMonData(&gPSSData->movingMon, MON_DATA_MARKINGS, &markings);
+ }
+ else
+ {
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ SetMonData(gPlayerParty + sBoxCursorPosition, MON_DATA_MARKINGS, &markings);
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX)
+ SetCurrentBoxMonData(sBoxCursorPosition, MON_DATA_MARKINGS, &markings);
+ }
+}
+
+bool8 CanMovePartyMon(void)
+{
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY && !sIsMonBeingMoved && CountPartyAliveNonEggMonsExcept(sBoxCursorPosition) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 CanShiftMon(void)
+{
+ if (sIsMonBeingMoved)
+ {
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY && CountPartyAliveNonEggMonsExcept(sBoxCursorPosition) == 0)
+ {
+ if (gPSSData->cursorMonIsEgg || GetMonData(&gPSSData->movingMon, MON_DATA_HP) == 0)
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 IsMonBeingMoved(void)
+{
+ return sIsMonBeingMoved;
+}
+
+bool8 IsCursorOnBox(void)
+{
+ return (sBoxCursorArea == CURSOR_AREA_BOX);
+}
+
+bool8 IsCursorOnCloseBox(void)
+{
+ return (sBoxCursorArea == CURSOR_AREA_BUTTONS && sBoxCursorPosition == 1);
+}
+
+bool8 IsCursorInBox(void)
+{
+ return (sBoxCursorArea == CURSOR_AREA_IN_BOX);
+}
+
+static void sub_8093A10(void)
+{
+ gPSSData->setMosaic = (sIsMonBeingMoved == FALSE);
+ if (!sIsMonBeingMoved)
+ {
+ switch (sBoxCursorArea)
+ {
+ case CURSOR_AREA_IN_PARTY:
+ if (sBoxCursorPosition < PARTY_SIZE)
+ {
+ SetCursorMonData(&gPlayerParty[sBoxCursorPosition], MODE_PARTY);
+ break;
+ }
+ // fallthrough
+ case CURSOR_AREA_BUTTONS:
+ case CURSOR_AREA_BOX:
+ SetCursorMonData(NULL, MODE_2);
+ break;
+ case CURSOR_AREA_IN_BOX:
+ SetCursorMonData(GetBoxedMonPtr(StorageGetCurrentBox(), sBoxCursorPosition), MODE_BOX);
+ break;
+ }
+ }
+}
+
+static void sub_8093AAC(void)
+{
+ if (sIsMonBeingMoved)
+ SetCursorMonData(&gUnknown_20397BC, MODE_PARTY);
+ else
+ sub_8093A10();
+}
+
+static void SetCursorMonData(void *pokemon, u8 mode)
+{
+ u8 *txtPtr;
+ u16 gender;
+ bool8 sanityIsBagEgg;
+
+ gPSSData->cursorMonItem = 0;
+ gender = MON_MALE;
+ sanityIsBagEgg = FALSE;
+ if (mode == MODE_PARTY)
+ {
+ struct Pokemon *mon = (struct Pokemon *)pokemon;
+
+ gPSSData->cursorMonSpecies = GetMonData(mon, MON_DATA_SPECIES2);
+ if (gPSSData->cursorMonSpecies != SPECIES_NONE)
+ {
+ sanityIsBagEgg = GetMonData(mon, MON_DATA_SANITY_IS_BAD_EGG);
+ if (sanityIsBagEgg)
+ gPSSData->cursorMonIsEgg = TRUE;
+ else
+ gPSSData->cursorMonIsEgg = GetMonData(mon, MON_DATA_IS_EGG);
+
+ GetMonData(mon, MON_DATA_NICKNAME, gPSSData->cursorMonNick);
+ StringGetEnd10(gPSSData->cursorMonNick);
+ gPSSData->cursorMonLevel = GetMonData(mon, MON_DATA_LEVEL);
+ gPSSData->cursorMonMarkings = GetMonData(mon, MON_DATA_MARKINGS);
+ gPSSData->cursorMonPersonality = GetMonData(mon, MON_DATA_PERSONALITY);
+ gPSSData->cursorMonPalette = GetMonFrontSpritePal(mon);
+ gender = GetMonGender(mon);
+ gPSSData->cursorMonItem = GetMonData(mon, MON_DATA_HELD_ITEM);
+ }
+ }
+ else if (mode == MODE_BOX)
+ {
+ struct BoxPokemon *boxMon = (struct BoxPokemon *)pokemon;
+
+ gPSSData->cursorMonSpecies = GetBoxMonData(pokemon, MON_DATA_SPECIES2);
+ if (gPSSData->cursorMonSpecies != SPECIES_NONE)
+ {
+ u32 otId = GetBoxMonData(boxMon, MON_DATA_OT_ID);
+ sanityIsBagEgg = GetBoxMonData(boxMon, MON_DATA_SANITY_IS_BAD_EGG);
+ if (sanityIsBagEgg)
+ gPSSData->cursorMonIsEgg = TRUE;
+ else
+ gPSSData->cursorMonIsEgg = GetBoxMonData(boxMon, MON_DATA_IS_EGG);
+
+
+ GetBoxMonData(boxMon, MON_DATA_NICKNAME, gPSSData->cursorMonNick);
+ StringGetEnd10(gPSSData->cursorMonNick);
+ gPSSData->cursorMonLevel = GetLevelFromBoxMonExp(boxMon);
+ gPSSData->cursorMonMarkings = GetBoxMonData(boxMon, MON_DATA_MARKINGS);
+ gPSSData->cursorMonPersonality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY);
+ gPSSData->cursorMonPalette = GetMonSpritePalFromSpeciesAndPersonality(gPSSData->cursorMonSpecies, otId, gPSSData->cursorMonPersonality);
+ gender = GetGenderFromSpeciesAndPersonality(gPSSData->cursorMonSpecies, gPSSData->cursorMonPersonality);
+ gPSSData->cursorMonItem = GetBoxMonData(boxMon, MON_DATA_HELD_ITEM);
+ }
+ }
+ else
+ {
+ gPSSData->cursorMonSpecies = SPECIES_NONE;
+ gPSSData->cursorMonItem = 0;
+ }
+
+ if (gPSSData->cursorMonSpecies == SPECIES_NONE)
+ {
+ StringFill(gPSSData->cursorMonNick, CHAR_SPACE, 5);
+ StringFill(gPSSData->cursorMonTexts[0], CHAR_SPACE, 8);
+ StringFill(gPSSData->cursorMonTexts[1], CHAR_SPACE, 8);
+ StringFill(gPSSData->cursorMonTexts[2], CHAR_SPACE, 8);
+ StringFill(gPSSData->cursorMonTexts[3], CHAR_SPACE, 8);
+ }
+ else if (gPSSData->cursorMonIsEgg)
+ {
+ if (sanityIsBagEgg)
+ StringCopyPadded(gPSSData->cursorMonTexts[0], gPSSData->cursorMonNick, CHAR_SPACE, 5);
+ else
+ StringCopyPadded(gPSSData->cursorMonTexts[0], gText_EggNickname, CHAR_SPACE, 8);
+
+ StringFill(gPSSData->cursorMonTexts[1], CHAR_SPACE, 8);
+ StringFill(gPSSData->cursorMonTexts[2], CHAR_SPACE, 8);
+ StringFill(gPSSData->cursorMonTexts[3], CHAR_SPACE, 8);
+ }
+ else
+ {
+ if (gPSSData->cursorMonSpecies == SPECIES_NIDORAN_F || gPSSData->cursorMonSpecies == SPECIES_NIDORAN_M)
+ gender = MON_GENDERLESS;
+
+ StringCopyPadded(gPSSData->cursorMonTexts[0], gPSSData->cursorMonNick, CHAR_SPACE, 5);
+
+ txtPtr = gPSSData->cursorMonTexts[1];
+ *(txtPtr)++ = CHAR_SLASH;
+ StringCopyPadded(txtPtr, gSpeciesNames[gPSSData->cursorMonSpecies], CHAR_SPACE, 5);
+
+ txtPtr = gPSSData->cursorMonTexts[2];
+ *(txtPtr)++ = EXT_CTRL_CODE_BEGIN;
+ *(txtPtr)++ = EXT_CTRL_CODE_COLOR_HIGHLIGHT_SHADOW;
+ switch (gender)
+ {
+ case MON_MALE:
+ *(txtPtr)++ = TEXT_COLOR_RED;
+ *(txtPtr)++ = TEXT_COLOR_WHITE;
+ *(txtPtr)++ = TEXT_COLOR_LIGHT_RED;
+ *(txtPtr)++ = CHAR_MALE;
+ break;
+ case MON_FEMALE:
+ *(txtPtr)++ = TEXT_COLOR_GREEN;
+ *(txtPtr)++ = TEXT_COLOR_WHITE;
+ *(txtPtr)++ = TEXT_COLOR_LIGHT_GREEN;
+ *(txtPtr)++ = CHAR_FEMALE;
+ break;
+ default:
+ *(txtPtr)++ = TEXT_COLOR_DARK_GREY;
+ *(txtPtr)++ = TEXT_COLOR_WHITE;
+ *(txtPtr)++ = TEXT_COLOR_LIGHT_GREY;
+ *(txtPtr)++ = CHAR_SPACE;
+ break;
+ }
+
+ *(txtPtr++) = EXT_CTRL_CODE_BEGIN;
+ *(txtPtr++) = EXT_CTRL_CODE_COLOR_HIGHLIGHT_SHADOW;
+ *(txtPtr++) = TEXT_COLOR_DARK_GREY;
+ *(txtPtr++) = TEXT_COLOR_WHITE;
+ *(txtPtr++) = TEXT_COLOR_LIGHT_GREY;
+ *(txtPtr++) = CHAR_SPACE;
+ *(txtPtr++) = CHAR_EXTRA_EMOJI;
+ *(txtPtr++) = 5; // LV_2
+
+ txtPtr = ConvertIntToDecimalStringN(txtPtr, gPSSData->cursorMonLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
+ txtPtr[0] = CHAR_SPACE;
+ txtPtr[1] = EOS;
+
+ if (gPSSData->cursorMonItem != 0)
+ StringCopyPadded(gPSSData->cursorMonTexts[3], ItemId_GetName(gPSSData->cursorMonItem), CHAR_SPACE, 8);
+ else
+ StringFill(gPSSData->cursorMonTexts[3], CHAR_SPACE, 8);
+ }
+}
+
+static u8 HandleInput_InBox(void)
+{
+ switch (gPSSData->inBoxMovingMode)
+ {
+ case 0:
+ default:
+ return InBoxInput_Normal();
+ case 1:
+ return InBoxInput_GrabbingMultiple();
+ case 2:
+ return InBoxInput_MovingMultiple();
+ }
+}
+
+static u8 InBoxInput_Normal(void)
+{
+ u8 retVal;
+ s8 cursorArea;
+ s8 cursorPosition;
+
+ do
+ {
+ cursorArea = sBoxCursorArea;
+ cursorPosition = sBoxCursorPosition;
+ gPSSData->field_CD2 = 0;
+ gPSSData->field_CD3 = 0;
+ gPSSData->field_CD7 = 0;
+ if (JOY_REPT(DPAD_UP))
+ {
+ retVal = TRUE;
+ if (sBoxCursorPosition >= IN_BOX_ROWS)
+ {
+ cursorPosition -= IN_BOX_ROWS;
+ }
+ else
+ {
+ cursorArea = CURSOR_AREA_BOX;
+ cursorPosition = 0;
+ }
+ break;
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ retVal = TRUE;
+ cursorPosition += IN_BOX_ROWS;
+ if (cursorPosition >= IN_BOX_COUNT)
+ {
+ cursorArea = CURSOR_AREA_BUTTONS;
+ cursorPosition -= IN_BOX_COUNT;
+ cursorPosition /= 3;
+ gPSSData->field_CD2 = 1;
+ gPSSData->field_CD7 = 1;
+ }
+ break;
+ }
+ else if (JOY_REPT(DPAD_LEFT))
+ {
+ retVal = TRUE;
+ if (sBoxCursorPosition % IN_BOX_ROWS != 0)
+ {
+ cursorPosition--;
+ }
+ else
+ {
+ gPSSData->field_CD3 = -1;
+ cursorPosition += (IN_BOX_ROWS - 1);
+ }
+ break;
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ retVal = TRUE;
+ if ((sBoxCursorPosition + 1) % IN_BOX_ROWS != 0)
+ {
+ cursorPosition++;
+ }
+ else
+ {
+ gPSSData->field_CD3 = 1;
+ cursorPosition -= (IN_BOX_ROWS - 1);
+ }
+ break;
+ }
+ else if (JOY_NEW(START_BUTTON))
+ {
+ retVal = TRUE;
+ cursorArea = CURSOR_AREA_BOX;
+ cursorPosition = 0;
+ break;
+ }
+
+ if ((JOY_NEW(A_BUTTON)) && sub_8094924())
+ {
+ if (!sCanOnlyMove)
+ return 8;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_MONS || sIsMonBeingMoved == TRUE)
+ {
+ switch (sub_8094E50(0))
+ {
+ case PC_TEXT_STORE:
+ return 11;
+ case PC_TEXT_WITHDRAW:
+ return 12;
+ case PC_TEXT_MOVE:
+ return 13;
+ case PC_TEXT_SHIFT:
+ return 14;
+ case PC_TEXT_PLACE:
+ return 15;
+ case PC_TEXT_TAKE:
+ return 16;
+ case PC_TEXT_GIVE:
+ return 17;
+ case PC_TEXT_SWITCH:
+ return 18;
+ }
+ }
+ else
+ {
+ gPSSData->inBoxMovingMode = 1;
+ return 20;
+ }
+ }
+
+ if (JOY_NEW(B_BUTTON))
+ return 19;
+
+ if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR)
+ {
+ if (JOY_HELD(L_BUTTON))
+ return 10;
+ if (JOY_HELD(R_BUTTON))
+ return 9;
+ }
+
+ if (JOY_NEW(SELECT_BUTTON))
+ {
+ sub_8094C84();
+ return 0;
+ }
+
+ retVal = 0;
+
+ } while (0);
+
+ if (retVal)
+ sub_80927E8(cursorArea, cursorPosition);
+
+ return retVal;
+}
+
+static u8 InBoxInput_GrabbingMultiple(void)
+{
+ if (JOY_HELD(A_BUTTON))
+ {
+ if (JOY_REPT(DPAD_UP))
+ {
+ if (sBoxCursorPosition / IN_BOX_ROWS != 0)
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition - IN_BOX_ROWS);
+ return 21;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ if (sBoxCursorPosition + IN_BOX_ROWS < IN_BOX_COUNT)
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition + IN_BOX_ROWS);
+ return 21;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_REPT(DPAD_LEFT))
+ {
+ if (sBoxCursorPosition % IN_BOX_ROWS != 0)
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition - 1);
+ return 21;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ if ((sBoxCursorPosition + 1) % IN_BOX_ROWS != 0)
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition + 1);
+ return 21;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (sub_8095AA0() == sBoxCursorPosition)
+ {
+ gPSSData->inBoxMovingMode = 0;
+ gPSSData->field_CB8->invisible = FALSE;
+ return 22;
+ }
+ else
+ {
+ sIsMonBeingMoved = (gPSSData->cursorMonSpecies != SPECIES_NONE);
+ gPSSData->inBoxMovingMode = 2;
+ sMovingMonOrigBoxId = StorageGetCurrentBox();
+ return 23;
+ }
+ }
+}
+
+static u8 InBoxInput_MovingMultiple(void)
+{
+ if (JOY_REPT(DPAD_UP))
+ {
+ if (sub_8095474(0))
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition - IN_BOX_ROWS);
+ return 25;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ if (sub_8095474(1))
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition + IN_BOX_ROWS);
+ return 25;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_REPT(DPAD_LEFT))
+ {
+ if (sub_8095474(2))
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition - 1);
+ return 25;
+ }
+ else
+ {
+ return 10;
+ }
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ if (sub_8095474(3))
+ {
+ sub_80927E8(CURSOR_AREA_IN_BOX, sBoxCursorPosition + 1);
+ return 25;
+ }
+ else
+ {
+ return 9;
+ }
+ }
+ else if (JOY_NEW(A_BUTTON))
+ {
+ if (sub_8095ABC())
+ {
+ sIsMonBeingMoved = FALSE;
+ gPSSData->inBoxMovingMode = 0;
+ return 26;
+ }
+ else
+ {
+ return 24;
+ }
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ return 24;
+ }
+ else
+ {
+ if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR)
+ {
+ if (JOY_HELD(L_BUTTON))
+ return 10;
+ if (JOY_HELD(R_BUTTON))
+ return 9;
+ }
+
+ return 0;
+ }
+}
+
+static u8 HandleInput_InParty(void)
+{
+ u8 retVal;
+ bool8 gotoBox;
+ s8 cursorArea;
+ s8 cursorPosition;
+
+ do
+ {
+ cursorArea = sBoxCursorArea;
+ cursorPosition = sBoxCursorPosition;
+ gPSSData->field_CD3 = 0;
+ gPSSData->field_CD2 = 0;
+ gPSSData->field_CD7 = 0;
+ gotoBox = FALSE;
+ retVal = 0;
+
+ if (JOY_REPT(DPAD_UP))
+ {
+ if (--cursorPosition < 0)
+ cursorPosition = PARTY_SIZE;
+ if (cursorPosition != sBoxCursorPosition)
+ retVal = 1;
+ break;
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ if (++cursorPosition > PARTY_SIZE)
+ cursorPosition = 0;
+ if (cursorPosition != sBoxCursorPosition)
+ retVal = 1;
+ break;
+ }
+ else if (JOY_REPT(DPAD_LEFT) && sBoxCursorPosition != 0)
+ {
+ retVal = 1;
+ gPSSData->field_CD6 = sBoxCursorPosition;
+ cursorPosition = 0;
+ break;
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ if (sBoxCursorPosition == 0)
+ {
+ retVal = 1;
+ cursorPosition = gPSSData->field_CD6;
+ }
+ else
+ {
+ retVal = 6;
+ cursorArea = CURSOR_AREA_IN_BOX;
+ cursorPosition = 0;
+ }
+ break;
+ }
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ if (sBoxCursorPosition == PARTY_SIZE)
+ {
+ if (gPSSData->boxOption == BOX_OPTION_DEPOSIT)
+ return 4;
+
+ gotoBox = TRUE;
+ }
+ else if (sub_8094924())
+ {
+ if (!sCanOnlyMove)
+ return 8;
+
+ switch (sub_8094E50(0))
+ {
+ case PC_TEXT_STORE:
+ return 11;
+ case PC_TEXT_WITHDRAW:
+ return 12;
+ case PC_TEXT_MOVE:
+ return 13;
+ case PC_TEXT_SHIFT:
+ return 14;
+ case PC_TEXT_PLACE:
+ return 15;
+ case PC_TEXT_TAKE:
+ return 16;
+ case PC_TEXT_GIVE:
+ return 17;
+ case PC_TEXT_SWITCH:
+ return 18;
+ }
+ }
+ }
+
+ if (JOY_NEW(B_BUTTON))
+ {
+ if (gPSSData->boxOption == BOX_OPTION_DEPOSIT)
+ return 19;
+
+ gotoBox = TRUE;
+ }
+
+ if (gotoBox)
+ {
+ retVal = 6;
+ cursorArea = CURSOR_AREA_IN_BOX;
+ cursorPosition = 0;
+ }
+ else if (JOY_NEW(SELECT_BUTTON))
+ {
+ sub_8094C84();
+ return 0;
+ }
+
+ } while (0);
+
+ if (retVal != 0)
+ {
+ if (retVal != 6)
+ sub_80927E8(cursorArea, cursorPosition);
+ }
+
+ return retVal;
+}
+
+static u8 HandleInput_OnBox(void)
+{
+ u8 retVal;
+ s8 cursorArea;
+ s8 cursorPosition;
+
+ do
+ {
+ gPSSData->field_CD3 = 0;
+ gPSSData->field_CD2 = 0;
+ gPSSData->field_CD7 = 0;
+
+ if (JOY_REPT(DPAD_UP))
+ {
+ retVal = 1;
+ cursorArea = CURSOR_AREA_BUTTONS;
+ cursorPosition = 0;
+ gPSSData->field_CD7 = 1;
+ break;
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ retVal = 1;
+ cursorArea = CURSOR_AREA_IN_BOX;
+ cursorPosition = 2;
+ break;
+ }
+
+ if (JOY_HELD(DPAD_LEFT))
+ return 10;
+ if (JOY_HELD(DPAD_RIGHT))
+ return 9;
+
+ if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR)
+ {
+ if (JOY_HELD(L_BUTTON))
+ return 10;
+ if (JOY_HELD(R_BUTTON))
+ return 9;
+ }
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ sub_80920FC(FALSE);
+ AddBoxMenu();
+ return 7;
+ }
+
+ if (JOY_NEW(B_BUTTON))
+ return 19;
+
+ if (JOY_NEW(SELECT_BUTTON))
+ {
+ sub_8094C84();
+ return 0;
+ }
+
+ retVal = 0;
+
+ } while (0);
+
+ if (retVal)
+ {
+ if (cursorArea != CURSOR_AREA_BOX)
+ sub_80920FC(FALSE);
+ sub_80927E8(cursorArea, cursorPosition);
+ }
+
+ return retVal;
+}
+
+static u8 HandleInput_OnButtons(void)
+{
+ u8 retVal;
+ s8 cursorArea;
+ s8 cursorPosition;
+ s8 prevPos;
+
+ do
+ {
+ cursorArea = sBoxCursorArea;
+ cursorPosition = sBoxCursorPosition;
+ gPSSData->field_CD3 = 0;
+ gPSSData->field_CD2 = 0;
+ gPSSData->field_CD7 = 0;
+
+ if (JOY_REPT(DPAD_UP))
+ {
+ retVal = 1;
+ cursorArea = CURSOR_AREA_IN_BOX;
+ gPSSData->field_CD2 = -1;
+ if (sBoxCursorPosition == 0)
+ cursorPosition = IN_BOX_COUNT - 1 - 5;
+ else
+ cursorPosition = IN_BOX_COUNT - 1;
+ gPSSData->field_CD7 = 1;
+ break;
+ }
+ else if (JOY_REPT(DPAD_DOWN | START_BUTTON))
+ {
+ retVal = 1;
+ cursorArea = CURSOR_AREA_BOX;
+ cursorPosition = 0;
+ gPSSData->field_CD7 = 1;
+ break;
+ }
+
+ if (JOY_REPT(DPAD_LEFT))
+ {
+ retVal = 1;
+ if (--cursorPosition < 0)
+ cursorPosition = 1;
+ break;
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ retVal = 1;
+ if (++cursorPosition > 1)
+ cursorPosition = 0;
+ break;
+ }
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ return cursorPosition == 0 ? 5 : 4;
+ }
+ if (JOY_NEW(B_BUTTON))
+ return 19;
+
+ if (JOY_NEW(SELECT_BUTTON))
+ {
+ sub_8094C84();
+ return 0;
+ }
+
+ retVal = 0;
+ } while (0);
+
+ if (retVal != 0)
+ sub_80927E8(cursorArea, cursorPosition);
+
+ return retVal;
+}
+
+u8 HandleInput(void)
+{
+ struct
+ {
+ u8 (*func)(void);
+ s8 area;
+ }
+ static const inputFuncs[] = {
+ {HandleInput_InBox, CURSOR_AREA_IN_BOX},
+ {HandleInput_InParty, CURSOR_AREA_IN_PARTY},
+ {HandleInput_OnBox, CURSOR_AREA_BOX},
+ {HandleInput_OnButtons, CURSOR_AREA_BUTTONS},
+ {NULL, 0},
+ };
+
+ u16 i = 0;
+ while (inputFuncs[i].func != NULL)
+ {
+ if (inputFuncs[i].area == sBoxCursorArea)
+ return inputFuncs[i].func();
+ i++;
+ }
+
+ return 0;
+}
+
+static void AddBoxMenu(void)
+{
+ InitMenu();
+ SetMenuText(PC_TEXT_JUMP);
+ SetMenuText(PC_TEXT_WALLPAPER);
+ SetMenuText(PC_TEXT_NAME);
+ SetMenuText(PC_TEXT_CANCEL);
+}
+
+static bool8 sub_8094924(void)
+{
+ InitMenu();
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return sub_809494C();
+ else
+ return sub_8094A0C();
+}
+
+static bool8 sub_809494C(void)
+{
+ u16 var0 = sub_8092458();
+
+ switch (gPSSData->boxOption)
+ {
+ case BOX_OPTION_DEPOSIT:
+ if (var0)
+ SetMenuText(PC_TEXT_STORE);
+ else
+ return FALSE;
+ break;
+ case BOX_OPTION_WITHDRAW:
+ if (var0)
+ SetMenuText(PC_TEXT_WITHDRAW);
+ else
+ return FALSE;
+ break;
+ case BOX_OPTION_MOVE_MONS:
+ if (sIsMonBeingMoved)
+ {
+ if (var0)
+ SetMenuText(PC_TEXT_SHIFT);
+ else
+ SetMenuText(PC_TEXT_PLACE);
+ }
+ else
+ {
+ if (var0)
+ SetMenuText(PC_TEXT_MOVE);
+ else
+ return FALSE;
+ }
+ break;
+ case BOX_OPTION_MOVE_ITEMS:
+ default:
+ return FALSE;
+ }
+
+ SetMenuText(PC_TEXT_SUMMARY);
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_MONS)
+ {
+ if (!sBoxCursorArea)
+ SetMenuText(PC_TEXT_WITHDRAW);
+ else
+ SetMenuText(PC_TEXT_STORE);
+ }
+
+ SetMenuText(PC_TEXT_MARK);
+ SetMenuText(PC_TEXT_RELEASE);
+ SetMenuText(PC_TEXT_CANCEL);
+ return TRUE;
+}
+
+static bool8 sub_8094A0C(void)
+{
+ if (gPSSData->cursorMonSpecies == SPECIES_EGG)
+ return FALSE;
+
+ if (!IsActiveItemMoving())
+ {
+ if (gPSSData->cursorMonItem == ITEM_NONE)
+ {
+ if (gPSSData->cursorMonSpecies == SPECIES_NONE)
+ return FALSE;
+
+ SetMenuText(PC_TEXT_GIVE2);
+ }
+ else
+ {
+ if (!ItemIsMail(gPSSData->cursorMonItem))
+ {
+ SetMenuText(PC_TEXT_TAKE);
+ SetMenuText(PC_TEXT_BAG);
+ }
+ SetMenuText(PC_TEXT_INFO);
+ }
+ }
+ else
+ {
+ if (gPSSData->cursorMonItem == ITEM_NONE)
+ {
+ if (gPSSData->cursorMonSpecies == SPECIES_NONE)
+ return FALSE;
+
+ SetMenuText(PC_TEXT_GIVE);
+ }
+ else
+ {
+ if (ItemIsMail(gPSSData->cursorMonItem) == TRUE)
+ return FALSE;
+
+ SetMenuText(PC_TEXT_SWITCH);
+ }
+ }
+
+ SetMenuText(PC_TEXT_CANCEL);
+ return TRUE;
+}
+
+static void sub_8094AB8(struct Sprite *sprite)
+{
+ sprite->pos1.x = gPSSData->field_CB4->pos1.x;
+ sprite->pos1.y = gPSSData->field_CB4->pos1.y + 20;
+}
+
+static void sub_8094AD8(void)
+{
+ u16 x, y;
+ u8 spriteId;
+ u8 priority, subpriority;
+ struct SpriteSheet spriteSheets[] = {
+ {sHandCursorTiles, 0x800, TAG_TILE_0},
+ {sHandCursorShadowTiles, 0x80, TAG_TILE_1},
+ {}
+ };
+
+ struct SpritePalette spritePalettes[] = {
+ {sHandCursorPalette, TAG_PAL_DAC7},
+ {}
+ };
+
+ static const struct OamData sOamData_857BA0C = {
+ .shape = SPRITE_SHAPE(32x32),
+ .size = SPRITE_SIZE(32x32),
+ .priority = 1,
+ };
+ static const struct OamData sOamData_857BA14 = {
+ .shape = SPRITE_SHAPE(16x16),
+ .size = SPRITE_SIZE(16x16),
+ .priority = 1,
+ };
+
+ static const union AnimCmd sSpriteAnim_857BA1C[] = {
+ ANIMCMD_FRAME(0, 30),
+ ANIMCMD_FRAME(16, 30),
+ ANIMCMD_JUMP(0)
+ };
+ static const union AnimCmd sSpriteAnim_857BA28[] = {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+ };
+ static const union AnimCmd sSpriteAnim_857BA30[] = {
+ ANIMCMD_FRAME(32, 5),
+ ANIMCMD_END
+ };
+ static const union AnimCmd sSpriteAnim_857BA38[] = {
+ ANIMCMD_FRAME(48, 5),
+ ANIMCMD_END
+ };
+
+ static const union AnimCmd *const sSpriteAnimTable_857BA40[] = {
+ sSpriteAnim_857BA1C,
+ sSpriteAnim_857BA28,
+ sSpriteAnim_857BA30,
+ sSpriteAnim_857BA38
+ };
+
+ static const struct SpriteTemplate gSpriteTemplate_857BA50 = {
+ .tileTag = TAG_TILE_0,
+ .paletteTag = TAG_PAL_WAVEFORM,
+ .oam = &sOamData_857BA0C,
+ .anims = sSpriteAnimTable_857BA40,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+ };
+
+ static const struct SpriteTemplate gSpriteTemplate_857BA68 = {
+ .tileTag = TAG_TILE_1,
+ .paletteTag = TAG_PAL_WAVEFORM,
+ .oam = &sOamData_857BA14,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_8094AB8,
+ };
+
+ LoadSpriteSheets(spriteSheets);
+ LoadSpritePalettes(spritePalettes);
+ gPSSData->field_CD8[0] = IndexOfSpritePaletteTag(TAG_PAL_WAVEFORM);
+ gPSSData->field_CD8[1] = IndexOfSpritePaletteTag(TAG_PAL_DAC7);
+
+ sub_8092398(sBoxCursorArea, sBoxCursorPosition, &x, &y);
+ spriteId = CreateSprite(&gSpriteTemplate_857BA50, x, y, 6);
+ if (spriteId != MAX_SPRITES)
+ {
+ gPSSData->field_CB4 = &gSprites[spriteId];
+ gPSSData->field_CB4->oam.paletteNum = gPSSData->field_CD8[sCanOnlyMove];
+ gPSSData->field_CB4->oam.priority = 1;
+ if (sIsMonBeingMoved)
+ StartSpriteAnim(gPSSData->field_CB4, 3);
+ }
+ else
+ {
+ gPSSData->field_CB4 = NULL;
+ }
+
+ if (sBoxCursorArea == CURSOR_AREA_IN_PARTY)
+ {
+ subpriority = 13;
+ priority = 1;
+ }
+ else
+ {
+ subpriority = 21;
+ priority = 2;
+ }
+
+ spriteId = CreateSprite(&gSpriteTemplate_857BA68, 0, 0, subpriority);
+ if (spriteId != MAX_SPRITES)
+ {
+ gPSSData->field_CB8 = &gSprites[spriteId];
+ gPSSData->field_CB8->oam.priority = priority;
+ if (sBoxCursorArea)
+ gPSSData->field_CB8->invisible = 1;
+ }
+ else
+ {
+ gPSSData->field_CB8 = NULL;
+ }
+}
+
+static void sub_8094C84(void)
+{
+ sCanOnlyMove = !sCanOnlyMove;
+ gPSSData->field_CB4->oam.paletteNum = gPSSData->field_CD8[sCanOnlyMove];
+}
+
+u8 GetBoxCursorPosition(void)
+{
+ return sBoxCursorPosition;
+}
+
+void sub_8094CD4(u8 *arg0, u8 *arg1)
+{
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX)
+ {
+ *arg0 = sBoxCursorPosition % IN_BOX_ROWS;
+ *arg1 = sBoxCursorPosition / IN_BOX_ROWS;
+ }
+ else
+ {
+ *arg0 = 0;
+ *arg1 = 0;
+ }
+}
+
+void sub_8094D14(u8 animNum)
+{
+ StartSpriteAnim(gPSSData->field_CB4, animNum);
+}
+
+u8 sub_8094D34(void)
+{
+ return sMovingMonOrigBoxId;
+}
+
+void sub_8094D40(void)
+{
+ gPSSData->field_CB4->oam.priority = 1;
+}
+
+void sub_8094D60(void)
+{
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX)
+ sub_8095D44(CURSOR_AREA_IN_BOX, sBoxCursorPosition);
+}
+
+void sub_8094D84(void)
+{
+ if (sBoxCursorArea == CURSOR_AREA_IN_BOX)
+ sub_8095C84(CURSOR_AREA_IN_BOX, sBoxCursorPosition);
+}
diff --git a/src/pokemon_storage_system_6.c b/src/pokemon_storage_system_6.c
new file mode 100644
index 000000000..a1d3af8f2
--- /dev/null
+++ b/src/pokemon_storage_system_6.c
@@ -0,0 +1,147 @@
+#include "global.h"
+#include "gflib.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "pokemon_storage_system_internal.h"
+#include "strings.h"
+#include "constants/songs.h"
+
+void InitMenu(void)
+{
+ gPSSData->menuItemsCount = 0;
+ gPSSData->menuWidth = 0;
+ gPSSData->menuWindow.bg = 0;
+ gPSSData->menuWindow.paletteNum = 15;
+ gPSSData->menuWindow.baseBlock = 92;
+}
+
+static const u8 *const sMenuTexts[] = {
+ [PC_TEXT_CANCEL] = gPCText_Cancel,
+ [PC_TEXT_STORE] = gPCText_Store,
+ [PC_TEXT_WITHDRAW] = gPCText_Withdraw,
+ [PC_TEXT_MOVE] = gPCText_Move,
+ [PC_TEXT_SHIFT] = gPCText_Shift,
+ [PC_TEXT_PLACE] = gPCText_Place,
+ [PC_TEXT_SUMMARY] = gPCText_Summary,
+ [PC_TEXT_RELEASE] = gPCText_Release,
+ [PC_TEXT_MARK] = gPCText_Mark,
+ [PC_TEXT_JUMP] = gPCText_Jump,
+ [PC_TEXT_WALLPAPER] = gPCText_Wallpaper,
+ [PC_TEXT_NAME] = gPCText_Name,
+ [PC_TEXT_TAKE] = gPCText_Take,
+ [PC_TEXT_GIVE] = gPCText_Give,
+ [PC_TEXT_GIVE2] = gPCText_Give,
+ [PC_TEXT_SWITCH] = gPCText_Switch,
+ [PC_TEXT_BAG] = gPCText_Bag,
+ [PC_TEXT_INFO] = gPCText_Info,
+ [PC_TEXT_SCENERY1] = gPCText_Scenery1,
+ [PC_TEXT_SCENERY2] = gPCText_Scenery2,
+ [PC_TEXT_SCENERY3] = gPCText_Scenery3,
+ [PC_TEXT_ETCETERA] = gPCText_Etcetera,
+ [PC_TEXT_FOREST] = gPCText_Forest,
+ [PC_TEXT_CITY] = gPCText_City,
+ [PC_TEXT_DESERT] = gPCText_Desert,
+ [PC_TEXT_SAVANNA] = gPCText_Savanna,
+ [PC_TEXT_CRAG] = gPCText_Crag,
+ [PC_TEXT_VOLCANO] = gPCText_Volcano,
+ [PC_TEXT_SNOW] = gPCText_Snow,
+ [PC_TEXT_CAVE] = gPCText_Cave,
+ [PC_TEXT_BEACH] = gPCText_Beach,
+ [PC_TEXT_SEAFLOOR] = gPCText_Seafloor,
+ [PC_TEXT_RIVER] = gPCText_River,
+ [PC_TEXT_SKY] = gPCText_Sky,
+ [PC_TEXT_POLKADOT] = gPCText_PolkaDot,
+ [PC_TEXT_POKECENTER] = gPCText_Pokecenter,
+ [PC_TEXT_MACHINE] = gPCText_Machine,
+ [PC_TEXT_SIMPLE] = gPCText_Simple,
+};
+
+void SetMenuText(u8 textId)
+{
+ if (gPSSData->menuItemsCount < MAX_MENU_ITEMS)
+ {
+ u8 len;
+ struct StorageMenu *menu = &gPSSData->menuItems[gPSSData->menuItemsCount];
+
+ menu->text = sMenuTexts[textId];
+ menu->textId = textId;
+ len = StringLength(menu->text);
+ if (len > gPSSData->menuWidth)
+ gPSSData->menuWidth = len;
+
+ gPSSData->menuItemsCount++;
+ }
+}
+
+s8 sub_8094E50(u8 arg0)
+{
+ if (arg0 >= gPSSData->menuItemsCount)
+ return -1;
+ else
+ return gPSSData->menuItems[arg0].textId;
+}
+
+void AddMenu(void)
+{
+ gPSSData->menuWindow.width = gPSSData->menuWidth + 2;
+ gPSSData->menuWindow.height = 2 * gPSSData->menuItemsCount;
+ gPSSData->menuWindow.tilemapLeft = 29 - gPSSData->menuWindow.width;
+ gPSSData->menuWindow.tilemapTop = 15 - gPSSData->menuWindow.height;
+ gPSSData->field_CB0 = AddWindow(&gPSSData->menuWindow);
+ ClearWindowTilemap(gPSSData->field_CB0);
+ DrawStdFrameWithCustomTileAndPalette(gPSSData->field_CB0, FALSE, 0x00b, 14);
+ PrintTextArray(gPSSData->field_CB0, 1, 8, 2, 16, gPSSData->menuItemsCount, (void*)gPSSData->menuItems);
+ Menu_InitCursor(gPSSData->field_CB0, 1, 0, 2, 16, gPSSData->menuItemsCount, 0);
+ ScheduleBgCopyTilemapToVram(0);
+ gPSSData->field_CAE = 0;
+}
+
+bool8 sub_8094F90(void)
+{
+ // Some debug flag?
+ return FALSE;
+}
+
+s16 sub_8094F94(void)
+{
+ s32 textId = -2;
+
+ do
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ textId = Menu_GetCursorPos();
+ break;
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ textId = -1;
+ }
+
+ if (JOY_NEW(DPAD_UP))
+ {
+ PlaySE(SE_SELECT);
+ Menu_MoveCursor(-1);
+ }
+ else if (JOY_NEW(DPAD_DOWN))
+ {
+ PlaySE(SE_SELECT);
+ Menu_MoveCursor(1);
+ }
+ } while (0);
+
+ if (textId != -2)
+ sub_8095024();
+
+ if (textId >= 0)
+ textId = gPSSData->menuItems[textId].textId;
+
+ return textId;
+}
+
+void sub_8095024(void)
+{
+ ClearStdWindowAndFrameToTransparent(gPSSData->field_CB0, TRUE);
+ RemoveWindow(gPSSData->field_CB0);
+}
diff --git a/src/pokemon_storage_system_7.c b/src/pokemon_storage_system_7.c
new file mode 100644
index 000000000..367477a89
--- /dev/null
+++ b/src/pokemon_storage_system_7.c
@@ -0,0 +1,582 @@
+#include <stdlib.h> // to declare abs
+#include "global.h"
+#include "gflib.h"
+#include "pokemon_icon.h"
+#include "pokemon_storage_system_internal.h"
+#include "text_window.h"
+#include "constants/species.h"
+
+struct MoveMons
+{
+ u8 field_0;
+ u8 state;
+ u8 fromRow;
+ u8 fromColumn;
+ u8 toRow;
+ u8 toColumn;
+ u8 field_6;
+ u8 field_7;
+ u8 minRow;
+ u8 minColumn;
+ u8 rowsTotal;
+ u8 columsTotal;
+ u16 bgX;
+ u16 bgY;
+ u16 field_10;
+ struct BoxPokemon boxMons[IN_BOX_COUNT];
+};
+
+static EWRAM_DATA struct MoveMons *sMoveMonsPtr = NULL;
+
+static bool8 sub_8095138(void);
+static bool8 sub_8095234(void);
+static bool8 sub_80952A0(void);
+static bool8 sub_8095314(void);
+static bool8 sub_8095394(void);
+static bool8 sub_80953BC(void);
+static void sub_8095520(void);
+static void sub_80955C4(u8 arg0, u8 arg1, u8 arg2);
+static void sub_80955FC(u8 arg0, u8 arg1, u8 arg2);
+static void sub_8095634(u8 arg0, u8 arg1, u8 arg2);
+static void sub_809566C(u8 arg0, u8 arg1, u8 arg2);
+static void sub_80956A4(u8 x, u8 y);
+static void sub_809572C(u8 x, u8 y);
+static void sub_8095780(u16 bgX, u16 bgY, u16 duration);
+static u8 sub_8095790(void);
+static void sub_80957C8(void);
+static void sub_80958A0(void);
+static void sub_8095918(void);
+static void sub_80959A8(void);
+static void sub_8095A58(void);
+
+static const struct WindowTemplate gUnknown_83D35D4 = {
+ .bg = 0,
+ .tilemapLeft = 10,
+ .tilemapTop = 3,
+ .width = 20,
+ .height = 18,
+ .paletteNum = 9,
+ .baseBlock = 0x00a
+};
+
+bool8 sub_8095050(void)
+{
+ sMoveMonsPtr = Alloc(sizeof(*sMoveMonsPtr));
+ if (sMoveMonsPtr != NULL)
+ {
+ gPSSData->field_2200 = AddWindow8Bit(&gUnknown_83D35D4);
+ if (gPSSData->field_2200 != 0xFF)
+ {
+ FillWindowPixelBuffer(gPSSData->field_2200, PIXEL_FILL(0));
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void sub_80950A4(void)
+{
+ if (sMoveMonsPtr != NULL)
+ Free(sMoveMonsPtr);
+}
+
+void sub_80950BC(u8 arg0)
+{
+ sMoveMonsPtr->field_0 = arg0;
+ sMoveMonsPtr->state = 0;
+}
+
+bool8 sub_80950D0(void)
+{
+ switch (sMoveMonsPtr->field_0)
+ {
+ case 0:
+ return sub_8095138();
+ case 1:
+ return sub_8095234();
+ case 2:
+ return sub_80952A0();
+ case 3:
+ return sub_8095314();
+ case 4:
+ return sub_8095394();
+ case 5:
+ return sub_80953BC();
+ }
+
+ return FALSE;
+}
+
+static bool8 sub_8095138(void)
+{
+ switch (sMoveMonsPtr->state)
+ {
+ case 0:
+ HideBg(0);
+ LoadMonIconPalettesAt(0x80);
+ sMoveMonsPtr->state++;
+ break;
+ case 1:
+ sub_8094CD4(&sMoveMonsPtr->fromRow, &sMoveMonsPtr->fromColumn);
+ sMoveMonsPtr->toRow = sMoveMonsPtr->fromRow;
+ sMoveMonsPtr->toColumn = sMoveMonsPtr->fromColumn;
+ ChangeBgX(0, -1024, 0);
+ ChangeBgY(0, -1024, 0);
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x20, 0x20);
+ FillWindowPixelBuffer8Bit(gPSSData->field_2200, PIXEL_FILL(0));
+ sub_80956A4(sMoveMonsPtr->fromRow, sMoveMonsPtr->fromColumn);
+ SetBgAttribute(0, BG_ATTR_PALETTEMODE, 1);
+ PutWindowTilemap(gPSSData->field_2200);
+ CopyWindowToVram8Bit(gPSSData->field_2200, 3);
+ BlendPalettes(0x3F00, 8, RGB_WHITE);
+ sub_8094D14(2);
+ SetGpuRegBits(REG_OFFSET_BG0CNT, BGCNT_256COLOR);
+ sMoveMonsPtr->state++;
+ break;
+ case 2:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_8095234(void)
+{
+ switch (sMoveMonsPtr->state)
+ {
+ case 0:
+ HideBg(0);
+ sMoveMonsPtr->state++;
+ break;
+ case 1:
+ sub_8095A58();
+ sub_8094D14(0);
+ sMoveMonsPtr->state++;
+ break;
+ case 2:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ sub_8094D40();
+ LoadPalette(stdpal_get(3), 0xD0, 0x20);
+ ShowBg(0);
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_80952A0(void)
+{
+ switch (sMoveMonsPtr->state)
+ {
+ case 0:
+ if (!sub_80924A8())
+ {
+ sub_8094CD4(&sMoveMonsPtr->field_6, &sMoveMonsPtr->field_7);
+ sub_8095520();
+ sMoveMonsPtr->toRow = sMoveMonsPtr->field_6;
+ sMoveMonsPtr->toColumn = sMoveMonsPtr->field_7;
+ CopyWindowToVram8Bit(gPSSData->field_2200, 2);
+ sMoveMonsPtr->state++;
+ }
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_8095314(void)
+{
+ u8 var1, var2;
+
+ switch (sMoveMonsPtr->state)
+ {
+ case 0:
+ sub_80957C8();
+ sub_80958A0();
+ sub_8092BAC(FALSE);
+ sMoveMonsPtr->state++;
+ break;
+ case 1:
+ if (!DoMonPlaceChange())
+ {
+ sub_8094D14(3);
+ sub_8095780(0, 256, 8);
+ sub_8092BAC(TRUE);
+ sMoveMonsPtr->state++;
+ }
+ break;
+ case 2:
+ var1 = sub_8095790();
+ var2 = DoMonPlaceChange();
+ if (!var1 && !var2)
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+
+static bool8 sub_8095394(void)
+{
+ u8 var1 = sub_80924A8();
+ u8 var2 = sub_8095790();
+
+ if (!var1 && !var2)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static bool8 sub_80953BC(void)
+{
+ switch (sMoveMonsPtr->state)
+ {
+ case 0:
+ sub_80959A8();
+ sub_8095780(0, -256, 8);
+ sub_8092BAC(FALSE);
+ sMoveMonsPtr->state++;
+ break;
+ case 1:
+ if (!DoMonPlaceChange() && !sub_8095790())
+ {
+ sub_8095918();
+ sub_8094D14(2);
+ sub_8092BAC(TRUE);
+ HideBg(0);
+ sMoveMonsPtr->state++;
+ }
+ break;
+ case 2:
+ if (!DoMonPlaceChange())
+ {
+ sub_8094D14(0);
+ sub_8095A58();
+ sMoveMonsPtr->state++;
+ }
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ LoadPalette(stdpal_get(3), 0xD0, 0x20);
+ sub_8094D40();
+ ShowBg(0);
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+bool8 sub_8095474(u8 arg0)
+{
+ switch (arg0)
+ {
+ case 0: // up
+ if (sMoveMonsPtr->minColumn == 0)
+ return FALSE;
+ sMoveMonsPtr->minColumn--;
+ sub_8095780(0, 1024, 6);
+ break;
+ case 1: // down
+ if (sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal >= 5)
+ return FALSE;
+ sMoveMonsPtr->minColumn++;
+ sub_8095780(0, -1024, 6);
+ break;
+ case 2: // left
+ if (sMoveMonsPtr->minRow == 0)
+ return FALSE;
+ sMoveMonsPtr->minRow--;
+ sub_8095780(1024, 0, 6);
+ break;
+ case 3: // right
+ if (sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal > 5)
+ return FALSE;
+ sMoveMonsPtr->minRow++;
+ sub_8095780(-1024, 0, 6);
+ break;
+ }
+
+ return TRUE;
+}
+
+static void sub_8095520(void)
+{
+ s16 var = (abs(sMoveMonsPtr->fromRow - sMoveMonsPtr->field_6)) - (abs(sMoveMonsPtr->fromRow - sMoveMonsPtr->toRow));
+ s16 var2 = (abs(sMoveMonsPtr->fromColumn - sMoveMonsPtr->field_7)) - (abs(sMoveMonsPtr->fromColumn - sMoveMonsPtr->toColumn));
+
+ if (var > 0)
+ sub_80955C4(sMoveMonsPtr->field_6, sMoveMonsPtr->fromColumn, sMoveMonsPtr->toColumn);
+
+ if (var < 0)
+ {
+ sub_8095634(sMoveMonsPtr->toRow, sMoveMonsPtr->fromColumn, sMoveMonsPtr->toColumn);
+ sub_80955C4(sMoveMonsPtr->field_6, sMoveMonsPtr->fromColumn, sMoveMonsPtr->toColumn);
+ }
+
+ if (var2 > 0)
+ sub_80955FC(sMoveMonsPtr->field_7, sMoveMonsPtr->fromRow, sMoveMonsPtr->toRow);
+
+ if (var2 < 0)
+ {
+ sub_809566C(sMoveMonsPtr->toColumn, sMoveMonsPtr->fromRow, sMoveMonsPtr->toRow);
+ sub_80955FC(sMoveMonsPtr->field_7, sMoveMonsPtr->fromRow, sMoveMonsPtr->toRow);
+ }
+}
+
+static void sub_80955C4(u8 arg0, u8 arg1, u8 arg2)
+{
+ u8 var1 = arg1;
+
+ if (arg1 > arg2)
+ {
+ arg1 = arg2;
+ arg2 = var1;
+ }
+
+ while (arg1 <= arg2)
+ sub_80956A4(arg0, arg1++);
+}
+
+static void sub_80955FC(u8 arg0, u8 arg1, u8 arg2)
+{
+ u8 var1 = arg1;
+
+ if (arg1 > arg2)
+ {
+ arg1 = arg2;
+ arg2 = var1;
+ }
+
+ while (arg1 <= arg2)
+ sub_80956A4(arg1++, arg0);
+}
+
+static void sub_8095634(u8 arg0, u8 arg1, u8 arg2)
+{
+ u8 var1 = arg1;
+
+ if (arg1 > arg2)
+ {
+ arg1 = arg2;
+ arg2 = var1;
+ }
+
+ while (arg1 <= arg2)
+ sub_809572C(arg0, arg1++);
+}
+
+static void sub_809566C(u8 arg0, u8 arg1, u8 arg2)
+{
+ u8 var1 = arg1;
+
+ if (arg1 > arg2)
+ {
+ arg1 = arg2;
+ arg2 = var1;
+ }
+
+ while (arg1 <= arg2)
+ sub_809572C(arg1++, arg0);
+}
+
+static void sub_80956A4(u8 x, u8 y)
+{
+ u8 position = x + (IN_BOX_ROWS * y);
+ u16 species = GetCurrentBoxMonData(position, MON_DATA_SPECIES2);
+ u32 personality = GetCurrentBoxMonData(position, MON_DATA_PERSONALITY);
+
+ if (species != SPECIES_NONE)
+ {
+ const u8 *iconGfx = GetMonIconPtr(species, personality, 1);
+ u8 index = GetValidMonIconPalIndex(species) + 8;
+
+ BlitBitmapRectToWindow4BitTo8Bit(gPSSData->field_2200,
+ iconGfx,
+ 0,
+ 0,
+ 32,
+ 32,
+ 24 * x,
+ 24 * y,
+ 32,
+ 32,
+ index);
+ }
+}
+
+static void sub_809572C(u8 x, u8 y)
+{
+ u8 position = x + (IN_BOX_ROWS * y);
+ u16 species = GetCurrentBoxMonData(position, MON_DATA_SPECIES2);
+
+ if (species != SPECIES_NONE)
+ {
+ FillWindowPixelRect8Bit(gPSSData->field_2200,
+ PIXEL_FILL(0),
+ 24 * x,
+ 24 * y,
+ 32,
+ 32);
+ }
+}
+
+static void sub_8095780(u16 bgX, u16 bgY, u16 duration)
+{
+ sMoveMonsPtr->bgX = bgX;
+ sMoveMonsPtr->bgY = bgY;
+ sMoveMonsPtr->field_10 = duration;
+}
+
+static u8 sub_8095790(void)
+{
+ if (sMoveMonsPtr->field_10 != 0)
+ {
+ ChangeBgX(0, sMoveMonsPtr->bgX, 1);
+ ChangeBgY(0, sMoveMonsPtr->bgY, 1);
+ sMoveMonsPtr->field_10--;
+ }
+
+ return sMoveMonsPtr->field_10;
+}
+
+static void sub_80957C8(void)
+{
+ s32 i, j;
+ s32 rowCount, columnCount;
+ u8 boxId;
+ u8 monArrayId;
+
+ sMoveMonsPtr->minRow = min(sMoveMonsPtr->fromRow, sMoveMonsPtr->toRow);
+ sMoveMonsPtr->minColumn = min(sMoveMonsPtr->fromColumn, sMoveMonsPtr->toColumn);
+ sMoveMonsPtr->rowsTotal = abs(sMoveMonsPtr->fromRow - sMoveMonsPtr->toRow) + 1;
+ sMoveMonsPtr->columsTotal = abs(sMoveMonsPtr->fromColumn - sMoveMonsPtr->toColumn) + 1;
+ boxId = StorageGetCurrentBox();
+ monArrayId = 0;
+ rowCount = sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal;
+ columnCount = sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal;
+ for (i = sMoveMonsPtr->minColumn; i < columnCount; i++)
+ {
+ u8 boxPosition = (IN_BOX_ROWS * i) + sMoveMonsPtr->minRow;
+ for (j = sMoveMonsPtr->minRow; j < rowCount; j++)
+ {
+ struct BoxPokemon *boxMon = GetBoxedMonPtr(boxId, boxPosition);
+
+ sMoveMonsPtr->boxMons[monArrayId] = *boxMon;
+ monArrayId++;
+ boxPosition++;
+ }
+ }
+}
+
+static void sub_80958A0(void)
+{
+ s32 i, j;
+ s32 rowCount = sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal;
+ s32 columnCount = sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal;
+ u8 boxId = StorageGetCurrentBox();
+
+ for (i = sMoveMonsPtr->minColumn; i < columnCount; i++)
+ {
+ u8 boxPosition = (IN_BOX_ROWS * i) + sMoveMonsPtr->minRow;
+ for (j = sMoveMonsPtr->minRow; j < rowCount; j++)
+ {
+ DestroyBoxMonIconAtPosition(boxPosition);
+ ZeroBoxMonAt(boxId, boxPosition);
+ boxPosition++;
+ }
+ }
+}
+
+static void sub_8095918(void)
+{
+ s32 i, j;
+ s32 rowCount = sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal;
+ s32 columnCount = sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal;
+ u8 monArrayId = 0;
+
+ for (i = sMoveMonsPtr->minColumn; i < columnCount; i++)
+ {
+ u8 boxPosition = (IN_BOX_ROWS * i) + sMoveMonsPtr->minRow;
+ for (j = sMoveMonsPtr->minRow; j < rowCount; j++)
+ {
+ if (GetBoxMonData(&sMoveMonsPtr->boxMons[monArrayId], MON_DATA_SANITY_HAS_SPECIES))
+ sub_80901EC(boxPosition);
+ monArrayId++;
+ boxPosition++;
+ }
+ }
+}
+
+static void sub_80959A8(void)
+{
+ s32 i, j;
+ s32 rowCount = sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal;
+ s32 columnCount = sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal;
+ u8 boxId = StorageGetCurrentBox();
+ u8 monArrayId = 0;
+
+ for (i = sMoveMonsPtr->minColumn; i < columnCount; i++)
+ {
+ u8 boxPosition = (IN_BOX_ROWS * i) + sMoveMonsPtr->minRow;
+ for (j = sMoveMonsPtr->minRow; j < rowCount; j++)
+ {
+ if (GetBoxMonData(&sMoveMonsPtr->boxMons[monArrayId], MON_DATA_SANITY_HAS_SPECIES))
+ SetBoxMonAt(boxId, boxPosition, &sMoveMonsPtr->boxMons[monArrayId]);
+ boxPosition++;
+ monArrayId++;
+ }
+ }
+}
+
+static void sub_8095A58(void)
+{
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ SetBgAttribute(0, BG_ATTR_PALETTEMODE, 0);
+ ClearGpuRegBits(REG_OFFSET_BG0CNT, BGCNT_256COLOR);
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32);
+ CopyBgTilemapBufferToVram(0);
+}
+
+u8 sub_8095AA0(void)
+{
+ return (IN_BOX_ROWS * sMoveMonsPtr->fromColumn) + sMoveMonsPtr->fromRow;
+}
+
+bool8 sub_8095ABC(void)
+{
+ s32 i, j;
+ s32 rowCount = sMoveMonsPtr->minRow + sMoveMonsPtr->rowsTotal;
+ s32 columnCount = sMoveMonsPtr->minColumn + sMoveMonsPtr->columsTotal;
+ u8 monArrayId = 0;
+
+ for (i = sMoveMonsPtr->minColumn; i < columnCount; i++)
+ {
+ u8 boxPosition = (IN_BOX_ROWS * i) + sMoveMonsPtr->minRow;
+ for (j = sMoveMonsPtr->minRow; j < rowCount; j++)
+ {
+ if (GetBoxMonData(&sMoveMonsPtr->boxMons[monArrayId], MON_DATA_SANITY_HAS_SPECIES)
+ && GetCurrentBoxMonData(boxPosition, MON_DATA_SANITY_HAS_SPECIES))
+ return FALSE;
+
+ monArrayId++;
+ boxPosition++;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/pokemon_storage_system_8.c b/src/pokemon_storage_system_8.c
new file mode 100644
index 000000000..3e9c27555
--- /dev/null
+++ b/src/pokemon_storage_system_8.c
@@ -0,0 +1,755 @@
+#include "global.h"
+#include "gflib.h"
+#include "decompress.h"
+#include "item.h"
+#include "item_menu_icons.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "pokemon_storage_system_internal.h"
+#include "trig.h"
+#include "constants/items.h"
+
+static u8 sub_80961D8(void);
+static bool32 sub_8096210(u8 cursorArea, u8 cursorPos);
+static u8 sub_8096258(u8 cursorArea, u8 cursorPos);
+static void sub_80962F0(u8 id, u8 cursorArea, u8 cursorPos);
+static void sub_8096408(u8 id, const u32 * tiles, const u32 * pal);
+static void sub_80964B8(u8 id, u8 affineAnimNo);
+static void sub_80964E8(u8 id, u8 command, u8 cursorArea, u8 cursorPos);
+static void sub_8096624(u8 id, bool8 show);
+static const u32 *GetItemIconPic(u16 itemId);
+static const u32 *GetItemIconPalette(u16 itemId);
+static void sub_8096898(u32 x);
+static void sub_809692C(struct Sprite * sprite);
+static void sub_8096958(struct Sprite * sprite);
+static void sub_80969BC(struct Sprite * sprite);
+static void sub_80969F4(struct Sprite * sprite);
+static void sub_8096A74(struct Sprite * sprite);
+static void sub_8096B10(struct Sprite * sprite);
+static void sub_8096BAC(struct Sprite * sprite);
+
+static const u32 gUnknown_83D35DC[] = INCBIN_U32("graphics/interface/pss_unk_83D35DC.4bpp");
+
+static const struct OamData gUnknown_83D365C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(32x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x32),
+ .tileNum = 0x000,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0
+};
+
+static const union AffineAnimCmd gUnknown_83D3664[] = {
+ AFFINEANIMCMD_FRAME(128, 128, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D3674[] = {
+ AFFINEANIMCMD_FRAME(88, 88, 0, 0),
+ AFFINEANIMCMD_FRAME(5, 5, 0, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D368C[] = {
+ AFFINEANIMCMD_FRAME(128, 128, 0, 0),
+ AFFINEANIMCMD_FRAME(-5, -5, 0, 8),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D36A4[] = {
+ AFFINEANIMCMD_FRAME(128, 128, 0, 0),
+ AFFINEANIMCMD_FRAME(10, 10, 0, 12),
+ AFFINEANIMCMD_FRAME(256, 256, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D36C4[] = {
+ AFFINEANIMCMD_FRAME(256, 256, 0, 0),
+ AFFINEANIMCMD_FRAME(-10, -10, 0, 12),
+ AFFINEANIMCMD_FRAME(128, 128, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D36E4[] = {
+ AFFINEANIMCMD_FRAME(256, 256, 0, 0),
+ AFFINEANIMCMD_FRAME(-5, -5, 0, 16),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D36FC[] = {
+ AFFINEANIMCMD_FRAME(256, 256, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const gUnknown_83D370C[] = {
+ gUnknown_83D3664,
+ gUnknown_83D3674,
+ gUnknown_83D368C,
+ gUnknown_83D36A4,
+ gUnknown_83D36C4,
+ gUnknown_83D36E4,
+ gUnknown_83D36FC
+};
+
+static const struct SpriteTemplate gUnknown_83D3728 = {
+ .tileTag = TAG_TILE_7,
+ .paletteTag = TAG_PAL_DACB,
+ .oam = &gUnknown_83D365C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gUnknown_83D370C,
+ .callback = SpriteCallbackDummy,
+};
+
+void sub_8095B5C(void)
+{
+ s32 i;
+ u8 spriteId;
+ struct CompressedSpriteSheet spriteSheet;
+ struct SpriteTemplate spriteTemplate;
+ static u32 gUnknown_3000FE8[0x61];
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ spriteSheet.data = gUnknown_3000FE8;
+ spriteSheet.size = 0x200;
+ spriteTemplate = gUnknown_83D3728;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ spriteSheet.tag = TAG_TILE_7 + i;
+ LoadCompressedSpriteSheet(&spriteSheet);
+ gPSSData->itemIconSprites[i].tiles = GetSpriteTileStartByTag(spriteSheet.tag) * 32 + (void*)(OBJ_VRAM0);
+ gPSSData->itemIconSprites[i].palIndex = AllocSpritePalette(TAG_PAL_DACB + i);
+ gPSSData->itemIconSprites[i].palIndex *= 16;
+ gPSSData->itemIconSprites[i].palIndex += 0x100;
+ spriteTemplate.tileTag = TAG_TILE_7 + i;
+ spriteTemplate.paletteTag = TAG_PAL_DACB + i;
+ spriteId = CreateSprite(&spriteTemplate, 0, 0, 11);
+ gPSSData->itemIconSprites[i].sprite = &gSprites[spriteId];
+ gPSSData->itemIconSprites[i].sprite->invisible = TRUE;
+ gPSSData->itemIconSprites[i].active = 0;
+ }
+ }
+ gPSSData->movingItem = ITEM_NONE;
+}
+
+void sub_8095C84(u8 cursorArea, u8 cursorPos)
+{
+ u16 heldItem;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+ if (sub_8096210(cursorArea, cursorPos))
+ return;
+
+ switch (cursorArea)
+ {
+ case CURSOR_AREA_IN_BOX:
+ if (!GetCurrentBoxMonData(cursorPos, MON_DATA_SANITY_HAS_SPECIES))
+ return;
+ heldItem = GetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM);
+ break;
+ case CURSOR_AREA_IN_PARTY:
+ if (!GetMonData(&gPlayerParty[cursorPos], MON_DATA_SANITY_HAS_SPECIES))
+ return;
+ heldItem = GetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM);
+ break;
+ default:
+ return;
+ }
+
+ if (heldItem != ITEM_NONE)
+ {
+ const u32 *tiles = GetItemIconPic(heldItem);
+ const u32 *pal = GetItemIconPalette(heldItem);
+ u8 id = sub_80961D8();
+
+ sub_80962F0(id, cursorArea, cursorPos);
+ sub_8096408(id, tiles, pal);
+ sub_80964B8(id, 1);
+ sub_8096624(id, TRUE);
+ }
+}
+
+void sub_8095D44(u8 cursorArea, u8 cursorPos)
+{
+ u8 id;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ id = sub_8096258(cursorArea, cursorPos);
+ sub_80964B8(id, 2);
+ sub_80964E8(id, 0, cursorArea, cursorPos);
+}
+
+void Item_FromMonToMoving(u8 cursorArea, u8 cursorPos)
+{
+ u8 id;
+ u16 item;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ id = sub_8096258(cursorArea, cursorPos);
+ item = 0;
+ sub_80964B8(id, 3);
+ sub_80964E8(id, 1, cursorArea, cursorPos);
+ sub_80962F0(id, 2, 0);
+ if (cursorArea == CURSOR_AREA_IN_BOX)
+ {
+ SetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM, &item);
+ SetBoxMonIconObjMode(cursorPos, ST_OAM_OBJ_BLEND);
+ }
+ else
+ {
+ SetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM, &item);
+ SetPartyMonIconObjMode(cursorPos, ST_OAM_OBJ_BLEND);
+ }
+
+ gPSSData->movingItem = gPSSData->cursorMonItem;
+}
+
+void sub_8095E2C(u16 item)
+{
+ const u32 *tiles = GetItemIconPic(item);
+ const u32 *pal = GetItemIconPalette(item);
+ u8 id = sub_80961D8();
+
+ sub_8096408(id, tiles, pal);
+ sub_80964B8(id, 6);
+ sub_80964E8(id, 1, CURSOR_AREA_IN_BOX, 0);
+ sub_80962F0(id, CURSOR_AREA_BOX, 0);
+ sub_8096624(id, TRUE);
+ gPSSData->movingItem = item;
+}
+
+void Item_SwitchMonsWithMoving(u8 cursorArea, u8 cursorPos)
+{
+ u8 id;
+ u16 item;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ id = sub_8096258(cursorArea, cursorPos);
+ sub_80964B8(id, 3);
+ sub_80964E8(id, 3, CURSOR_AREA_BOX, 0);
+ if (cursorArea == CURSOR_AREA_IN_BOX)
+ {
+ item = GetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM);
+ SetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM, &gPSSData->movingItem);
+ gPSSData->movingItem = item;
+ }
+ else
+ {
+ item = GetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM);
+ SetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM, &gPSSData->movingItem);
+ gPSSData->movingItem = item;
+ }
+
+ id = sub_8096258(2, 0);
+ sub_80964B8(id, 4);
+ sub_80964E8(id, 4, cursorArea, cursorPos);
+}
+
+void Item_GiveMovingToMon(u8 cursorArea, u8 cursorPos)
+{
+ u8 id;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ id = sub_8096258(2, 0);
+ sub_80964B8(id, 4);
+ sub_80964E8(id, 2, cursorArea, cursorPos);
+ if (cursorArea == CURSOR_AREA_IN_BOX)
+ {
+ SetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM, &gPSSData->movingItem);
+ SetBoxMonIconObjMode(cursorPos, ST_OAM_OBJ_NORMAL);
+ }
+ else
+ {
+ SetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM, &gPSSData->movingItem);
+ SetPartyMonIconObjMode(cursorPos, ST_OAM_OBJ_NORMAL);
+ }
+}
+
+void Item_TakeMons(u8 cursorArea, u8 cursorPos)
+{
+ u8 id;
+ u16 item;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ item = 0;
+ id = sub_8096258(cursorArea, cursorPos);
+ sub_80964B8(id, 2);
+ sub_80964E8(id, 0, cursorArea, cursorPos);
+ if (cursorArea == CURSOR_AREA_IN_BOX)
+ {
+ SetCurrentBoxMonData(cursorPos, MON_DATA_HELD_ITEM, &item);
+ SetBoxMonIconObjMode(cursorPos, ST_OAM_OBJ_BLEND);
+ }
+ else
+ {
+ SetMonData(&gPlayerParty[cursorPos], MON_DATA_HELD_ITEM, &item);
+ SetPartyMonIconObjMode(cursorPos, ST_OAM_OBJ_BLEND);
+ }
+}
+
+void sub_8096088(void)
+{
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ u8 id = sub_8096258(2, 0);
+ sub_80964B8(id, 5);
+ sub_80964E8(id, 0, CURSOR_AREA_BOX, 0);
+ }
+}
+
+void sub_80960C0(void)
+{
+ s32 i;
+
+ if (gPSSData->boxOption != BOX_OPTION_MOVE_ITEMS)
+ return;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active && gPSSData->itemIconSprites[i].cursorArea == CURSOR_AREA_IN_PARTY)
+ sub_80964E8(i, 7, CURSOR_AREA_BOX, 0);
+ }
+}
+
+bool8 sub_809610C(void)
+{
+ s32 i;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active)
+ {
+ if (!gPSSData->itemIconSprites[i].sprite->affineAnimEnded && gPSSData->itemIconSprites[i].sprite->affineAnimBeginning)
+ return TRUE;
+ if (gPSSData->itemIconSprites[i].sprite->callback != SpriteCallbackDummy && gPSSData->itemIconSprites[i].sprite->callback != sub_80969BC)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool8 IsActiveItemMoving(void)
+{
+ s32 i;
+
+ if (gPSSData->boxOption == BOX_OPTION_MOVE_ITEMS)
+ {
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active && gPSSData->itemIconSprites[i].cursorArea == CURSOR_AREA_BOX)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+const u8 *GetMovingItemName(void)
+{
+ return ItemId_GetName(gPSSData->movingItem);
+}
+
+u16 GetMovingItem(void)
+{
+ return gPSSData->movingItem;
+}
+
+static u8 sub_80961D8(void)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (!gPSSData->itemIconSprites[i].active)
+ {
+ gPSSData->itemIconSprites[i].active = TRUE;
+ return i;
+ }
+ }
+
+ return MAX_ITEM_ICONS;
+}
+
+static bool32 sub_8096210(u8 cursorArea, u8 cursorPos)
+{
+ s32 i;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active
+ && gPSSData->itemIconSprites[i].cursorArea == cursorArea
+ && gPSSData->itemIconSprites[i].cursorPos == cursorPos)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static u8 sub_8096258(u8 cursorArea, u8 cursorPos)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active
+ && gPSSData->itemIconSprites[i].cursorArea == cursorArea
+ && gPSSData->itemIconSprites[i].cursorPos == cursorPos)
+ return i;
+ }
+
+ return MAX_ITEM_ICONS;
+}
+
+static u8 sub_80962A8(struct Sprite *sprite)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_ITEM_ICONS; i++)
+ {
+ if (gPSSData->itemIconSprites[i].active
+ && gPSSData->itemIconSprites[i].sprite == sprite)
+ return i;
+ }
+
+ return MAX_ITEM_ICONS;
+}
+
+static void sub_80962F0(u8 id, u8 cursorArea, u8 cursorPos)
+{
+ u8 row, column;
+
+ if (id >= MAX_ITEM_ICONS)
+ return;
+
+ switch (cursorArea)
+ {
+ case CURSOR_AREA_IN_BOX:
+ row = cursorPos % IN_BOX_ROWS;
+ column = cursorPos / IN_BOX_ROWS;
+ gPSSData->itemIconSprites[id].sprite->pos1.x = (24 * row) + 112;
+ gPSSData->itemIconSprites[id].sprite->pos1.y = (24 * column) + 56;
+ gPSSData->itemIconSprites[id].sprite->oam.priority = 2;
+ break;
+ case CURSOR_AREA_IN_PARTY:
+ if (cursorPos == 0)
+ {
+ gPSSData->itemIconSprites[id].sprite->pos1.x = 116;
+ gPSSData->itemIconSprites[id].sprite->pos1.y = 76;
+ }
+ else
+ {
+ gPSSData->itemIconSprites[id].sprite->pos1.x = 164;
+ gPSSData->itemIconSprites[id].sprite->pos1.y = 24 * (cursorPos - 1) + 28;
+ }
+ gPSSData->itemIconSprites[id].sprite->oam.priority = 1;
+ break;
+ }
+
+ gPSSData->itemIconSprites[id].cursorArea = cursorArea;
+ gPSSData->itemIconSprites[id].cursorPos = cursorPos;
+}
+
+static void sub_8096408(u8 id, const u32 *itemTiles, const u32 *itemPal)
+{
+ s32 i;
+
+ if (id >= MAX_ITEM_ICONS)
+ return;
+
+ CpuFastFill(0, gPSSData->field_42C4, 0x200);
+ LZ77UnCompWram(itemTiles, gPSSData->field_22C4);
+ for (i = 0; i < 3; i++)
+ CpuFastCopy(gPSSData->field_22C4 + (i * 0x60), gPSSData->field_42C4 + (i * 0x80), 0x60);
+
+ CpuFastCopy(gPSSData->field_42C4, gPSSData->itemIconSprites[id].tiles, 0x200);
+ LZ77UnCompWram(itemPal, gPSSData->field_42C4);
+ LoadPalette(gPSSData->field_42C4, gPSSData->itemIconSprites[id].palIndex, 0x20);
+}
+
+static void sub_80964B8(u8 id, u8 animNum)
+{
+ if (id >= MAX_ITEM_ICONS)
+ return;
+
+ StartSpriteAffineAnim(gPSSData->itemIconSprites[id].sprite, animNum);
+}
+
+static void sub_80964E8(u8 id, u8 command, u8 cursorArea, u8 cursorPos)
+{
+ if (id >= MAX_ITEM_ICONS)
+ return;
+
+ switch (command)
+ {
+ case 0:
+ gPSSData->itemIconSprites[id].sprite->data[0] = id;
+ gPSSData->itemIconSprites[id].sprite->callback = sub_809692C;
+ break;
+ case 1:
+ gPSSData->itemIconSprites[id].sprite->data[0] = 0;
+ gPSSData->itemIconSprites[id].sprite->callback = sub_8096958;
+ break;
+ case 2:
+ gPSSData->itemIconSprites[id].sprite->data[0] = 0;
+ gPSSData->itemIconSprites[id].sprite->data[6] = cursorArea;
+ gPSSData->itemIconSprites[id].sprite->data[7] = cursorPos;
+ gPSSData->itemIconSprites[id].sprite->callback = sub_80969F4;
+ break;
+ case 3:
+ gPSSData->itemIconSprites[id].sprite->data[0] = 0;
+ gPSSData->itemIconSprites[id].sprite->callback = sub_8096A74;
+ gPSSData->itemIconSprites[id].sprite->data[6] = cursorArea;
+ gPSSData->itemIconSprites[id].sprite->data[7] = cursorPos;
+ break;
+ case 4:
+ gPSSData->itemIconSprites[id].sprite->data[0] = 0;
+ gPSSData->itemIconSprites[id].sprite->data[6] = cursorArea;
+ gPSSData->itemIconSprites[id].sprite->data[7] = cursorPos;
+ gPSSData->itemIconSprites[id].sprite->callback = sub_8096B10;
+ break;
+ case 7:
+ gPSSData->itemIconSprites[id].sprite->callback = sub_8096BAC;
+ break;
+ }
+}
+
+static void sub_8096624(u8 id, bool8 show)
+{
+ if (id >= MAX_ITEM_ICONS)
+ return;
+
+ gPSSData->itemIconSprites[id].active = show;
+ gPSSData->itemIconSprites[id].sprite->invisible = (show == FALSE);
+}
+
+static const u32 *GetItemIconPic(u16 itemId)
+{
+ return GetItemIconGfxPtr(itemId, 0);
+}
+
+static const u32 *GetItemIconPalette(u16 itemId)
+{
+ return GetItemIconGfxPtr(itemId, 1);
+}
+
+void PrintItemDescription(void)
+{
+ const u8 *description;
+
+ if (IsActiveItemMoving())
+ description = ItemId_GetDescription(gPSSData->movingItem);
+ else
+ description = ItemId_GetDescription(gPSSData->cursorMonItem);
+
+ FillWindowPixelBuffer(2, PIXEL_FILL(1));
+ AddTextPrinterParameterized5(2, 2, description, 2, 0, 0, NULL, 0, 0);
+}
+
+void sub_80966F4(void)
+{
+ gPSSData->field_2236 = 25;
+ LoadBgTiles(0, gUnknown_83D35DC, 0x80, 0x1A4);
+ sub_8096898(0);
+}
+
+bool8 sub_8096728(void)
+{
+ s32 i, var;
+
+ if (gPSSData->field_2236 == 0)
+ return FALSE;
+
+ gPSSData->field_2236--;
+ var = 25 - gPSSData->field_2236;
+ for (i = 0; i < var; i++)
+ {
+ WriteSequenceToBgTilemapBuffer(0, GetBgAttribute(0, BG_ATTR_BASETILE) + 0x14 + gPSSData->field_2236 + i, i, 12, 1, 8, 15, 25);
+ }
+
+ sub_8096898(var);
+ return (gPSSData->field_2236 != 0);
+}
+
+bool8 sub_80967C0(void)
+{
+ s32 i, var;
+
+ if (gPSSData->field_2236 == 25)
+ return FALSE;
+
+ if (gPSSData->field_2236 == 0)
+ FillBgTilemapBufferRect(0, 0, 25, 11, 1, 10, 17);
+
+ gPSSData->field_2236++;
+ var = 25 - gPSSData->field_2236;
+ for (i = 0; i < var; i++)
+ {
+ WriteSequenceToBgTilemapBuffer(0, GetBgAttribute(0, BG_ATTR_BASETILE) + 0x14 + gPSSData->field_2236 + i, i, 12, 1, 8, 15, 25);
+ }
+
+ sub_8096898(var);
+
+ FillBgTilemapBufferRect(0, 0, var, 11, 1, 10, 0x11);
+ return (gPSSData->field_2236 != 25);
+}
+
+static void sub_8096898(u32 x)
+{
+ if (x != 0)
+ {
+ FillBgTilemapBufferRect(0, 0x1A4, 0, 0xB, x, 1, 0xFu);
+ FillBgTilemapBufferRect(0, 0x9A4, 0, 0x14, x, 1, 0xFu);
+ }
+ FillBgTilemapBufferRect(0, 0x1A5, x, 0xC, 1, 8, 0xFu);
+ FillBgTilemapBufferRect(0, 0x1A6, x, 0xB, 1, 1, 0xFu);
+ FillBgTilemapBufferRect(0, 0x1A7, x, 0x14, 1, 1, 0xFu);
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void sub_809692C(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ sub_8096624(sprite->data[0], FALSE);
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+static void sub_8096958(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->data[1] = sprite->pos1.x << 4;
+ sprite->data[2] = sprite->pos1.y << 4;
+ sprite->data[3] = 10;
+ sprite->data[4] = 21;
+ sprite->data[5] = 0;
+ sprite->data[0]++;
+ case 1:
+ sprite->data[1] -= sprite->data[3];
+ sprite->data[2] -= sprite->data[4];
+ sprite->pos1.x = sprite->data[1] >> 4;
+ sprite->pos1.y = sprite->data[2] >> 4;
+ if (++sprite->data[5] > 11)
+ sprite->callback = sub_80969BC;
+ break;
+ }
+}
+
+static void sub_80969BC(struct Sprite *sprite)
+{
+ sprite->pos1.x = gPSSData->field_CB4->pos1.x + 4;
+ sprite->pos1.y = gPSSData->field_CB4->pos1.y + gPSSData->field_CB4->pos2.y + 8;
+ sprite->oam.priority = gPSSData->field_CB4->oam.priority;
+}
+
+static void sub_80969F4(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->data[1] = sprite->pos1.x << 4;
+ sprite->data[2] = sprite->pos1.y << 4;
+ sprite->data[3] = 10;
+ sprite->data[4] = 21;
+ sprite->data[5] = 0;
+ sprite->data[0]++;
+ case 1:
+ sprite->data[1] += sprite->data[3];
+ sprite->data[2] += sprite->data[4];
+ sprite->pos1.x = sprite->data[1] >> 4;
+ sprite->pos1.y = sprite->data[2] >> 4;
+ if (++sprite->data[5] > 11)
+ {
+ sub_80962F0(sub_80962A8(sprite), sprite->data[6], sprite->data[7]);
+ sprite->callback = SpriteCallbackDummy;
+ }
+ break;
+ }
+}
+
+static void sub_8096A74(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->data[1] = sprite->pos1.x << 4;
+ sprite->data[2] = sprite->pos1.y << 4;
+ sprite->data[3] = 10;
+ sprite->data[4] = 21;
+ sprite->data[5] = 0;
+ sprite->data[0]++;
+ case 1:
+ sprite->data[1] -= sprite->data[3];
+ sprite->data[2] -= sprite->data[4];
+ sprite->pos1.x = sprite->data[1] >> 4;
+ sprite->pos1.y = sprite->data[2] >> 4;
+ sprite->pos2.x = gSineTable[sprite->data[5] * 8] >> 4;
+ if (++sprite->data[5] > 11)
+ {
+ sub_80962F0(sub_80962A8(sprite), sprite->data[6], sprite->data[7]);
+ sprite->pos2.x = 0;
+ sprite->callback = sub_80969BC;
+ }
+ break;
+ }
+}
+
+static void sub_8096B10(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->data[1] = sprite->pos1.x << 4;
+ sprite->data[2] = sprite->pos1.y << 4;
+ sprite->data[3] = 10;
+ sprite->data[4] = 21;
+ sprite->data[5] = 0;
+ sprite->data[0]++;
+ case 1:
+ sprite->data[1] += sprite->data[3];
+ sprite->data[2] += sprite->data[4];
+ sprite->pos1.x = sprite->data[1] >> 4;
+ sprite->pos1.y = sprite->data[2] >> 4;
+ sprite->pos2.x = -(gSineTable[sprite->data[5] * 8] >> 4);
+ if (++sprite->data[5] > 11)
+ {
+ sub_80962F0(sub_80962A8(sprite), sprite->data[6], sprite->data[7]);
+ sprite->callback = SpriteCallbackDummy;
+ sprite->pos2.x = 0;
+ }
+ break;
+ }
+}
+
+static void sub_8096BAC(struct Sprite *sprite)
+{
+ sprite->pos1.y -= 8;
+ if (sprite->pos1.y + sprite->pos2.y < -16)
+ {
+ sprite->callback = SpriteCallbackDummy;
+ sub_8096624(sub_80962A8(sprite), FALSE);
+ }
+}
diff --git a/src/pokemon_storage_system_9.c b/src/pokemon_storage_system_9.c
new file mode 100644
index 000000000..42fecfd97
--- /dev/null
+++ b/src/pokemon_storage_system_9.c
@@ -0,0 +1,87 @@
+#include "global.h"
+#include "gflib.h"
+#include "pokemon_storage_system_internal.h"
+
+static EWRAM_DATA struct UnkStruct_2000020 *gUnknown_203982C = NULL;
+
+static void sub_8096CDC(struct UnkStruct_2000028 *unkStruct);
+static void sub_8096D70(struct UnkStruct_2000028 *unkStruct);
+
+void sub_8096BE4(struct UnkStruct_2000020 *arg0, struct UnkStruct_2000028 *arg1, u32 arg2)
+{
+ gUnknown_203982C = arg0;
+ arg0->unk_00 = arg1;
+ arg0->unk_05 = arg2;
+ arg0->unk_04 = 0;
+}
+
+void sub_8096BF8(void)
+{
+ u16 i;
+
+ if (gUnknown_203982C->unk_04)
+ {
+ for (i = 0; i < gUnknown_203982C->unk_04; i++)
+ {
+ struct UnkStruct_2000028 *unkStruct = &gUnknown_203982C->unk_00[i];
+ unkStruct->unk_0c(unkStruct);
+ }
+
+ gUnknown_203982C->unk_04 = 0;
+ }
+}
+
+static bool8 sub_8096C40(u8 *dest, u16 dLeft, u16 dTop, const u8 *src, u16 sLeft, u16 sTop, u16 width, u16 height, u16 unkArg)
+{
+ struct UnkStruct_2000028 *unkStruct;
+
+ if (gUnknown_203982C->unk_04 >= gUnknown_203982C->unk_05)
+ return FALSE;
+
+ unkStruct = &gUnknown_203982C->unk_00[gUnknown_203982C->unk_04++];
+ unkStruct->unk_08 = width * 2;
+ unkStruct->unk_04 = dest + 2 * (dTop * 32 + dLeft);
+ unkStruct->unk_00 = src + 2 * (sTop * unkArg + sLeft);
+ unkStruct->newField = height;
+ unkStruct->unk_0a = unkArg;
+ unkStruct->unk_0c = sub_8096CDC;
+ return TRUE;
+}
+
+static void sub_8096CDC(struct UnkStruct_2000028 *unkStruct)
+{
+ u16 i;
+
+ for (i = 0; i < unkStruct->newField; i++)
+ {
+ CpuCopy16(unkStruct->unk_00, unkStruct->unk_04, unkStruct->unk_08);
+ unkStruct->unk_04 += 64;
+ unkStruct->unk_00 += (unkStruct->unk_0a * 2);
+ }
+}
+
+static bool8 sub_8096D14(void *dest, u16 dLeft, u16 dTop, u16 width, u16 height)
+{
+ struct UnkStruct_2000028 *unkStruct;
+
+ if (gUnknown_203982C->unk_04 >= gUnknown_203982C->unk_05)
+ return FALSE;
+
+ unkStruct = &gUnknown_203982C->unk_00[gUnknown_203982C->unk_04++];
+ unkStruct->unk_08 = width * 2;
+ unkStruct->unk_04 = dest + ((dTop * 32) + dLeft) * 2;
+ unkStruct->newField = height;
+ unkStruct->unk_0c = sub_8096D70;
+ return TRUE;
+}
+
+static void sub_8096D70(struct UnkStruct_2000028 *unkStruct)
+{
+ u16 i;
+
+ for (i = 0; i < unkStruct->newField; i++)
+ {
+ Dma3FillLarge_(0, unkStruct->unk_04, unkStruct->unk_08, 16);
+ unkStruct->unk_04 += 64;
+ }
+}
diff --git a/src/quest_log.c b/src/quest_log.c
index 91c07223e..bc8e67a6b 100644
--- a/src/quest_log.c
+++ b/src/quest_log.c
@@ -752,7 +752,7 @@ void sub_8111438(void)
{
for (r3 = 0; r3 < 5; r3++)
{
- sub_808BCB4(0, r3);
+ ZeroBoxMonAt(0, r3);
}
for (r3 = r5; r3 < r9->sanePartyCount; r3++)
{
@@ -767,9 +767,9 @@ void sub_8111438(void)
{
for (r6 = 0; r6 < 30; r6++)
{
- if (GetBoxMonDataFromAnyBox(r3, r6, MON_DATA_SANITY_HAS_SPECIES))
+ if (GetBoxMonDataAt(r3, r6, MON_DATA_SANITY_HAS_SPECIES))
{
- sub_808BCB4(r3, r6);
+ ZeroBoxMonAt(r3, r6);
r5--;
if (r5 == r9->saneBoxesCount)
break;
@@ -832,7 +832,7 @@ static u16 QuestLog_GetSaneBoxCount(void)
{
for (j = 0; j < IN_BOX_COUNT; j++)
{
- if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SANITY_HAS_SPECIES))
+ if (GetBoxMonDataAt(i, j, MON_DATA_SANITY_HAS_SPECIES))
count++;
}
}
diff --git a/src/string_util.c b/src/string_util.c
index 4c1106df8..0a2365d25 100644
--- a/src/string_util.c
+++ b/src/string_util.c
@@ -532,11 +532,11 @@ u8 *StringFillWithTerminator(u8 *dest, u16 n)
return StringFill(dest, EOS, n);
}
-u8 *StringCopyN_Multibyte(u8 *dest, u8 *src, u32 n)
+u8 *StringCopyN_Multibyte(u8 *dest, const u8 *src, u32 n)
{
u32 i;
- for (i = n - 1; i != (u32)-1; i--)
+ for (i = n - 1; i != -1u; i--)
{
if (*src == EOS)
{
@@ -554,7 +554,7 @@ u8 *StringCopyN_Multibyte(u8 *dest, u8 *src, u32 n)
return dest;
}
-u32 StringLength_Multibyte(u8 *str)
+u32 StringLength_Multibyte(const u8 *str)
{
u32 length = 0;
diff --git a/src/strings.c b/src/strings.c
index f5040838a..faf42c86a 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -601,87 +601,87 @@ const u8 gString_BattleRecords_4Dashes[] = _("----");
const u8 gFameCheckerText_FameCheckerWillBeClosed[] = _("The FAME CHECKER will be closed.");
const u8 gFameCheckerText_ClearTextbox[] = _("\n ");
const u8 gUnknown_8418204[] = _("やめる");
-const u8 gUnknown_8418208[] = _("Exit from the BOX.");
-const u8 gUnknown_841821B[] = _("What do you want to do?");
-const u8 gUnknown_8418233[] = _("Please pick a theme.");
-const u8 gUnknown_8418248[] = _("Pick the wallpaper.");
-const u8 gUnknown_841825C[] = _("{DYNAMIC 0x00} is selected.");
-const u8 gUnknown_841826C[] = _("Jump to which BOX?");
-const u8 gUnknown_841827F[] = _("Deposit in which BOX?");
-const u8 gUnknown_8418295[] = _("{DYNAMIC 0x00} was deposited.");
-const u8 gUnknown_84182A7[] = _("The BOX is full.");
-const u8 gUnknown_84182B8[] = _("Release this POKéMON?");
-const u8 gUnknown_84182CE[] = _("{DYNAMIC 0x00} was released.");
-const u8 gUnknown_84182DF[] = _("Bye-bye, {DYNAMIC 0x00}!");
-const u8 gUnknown_84182EC[] = _("Mark your POKéMON.");
-const u8 gUnknown_84182FF[] = _("That's your last POKéMON!");
-const u8 gUnknown_8418319[] = _("Your party's full!");
-const u8 gUnknown_841832C[] = _("You're holding a POKéMON!");
-const u8 gUnknown_8418346[] = _("Which one will you take?");
-const u8 gUnknown_841835F[] = _("You can't release an EGG.");
-const u8 gUnknown_8418379[] = _("Continue BOX operations?");
-const u8 gUnknown_8418392[] = _("{DYNAMIC 0x00} came back!");
-const u8 gUnknown_84183A0[] = _("Was it worried about you?");
-const u8 gUnknown_84183BA[] = _("‥ ‥ ‥ ‥ ‥!");
-const u8 gUnknown_84183C5[] = _("Please remove the MAIL.");
-const u8 gUnknown_84183DD[] = _("GIVE to a POKéMON?");
-const u8 gUnknown_84183F0[] = _("Placed item in the BAG.");
-const u8 gUnknown_8418408[] = _("The BAG is full.");
-const u8 gUnknown_8418419[] = _("Put this item in the BAG?");
-const u8 gUnknown_8418433[] = _("{DYNAMIC 0x00} is now held.");
-const u8 gUnknown_8418443[] = _("Changed to {DYNAMIC 0x00}.");
-const u8 gUnknown_8418452[] = _("MAIL can't be stored!");
-const u8 gUnknown_8418468[] = _("CANCEL");
-const u8 gUnknown_841846F[] = _("STORE");
-const u8 gUnknown_8418475[] = _("WITHDRAW");
-const u8 gUnknown_841847E[] = _("SHIFT");
-const u8 gUnknown_8418484[] = _("MOVE");
-const u8 gUnknown_8418489[] = _("PLACE");
-const u8 gUnknown_841848F[] = _("SUMMARY");
-const u8 gUnknown_8418497[] = _("RELEASE");
-const u8 gUnknown_841849F[] = _("MARK");
-const u8 gUnknown_84184A4[] = _("NAME");
-const u8 gUnknown_84184A9[] = _("JUMP");
-const u8 gUnknown_84184AE[] = _("WALLPAPER");
-const u8 gUnknown_84184B8[] = _("TAKE");
-const u8 gUnknown_84184BD[] = _("GIVE");
-const u8 gUnknown_84184C2[] = _("SWITCH");
-const u8 gUnknown_84184C9[] = _("BAG");
-const u8 gUnknown_84184CD[] = _("INFO");
-const u8 gUnknown_84184D2[] = _("SCENERY 1");
-const u8 gUnknown_84184DC[] = _("SCENERY 2");
-const u8 gUnknown_84184E6[] = _("SCENERY 3");
-const u8 gUnknown_84184F0[] = _("ETCETERA");
-const u8 gUnknown_84184F9[] = _("FOREST");
-const u8 gUnknown_8418500[] = _("CITY");
-const u8 gUnknown_8418505[] = _("DESERT");
-const u8 gUnknown_841850C[] = _("SAVANNA");
-const u8 gUnknown_8418514[] = _("CRAG");
-const u8 gUnknown_8418519[] = _("VOLCANO");
-const u8 gUnknown_8418521[] = _("SNOW");
-const u8 gUnknown_8418526[] = _("CAVE");
-const u8 gUnknown_841852B[] = _("BEACH");
-const u8 gUnknown_8418531[] = _("SEAFLOOR");
-const u8 gUnknown_841853A[] = _("RIVER");
-const u8 gUnknown_8418540[] = _("SKY");
-const u8 gUnknown_8418544[] = _("STARS");
-const u8 gUnknown_841854A[] = _("POKéCENTER");
-const u8 gUnknown_8418555[] = _("TILES");
-const u8 gUnknown_841855B[] = _("SIMPLE");
+const u8 gText_ExitFromBox[] = _("Exit from the BOX.");
+const u8 gText_WhatDoYouWantToDo[] = _("What do you want to do?");
+const u8 gText_PleasePickATheme[] = _("Please pick a theme.");
+const u8 gText_PickTheWallpaper[] = _("Pick the wallpaper.");
+const u8 gText_PkmnIsSelected[] = _("{DYNAMIC 0x00} is selected.");
+const u8 gText_JumpToWhichBox[] = _("Jump to which BOX?");
+const u8 gText_DepositInWhichBox[] = _("Deposit in which BOX?");
+const u8 gText_PkmnWasDeposited[] = _("{DYNAMIC 0x00} was deposited.");
+const u8 gText_BoxIsFull2[] = _("The BOX is full.");
+const u8 gText_ReleaseThisPokemon[] = _("Release this POKéMON?");
+const u8 gText_PkmnWasReleased[] = _("{DYNAMIC 0x00} was released.");
+const u8 gText_ByeByePkmn[] = _("Bye-bye, {DYNAMIC 0x00}!");
+const u8 gText_MarkYourPkmn[] = _("Mark your POKéMON.");
+const u8 gText_ThatsYourLastPkmn[] = _("That's your last POKéMON!");
+const u8 gText_YourPartysFull[] = _("Your party's full!");
+const u8 gText_YoureHoldingAPkmn[] = _("You're holding a POKéMON!");
+const u8 gText_WhichOneWillYouTake[] = _("Which one will you take?");
+const u8 gText_YouCantReleaseAnEgg[] = _("You can't release an EGG.");
+const u8 gText_ContinueBoxOperations[] = _("Continue BOX operations?");
+const u8 gText_PkmnCameBack[] = _("{DYNAMIC 0x00} came back!");
+const u8 gText_WasItWorriedAboutYou[] = _("Was it worried about you?");
+const u8 gText_FourEllipsesExclamation[] = _("‥ ‥ ‥ ‥ ‥!");
+const u8 gText_PleaseRemoveTheMail[] = _("Please remove the MAIL.");
+const u8 gText_GiveToAPkmn[] = _("GIVE to a POKéMON?");
+const u8 gText_PlacedItemInBag[] = _("Placed item in the BAG.");
+const u8 gText_BagIsFull2[] = _("The BAG is full.");
+const u8 gText_PutItemInBag[] = _("Put this item in the BAG?");
+const u8 gText_ItemIsNowHeld[] = _("{DYNAMIC 0x00} is now held.");
+const u8 gText_ChangedToNewItem[] = _("Changed to {DYNAMIC 0x00}.");
+const u8 gText_MailCantBeStored[] = _("MAIL can't be stored!");
+const u8 gPCText_Cancel[] = _("CANCEL");
+const u8 gPCText_Store[] = _("STORE");
+const u8 gPCText_Withdraw[] = _("WITHDRAW");
+const u8 gPCText_Shift[] = _("SHIFT");
+const u8 gPCText_Move[] = _("MOVE");
+const u8 gPCText_Place[] = _("PLACE");
+const u8 gPCText_Summary[] = _("SUMMARY");
+const u8 gPCText_Release[] = _("RELEASE");
+const u8 gPCText_Mark[] = _("MARK");
+const u8 gPCText_Name[] = _("NAME");
+const u8 gPCText_Jump[] = _("JUMP");
+const u8 gPCText_Wallpaper[] = _("WALLPAPER");
+const u8 gPCText_Take[] = _("TAKE");
+const u8 gPCText_Give[] = _("GIVE");
+const u8 gPCText_Switch[] = _("SWITCH");
+const u8 gPCText_Bag[] = _("BAG");
+const u8 gPCText_Info[] = _("INFO");
+const u8 gPCText_Scenery1[] = _("SCENERY 1");
+const u8 gPCText_Scenery2[] = _("SCENERY 2");
+const u8 gPCText_Scenery3[] = _("SCENERY 3");
+const u8 gPCText_Etcetera[] = _("ETCETERA");
+const u8 gPCText_Forest[] = _("FOREST");
+const u8 gPCText_City[] = _("CITY");
+const u8 gPCText_Desert[] = _("DESERT");
+const u8 gPCText_Savanna[] = _("SAVANNA");
+const u8 gPCText_Crag[] = _("CRAG");
+const u8 gPCText_Volcano[] = _("VOLCANO");
+const u8 gPCText_Snow[] = _("SNOW");
+const u8 gPCText_Cave[] = _("CAVE");
+const u8 gPCText_Beach[] = _("BEACH");
+const u8 gPCText_Seafloor[] = _("SEAFLOOR");
+const u8 gPCText_River[] = _("RIVER");
+const u8 gPCText_Sky[] = _("SKY");
+const u8 gPCText_PolkaDot[] = _("STARS");
+const u8 gPCText_Pokecenter[] = _("POKéCENTER");
+const u8 gPCText_Machine[] = _("TILES");
+const u8 gPCText_Simple[] = _("SIMPLE");
const u8 gUnknown_8418562[] = _("なにを しますか?");
-const u8 gUnknown_841856C[] = _("WITHDRAW POKéMON");
-const u8 gUnknown_841857D[] = _("DEPOSIT POKéMON");
-const u8 gUnknown_841858D[] = _("MOVE POKéMON");
-const u8 gUnknown_841859A[] = _("MOVE ITEMS");
-const u8 gUnknown_84185A5[] = _("SEE YA!");
-const u8 gUnknown_84185AD[] = _("You can withdraw a POKéMON if you\nhave any in a BOX.");
-const u8 gUnknown_84185E2[] = _("You can deposit your party\nPOKéMON in any BOX.");
-const u8 gUnknown_8418611[] = _("You can move POKéMON that are\nstored in any BOX.");
-const u8 gUnknown_8418642[] = _("You can move items held by any\nPOKéMON in a BOX or your party.");
-const u8 gUnknown_8418681[] = _("See you later!");
-const u8 gUnknown_8418690[] = _("Can't deposit the last POKéMON!");
-const u8 gUnknown_84186B0[] = _("Can't take any more POKéMON.");
-const u8 gUnknown_84186CD[] = _("BOX");
+const u8 gText_WithdrawPokemon[] = _("WITHDRAW POKéMON");
+const u8 gText_DepositPokemon[] = _("DEPOSIT POKéMON");
+const u8 gText_MovePokemon[] = _("MOVE POKéMON");
+const u8 gText_MoveItems[] = _("MOVE ITEMS");
+const u8 gText_SeeYa[] = _("SEE YA!");
+const u8 gText_WithdrawMonDescription[] = _("You can withdraw a POKéMON if you\nhave any in a BOX.");
+const u8 gText_DepositMonDescription[] = _("You can deposit your party\nPOKéMON in any BOX.");
+const u8 gText_MoveMonDescription[] = _("You can move POKéMON that are\nstored in any BOX.");
+const u8 gText_MoveItemsDescription[] = _("You can move items held by any\nPOKéMON in a BOX or your party.");
+const u8 gText_SeeYaDescription[] = _("See you later!");
+const u8 gText_JustOnePkmn[] = _("Can't deposit the last POKéMON!");
+const u8 gText_PartyFull[] = _("Can't take any more POKéMON.");
+const u8 gText_Box[] = _("BOX");
const u8 gUnknown_84186D1[] = _("Combine four words or phrases");
const u8 gUnknown_84186EF[] = _("and make your profile.");
const u8 gUnknown_8418706[] = _("Make a message of six phrases.");
diff --git a/src/title_screen.c b/src/title_screen.c
index 0ff0a6b96..e1bcf5dd2 100644
--- a/src/title_screen.c
+++ b/src/title_screen.c
@@ -305,6 +305,22 @@ static const u16 gUnknown_LG_83BFA10[] = {
};
#endif
+static const u32 gUnknown_83BFBE4[] = INCBIN_U32("graphics/title_screen/unk_83BFBE4.bin.lz");
+static const u32 gUnknown_83C0408[] = INCBIN_U32("graphics/title_screen/unk_83C0408.bin.lz");
+static const u32 gUnknown_83C0C00[] = INCBIN_U32("graphics/title_screen/unk_83C0C00.bin.lz");
+static const u32 gUnknown_83C139C[] = INCBIN_U32("graphics/title_screen/unk_83C139C.bin.lz");
+static const u32 gUnknown_83C1BB8[] = INCBIN_U32("graphics/title_screen/unk_83C1BB8.bin.lz");
+static const u32 gUnknown_83C2380[] = INCBIN_U32("graphics/title_screen/unk_83C2380.bin.lz");
+
+static const u32 *const gUnknown_83C2BA4[] = {
+ gUnknown_83BFBE4,
+ gUnknown_83C0408,
+ gUnknown_83C0C00,
+ gUnknown_83C139C,
+ gUnknown_83C1BB8,
+ gUnknown_83C2380
+};
+
void CB2_InitTitleScreen(void)
{
switch (gMain.state)
diff --git a/src/tm_case.c b/src/tm_case.c
index 2f27cc0db..7bb471719 100644
--- a/src/tm_case.c
+++ b/src/tm_case.c
@@ -959,7 +959,7 @@ static void Task_SelectTMAction_Type3(u8 taskId)
if (!itemid_is_unique(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])))
{
- sTMCaseDynamicResources->savedCallback = sub_808CE60;
+ sTMCaseDynamicResources->savedCallback = Cb2_ReturnToPSS;
Task_BeginFadeOutFromTMCase(taskId);
}
else
diff --git a/src/trade.c b/src/trade.c
index 30bfa8389..bd6860e85 100644
--- a/src/trade.c
+++ b/src/trade.c
@@ -882,10 +882,10 @@ static void sub_804C728(void)
gMain.state++;
break;
case 10:
- PSS_RenderTextToVramViaBuffer(gSaveBlock2Ptr->playerName, sSpriteTextTilePtrs[0], 0, 0, gDecompressionBuffer, 3);
+ DrawTextWindowAndBufferTiles(gSaveBlock2Ptr->playerName, sSpriteTextTilePtrs[0], 0, 0, gDecompressionBuffer, 3);
id = GetMultiplayerId();
- PSS_RenderTextToVramViaBuffer(gLinkPlayers[id ^ 1].name, sSpriteTextTilePtrs[3], 0, 0, gDecompressionBuffer, 3);
- PSS_RenderTextToVramViaBuffer(sTradeUITextPtrs[TRADEUITEXT_CANCEL], sSpriteTextTilePtrs[6], 0, 0, gDecompressionBuffer, 2);
+ DrawTextWindowAndBufferTiles(gLinkPlayers[id ^ 1].name, sSpriteTextTilePtrs[3], 0, 0, gDecompressionBuffer, 3);
+ DrawTextWindowAndBufferTiles(sTradeUITextPtrs[TRADEUITEXT_CANCEL], sSpriteTextTilePtrs[6], 0, 0, gDecompressionBuffer, 2);
RenderTextToVramViaBuffer(sTradeUITextPtrs[TRADEUITEXT_CHOOSE], sSpriteTextTilePtrs[8], 24);
gMain.state++;
sTradeMenuResourcesPtr->unk_A8 = 0;
@@ -1080,10 +1080,10 @@ void sub_804CF14(void)
gMain.state++;
break;
case 10:
- PSS_RenderTextToVramViaBuffer(gSaveBlock2Ptr->playerName, sSpriteTextTilePtrs[0], 0, 0, gDecompressionBuffer, 3);
+ DrawTextWindowAndBufferTiles(gSaveBlock2Ptr->playerName, sSpriteTextTilePtrs[0], 0, 0, gDecompressionBuffer, 3);
id = GetMultiplayerId();
- PSS_RenderTextToVramViaBuffer(gLinkPlayers[id ^ 1].name, sSpriteTextTilePtrs[3], 0, 0, gDecompressionBuffer, 3);
- PSS_RenderTextToVramViaBuffer(sTradeUITextPtrs[TRADEUITEXT_CANCEL], sSpriteTextTilePtrs[6], 0, 0, gDecompressionBuffer, 2);
+ DrawTextWindowAndBufferTiles(gLinkPlayers[id ^ 1].name, sSpriteTextTilePtrs[3], 0, 0, gDecompressionBuffer, 3);
+ DrawTextWindowAndBufferTiles(sTradeUITextPtrs[TRADEUITEXT_CANCEL], sSpriteTextTilePtrs[6], 0, 0, gDecompressionBuffer, 2);
RenderTextToVramViaBuffer(sTradeUITextPtrs[TRADEUITEXT_CHOOSE], sSpriteTextTilePtrs[8], 24);
gMain.state++;
sTradeMenuResourcesPtr->unk_A8 = 0;
@@ -2502,7 +2502,7 @@ static bool8 sub_804F610(void)
static void RenderTextToVramViaBuffer(const u8 *name, u8 *dest, u8 unused)
{
- PSS_RenderTextToVramViaBuffer(name, dest, 0, 0, gDecompressionBuffer, 6);
+ DrawTextWindowAndBufferTiles(name, dest, 0, 0, gDecompressionBuffer, 6);
}
static void sub_804F748(u8 who)
diff --git a/src/window_8bpp.c b/src/window_8bpp.c
index c58c13802..8977d61e4 100644
--- a/src/window_8bpp.c
+++ b/src/window_8bpp.c
@@ -13,7 +13,7 @@ static void nullsub_9(void)
{
}
-u16 AddWindow8Bit(struct WindowTemplate *template)
+u16 AddWindow8Bit(const struct WindowTemplate *template)
{
u16 windowId;
u8* memAddress;
@@ -81,7 +81,7 @@ void FillWindowPixelRect8Bit(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width,
FillBitmapRect8Bit(&pixelRect, x, y, width, height, fillValue);
}
-void BlitBitmapRectToWindow4BitTo8Bit(u8 windowId, u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight, u8 paletteNum)
+void BlitBitmapRectToWindow4BitTo8Bit(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight, u8 paletteNum)
{
struct Bitmap sourceRect;
struct Bitmap destRect;