diff --git a/graphics/link_games/dodrioberry_berrysprites.png b/graphics/dodrio_berry_picking/berries.png similarity index 100% rename from graphics/link_games/dodrioberry_berrysprites.png rename to graphics/dodrio_berry_picking/berries.png diff --git a/graphics/link_games/dodrioberry_bg1.bin b/graphics/dodrio_berry_picking/bg.bin similarity index 100% rename from graphics/link_games/dodrioberry_bg1.bin rename to graphics/dodrio_berry_picking/bg.bin diff --git a/graphics/link_games/dodrioberry_bg1.pal b/graphics/dodrio_berry_picking/bg.pal similarity index 100% rename from graphics/link_games/dodrioberry_bg1.pal rename to graphics/dodrio_berry_picking/bg.pal diff --git a/graphics/link_games/dodrioberry_bg1.png b/graphics/dodrio_berry_picking/bg.png similarity index 100% rename from graphics/link_games/dodrioberry_bg1.png rename to graphics/dodrio_berry_picking/bg.png diff --git a/graphics/link_games/dodrioberry_platform.png b/graphics/dodrio_berry_picking/cloud.png similarity index 100% rename from graphics/link_games/dodrioberry_platform.png rename to graphics/dodrio_berry_picking/cloud.png diff --git a/graphics/link_games/dodrioberry_pkmn.png b/graphics/dodrio_berry_picking/dodrio.png similarity index 100% rename from graphics/link_games/dodrioberry_pkmn.png rename to graphics/dodrio_berry_picking/dodrio.png diff --git a/graphics/link_games/dodrioberry_shiny.pal b/graphics/dodrio_berry_picking/shiny.pal similarity index 100% rename from graphics/link_games/dodrioberry_shiny.pal rename to graphics/dodrio_berry_picking/shiny.pal diff --git a/graphics/link_games/dodrioberry_status.png b/graphics/dodrio_berry_picking/status.png similarity index 100% rename from graphics/link_games/dodrioberry_status.png rename to graphics/dodrio_berry_picking/status.png diff --git a/graphics/link_games/dodrioberry_bg2.pal b/graphics/dodrio_berry_picking/tree_border.pal similarity index 100% rename from graphics/link_games/dodrioberry_bg2.pal rename to graphics/dodrio_berry_picking/tree_border.pal diff --git a/graphics/link_games/dodrioberry_bg2.png b/graphics/dodrio_berry_picking/tree_border.png similarity index 100% rename from graphics/link_games/dodrioberry_bg2.png rename to graphics/dodrio_berry_picking/tree_border.png diff --git a/graphics/link_games/dodrioberry_bg2left.bin b/graphics/dodrio_berry_picking/tree_border_left.bin similarity index 100% rename from graphics/link_games/dodrioberry_bg2left.bin rename to graphics/dodrio_berry_picking/tree_border_left.bin diff --git a/graphics/link_games/dodrioberry_bg2right.bin b/graphics/dodrio_berry_picking/tree_border_right.bin similarity index 100% rename from graphics/link_games/dodrioberry_bg2right.bin rename to graphics/dodrio_berry_picking/tree_border_right.bin diff --git a/graphics/interface/blank_1x2.png b/graphics/interface/comm_error_bg.png similarity index 100% rename from graphics/interface/blank_1x2.png rename to graphics/interface/comm_error_bg.png diff --git a/include/dodrio_berry_picking.h b/include/dodrio_berry_picking.h index 5decbeccb..a93fb27cd 100644 --- a/include/dodrio_berry_picking.h +++ b/include/dodrio_berry_picking.h @@ -1,7 +1,7 @@ #ifndef GUARD_DODRIO_BERRY_PICKING_H #define GUARD_DODRIO_BERRY_PICKING_H -void StartDodrioBerryPicking(u16 a0, void (*callback)(void)); +void StartDodrioBerryPicking(u16 partyId, void (*exitCallback)(void)); void IsDodrioInParty(void); void ShowDodrioBerryPickingRecords(void); diff --git a/include/link_rfu.h b/include/link_rfu.h index 9476da6b7..e1c3a6fba 100644 --- a/include/link_rfu.h +++ b/include/link_rfu.h @@ -262,7 +262,7 @@ bool8 LinkRfu_GetNameIfSerial7F7D(struct GFtgtGname *buff1, u8 *buff2, u8 idx); s32 sub_800E87C(u8 idx); void CreateTask_RfuIdle(void); void DestroyTask_RfuIdle(void); -void sub_8011AC8(void); +void ClearRecvCommands(void); void LinkRfu_FatalError(void); bool32 sub_8011A9C(void); void sub_80104B0(void); diff --git a/include/sound.h b/include/sound.h index 7d47b7456..25ffa2d6e 100644 --- a/include/sound.h +++ b/include/sound.h @@ -1,6 +1,27 @@ #ifndef GUARD_SOUND_H #define GUARD_SOUND_H +enum { + FANFARE_LEVEL_UP, + FANFARE_OBTAIN_ITEM, + FANFARE_EVOLVED, + FANFARE_OBTAIN_TMHM, + FANFARE_HEAL, + FANFARE_OBTAIN_BADGE, + FANFARE_MOVE_DELETED, + FANFARE_OBTAIN_BERRY, + FANFARE_AWAKEN_LEGEND, + FANFARE_SLOTS_JACKPOT, + FANFARE_SLOTS_WIN, + FANFARE_TOO_BAD, + FANFARE_RG_POKE_FLUTE, + FANFARE_RG_OBTAIN_KEY_ITEM, + FANFARE_RG_DEX_RATING, + FANFARE_OBTAIN_B_POINTS, + FANFARE_OBTAIN_SYMBOL, + FANFARE_REGISTER_MATCH_CALL, +}; + void InitMapMusic(void); void MapMusicMain(void); void ResetMapMusic(void); diff --git a/src/berry_crush.c b/src/berry_crush.c index b11af5529..9732e1205 100755 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -2516,12 +2516,12 @@ void sub_80236B8(struct BerryCrushGame *r5) { if (r5->unk10 > 70) { - sub_8011AC8(); + ClearRecvCommands(); r5->unk10 = 0; } else if (r5->unk5C.unk02_3 == 0) { - sub_8011AC8(); + ClearRecvCommands(); r5->unk10 = 0; } } diff --git a/src/dodrio_berry_picking.c b/src/dodrio_berry_picking.c index 47839a79a..fb6f1a421 100644 --- a/src/dodrio_berry_picking.c +++ b/src/dodrio_berry_picking.c @@ -25,252 +25,3456 @@ #include "constants/items.h" #include "constants/songs.h" -struct DodrioSubstruct_0160 +// Note that in this file 'Dodrio Berry Picking' is often +// shortened to DodrioGame or just Game for convenience + +#define MAX_SCORE 999990 +#define MAX_BERRIES 9999 + +// The minimum score needed to receive a prize +#define PRIZE_SCORE 3000 + +// Difficulty increases as berries are eaten. The rate of new berries increases and the types of berries changes +// When the max difficulty is reached it starts again from the beginning +#define NUM_DIFFICULTIES 7 + +#define MAX_FALL_DIST 10 // The number of times a berry needs to fall before hitting the ground +#define EAT_FALL_DIST 7 // The number of times a berry needs to fall to be available to eat + +enum { + BG_INTERFACE, + BG_TREE_LEFT, + BG_TREE_RIGHT, + BG_SCENERY +}; + +enum { + FUNC_INTRO, + FUNC_INIT_COUNTDOWN, + FUNC_COUNTDOWN, + FUNC_WAIT_START, + FUNC_PLAY_GAME, + FUNC_INIT_RESULTS, + FUNC_RESULTS, + FUNC_ASK_PLAY_AGAIN, + FUNC_END_LINK, + FUNC_EXIT, + FUNC_RESET_GAME, + FUNC_WAIT_END_GAME, +}; + +enum { + GFXFUNC_LOAD, + GFXFUNC_SHOW_NAMES, + GFXFUNC_SHOW_RESULTS, + GFXFUNC_MSG_PLAY_AGAIN, + GFXFUNC_MSG_SAVING, + GFXFUNC_MSG_COMM_STANDBY, + GFXFUNC_ERASE_MSG, + GFXFUNC_MSG_PLAYER_DROPPED, + GFXFUNC_STOP, + GFXFUNC_IDLE, +}; + +enum { + PACKET_READY_START = 1, + PACKET_GAME_STATE, + PACKET_PICK_STATE, + PACKET_READY_END, +}; + +enum { + PLAY_AGAIN_NONE, + PLAY_AGAIN_YES, + PLAY_AGAIN_NO, + PLAY_AGAIN_DROPPED = 5, +}; + +enum { + PICK_NONE, // Dodrio standing still + PICK_RIGHT, // Dodrio reaching right + PICK_MIDDLE, // Dodrio reaching up + PICK_LEFT, // Dodrio reaching left + PICK_DISABLED, // Dodrio down after game over +}; + +enum { + BERRY_BLUE, + BERRY_GREEN, + BERRY_GOLD, + BERRY_MISSED, + BERRY_PRIZE, + BERRY_IN_ROW, + NUM_BERRY_IDS +}; + +#define NUM_BERRY_TYPES 4 // Blue, Green, Gold, and 'missed' + + // Eaten anim comes after the normal & missed versions of other berries +#define ANIM_EATEN (BERRY_MISSED * 2) + +enum { + BERRYSTATE_NONE, + BERRYSTATE_PICKED, // Berry has been picked by a Dodrio, replaced with blue hit sprite (still falling) + BERRYSTATE_EATEN, // Berry has been eaten (after being picked), berry is gone now + BERRYSTATE_SQUISHED, // Berry has hit the ground +}; + +enum { + INPUTSTATE_NONE, + INPUTSTATE_TRY_PICK, + INPUTSTATE_PICKED, + INPUTSTATE_ATE_BERRY, + INPUTSTATE_BAD_MISS, +}; + +// Colors for status bar squares +// Colored gray when a berry is missed +// Flash red when few yellow squares remain +enum { + STATUS_YELLOW, + STATUS_GRAY, + STATUS_RED, +}; + +#define NUM_STATUS_SQUARES 10 + +// Berries fall in predefined columns. +// A total of 10 are available, though fewer will be used with < 5 players +// The 11th column is a repeat of the 1st column wrapped around, so only +// the values 0-9 are unique 'valid' columns +#define NUM_BERRY_COLUMNS 11 + +#define GFXTAG_DODRIO 0 +#define GFXTAG_STATUS 1 +#define GFXTAG_BERRIES 2 +#define GFXTAG_CLOUD 5 + +#define PALTAG_DODRIO_NORMAL 0 +#define PALTAG_DODRIO_SHINY 1 +#define PALTAG_STATUS 2 +#define PALTAG_BERRIES 3 +#define PALTAG_CLOUD 6 + +#define NUM_CLOUDS 2 + +#define PLAYER_NONE 0xFF + +struct DodrioGame_Gfx { - /*0x0000 : 0x3000*/ u16 ALIGNED(4) tilemapBuffers[3][BG_SCREEN_SIZE]; - /*0x3000 : 0x3160*/ bool32 finished; - /*0x3004 : 0x3164*/ u8 ALIGNED(4) unk3004; - /*0x3008 : 0x3168*/ u8 ALIGNED(4) unk3008[10]; - /*0x3014 : 0x3174*/ u8 ALIGNED(4) state; - /*0x3018 : 0x3178*/ u8 ALIGNED(4) unk3018; - /*0x301C : 0x317C*/ u16 ALIGNED(4) unk301C; - /*0x3020 : 0x3180*/ u8 ALIGNED(4) unk3020; - /*0x3024 : 0x3184*/ u8 ALIGNED(4) unk3024; - /*0x3024 : 0x3184*/ void (*unk3028)(void); + u16 ALIGNED(4) tilemapBuffers[3][BG_SCREEN_SIZE]; + bool32 finished; + u8 ALIGNED(4) taskId; + u8 ALIGNED(4) windowIds[MAX_RFU_PLAYERS + 5]; // The latter 5 are never used + u8 ALIGNED(4) state; + u8 ALIGNED(4) loadState; + u16 ALIGNED(4) timer; + u8 ALIGNED(4) cursorSelection; + u8 ALIGNED(4) playAgainState; + void (*func)(void); }; // size = 0x302C -struct DodrioStruct_2022CF4 +struct StatusBar { - u8 filler_00[0xc]; - u8 unkC[10]; - s16 unk16[10]; - u16 unk2A[10]; - u16 unk3E; + u8 unused[12]; + bool8 entered[NUM_STATUS_SQUARES]; + s16 yChange[NUM_STATUS_SQUARES]; + u16 spriteIds[NUM_STATUS_SQUARES]; + u16 flashTimer; }; // size = 0x40 -struct DodrioSubstruct_31A0_14 +struct DodrioGame_Berries { - u8 unk0[11]; - u8 unkB[11]; + u8 ids[NUM_BERRY_COLUMNS]; + u8 fallDist[NUM_BERRY_COLUMNS]; }; -struct DodrioSubstruct_31A0_2C +struct DodrioGame_PlayerCommData { - u8 unk0; - u8 ALIGNED(4) unk4; - u8 ALIGNED(4) unk8; + u8 pickState; + bool8 ALIGNED(4) ateBerry; + bool8 ALIGNED(4) missedBerry; }; -struct DodrioSubstruct_31A0 +struct DodrioGame_Player { - u8 name[0x10]; - u32 unk10; - struct DodrioSubstruct_31A0_14 unk14; - struct DodrioSubstruct_31A0_2C unk2C; - u8 filler_35[4]; + u8 name[16]; + bool32 receivedGameStatePacket; // Never read + struct DodrioGame_Berries berries; + struct DodrioGame_PlayerCommData comm; + u32 unused; }; // size = 0x3C -struct DodrioSubstruct_318C +// Because Dodrio is required for this minigame, +// the only relevant information about the selected +// Pokémon is whether or not it's shiny +struct DodrioGame_MonInfo { bool8 isShiny; }; -struct DodrioSubstruct_3308 +struct DodrioGame_ScoreResults { - u8 unk0; - u32 unk4; + u8 ranking; + u32 score; }; -struct DodrioStruct +struct DodrioGame { - /*0x0000*/ void (*savedCallback)(void); - /*0x0004*/ u8 ALIGNED(4) unk04; - /*0x0008*/ u8 ALIGNED(4) unk08; - /*0x000C*/ u8 ALIGNED(4) unk0C; - /*0x0010*/ u8 ALIGNED(4) unk10; - /*0x0014*/ u8 ALIGNED(4) unk14; - /*0x0018*/ u8 ALIGNED(4) unk18; - /*0x001C*/ u8 ALIGNED(4) unk1C; - /*0x0020*/ u8 ALIGNED(4) unk20; - /*0x0024*/ u8 ALIGNED(4) unk24; + /*0x0000*/ void (*exitCallback)(void); + /*0x0004*/ u8 ALIGNED(4) taskId; + /*0x0008*/ u8 ALIGNED(4) playersReceived; + /*0x000C*/ u8 ALIGNED(4) startState; + /*0x0010*/ u8 ALIGNED(4) state; + /*0x0014*/ u8 ALIGNED(4) timer; + /*0x0018*/ u8 ALIGNED(4) funcId; + /*0x001C*/ u8 ALIGNED(4) prevFuncId; // Set, never read + /*0x0020*/ bool8 ALIGNED(4) isLeader; + /*0x0024*/ u8 ALIGNED(4) numPlayers; /*0x0028*/ u8 ALIGNED(4) multiplayerId; - /*0x0029*/ u8 filler_0029[7]; - /*0x0030*/ u8 ALIGNED(4) unk30; - /*0x0034*/ u8 ALIGNED(4) unk34[5]; - /*0x003C*/ u8 ALIGNED(4) unk3C; - /*0x0040*/ u8 ALIGNED(4) unk40; - /*0x0044*/ u8 ALIGNED(4) unk44; - /*0x0048*/ u8 ALIGNED(4) unk48; - /*0x004A*/ u16 unk4A[5][6]; - /*0x0086*/ u16 unk86[5]; - /*0x0090*/ u8 ALIGNED(4) unk90[5]; - /*0x0098*/ u8 ALIGNED(4) unk98[4]; - /*0x009C*/ u8 ALIGNED(4) unk9C[11]; - /*0x00A8*/ u8 ALIGNED(4) unkA8[5]; - /*0x00B0*/ u8 ALIGNED(4) unkB0[5]; - /*0x00B8*/ u8 ALIGNED(4) unkB8[11]; - /*0x00C4*/ u8 ALIGNED(4) unkC4[11]; - /*0x00D0*/ u8 ALIGNED(4) unkD0[11]; - /*0x00DC*/ u8 ALIGNED(4) unkDC[11]; - /*0x00E8*/ u8 ALIGNED(4) unkE8[11]; - /*0x00F4*/ u8 ALIGNED(4) unkF4[11][2]; - /*0x010C*/ u8 ALIGNED(4) unk10C[5]; - /*0x0112*/ u16 unk112; - /*0x0114*/ u16 unk114; - /*0x0118*/ u32 unk118; - /*0x011C*/ u32 unk11C; - /*0x0120*/ u32 unk120; - /*0x0124*/ u8 ALIGNED(4) unk124; - /*0x0128*/ u8 ALIGNED(4) unk128; - /*0x012C*/ u32 unk12C; - /*0x0130*/ u32 unk130[5]; - /*0x0144*/ u8 ALIGNED(4) unk144; - /*0x0148*/ u8 ALIGNED(4) unk148[11]; - /*0x0154*/ u8 ALIGNED(4) unk154; - /*0x0158*/ u8 ALIGNED(4) unk158[5]; - /*0x0160*/ struct DodrioSubstruct_0160 unk160; - /*0x318C*/ struct DodrioSubstruct_318C unk318C[5]; - /*0x31A0*/ struct DodrioSubstruct_31A0 unk31A0[5]; - /*0x32CC*/ struct DodrioSubstruct_31A0 unk32CC; - /*0x3308*/ struct DodrioSubstruct_3308 unk3308[5]; + /*0x0029*/ u8 unused1[7]; + /*0x0030*/ u8 ALIGNED(4) countdownEndDelay; + /*0x0034*/ u8 ALIGNED(4) posToPlayerId[MAX_RFU_PLAYERS]; + /*0x003C*/ u8 ALIGNED(4) unused2; // Set to 0, never read + /*0x0040*/ u8 ALIGNED(4) numGraySquares; + /*0x0044*/ u8 ALIGNED(4) berryColStart; + /*0x0048*/ u8 ALIGNED(4) berryColEnd; + /*0x004A*/ u16 berryResults[MAX_RFU_PLAYERS][NUM_BERRY_IDS]; + /*0x0086*/ u16 berriesEaten[MAX_RFU_PLAYERS]; + /*0x0090*/ u8 ALIGNED(4) difficulty[MAX_RFU_PLAYERS]; + /*0x0098*/ u8 ALIGNED(4) pickStateQueue[4]; + /*0x009C*/ u8 ALIGNED(4) eatTimer[NUM_BERRY_COLUMNS]; + /*0x00A8*/ u8 ALIGNED(4) inputState[MAX_RFU_PLAYERS]; + /*0x00B0*/ u8 ALIGNED(4) inputDelay[MAX_RFU_PLAYERS]; + /*0x00B8*/ u8 ALIGNED(4) berryEatenBy[NUM_BERRY_COLUMNS]; + /*0x00C4*/ u8 ALIGNED(4) berryState[NUM_BERRY_COLUMNS]; + /*0x00D0*/ u8 ALIGNED(4) fallTimer[NUM_BERRY_COLUMNS]; + /*0x00DC*/ u8 ALIGNED(4) newBerryTimer[NUM_BERRY_COLUMNS]; + /*0x00E8*/ u8 ALIGNED(4) prevBerryIds[NUM_BERRY_COLUMNS]; + /*0x00F4*/ u8 ALIGNED(4) playersAttemptingPick[NUM_BERRY_COLUMNS][2]; + /*0x010C*/ u8 ALIGNED(4) playAgainStates[MAX_RFU_PLAYERS]; + /*0x0112*/ u16 berriesPickedInRow; + /*0x0114*/ u16 maxBerriesPickedInRow; + /*0x0118*/ bool32 startCountdown; // Never read + /*0x011C*/ bool32 startGame; + /*0x0120*/ bool32 berriesFalling; + /*0x0124*/ u8 ALIGNED(4) clearRecvCmdTimer; + /*0x0128*/ bool8 ALIGNED(4) clearRecvCmds; + /*0x012C*/ bool32 allReadyToEnd; + /*0x0130*/ bool32 readyToEnd[MAX_RFU_PLAYERS]; + /*0x0144*/ bool8 ALIGNED(4) playingPickSound; + /*0x0148*/ bool8 ALIGNED(4) playingSquishSound[NUM_BERRY_COLUMNS]; + /*0x0154*/ u8 ALIGNED(4) endSoundState; + /*0x0158*/ bool8 ALIGNED(4) readyToStart[MAX_RFU_PLAYERS]; + /*0x0160*/ struct DodrioGame_Gfx gfx; + /*0x318C*/ struct DodrioGame_MonInfo monInfo[MAX_RFU_PLAYERS]; + /*0x31A0*/ struct DodrioGame_Player players[MAX_RFU_PLAYERS]; + /*0x32CC*/ struct DodrioGame_Player player; + /*0x3308*/ struct DodrioGame_ScoreResults scoreResults[MAX_RFU_PLAYERS]; }; // size = 0x3330 -EWRAM_DATA static struct DodrioStruct * gUnknown_02022C98 = NULL; -EWRAM_DATA static u16 *gUnknown_02022C9C[5] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CB0[2] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CB8[11] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CE4[4] = {NULL}; -EWRAM_DATA static struct DodrioStruct_2022CF4 *gUnknown_02022CF4 = NULL; -EWRAM_DATA static struct DodrioSubstruct_0160 *gUnknown_02022CF8 = NULL; +EWRAM_DATA static struct DodrioGame * sGame = NULL; +EWRAM_DATA static u16 * sDodrioSpriteIds[MAX_RFU_PLAYERS] = {NULL}; +EWRAM_DATA static u16 * sCloudSpriteIds[NUM_CLOUDS] = {NULL}; +EWRAM_DATA static u16 * sBerrySpriteIds[NUM_BERRY_COLUMNS] = {NULL}; +EWRAM_DATA static u16 * sBerryIconSpriteIds[NUM_BERRY_TYPES] = {NULL}; +EWRAM_DATA static struct StatusBar * sStatusBar = NULL; +EWRAM_DATA static struct DodrioGame_Gfx * sGfx = NULL; -static bool32 gUnknown_03000DB0; +static bool32 sExitingGame; -static void sub_8024A1C(void); -static void sub_8024A30(struct DodrioStruct *); -static void sub_8024BC8(u8 taskId); -static void sub_8024DBC(void); -static void sub_8024E00(void); -static void sub_8024E38(void); -static void sub_8024F10(void); -static void sub_8024F38(void); -static void sub_8024FFC(void); -static void sub_80250D4(void); -static void sub_8025158(void); -static void sub_8025198(void); -static void sub_8025230(void); -static void sub_8025324(void); -static void sub_8025470(void); -static void sub_8025644(void); -static void sub_80256AC(void); -static void sub_8025758(void); -static void sub_802589C(u8 taskId); -static void sub_8025910(u8 taskId); -static void sub_8025D04(void); -static void sub_8025D50(void); -static void sub_8025E0C(void); -static void sub_8025ED8(void); -static void sub_8025F48(void); -static void sub_8026044(void); -static void sub_80261CC(void); -static void sub_80261E4(void); -static void sub_80261F8(struct DodrioSubstruct_318C *, struct Pokemon *); -static void sub_802620C(TaskFunc, u8); -static void sub_802621C(TaskFunc); -static void sub_8026240(u8); -static bool32 sub_8026264(void); -static void sub_80262C0(void); -static bool32 sub_8026634(u8, u8, u8); -static void sub_802671C(void); -static void sub_8026AF4(void); -static void sub_8026B28(void); -static void sub_8026B5C(u8, u8*, u8*); -static bool32 sub_8026BB8(void); -static void sub_8026C28(void); -static bool32 sub_8026C50(void); -static bool32 sub_8026C90(void); -static void sub_8026D1C(u8); -static u8 sub_8026D8C(u8); -static u8 sub_8026DB0(u8, u8); -static void sub_8026F1C(u8, u8, u8); -static void sub_8027234(bool32 arg0); -static void sub_80272A4(void); -static void sub_80272E8(void); -static void sub_80273F0(void); -static void sub_802749C(void); -static u8 sub_8027518(u8); -static void sub_8027554(void); -static void sub_8027608(void); -static u32 sub_8027748(void); -static void sub_8027DD0(u32 arg0); -static void sub_8027E30(struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 arg6, u32 arg7, u32 arg8); -static u32 sub_8028164(u32 unused, struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 *arg6, u32 *arg7, u32 *arg8); -static void sub_80282EC(u8); -static u32 sub_8028318(u32 arg0, u8 *arg1); -static void sub_8028350(u32 arg0); -static u32 sub_8028374(u32 arg0); -static void sub_80283A8(void); -static void sub_8028408(struct DodrioSubstruct_318C *arg0, u8 arg1, u8 id, u8 arg3); -static void sub_80284CC(u8); -static void sub_8028504(u8); -static void sub_8028614(u8 count); -static void sub_802868C(bool8 invisible, u8 count); -static void sub_8028734(void); -static void sub_80287E4(void); -static void sub_80289E8(bool8 invisible); -static void sub_80286E4(void); -static bool32 sub_8028828(void); -static void sub_8028A34(void); -static void sub_8028A88(void); -static void sub_8028B80(void); -static void sub_8028D44(void); -static void sub_8028DFC(void); -static void sub_8028E4C(void); -static void sub_8028E84(void); -static void sub_8028EC8(bool8 invisible); -static void sub_8028FCC(void); -static void sub_802903C(void); -static void sub_8029274(struct DodrioSubstruct_0160 *PTR); -static void sub_80292E0(u8); -static bool32 sub_802A770(void); -static u8 sub_802A794(void); -static void sub_8028BF8(u8 id, bool8 invisible); -static void sub_8028C30(bool8 invisible); -static void sub_8028CA4(u16 id, u8 frameNum); -static void sub_8028C7C(u8 id, u8 y); -static void sub_80286B4(u8 id, u8 frameNum); -static u8 sub_8026E70(u8 arg0, u8 arg1); -static void sub_80288D4(u8 arg0); -static u32 sub_8027DFC(u32 arg0); -static u32 IncrementWithLimit(u32 arg0, u32 arg1); -static u32 Min(u32 arg0, u32 arg1); -static u32 sub_80276C0(u8 arg0); -static void Task_ShowDodrioBerryPickingRecords(u8 taskId); -static void sub_8029314(u8 taskId); -static void sub_8027BEC(u8 windowId, s32 width); -static void nullsub_15(struct Sprite *sprite); -static void sub_80284A8(struct Sprite *sprite); -static u32 sub_802853C(struct Sprite *sprite); -static u32 sub_80285AC(struct Sprite *sprite); -static s16 sub_8028F14(u8 arg0, u8 arg1); -static void sub_8028654(bool8 invisible, u8 id); -static void sub_8029338(void); -static bool32 sub_802A8E8(void); -static void sub_802A7A8(void); -static void sub_802A72C(void (*func)(void)); -static void (*sub_802A75C(void))(void); -static void sub_8029338(void); -static void sub_8029440(void); -static void sub_802988C(void); -static void sub_802A010(void); -static void sub_802A380(void); -static void sub_802A454(void); -static void sub_802A534(void); -static void sub_802A588(void); -static void sub_802A6FC(void); -static void nullsub_16(void); +static void ResetTasksAndSprites(void); +static void InitDodrioGame(struct DodrioGame *); +static void Task_StartDodrioGame(u8); +static void DoGameIntro(void); +static void InitCountdown(void); +static void DoCountdown(void); +static void WaitGameStart(void); +static void PlayGame_Leader(void); +static void PlayGame_Member(void); +static void WaitEndGame_Leader(void); +static void WaitEndGame_Member(void); +static void InitResults_Leader(void); +static void InitResults_Member(void); +static void DoResults(void); +static void AskPlayAgain(void); +static void EndLink(void); +static void ExitGame(void); +static void ResetGame(void); +static void Task_NewGameIntro(u8); +static void Task_CommunicateMonInfo(u8); +static void RecvLinkData_Leader(void); +static void SendLinkData_Leader(void); +static void RecvLinkData_Member(void); +static void SendLinkData_Member(void); +static void HandleSound_Leader(void); +static void HandleSound_Member(void); +static void CB2_DodrioGame(void); +static void VBlankCB_DodrioGame(void); +static void InitMonInfo(struct DodrioGame_MonInfo *, struct Pokemon *); +static void CreateTask_(TaskFunc, u8); +static void CreateDodrioGameTask(TaskFunc); +static void SetGameFunc(u8); +static bool32 SlideTreeBordersOut(void); +static void InitFirstWaveOfBerries(void); +static bool32 TryPickBerry(u8, u8, u8); +static void UpdateFallingBerries(void); +static void UpdateGame_Leader(void); +static void UpdateGame_Member(void); +static void GetActiveBerryColumns(u8, u8*, u8*); +static bool32 AllPlayersReadyToStart(void); +static void ResetReadyToStart(void); +static bool32 ReadyToEndGame_Leader(void); +static bool32 ReadyToEndGame_Member(void); +static void TryIncrementDifficulty(u8); +static u8 GetPlayerIdAtColumn(u8); +static u8 GetNewBerryId(u8, u8); +static void IncrementBerryResult(u8, u8, u8); +static void UpdateBerriesPickedInRow(bool32); +static void SetMaxBerriesPickedInRow(void); +static void ResetForPlayAgainPrompt(void); +static void SetRandomPrize(void); +static void TryUpdateRecords(void); +static u8 UpdatePickStateQueue(u8); +static void HandleWaitPlayAgainInput(void); +static void ResetPickState(void); +static u32 GetHighestScore(void); +static void SendPacket_ReadyToStart(bool32); +static void SendPacket_GameState(struct DodrioGame_Player *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + u8 , bool32 , bool32 ); +static bool32 RecvPacket_GameState(u32, + struct DodrioGame_Player *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + u8 *, bool32 *, bool32 *); +static void SendPacket_PickState(u8); +static bool32 RecvPacket_PickState(u32, u8 *); +static void SendPacket_ReadyToEnd(bool32); +static bool32 RecvPacket_ReadyToEnd(u32); +static void LoadDodrioGfx(void); +static void CreateDodrioSprite(struct DodrioGame_MonInfo *, u8, u8, u8); +static void StartDodrioMissedAnim(u8); +static void StartDodrioIntroAnim(u8); +static void FreeDodrioSprites(u8); +static void SetAllDodrioInvisibility(bool8, u8); +static void CreateStatusBarSprites(void); +static void FreeStatusBar(void); +static void SetStatusBarInvisibility(bool8); +static void InitStatusBarPos(void); +static bool32 DoStatusBarIntro(void); +static void LoadBerryGfx(void); +static void CreateBerrySprites(void); +static void FreeBerrySprites(void); +static void CreateCloudSprites(void); +static void ResetCloudPos(void); +static void StartCloudMovement(void); +static void FreeCloudSprites(void); +static void SetCloudInvisibility(bool8); +static void ResetBerryAndStatusBarSprites(void); +static void ResetGfxState(void); +static void InitGameGfx(struct DodrioGame_Gfx *); +static void SetGfxFuncById(u8); +static bool32 IsGfxFuncActive(void); +static u8 GetPlayAgainState(void); +static void SetBerryInvisibility(u8, bool8); +static void SetBerryIconsInvisibility(bool8); +static void SetBerryAnim(u16, u8); +static void SetBerryYPos(u8, u8); +static void SetDodrioAnim(u8, u8); +static u8 GetNewBerryIdByDifficulty(u8, u8); +static void UpdateStatusBarAnim(u8); +static u32 RecvPacket_ReadyToStart(u32); +static u32 IncrementWithLimit(u32, u32); +static u32 Min(u32, u32); +static u32 GetScore(u8); +static void Task_ShowDodrioBerryPickingRecords(u8); +static void Task_TryRunGfxFunc(u8); +static void PrintRecordsText(u8, s32); +static void SpriteCB_Status(struct Sprite *); +static void SpriteCB_Dodrio(struct Sprite *); +static u32 DoDodrioMissedAnim(struct Sprite *); +static u32 DoDodrioIntroAnim(struct Sprite *); +static s16 GetDodrioXPos(u8, u8); +static void SetDodrioInvisibility(bool8, u8); +static void LoadGfx(void); +static bool32 LoadBgGfx(void); +static void InitBgs(void); +static void SetGfxFunc(void (*func)(void)); +static void (*GetGfxFunc(void))(void); +static void ShowNames(void); +static void ShowResults(void); +static void Msg_WantToPlayAgain(void); +static void Msg_SavingDontTurnOff(void); +static void Msg_CommunicationStandby(void); +static void EraseMessage(void); +static void Msg_SomeoneDroppedOut(void); +static void StopGfxFuncs(void); +static void GfxIdle(void); -// const rom data -static const u8 gUnknown_082F449C[5][5][11] = +// For each player, the array is a list of all the columns starting with the column to their left +// Only the range of active columns is read from the array (dependent on the number of players), +// so the arrays are spaced such that the numbers in the center are where the data that's read starts and end. +static const u8 sActiveColumnMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = +{ + { // 1 player (never used), columns 4-6. + // Sometimes read to get default order regardless of the current number of players + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + }, + { // 2 players (never used), columns 3-6 + {0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0}, + {0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0}, + }, + { // 3 players, columns 2-7 + {0, 1, 2, 3, 4, 5, 6, 7, 2, 9, 0}, + {0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0}, + {0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0}, + }, + { // 4 players, columns 1-8 + {0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0}, + {0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0}, + {0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0}, + {0, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0}, + }, + { // 5 players, all columns (0-9) + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, + { 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2 }, + { 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4 }, + { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 }, + { 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + }, +}; + +// A table for which falling berry column corresponds to which Dodrio head for each player +// The numbers in each array are the column number for each head, {left, middle, right} +// Dependent on the number of players +static const u8 sDodrioHeadToColumnMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = +{ + { // 1 player (never used) + {4, 5, 6}, + }, + { // 2 players (never used) + {3, 4, 5}, + {5, 6, 3}, + }, + { // 3 players + {4, 5, 6}, + {6, 7, 2}, + {2, 3, 4}, + }, + { // 4 players + {3, 4, 5}, + {5, 6, 7}, + {7, 8, 1}, + {1, 2, 3}, + }, + { // 5 players + {4, 5, 6}, + {6, 7, 8}, + {8, 9, 0}, + {0, 1, 2}, + {2, 3, 4}, + }, +}; + +// A table of player ids and their neighbor, dependent on the total number of players +// {L, M, R}, where M is the player in question, L is their neighbor to the left, and R is their neighbor to the right +static const u8 sDodrioNeighborMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = +{ + { // 1 player (never used) + {1, 0, 1}, + }, + { // 2 players (never used) + {1, 0, 1}, + {0, 1, 0}, + }, + { // 3 players + {2, 0, 1}, + {0, 1, 2}, + {1, 2, 0}, + }, + { // 4 players + {3, 0, 1}, + {0, 1, 2}, + {1, 2, 3}, + {2, 3, 0}, + }, + { // 5 players + {4, 0, 1}, + {0, 1, 2}, + {1, 2, 3}, + {2, 3, 4}, + {3, 4, 0}, + }, +}; + +#define __ 9 // No player at this column. This may go out of bounds if this is returned + +// Takes the number of players and a column and returns the player id at that column. +// Note that the assignment is somewhat arbitrary as players share neighboring columns. +ALIGNED(4) +static const u8 sPlayerIdAtColumn[MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = +{ + {__, __, __, __, 1, 1, 1, __, __, __, __}, // 1 player + {__, __, __, 0, 0, 1, 1, 0, __, __, __}, // 2 players + {__, __, 2, 2, 0, 0, 1, 1, 1, __, __}, // 3 players + {__, 3, 3, 0, 0, 1, 1, 2, 2, 3, __}, // 4 players + { 3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, // 5 players +}; + +#undef __ + +// Each array contains the columns that belong solely to one player, dependent on the number of players +// When determing how difficult the berries in a column should be, the highest +// difficulty of the players sharing that column is used. +// This table is used to skip that check, and instead automatically use the +// difficulty of the only player who can use the column. +static const u8 sUnsharedColumns[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS] = +{ + {5}, + {4, 6}, + {3, 5, 7}, + {2, 4, 6, 8}, +#ifndef BUGFIX + {1, 3, 5, 6, 9}, // BUG: Column 6 is shared, 7 is not. As a result, the player in column 7 will have their difficulty influenced by their neighbors +#else + {1, 3, 5, 7, 9}, +#endif +}; + +// Duplicate and unused gfx. Feel free to remove. +static const u32 sDuplicateGfx[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.gbapal", + "graphics/dodrio_berry_picking/tree_border.gbapal", + "graphics/dodrio_berry_picking/dodrio.gbapal", + "graphics/dodrio_berry_picking/shiny.gbapal", + "graphics/dodrio_berry_picking/status.gbapal", + "graphics/dodrio_berry_picking/berries.gbapal", + "graphics/dodrio_berry_picking/berries.4bpp.lz", + "graphics/dodrio_berry_picking/cloud.gbapal", + "graphics/dodrio_berry_picking/bg.4bpp.lz", + "graphics/dodrio_berry_picking/tree_border.4bpp.lz", + "graphics/dodrio_berry_picking/status.4bpp.lz", + "graphics/dodrio_berry_picking/cloud.4bpp.lz", + "graphics/dodrio_berry_picking/dodrio.4bpp.lz", + "graphics/dodrio_berry_picking/bg.bin.lz", + "graphics/dodrio_berry_picking/tree_border_right.bin.lz", + "graphics/dodrio_berry_picking/tree_border_left.bin.lz"); + + +static const u8 sBerryFallDelays[][3] = +{ + { [BERRY_BLUE] = 40, [BERRY_GREEN] = 24, [BERRY_GOLD] = 13 }, + { [BERRY_BLUE] = 32, [BERRY_GREEN] = 19, [BERRY_GOLD] = 10 }, + { [BERRY_BLUE] = 22, [BERRY_GREEN] = 13, [BERRY_GOLD] = 7 }, +}; + +// How far the outer tree borders should slide to reveal the game screen. +// Dependent on how many players are playing. +// Curiously the 2-player screen is narrower than the 1-player, though neither +// gets used as there's a 3 player minimum +ALIGNED(4) +static const u8 sTreeBorderXPos[MAX_RFU_PLAYERS] = {8, 5, 8, 11, 15}; + +// The number of berries eaten needed to progress to the next difficulty +ALIGNED(4) +static const u8 sDifficultyThresholds[NUM_DIFFICULTIES] = {5, 10, 20, 30, 50, 70, 100}; + +ALIGNED(4) +static const u8 sPrizeBerryIds[][10] = +{ + { // Possible prizes with 3 players + ITEM_TO_BERRY(ITEM_RAZZ_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BLUK_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NANAB_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WEPEAR_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PINAP_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PINAP_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WEPEAR_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NANAB_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BLUK_BERRY) - 1, + ITEM_TO_BERRY(ITEM_RAZZ_BERRY) - 1 + }, + { // Possible prizes with 4 players + ITEM_TO_BERRY(ITEM_POMEG_BERRY) - 1, + ITEM_TO_BERRY(ITEM_KELPSY_BERRY) - 1, + ITEM_TO_BERRY(ITEM_QUALOT_BERRY) - 1, + ITEM_TO_BERRY(ITEM_HONDEW_BERRY) - 1, + ITEM_TO_BERRY(ITEM_GREPA_BERRY) - 1, + ITEM_TO_BERRY(ITEM_TAMATO_BERRY) - 1, + ITEM_TO_BERRY(ITEM_CORNN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_MAGOST_BERRY) - 1, + ITEM_TO_BERRY(ITEM_RABUTA_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NOMEL_BERRY) - 1 + }, + { // Possible prizes with 5 players + ITEM_TO_BERRY(ITEM_SPELON_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PAMTRE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WATMEL_BERRY) - 1, + ITEM_TO_BERRY(ITEM_DURIN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BELUE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BELUE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_DURIN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WATMEL_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PAMTRE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_SPELON_BERRY) - 1 + }, +}; + +static void (*const sLeaderFuncs[])(void) = +{ + [FUNC_INTRO] = DoGameIntro, + [FUNC_INIT_COUNTDOWN] = InitCountdown, + [FUNC_COUNTDOWN] = DoCountdown, + [FUNC_WAIT_START] = WaitGameStart, + [FUNC_PLAY_GAME] = PlayGame_Leader, + [FUNC_INIT_RESULTS] = InitResults_Leader, + [FUNC_RESULTS] = DoResults, + [FUNC_ASK_PLAY_AGAIN] = AskPlayAgain, + [FUNC_END_LINK] = EndLink, + [FUNC_EXIT] = ExitGame, + [FUNC_RESET_GAME] = ResetGame, + [FUNC_WAIT_END_GAME] = WaitEndGame_Leader +}; + +static void (*const sMemberFuncs[])(void) = +{ + [FUNC_INTRO] = DoGameIntro, + [FUNC_INIT_COUNTDOWN] = InitCountdown, + [FUNC_COUNTDOWN] = DoCountdown, + [FUNC_WAIT_START] = WaitGameStart, + [FUNC_PLAY_GAME] = PlayGame_Member, + [FUNC_INIT_RESULTS] = InitResults_Member, + [FUNC_RESULTS] = DoResults, + [FUNC_ASK_PLAY_AGAIN] = AskPlayAgain, + [FUNC_END_LINK] = EndLink, + [FUNC_EXIT] = ExitGame, + [FUNC_RESET_GAME] = ResetGame, + [FUNC_WAIT_END_GAME] = WaitEndGame_Member +}; + +void StartDodrioBerryPicking(u16 partyId, void (*exitCallback)(void)) +{ + sExitingGame = FALSE; + + if (gReceivedRemoteLinkPlayers != 0 && (sGame = AllocZeroed(sizeof(*sGame)))) + { + ResetTasksAndSprites(); + InitDodrioGame(sGame); + sGame->exitCallback = exitCallback; + sGame->multiplayerId = GetMultiplayerId(); + sGame->player = sGame->players[sGame->multiplayerId]; + InitMonInfo(&sGame->monInfo[sGame->multiplayerId], &gPlayerParty[partyId]); + CreateTask(Task_StartDodrioGame, 1); + SetMainCallback2(CB2_DodrioGame); + SetRandomPrize(); + GetActiveBerryColumns(sGame->numPlayers, &sGame->berryColStart, &sGame->berryColEnd); + StopMapMusic(); + PlayNewMapMusic(MUS_RG_BERRY_PICK); + } + else + { + // Exit - Alloc failed, or players not connected + SetMainCallback2(exitCallback); + return; + } +} + +static void ResetTasksAndSprites(void) +{ + ResetTasks(); + ResetSpriteData(); + FreeAllSpritePalettes(); +} + +static void InitDodrioGame(struct DodrioGame * game) +{ + u8 i; + + game->startState = 0; + game->state = 0; + game->timer = 0; + game->funcId = FUNC_INTRO; + game->prevFuncId = FUNC_INTRO; + game->startGame = FALSE; + game->berriesFalling = FALSE; + game->countdownEndDelay = 0; + game->numGraySquares = 0; + game->unused2 = 0; + game->allReadyToEnd = FALSE; + + for (i = 0; i < ARRAY_COUNT(game->pickStateQueue); i++) + game->pickStateQueue[i] = PICK_NONE; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + game->inputState[i] = INPUTSTATE_NONE; + game->inputDelay[i] = 0; + game->berryResults[i][BERRY_BLUE] = 0; + game->berryResults[i][BERRY_GREEN] = 0; + game->berryResults[i][BERRY_GOLD] = 0; + game->berryResults[i][BERRY_MISSED] = 0; + game->berryResults[i][BERRY_IN_ROW] = 0; + game->playAgainStates[i] = PLAY_AGAIN_NONE; + game->readyToEnd[i] = FALSE; + } + + for (i = 0; i < NUM_BERRY_COLUMNS; i++) + { + game->fallTimer[i] = 0; + game->newBerryTimer[i] = 0; + game->berryState[i] = BERRYSTATE_NONE; + game->playersAttemptingPick[i][0] = PLAYER_NONE; + game->playersAttemptingPick[i][1] = PLAYER_NONE; + } + + game->isLeader = GetMultiplayerId() == 0 ? TRUE : FALSE; + game->numPlayers = GetLinkPlayerCount(); + game->posToPlayerId[0] = GetMultiplayerId(); + for (i = 1; i < game->numPlayers; i++) + { + game->posToPlayerId[i] = game->posToPlayerId[i - 1] + 1; + if (game->posToPlayerId[i] > game->numPlayers - 1) + game->posToPlayerId[i] %= game->numPlayers; + } +} + +static void Task_StartDodrioGame(u8 taskId) +{ + u8 i, numPlayers; + + switch (sGame->startState) + { + case 0: + SetVBlankCallback(NULL); + CreateTask_(Task_CommunicateMonInfo, 4); + sGame->startState++; + break; + case 1: + if (!FuncIsActiveTask(Task_CommunicateMonInfo)) + { + InitGameGfx(&sGame->gfx); + sGame->startState++; + } + break; + case 2: + if (!IsGfxFuncActive()) + { + Rfu_SetLinkStandbyCallback(); + sGame->startState++; + } + break; + case 3: + if (IsLinkTaskFinished()) + { + if (gReceivedRemoteLinkPlayers != 0) + { + LoadWirelessStatusIndicatorSpriteGfx(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + sGame->startState++; + } + break; + case 4: + numPlayers = sGame->numPlayers; + LoadDodrioGfx(); + for (i = 0; i < numPlayers; i++) + CreateDodrioSprite(&sGame->monInfo[sGame->posToPlayerId[i]], i, sGame->posToPlayerId[i], sGame->numPlayers); + + SetAllDodrioInvisibility(FALSE, sGame->numPlayers); + sGame->startState++; + break; + case 5: + LoadBerryGfx(); + CreateBerrySprites(); + CreateCloudSprites(); + CreateStatusBarSprites(); + sGame->startState++; + break; + case 6: + BlendPalettes(PALETTES_ALL, 0x10, 0x00); + BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); + SetVBlankCallback(VBlankCB_DodrioGame); + sGame->startState++; + break; + case 7: + UpdatePaletteFade(); + if (!gPaletteFade.active) + sGame->startState++; + break; + default: + DestroyTask(taskId); + CreateDodrioGameTask(Task_NewGameIntro); + break; + } +} + +static void Task_DodrioGame_Leader(u8 taskId) +{ + RecvLinkData_Leader(); + sLeaderFuncs[sGame->funcId](); + if (!sExitingGame) + UpdateGame_Leader(); + + SendLinkData_Leader(); +} + +static void Task_DodrioGame_Member(u8 taskId) +{ + RecvLinkData_Member(); + sMemberFuncs[sGame->funcId](); + if (!sExitingGame) + UpdateGame_Member(); + + SendLinkData_Member(); +} + +static void DoGameIntro(void) +{ + switch (sGame->state) + { + case 0: + StartDodrioIntroAnim(1); + SetGfxFuncById(GFXFUNC_SHOW_NAMES); + sGame->state++; + break; + case 1: + if (!IsGfxFuncActive()) + SetGameFunc(FUNC_INIT_COUNTDOWN); + break; + } +} + +static void InitCountdown(void) +{ + switch (sGame->state) + { + case 0: + InitFirstWaveOfBerries(); + sGame->state++; + break; + default: + sGame->startCountdown = TRUE; + SetGameFunc(FUNC_COUNTDOWN); + break; + } +} + +static void DoCountdown(void) +{ + switch (sGame->state) + { + case 0: + StartMinigameCountdown(7, 8, 120, 80, 0); + sGame->state++; + break; + case 1: + Rfu_SetLinkStandbyCallback(); + sGame->state++; + break; + case 2: + if (IsLinkTaskFinished()) + { + sGame->state++; + sGame->countdownEndDelay = 0; + } + break; + case 3: + if (!IsMinigameCountdownRunning()) + sGame->state++; + break; + case 4: + if (++sGame->countdownEndDelay > 5) + { + Rfu_SetLinkStandbyCallback(); + sGame->state++; + } + break; + case 5: + if (IsLinkTaskFinished()) + SetGameFunc(FUNC_WAIT_START); + break; + } +} + +static void WaitGameStart(void) +{ + switch (sGame->state) + { + case 0: + if (sGame->startGame) + SetGameFunc(FUNC_PLAY_GAME); + break; + } +} + +static void PlayGame_Leader(void) +{ + switch (sGame->state) + { + case 0: + if (sGame->numGraySquares < NUM_STATUS_SQUARES) + { + if (sGame->inputState[0] == INPUTSTATE_NONE) + { + if (JOY_NEW(DPAD_UP)) + { + if (sGame->players[0].comm.pickState == PICK_NONE) + { + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_MIDDLE); + } + } + else if (JOY_NEW(DPAD_RIGHT)) + { + if (sGame->players[0].comm.pickState == PICK_NONE) + { + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_RIGHT); + } + } + else if (JOY_NEW(DPAD_LEFT)) + { + if (sGame->players[0].comm.pickState == PICK_NONE) + { + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_LEFT); + } + } + else + { + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_NONE); + } + } + } + else + { + SetGameFunc(FUNC_WAIT_END_GAME); + } + UpdateFallingBerries(); + HandleSound_Leader(); + break; + } +} + +static void PlayGame_Member(void) +{ + if (sGame->numGraySquares < NUM_STATUS_SQUARES) + { + if (JOY_NEW(DPAD_UP)) + { + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) + { + sGame->player.comm.pickState = PICK_MIDDLE; + } + } + else if (JOY_NEW(DPAD_RIGHT)) + { + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) + { + sGame->player.comm.pickState = PICK_RIGHT; + } + } + else if (JOY_NEW(DPAD_LEFT)) + { + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) + { + sGame->player.comm.pickState = PICK_LEFT; + } + } + else + { + sGame->player.comm.pickState = PICK_NONE; + } + } + else + { + SetGameFunc(FUNC_WAIT_END_GAME); + } + HandleSound_Member(); +} + +static void WaitEndGame_Leader(void) +{ + u8 i; + + UpdateFallingBerries(); + HandleSound_Leader(); + if (ReadyToEndGame_Leader() == TRUE) + { + SetMaxBerriesPickedInRow(); + SetGameFunc(FUNC_INIT_RESULTS); + } + else + { + sGame->allReadyToEnd = TRUE; + for (i = 1; i < sGame->numPlayers; i++) + { + if (sGame->readyToEnd[i] != TRUE) + { + sGame->allReadyToEnd = FALSE; + break; + } + } + } +} + +static void WaitEndGame_Member(void) +{ + HandleSound_Member(); + if (ReadyToEndGame_Member() == TRUE) + SetGameFunc(FUNC_INIT_RESULTS); +} + +static bool32 AllLinkBlocksReceived(void) +{ + u8 recvStatus = GetBlockReceivedStatus(); + u8 playerFlags = GetLinkPlayerCountAsBitFlags(); + if (recvStatus == playerFlags) + { + ResetBlockReceivedFlags(); + return TRUE; + } + else + { + return FALSE; + } +} + +static void InitResults_Leader(void) +{ + switch (sGame->state) + { + case 0: + if (SendBlock(0, sGame->berryResults, sizeof(sGame->berryResults))) + { + sGame->playersReceived = 0; + sGame->state++; + } + break; + case 1: + if (IsLinkTaskFinished()) + { + sGame->state++; + } + break; + case 2: + if (AllLinkBlocksReceived()) + { + sGame->playersReceived = sGame->numPlayers; + } + if (sGame->playersReceived >= sGame->numPlayers) + { + sGame->timer++; + sGame->state++; + } + break; + default: + if (WaitFanfare(TRUE)) + { + SetGameFunc(FUNC_RESULTS); + FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); + } + break; + } +} + +static void InitResults_Member(void) +{ + u8 i; + + switch (sGame->state) { + case 0: + if (SendBlock(0, sGame->berryResults[sGame->timer], sizeof(sGame->berryResults))) { + sGame->playersReceived = 0; + sGame->state++; + } + break; + case 1: + if (IsLinkTaskFinished()) { + sGame->state++; + } + break; + case 2: + if (AllLinkBlocksReceived()) { + for (i = 0; i < sGame->numPlayers; i++) { + memcpy(sGame->berryResults, gBlockRecvBuffer, sizeof(sGame->berryResults)); + sGame->playersReceived = sGame->numPlayers; + } + } + if (sGame->playersReceived >= sGame->numPlayers) { + sGame->timer++; + sGame->state++; + } + break; + default: + if (WaitFanfare(TRUE)) { + sGame->maxBerriesPickedInRow = sGame->berryResults[sGame->multiplayerId][BERRY_IN_ROW]; + SetGameFunc(FUNC_RESULTS); + FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); + } + break; + } +} + +static void DoResults(void) +{ + u8 playAgainState = PLAY_AGAIN_YES; + u8 i; + + switch (sGame->state) + { + case 0: + TryUpdateRecords(); + SetStatusBarInvisibility(TRUE); + ResetCloudPos(); + SetCloudInvisibility(TRUE); + SetGfxFuncById(GFXFUNC_SHOW_RESULTS); + sGame->state++; + break; + case 1: + if (!IsGfxFuncActive()) + { + SetGfxFuncById(GFXFUNC_MSG_COMM_STANDBY); + sGame->state++; + } + break; + case 2: + playAgainState = GetPlayAgainState(); + if (SendBlock(0, &playAgainState, sizeof(playAgainState))) + sGame->state++; + break; + case 3: + if (IsLinkTaskFinished()) + { + sGame->state++; + sGame->playersReceived = 0; + } + break; + case 4: + if (AllLinkBlocksReceived()) + { + for (i = 0; i < sGame->numPlayers; i++) + { + *(&sGame->playAgainStates[i]) = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; + } + } + if (sGame->playersReceived >= sGame->numPlayers) + { + if (++sGame->timer >= 120) + { + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; + } + } + break; + default: + if (!IsGfxFuncActive()) + SetGameFunc(FUNC_ASK_PLAY_AGAIN); + break; + } +} + +static void AskPlayAgain(void) +{ + u8 playAgainState; + u8 i; + + switch (sGame->state) + { + case 0: + if (GetHighestScore() >= PRIZE_SCORE) + { + SetGfxFuncById(GFXFUNC_MSG_SAVING); + } + sGame->state++; + break; + case 1: + if (!IsGfxFuncActive()) + { + SetGfxFuncById(GFXFUNC_MSG_PLAY_AGAIN); + sGame->state++; + } + break; + case 2: + ResetBerryAndStatusBarSprites(); + ResetForPlayAgainPrompt(); + sGame->state++; + break; + case 3: + if ((playAgainState = GetPlayAgainState()) != PLAY_AGAIN_NONE) + { + sGame->state++; + } + break; + case 4: + if (!IsGfxFuncActive()) + { + SetGfxFuncById(GFXFUNC_MSG_COMM_STANDBY); + sGame->state++; + } + break; + case 5: + playAgainState = GetPlayAgainState(); + if (SendBlock(0, &playAgainState, sizeof(playAgainState))) + { + sGame->playersReceived = 0; + sGame->state++; + } + break; + case 6: + if (IsLinkTaskFinished()) + sGame->state++; + break; + case 7: + if (AllLinkBlocksReceived()) + { + for (i = 0; i < sGame->numPlayers; i++) + { + *(&sGame->playAgainStates[i]) = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; + } + } + if (sGame->playersReceived >= sGame->numPlayers) + { + if (++sGame->timer >= 120) + { + ResetPickState(); + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; + } + } + else + { + HandleWaitPlayAgainInput(); + } + break; + default: + if (!IsGfxFuncActive()) + { + for (i = 0; i < sGame->numPlayers; i++) + { + if (sGame->playAgainStates[i] == PLAY_AGAIN_NO) + { + SetGameFunc(FUNC_END_LINK); + return; + } + } + SetGameFunc(FUNC_RESET_GAME); + } + break; + } +} + +static void EndLink(void) +{ + switch (sGame->state) + { + case 0: + SetCloseLinkCallback(); + SetGfxFuncById(GFXFUNC_MSG_PLAYER_DROPPED); + sGame->state++; + break; + case 1: + if (!IsGfxFuncActive()) + sGame->state++; + break; + case 2: + if (GetPlayAgainState() == PLAY_AGAIN_DROPPED) + sGame->state++; + break; + default: + if (gReceivedRemoteLinkPlayers == 0) + { + SetGameFunc(FUNC_EXIT); + } + break; + } +} + +static void ExitGame(void) +{ + switch (sGame->state) + { + case 0: + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); + sGame->state++; + break; + case 1: + UpdatePaletteFade(); + if (!gPaletteFade.active) + sGame->state++; + break; + case 2: + FreeBerrySprites(); + FreeStatusBar(); + FreeDodrioSprites(sGame->numPlayers); + FreeCloudSprites(); + sExitingGame = TRUE; + SetGfxFuncById(GFXFUNC_STOP); + sGame->state++; + break; + default: + if (!IsGfxFuncActive()) + { + SetMainCallback2(sGame->exitCallback); + DestroyTask(sGame->taskId); + Free(sGame); + FreeAllWindowBuffers(); + } + break; + } +} + +static void ResetGame(void) +{ + switch (sGame->state) + { + case 0: + SetGfxFuncById(GFXFUNC_IDLE); + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); + sGame->state++; + break; + case 1: + UpdatePaletteFade(); + if (!gPaletteFade.active) + { + sGame->state++; + } + break; + case 2: + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); + sGame->state++; + break; + case 3: + StopMapMusic(); + sGame->state++; + break; + case 4: + PlayNewMapMusic(MUS_RG_BERRY_PICK); + StartCloudMovement(); + sGame->state++; + break; + case 5: + BlendPalettes(PALETTES_ALL, 16, 0); + BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); + sGame->state++; + break; + case 6: + UpdatePaletteFade(); + if (!gPaletteFade.active) + sGame->state++; + break; + default: + DestroyTask(sGame->taskId); + CreateDodrioGameTask(Task_NewGameIntro); + ResetGfxState(); + InitDodrioGame(sGame); + if (gReceivedRemoteLinkPlayers == 0) + sGame->numPlayers = 1; + + SetRandomPrize(); + SetCloudInvisibility(FALSE); + break; + } +} + +static void Task_NewGameIntro(u8 taskId) +{ + switch (sGame->state) + { + case 0: + if (SlideTreeBordersOut() == TRUE) + sGame->state++; + break; + case 1: + InitStatusBarPos(); + sGame->state++; + break; + case 2: + if (DoStatusBarIntro() == TRUE) + sGame->state++; + break; + default: + if (sGame->isLeader) + CreateDodrioGameTask(Task_DodrioGame_Leader); + else + CreateDodrioGameTask(Task_DodrioGame_Member); + + DestroyTask(taskId); + break; + } +} + +#define tState data[0] + +static void Task_CommunicateMonInfo(u8 taskId) +{ + s16 * data = gTasks[taskId].data; + u8 i; + + switch (tState) + { + case 0: + if (SendBlock(0, &sGame->monInfo[sGame->multiplayerId].isShiny, sizeof(sGame->monInfo[sGame->multiplayerId].isShiny))) + { + sGame->playersReceived = 0; + tState++; + } + break; + case 1: + if (IsLinkTaskFinished()) + tState++; + break; + case 2: + if (AllLinkBlocksReceived()) + { + for (i = 0; i < sGame->numPlayers; i++) + { + *(u8 *)&sGame->monInfo[i] = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; + } + } + if (sGame->playersReceived >= sGame->numPlayers) + { + DestroyTask(taskId); + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; + } + break; + } +} + +#undef tState + +static void RecvLinkData_Gameplay(void) +{ + u8 i; + u8 numPlayers = sGame->numPlayers; + + sGame->players[0].receivedGameStatePacket = RecvPacket_GameState(0, + &sGame->players[0], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + sGame->clearRecvCmds = TRUE; + + for (i = 1; i < numPlayers; i++) + { + if (sGame->inputState[i] == INPUTSTATE_NONE && !RecvPacket_PickState(i, &sGame->players[i].comm.pickState)) + { + sGame->players[i].comm.pickState = PICK_NONE; + sGame->clearRecvCmds = FALSE; + } + } + if (++sGame->clearRecvCmdTimer >= 60) + { + if (sGame->clearRecvCmds) + { + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; + } + else if (sGame->clearRecvCmdTimer > 70) + { + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; + } + } + + for (i = 0; i < numPlayers; i++) + { + if (sGame->players[i].comm.pickState != PICK_NONE && sGame->inputState[i] == INPUTSTATE_NONE) + { + sGame->inputState[i] = INPUTSTATE_TRY_PICK; + } + switch (sGame->inputState[i]) + { + case INPUTSTATE_NONE: + default: + break; + case INPUTSTATE_TRY_PICK: + case INPUTSTATE_PICKED: + case INPUTSTATE_ATE_BERRY: + if (++sGame->inputDelay[i] >= 6) + { + sGame->inputDelay[i] = 0; + sGame->inputState[i] = INPUTSTATE_NONE; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->players[i].comm.missedBerry = FALSE; + } + break; + case INPUTSTATE_BAD_MISS: + // Tried to pick with no berry in range, long delay until next input + if (++sGame->inputDelay[i] >= 40) + { + sGame->inputDelay[i] = 0; + sGame->inputState[i] = INPUTSTATE_NONE; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->players[i].comm.missedBerry = FALSE; + } + break; + } + } +} + +static void RecvLinkData_ReadyToEnd(void) +{ + u8 i; + u8 numPlayers = sGame->numPlayers; + + sGame->players[0].receivedGameStatePacket = RecvPacket_GameState(0, + &sGame->players[0], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + sGame->clearRecvCmds = TRUE; + + for (i = 1; i < numPlayers; i++) + { + if (RecvPacket_ReadyToEnd(i)) + { + sGame->readyToEnd[i] = TRUE; + sGame->clearRecvCmds = FALSE; + } + } + if (++sGame->clearRecvCmdTimer >= 60) + { + if (sGame->clearRecvCmds) + { + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; + } + else if (sGame->clearRecvCmdTimer > 70) + { + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; + } + } +} + +static void RecvLinkData_Leader(void) +{ + switch (sGame->funcId) + { + case FUNC_WAIT_START: + if (AllPlayersReadyToStart() == TRUE) + { + ResetReadyToStart(); + sGame->startGame = TRUE; + } + break; + case FUNC_PLAY_GAME: + RecvLinkData_Gameplay(); + break; + case FUNC_WAIT_END_GAME: + RecvLinkData_ReadyToEnd(); + break; + } +} + +static void SendLinkData_Leader(void) +{ + switch (sGame->funcId) + { + case FUNC_PLAY_GAME: + SendPacket_GameState(&sGame->player, + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + sGame->numGraySquares, + sGame->berriesFalling, + sGame->allReadyToEnd); + break; + case FUNC_WAIT_END_GAME: + SendPacket_GameState(&sGame->player, + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + sGame->numGraySquares, + sGame->berriesFalling, + sGame->allReadyToEnd); + break; + } +} + +static void RecvLinkData_Member(void) +{ + switch (sGame->funcId) + { + case FUNC_PLAY_GAME: + RecvPacket_GameState(sGame->multiplayerId, + &sGame->players[sGame->multiplayerId], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + break; + case FUNC_WAIT_END_GAME: + RecvPacket_GameState(sGame->multiplayerId, + &sGame->players[sGame->multiplayerId], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + break; + } +} + +static void SendLinkData_Member(void) +{ + switch (sGame->funcId) + { + case FUNC_WAIT_START: + SendPacket_ReadyToStart(TRUE); + sGame->startGame = TRUE; + break; + case FUNC_PLAY_GAME: + if (sGame->player.comm.pickState != PICK_NONE) + { + SendPacket_PickState(sGame->player.comm.pickState); + } + break; + case FUNC_WAIT_END_GAME: + if (!sGame->berriesFalling && !sGame->allReadyToEnd) + SendPacket_ReadyToEnd(TRUE); + break; + } +} + +static void HandleSound_Leader(void) +{ + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) + { + if (!IsSEPlaying()) + sGame->playingPickSound = FALSE; + } + else if (sGame->players[sGame->multiplayerId].comm.ateBerry == TRUE) + { + if (!sGame->playingPickSound) + { + m4aSongNumStop(SE_SUCCESS); + PlaySE(SE_SUCCESS); + sGame->playingPickSound = TRUE; + } + } + else if (sGame->players[sGame->multiplayerId].comm.missedBerry == TRUE) + { + if (!sGame->playingPickSound && !IsSEPlaying()) + { + PlaySE(SE_BOO); + StartDodrioMissedAnim(1); + sGame->playingPickSound = TRUE; + } + } + + if (sGame->endSoundState == 0 && sGame->numGraySquares >= NUM_STATUS_SQUARES) + { + // Ready to play game over sound + StopMapMusic(); + sGame->endSoundState = 1; + } + else if (sGame->endSoundState == 1) + { + // Play game over sound + PlayFanfareByFanfareNum(FANFARE_TOO_BAD); + sGame->endSoundState = 2; + } +} + +static void HandleSound_Member(void) +{ + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 i; + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) + { + if (sGame->players[sGame->multiplayerId].comm.ateBerry != TRUE + && sGame->players[sGame->multiplayerId].comm.missedBerry != TRUE) + sGame->playingPickSound = 0; + } + else if (sGame->players[sGame->multiplayerId].comm.ateBerry == TRUE) + { + if (!sGame->playingPickSound) + { + m4aSongNumStop(SE_SUCCESS); + PlaySE(SE_SUCCESS); + sGame->playingPickSound = TRUE; + } + } + else if (sGame->players[sGame->multiplayerId].comm.missedBerry == TRUE) + { + if (!sGame->playingPickSound && !IsSEPlaying()) + { + PlaySE(SE_BOO); + StartDodrioMissedAnim(1); + sGame->playingPickSound = TRUE; + } + } + for (i = berryStart; i < berryEnd; i++) + { + struct DodrioGame_Berries * berries = &sGame->players[sGame->multiplayerId].berries; + if (berries->fallDist[i] >= MAX_FALL_DIST) + { + if (!sGame->playingSquishSound[i]) + { + PlaySE(SE_BALLOON_RED + berries->ids[i]); + sGame->playingSquishSound[i] = TRUE; + } + } + else + { + sGame->playingSquishSound[i] = FALSE; + } + } + if (sGame->endSoundState == 0 && sGame->numGraySquares >= NUM_STATUS_SQUARES) + { + // Ready to play game over sound + StopMapMusic(); + sGame->endSoundState = 1; + } + else if (sGame->endSoundState == 1) + { + // Play game over sound + PlayFanfareByFanfareNum(FANFARE_TOO_BAD); + sGame->endSoundState = 2; + } +} + +static void CB2_DodrioGame(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void VBlankCB_DodrioGame(void) +{ + TransferPlttBuffer(); + LoadOam(); + ProcessSpriteCopyRequests(); +} + +static void InitMonInfo(struct DodrioGame_MonInfo * monInfo, struct Pokemon * mon) +{ + monInfo->isShiny = IsMonShiny(mon); +} + +static void CreateTask_(TaskFunc func, u8 priority) +{ + CreateTask(func, priority); +} + +static void CreateDodrioGameTask(TaskFunc func) +{ + sGame->taskId = CreateTask(func, 1); + sGame->state = 0; + sGame->startState = 0; + sGame->timer = 0; +} + +static void SetGameFunc(u8 funcId) +{ + sGame->prevFuncId = sGame->funcId; + sGame->funcId = funcId; + sGame->state = 0; + sGame->timer = 0; +} + +static bool32 SlideTreeBordersOut(void) +{ + u8 x = sGame->timer / 4; + sGame->timer++; + if (x != 0 && sGame->timer % 4 == 0) + { + if (x < sTreeBorderXPos[sGame->numPlayers - 1]) + { + // Update position + SetGpuReg(REG_OFFSET_BG1HOFS, (x * 8)); // BG_TREE_LEFT + SetGpuReg(REG_OFFSET_BG2HOFS, -(x * 8)); // BG_TREE_RIGHT + return FALSE; + } + else + { + // Animation finished + return TRUE; + } + } + else + { + return FALSE; + } +} + +static void InitFirstWaveOfBerries(void) +{ + u8 i; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + + for (i = berryStart; i < berryEnd; i++) + { + struct DodrioGame_Berries * berries = &sGame->player.berries; + berries->fallDist[i] = (i % 2 == 0) ? 1 : 0; + berries->ids[i] = BERRY_BLUE; + } +} + +// This function checks every berry and resolves if it should be eaten or not. +// It's run in a loop that handles moving each individual berry, which means +// that every time any berry moves, every single berry is checked. +static void HandlePickBerries(void) +{ + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 numPlayers = sGame->numPlayers; + u8 i, j, k, column; + + // Game is already over + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + return; + + for (i = 0; i < numPlayers; i++) + { + u8 *pickState = &sGame->players[i].comm.pickState; + if (*pickState != PICK_NONE && sGame->inputState[i] == INPUTSTATE_TRY_PICK) + { + // Player is attempting to pick a berry + for (j = berryStart; j < berryEnd; j++) + { + column = sActiveColumnMap[0][0][j]; + + // Attempt has already been checked + if (sGame->playersAttemptingPick[column][0] == i + || sGame->playersAttemptingPick[column][1] == i) + break; + + // Check berry pick attempt + if (TryPickBerry(i, *pickState, column) == TRUE) + { + // Attempt was successful + for (k = 0; k < ARRAY_COUNT(sGame->playersAttemptingPick[0]); k++) + { + if (sGame->playersAttemptingPick[column][k] == PLAYER_NONE) + { + sGame->playersAttemptingPick[column][k] = i; + sGame->inputState[i] = INPUTSTATE_PICKED; + sGame->berryState[column] = BERRYSTATE_PICKED; + break; + } + } + break; + } + if (sGame->players[i].comm.missedBerry == TRUE) + break; + } + } + } + + for (j = berryStart; j < berryEnd; j++) + { + u8 playerIdMissed = PLAYER_NONE; + column = sActiveColumnMap[0][0][j]; + if (sGame->berryState[column] == BERRYSTATE_PICKED) + { + s32 delayRemaining; + u8 playerIdPicked, delayStage = sGame->difficulty[GetPlayerIdAtColumn(column)] / NUM_DIFFICULTIES; + if (delayStage >= ARRAY_COUNT(sBerryFallDelays) - 1) + delayStage = ARRAY_COUNT(sBerryFallDelays) - 1; + + delayRemaining = sBerryFallDelays[delayStage][sGame->players[0].berries.ids[column]] - sGame->fallTimer[column]; + if (delayRemaining < 6) + sGame->eatTimer[column] += delayRemaining; + + if (++sGame->eatTimer[column] >= 6) + { + sGame->eatTimer[column] = 0; + + if (sGame->playersAttemptingPick[column][0] == PLAYER_NONE + && sGame->playersAttemptingPick[column][1] == PLAYER_NONE) + { + // No players attempting to pick this berry + continue; + } + else if (sGame->playersAttemptingPick[column][0] != PLAYER_NONE + && sGame->playersAttemptingPick[column][1] == PLAYER_NONE) + { + // One player attempting to pick this berry + playerIdPicked = sGame->playersAttemptingPick[column][0]; + } + else + { + // Two players attempting to pick this berry + // Randomly give it to one of them + u8 playerId1 = sGame->playersAttemptingPick[column][0]; + i = sGame->playersAttemptingPick[column][1]; // playerId2. Have to re-use the variable to match. + if (!(Random() & 1)) + { + playerIdPicked = playerId1; + playerIdMissed = i; + } + else + { + playerIdPicked = i; + playerIdMissed = playerId1; + } + } + + // Eat berry + sGame->player.berries.fallDist[column] = EAT_FALL_DIST; + sGame->berryState[column] = BERRYSTATE_EATEN; + sGame->inputState[playerIdPicked] = INPUTSTATE_ATE_BERRY; + sGame->berryEatenBy[column] = playerIdPicked; + sGame->players[playerIdPicked].comm.ateBerry = TRUE; +#ifdef UBFIX + if (playerIdMissed != PLAYER_NONE) +#endif + sGame->players[playerIdMissed].comm.missedBerry = TRUE; // UB: playerIdMissed can be PLAYER_NONE here, which is out of bounds + + sGame->berriesEaten[playerIdPicked]++; + IncrementBerryResult(0, column, playerIdPicked); + UpdateBerriesPickedInRow(TRUE); + TryIncrementDifficulty(playerIdPicked); + sGame->prevBerryIds[column] = sGame->player.berries.ids[column]; + sGame->player.berries.ids[column] = BERRY_MISSED; // Just to clear berry id, wasn't actually missed + sGame->playersAttemptingPick[column][0] = PLAYER_NONE; + sGame->playersAttemptingPick[column][1] = PLAYER_NONE; + } + } + } +} + +static bool32 TryPickBerry(u8 playerId, u8 pickState, u8 column) +{ + s32 pick = 0; + u8 numPlayersIdx = sGame->numPlayers - 1; + struct DodrioGame_Berries * berries = &sGame->player.berries; + + switch (pickState) + { + case PICK_LEFT: + default: + pick = 0; + break; + case PICK_MIDDLE: + pick = 1; + break; + case PICK_RIGHT: + pick = 2; + break; + } + + // Check if berry is within range to be picked + if (berries->fallDist[column] == EAT_FALL_DIST - 1 || berries->fallDist[column] == EAT_FALL_DIST) + { + // Check if this berry is the one the player is trying to pick + if (column == sDodrioHeadToColumnMap[numPlayersIdx][playerId][pick]) + { + // Check if berry has been picked/eaten by another player + if (sGame->berryState[column] == BERRYSTATE_PICKED || sGame->berryState[column] == BERRYSTATE_EATEN) + { + // Missed berry, picked by someone else + sGame->players[playerId].comm.missedBerry = TRUE; + return FALSE; + } + else + { + // Successfully picked berry + return TRUE; + } + } + } + else + { + // Check if this berry is the one the player is trying to pick + if (column == sDodrioHeadToColumnMap[numPlayersIdx][playerId][pick]) + { + // Missed berry, out of range + sGame->inputState[playerId] = INPUTSTATE_BAD_MISS; + sGame->players[playerId].comm.missedBerry = TRUE; + } + } + return FALSE; +} + +static void UpdateFallingBerries(void) +{ + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 delayStage = 0; + u8 otherBerryMissed = 0; + u8 i; + + sGame->berriesFalling = FALSE; + + for (i = berryStart; i < berryEnd - 1; i++) + { + struct DodrioGame *game = sGame; + + if (sGame->berryState[i] == BERRYSTATE_NONE || sGame->berryState[i] == BERRYSTATE_PICKED) + { + sGame->berriesFalling = TRUE; + + if (game->player.berries.fallDist[i] >= MAX_FALL_DIST) + { + // Berry hit the ground + game->player.berries.fallDist[i] = MAX_FALL_DIST; + sGame->berryState[i] = BERRYSTATE_SQUISHED; + if (!sGame->playingSquishSound[i]) + { + sGame->playingSquishSound[i] = TRUE; + PlaySE(SE_BALLOON_RED + game->player.berries.ids[i]); + } + if (sGame->numGraySquares < NUM_STATUS_SQUARES || otherBerryMissed == TRUE) + { + otherBerryMissed = TRUE; + sGame->playingSquishSound[i] = FALSE; + if (sGame->numGraySquares < NUM_STATUS_SQUARES) + sGame->numGraySquares++; + + IncrementBerryResult(BERRY_MISSED, i, 0); + UpdateBerriesPickedInRow(FALSE); + } + } + else + { + // Berry is still falling + u8 delay; + delayStage = sGame->difficulty[GetPlayerIdAtColumn(i)] / NUM_DIFFICULTIES; + if (delayStage >= ARRAY_COUNT(sBerryFallDelays) - 1) + delayStage = ARRAY_COUNT(sBerryFallDelays) - 1; + + delay = sBerryFallDelays[delayStage][game->player.berries.ids[i]]; + if (++sGame->fallTimer[i] >= delay) + { + game->player.berries.fallDist[i]++; + sGame->fallTimer[i] = 0; + } + HandlePickBerries(); + } + } + else if (sGame->berryState[i] == BERRYSTATE_EATEN) + { + // Berry has been eaten, wait and create a new berry + sGame->berriesFalling = TRUE; + if (++sGame->newBerryTimer[i] >= 20) + { + sGame->players[sGame->berryEatenBy[i]].comm.ateBerry = FALSE; + sGame->newBerryTimer[i] = 0; + sGame->fallTimer[i] = 0; + sGame->berryState[i] = BERRYSTATE_NONE; + game->player.berries.fallDist[i] = 1; + game->player.berries.ids[i] = GetNewBerryId(GetPlayerIdAtColumn(i), i); + } + } + else if (sGame->berryState[i] == BERRYSTATE_SQUISHED) + { + // Berry has already hit the ground, wait and create a new berry + if (++sGame->newBerryTimer[i] >= 20) + { + if (sGame->numGraySquares < NUM_STATUS_SQUARES) + { + sGame->newBerryTimer[i] = 0; + sGame->fallTimer[i] = 0; + sGame->berryState[i] = BERRYSTATE_NONE; + game->player.berries.fallDist[i] = 1; + sGame->prevBerryIds[i] = game->player.berries.ids[i]; + game->player.berries.ids[i] = GetNewBerryId(GetPlayerIdAtColumn(i), i); + } + } + } + } +} + +static void UpdateBerrySprites(void) +{ + u8 i; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + + for (i = berryStart; i < berryEnd; i++) + { + struct DodrioGame_Player *player = &sGame->players[sGame->multiplayerId]; + u8 column = sActiveColumnMap[sGame->numPlayers - 1][sGame->multiplayerId][i]; + + if (player->berries.fallDist[column] != 0) + SetBerryInvisibility(i, FALSE); + else + SetBerryInvisibility(i, TRUE); + + if (player->berries.fallDist[column] >= MAX_FALL_DIST) + { + // Berry was missed, set squished anim + SetBerryAnim(i, player->berries.ids[column] + BERRY_MISSED); + SetBerryYPos(i, player->berries.fallDist[column] * 2 - 1); + } + else if (player->berries.ids[column] == 3) + { + // Berry was picked, set eaten anim + player->berries.fallDist[column] = EAT_FALL_DIST; + SetBerryAnim(i, ANIM_EATEN); + SetBerryYPos(i, player->berries.fallDist[column] * 2 - 1); + } + else + { + // Berry is still falling + SetBerryAnim(i, player->berries.ids[column]); + SetBerryYPos(i, player->berries.fallDist[column] * 2); + } + } +} + +static void UpdateAllDodrioAnims(void) +{ + u8 i, numPlayers; + + numPlayers = sGame->numPlayers; + for (i = 0; i < numPlayers; i++) + { + struct DodrioGame_Player *player = &sGame->players[i]; + SetDodrioAnim(i, player->comm.pickState); + } +} + +static void SetAllDodrioDisabled(void) +{ + u8 i, numPlayers; + + numPlayers = sGame->numPlayers; + for (i = 0; i < numPlayers; i++) + SetDodrioAnim(i, PICK_DISABLED); +} + +static void UpdateGame_Leader(void) +{ + UpdateBerrySprites(); + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + SetAllDodrioDisabled(); + else + UpdateAllDodrioAnims(); + + UpdateStatusBarAnim(sGame->numGraySquares); +} + +// Identical to UpdateGame_Leader +static void UpdateGame_Member(void) +{ + UpdateBerrySprites(); + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + SetAllDodrioDisabled(); + else + UpdateAllDodrioAnims(); + + UpdateStatusBarAnim(sGame->numGraySquares); +} + +static void GetActiveBerryColumns(u8 numPlayers, u8 *start, u8 *end) +{ + switch (numPlayers) + { + case 1: + *start = 4, *end = 7; + break; + case 2: + *start = 3, *end = 8; + break; + case 3: + *start = 2, *end = 9; + break; + case 4: + *start = 1, *end = 10; + break; + case 5: + *start = 0, *end = 11; + break; + } +} + +static bool32 AllPlayersReadyToStart(void) +{ + u8 i, numPlayers; + + numPlayers = sGame->numPlayers; + for (i = 1; i < numPlayers; i++) + { + if (sGame->readyToStart[i] == FALSE) + sGame->readyToStart[i] = RecvPacket_ReadyToStart(i); + } + + numPlayers = numPlayers; // Needed to force compiler to keep loop below + +#ifdef BUGFIX + i = 1; // i isn't reset, loop below never runs. As a result, game can begin before all players ready +#endif + for (; i < numPlayers; i++) + { + if (sGame->readyToStart[i] == FALSE) + return FALSE; + } + + return TRUE; +} + +static void ResetReadyToStart(void) +{ + u8 i; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + sGame->readyToStart[i] = FALSE; +} + +static bool32 ReadyToEndGame_Leader(void) +{ + if (sGame->numGraySquares >= NUM_STATUS_SQUARES && !sGame->berriesFalling) + { + sGame->numGraySquares = NUM_STATUS_SQUARES; + if (sGame->allReadyToEnd) + return TRUE; + } + + return FALSE; +} + +static bool32 ReadyToEndGame_Member(void) +{ + u8 i, berryStart, berryEnd; + + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + { + berryStart = sGame->berryColStart; + berryEnd = sGame->berryColEnd; + sGame->numGraySquares = NUM_STATUS_SQUARES; + if (sGame->allReadyToEnd) + { + for (i = berryStart; i < berryEnd; i++) + { + struct DodrioGame_Player *player = &sGame->players[sGame->multiplayerId]; + u8 column = sActiveColumnMap[sGame->numPlayers - 1][sGame->multiplayerId][i]; + + if (player->berries.fallDist[column] != MAX_FALL_DIST) + return FALSE; + } + return TRUE; + } + } + + return FALSE; +} + +static void TryIncrementDifficulty(u8 playerId) +{ + u8 threshold = sDifficultyThresholds[sGame->difficulty[playerId] % NUM_DIFFICULTIES] + (sGame->difficulty[playerId] / NUM_DIFFICULTIES) * 100; + if (sGame->berriesEaten[playerId] >= threshold) + sGame->difficulty[playerId]++; +} + +static u8 GetPlayerIdAtColumn(u8 column) +{ + return sPlayerIdAtColumn[sGame->numPlayers - 1][column]; +} + +// Get a berry id for when a new falling berry is created. +// What type of berry it is depends on the current difficulty +// level of players who can pick berries from that column. +static u8 GetNewBerryId(u8 playerId, u8 column) +{ + u8 i, highestDifficulty; + u8 numPlayersIdx = sGame->numPlayers - 1; + u8 leftPlayer = sDodrioNeighborMap[numPlayersIdx][playerId][0]; + u8 middlePlayer = sDodrioNeighborMap[numPlayersIdx][playerId][1]; + u8 rightPlayer = sDodrioNeighborMap[numPlayersIdx][playerId][2]; + + for (i = 0; sUnsharedColumns[numPlayersIdx][i] != 0; i++) + { + // If only one player can use this column, just use their difficulty + if (column == sUnsharedColumns[numPlayersIdx][i]) + return GetNewBerryIdByDifficulty(sGame->difficulty[middlePlayer], column); + } + + // This column is shared, get the highest difficulty of adjacent players + if (sGame->difficulty[leftPlayer] > sGame->difficulty[middlePlayer]) + highestDifficulty = sGame->difficulty[leftPlayer]; + else + highestDifficulty = sGame->difficulty[middlePlayer]; + + if (sGame->difficulty[rightPlayer] > highestDifficulty) + highestDifficulty = sGame->difficulty[rightPlayer]; + + return GetNewBerryIdByDifficulty(highestDifficulty, column); +} + +// The berry types cycle through different distributions depending on the difficulty +static u8 GetNewBerryIdByDifficulty(u8 difficulty, u8 column) +{ + u8 prevBerryId = sGame->prevBerryIds[column]; + switch (difficulty % NUM_DIFFICULTIES) + { + default: return BERRY_BLUE; + case 0: return BERRY_BLUE; + case 1: return BERRY_GREEN; + case 2: return BERRY_GOLD; + case 3: + if (prevBerryId == BERRY_BLUE) + return BERRY_GREEN; + else + return BERRY_BLUE; + case 4: + if (prevBerryId == BERRY_BLUE) + return BERRY_GOLD; + else + return BERRY_BLUE; + case 5: + if (prevBerryId == BERRY_GOLD) + return BERRY_GREEN; + else + return BERRY_GOLD; + case 6: + if (prevBerryId == BERRY_BLUE) + return BERRY_GREEN; + else if (prevBerryId == BERRY_GREEN) + return BERRY_GOLD; + else + return BERRY_BLUE; + } +} + +static bool32 IsTotalBerriesMissedOver10(u16 berryResults[MAX_RFU_PLAYERS][NUM_BERRY_IDS]) +{ + int missed = 0, i = 0; + for (; i < GetLinkPlayerCount(); missed += berryResults[i][BERRY_MISSED], i++) + ; + + if (missed > 10) + return TRUE; + else + return FALSE; +} + +// Despite being set up to take a berry id as an argument, this +// function is only ever given BERRY_BLUE or BERRY_MISSED. +// It reads the actual berry id (if necessary) from ids +static void IncrementBerryResult(u8 berryIdArg, u8 column, u8 playerId) +{ + u8 berryId; + u8 numPlayers = sGame->numPlayers; + switch (berryIdArg) + { + case BERRY_BLUE: + case BERRY_GREEN: + case BERRY_GOLD: + berryId = sGame->players[0].berries.ids[column]; + sGame->berryResults[playerId][berryId] = IncrementWithLimit(sGame->berryResults[playerId][berryId], 20000); + break; + case BERRY_MISSED: + if (IsTotalBerriesMissedOver10(sGame->berryResults)) + break; + switch (numPlayers) + { + case 5: + switch (column) + { + case 0: + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[3][BERRY_MISSED]++; + break; + case 1: + sGame->berryResults[3][BERRY_MISSED]++; + break; + case 2: + sGame->berryResults[3][BERRY_MISSED]++; + sGame->berryResults[4][BERRY_MISSED]++; + break; + case 3: + sGame->berryResults[4][BERRY_MISSED]++; + break; + case 4: + sGame->berryResults[4][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 5: + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 6: + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 7: + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 8: + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; + break; + case 9: + sGame->berryResults[2][BERRY_MISSED]++; + break; + } + break; + case 4: + switch (column) + { + case 1: + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[3][BERRY_MISSED]++; + break; + case 2: + sGame->berryResults[3][BERRY_MISSED]++; + break; + case 3: + sGame->berryResults[3][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 4: + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 5: + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 6: + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 7: + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; + break; + case 8: + sGame->berryResults[2][BERRY_MISSED]++; + break; + } + break; + case 3: + switch (column) + { + case 2: + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; + break; + case 3: + sGame->berryResults[2][BERRY_MISSED]++; + break; + case 4: + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 5: + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 6: + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 7: + sGame->berryResults[1][BERRY_MISSED]++; + break; + } + break; + case 2: + switch (column) + { + case 3: + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 4: + sGame->berryResults[0][BERRY_MISSED]++; + break; + case 5: + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; + break; + case 6: + sGame->berryResults[1][BERRY_MISSED]++; + break; + } + break; + } + break; + } +} + +static void UpdateBerriesPickedInRow(bool32 picked) +{ + // The 'berries picked in row' stat is only + // counted for games with all 5 players + if (sGame->numPlayers != MAX_RFU_PLAYERS) + return; + + if (picked == TRUE) + { + if (++sGame->berriesPickedInRow > sGame->maxBerriesPickedInRow) + sGame->maxBerriesPickedInRow = sGame->berriesPickedInRow; + if (sGame->berriesPickedInRow > MAX_BERRIES) + sGame->berriesPickedInRow = MAX_BERRIES; + } + else // missed + { + if (sGame->berriesPickedInRow > sGame->maxBerriesPickedInRow) + sGame->maxBerriesPickedInRow = sGame->berriesPickedInRow; + sGame->berriesPickedInRow = 0; + } +} + +static void SetMaxBerriesPickedInRow(void) +{ + u8 i; + for (i = 0; i < sGame->numPlayers; i++) + sGame->berryResults[i][BERRY_IN_ROW] = sGame->maxBerriesPickedInRow; +} + +static void ResetForPlayAgainPrompt(void) +{ + u8 i, j; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + for (j = 0; j < NUM_BERRY_COLUMNS; j++) + sGame->players[i].berries.fallDist[j] = 0; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->difficulty[i] = 0; + sGame->berriesEaten[i] = 0; + sGame->scoreResults[i].ranking = 0; + sGame->scoreResults[i].score = 0; + sGame->berryResults[i][BERRY_BLUE] = 0; + sGame->berryResults[i][BERRY_GREEN] = 0; + sGame->berryResults[i][BERRY_GOLD] = 0; + sGame->berryResults[i][BERRY_MISSED] = 0; + sGame->berryResults[i][BERRY_PRIZE] = 0; + sGame->berryResults[i][BERRY_IN_ROW] = 0; + } + sGame->endSoundState = 0; + sGame->berriesPickedInRow = 0; + sGame->numGraySquares = 0; + UpdateAllDodrioAnims(); + UpdateBerrySprites(); +} + +static const s16 sBerryScoreMultipliers[] = { + [BERRY_BLUE] = 10, + [BERRY_GREEN] = 30, + [BERRY_GOLD] = 50, + [BERRY_MISSED] = 50 // Subtracted +}; + +static void SetRandomPrize(void) +{ + u8 i, prizeSet = 0, prizeIdx = 0; + + switch (sGame->numPlayers) + { + case 4: prizeSet = 1; break; + case 5: prizeSet = 2; break; + } + + prizeIdx = Random() % ARRAY_COUNT(sPrizeBerryIds[0]); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + sGame->berryResults[i][BERRY_PRIZE] = sPrizeBerryIds[prizeSet][prizeIdx]; +} + +static u32 GetBerriesPicked(u8 playerId) +{ + u32 sum = sGame->berryResults[playerId][BERRY_BLUE] + + sGame->berryResults[playerId][BERRY_GREEN] + + sGame->berryResults[playerId][BERRY_GOLD]; + return min(sum, MAX_BERRIES); +} + +static void TryUpdateRecords(void) +{ + u32 berriesPicked = Min(GetBerriesPicked(sGame->multiplayerId), MAX_BERRIES); // Min here is redundant + u32 score = Min(GetScore(sGame->multiplayerId), MAX_SCORE); + + if (gSaveBlock2Ptr->berryPick.bestScore < score) + gSaveBlock2Ptr->berryPick.bestScore = score; + if (gSaveBlock2Ptr->berryPick.berriesPicked < berriesPicked) + gSaveBlock2Ptr->berryPick.berriesPicked = berriesPicked; + if (gSaveBlock2Ptr->berryPick.berriesPickedInRow < sGame->maxBerriesPickedInRow) + gSaveBlock2Ptr->berryPick.berriesPickedInRow = sGame->maxBerriesPickedInRow; +} + +// Enqueue the given state, and dequeue and return +// the state that should be used next +static u8 UpdatePickStateQueue(u8 pickState) +{ + u8 i, nextState; + + nextState = sGame->pickStateQueue[ARRAY_COUNT(sGame->pickStateQueue) - 1]; + for (i = ARRAY_COUNT(sGame->pickStateQueue) - 1; i != 0; i--) + sGame->pickStateQueue[i] = sGame->pickStateQueue[i - 1]; + sGame->pickStateQueue[0] = pickState; + return nextState; +} + +// The player may extend their Dodrio's heads while they wait for +// other players to respond to the "Play again?" prompt +static void HandleWaitPlayAgainInput(void) +{ + if (sGame->inputDelay[sGame->multiplayerId] == 0) + { + if (JOY_NEW(DPAD_UP)) + { + sGame->players[sGame->multiplayerId].comm.pickState = PICK_MIDDLE; + sGame->inputDelay[sGame->multiplayerId] = 6; + PlaySE(SE_M_CHARM); + } + else if (JOY_NEW(DPAD_LEFT)) + { + sGame->players[sGame->multiplayerId].comm.pickState = PICK_LEFT; + sGame->inputDelay[sGame->multiplayerId] = 6; + PlaySE(SE_M_CHARM); + } + else if (JOY_NEW(DPAD_RIGHT)) + { + sGame->players[sGame->multiplayerId].comm.pickState = PICK_RIGHT; + sGame->inputDelay[sGame->multiplayerId] = 6; + PlaySE(SE_M_CHARM); + } + else + { + sGame->players[sGame->multiplayerId].comm.pickState = PICK_NONE; + } + } + else + { + sGame->inputDelay[sGame->multiplayerId]--; + } +} + +static void ResetPickState(void) +{ + sGame->players[sGame->multiplayerId].comm.pickState = PICK_NONE; +} + +static u16 GetPrizeItemId(void) +{ + return sGame->berryResults[sGame->multiplayerId][BERRY_PRIZE] + FIRST_BERRY_INDEX; +} + +static u8 GetNumPlayers(void) +{ + return sGame->numPlayers; +} + +static u8 *GetPlayerName(u8 id) +{ + if (gReceivedRemoteLinkPlayers) + return gLinkPlayers[id].name; + else + return sGame->players[id].name; +} + +static u16 GetBerryResult(u8 playerId, u8 berryId) +{ + return sGame->berryResults[playerId][berryId]; +} + +static u32 GetScore(u8 playerId) +{ + u8 i; + u32 scoreLost, score = 0; + + // Sum up points for berries picked + for (i = 0; i < BERRY_MISSED; i++) + score += sGame->berryResults[playerId][i] * sBerryScoreMultipliers[i]; + + // Get points lost for berries missed + scoreLost = sGame->berryResults[playerId][BERRY_MISSED] * sBerryScoreMultipliers[BERRY_MISSED]; + + if (score <= scoreLost) + return 0; + else + return score - scoreLost; +} + +static u32 GetHighestScore(void) +{ + u8 i, numPlayers = sGame->numPlayers; + u32 maxScore = GetScore(0); + + for (i = 1; i < numPlayers; i++) + { + u32 score = GetScore(i); + if (score > maxScore) + maxScore = score; + } + return Min(maxScore, MAX_SCORE); +} + +static u32 GetHighestBerryResult(u8 berryId) +{ + u8 i, numPlayers = sGame->numPlayers; + u16 maxScore = sGame->berryResults[0][berryId]; + + for (i = 0; i < numPlayers; i++) + { + u16 score = sGame->berryResults[i][berryId]; + if (score > maxScore) + maxScore = score; + } + return maxScore; +} + +static u32 GetScoreByRanking(u8 ranking) +{ + u32 scores[MAX_RFU_PLAYERS], temp; + s16 unsorted = TRUE; + u8 i; + u8 numPlayers = sGame->numPlayers; + + for (i = 0; i < numPlayers; i++) + scores[i] = temp = GetScore(i); + + // Sort the scores in the array highest to lowest + while (unsorted) + { + unsorted = FALSE; + for (i = 0; i < numPlayers - 1; i++) + { + if (scores[i] < scores[i + 1]) + { + SWAP(scores[i], scores[i + 1], temp); + unsorted = TRUE; + } + } + } + + return scores[ranking]; +} + +static u32 SetScoreResults(void) +{ + u8 i, ranking = 0, nextRanking = 0, playersRanked = 0; + u8 numPlayers = sGame->numPlayers; + + GetHighestScore(); // Useless call + + if (GetHighestScore() == 0) + { + // No one scored any points, put everyone in last place with a score of 0. + // Presumably this was supposed to then return, as the assignments in this + // loop are then overwritten by the rest of the function + for (i = 0; i < numPlayers; i++) + { + sGame->scoreResults[i].ranking = MAX_RFU_PLAYERS - 1; + sGame->scoreResults[i].score = 0; + } + } + + // Set scores + for (i = 0; i < numPlayers; i++) + sGame->scoreResults[i].score = Min(GetScore(i), MAX_SCORE); + + // Set rankings + do + { + u32 score = GetScoreByRanking(ranking); + u8 curRanking = nextRanking; + + // Find all players with the score for this ranking. + // Increment nextRanking but not curRanking to allow + // for ties + for (i = 0; i < numPlayers; i++) + { + if (score == sGame->scoreResults[i].score) + { + sGame->scoreResults[i].ranking = curRanking; + nextRanking++; + playersRanked++; + } + } + ranking = nextRanking; + } while (playersRanked < numPlayers); + + return 0; +} + +static void GetScoreResults(struct DodrioGame_ScoreResults *dst, u8 playerId) +{ + *dst = sGame->scoreResults[playerId]; +} + +// Unused +// Returns where the specified player's score ranks, 0 being first (highest score) +static u8 GetScoreRanking(u8 playerId) +{ + u8 i, ranking = 0; + u8 numPlayers = sGame->numPlayers; + u32 playersScore; + u32 scores[MAX_RFU_PLAYERS] = {0}; + + for (i = 0; i < numPlayers; i++) + scores[i] = GetScore(i); + + playersScore = scores[playerId]; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + if (i != playerId && playersScore < scores[i]) + ranking++; + } + + return ranking; +} + +enum { + PRIZE_RECEIVED, + PRIZE_FILLED_BAG, + PRIZE_NO_ROOM, + NO_PRIZE, +}; + +static u8 TryGivePrize(void) +{ + u8 multiplayerId = sGame->multiplayerId; + u16 itemId = GetPrizeItemId(); + + if (GetScore(multiplayerId) != GetHighestScore()) + return NO_PRIZE; + if (!CheckBagHasSpace(itemId, 1)) + return PRIZE_NO_ROOM; + + AddBagItem(itemId, 1); + if (!CheckBagHasSpace(itemId, 1)) + return PRIZE_FILLED_BAG; + return PRIZE_RECEIVED; +} + +static u32 IncrementWithLimit(u32 a, u32 max) +{ + if (a < max) + return a + 1; + else + return max; +} + +static u32 Min(u32 a, u32 b) +{ + if (a < b) + return a; + else + return b; +} + +static u8 GetPlayerIdByPos(u8 id) +{ + return sGame->posToPlayerId[id]; +} + +void IsDodrioInParty(void) +{ + int i; + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_HAS_SPECIES) + && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_DODRIO) + { + gSpecialVar_Result = TRUE; + return; + } + } + + gSpecialVar_Result = FALSE; +} + +#define NUM_RECORD_TYPES 3 + +void ShowDodrioBerryPickingRecords(void) +{ + u8 taskId = CreateTask(Task_ShowDodrioBerryPickingRecords, 0); + Task_ShowDodrioBerryPickingRecords(taskId); +} + +static const struct WindowTemplate sWindowTemplates_Records = +{ + .bg = 0, + .tilemapLeft = 5, + .tilemapTop = 1, + .width = 20, + .height = 11, + .paletteNum = 15, + .baseBlock = 0x1, +}; + +static const u8 *const sRecordsTexts[NUM_RECORD_TYPES] = {gText_BerriesPicked, gText_BestScore, gText_BerriesInRowFivePlayers}; +static const u8 sRecordNumMaxDigits[NUM_RECORD_TYPES] = {4, 7, 4}; +ALIGNED(4) +static const u8 sRecordTextYCoords[NUM_RECORD_TYPES][2] = {{25}, {41}, {57}}; +static const u8 sRecordNumYCoords[NUM_RECORD_TYPES][2] = {{25}, {41}, {73}}; + +#define tState data[0] +#define tWindowId data[1] + +static void Task_ShowDodrioBerryPickingRecords(u8 taskId) +{ + struct WindowTemplate window; + s32 i, width, widthCurr; + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + window = sWindowTemplates_Records; + width = GetStringWidth(1, gText_BerryPickingRecords, 0); + for (i = 0; i < ARRAY_COUNT(sRecordsTexts); i++) + { + widthCurr = GetStringWidth(1, sRecordsTexts[i], 0) + 50; + if (widthCurr > width) + width = widthCurr; + } + width = (width + 7) / 8; + if (width & 1) + width++; + window.tilemapLeft = (30 - width) / 2; + window.width = width; + tWindowId = AddWindow(&window); + PrintRecordsText(tWindowId, width); + CopyWindowToVram(tWindowId, 3); + tState++; + break; + case 1: + if (!IsDma3ManagerBusyWithBgCopy()) + tState++; + break; + case 2: + if (JOY_NEW(A_BUTTON | B_BUTTON)) + { + rbox_fill_rectangle(tWindowId); + CopyWindowToVram(tWindowId, 1); + tState++; + } + break; + case 3: + if (!IsDma3ManagerBusyWithBgCopy()) + { + RemoveWindow(tWindowId); + DestroyTask(taskId); + EnableBothScriptContexts(); + } + break; + } +} + +#undef tState +#undef tWindowId + +static void PrintRecordsText(u8 windowId, s32 width) +{ + s32 i, x, numWidth; + s32 recordNums[NUM_RECORD_TYPES]; + recordNums[0] = gSaveBlock2Ptr->berryPick.berriesPicked; + recordNums[1] = gSaveBlock2Ptr->berryPick.bestScore; + recordNums[2] = gSaveBlock2Ptr->berryPick.berriesPickedInRow; + + LoadUserWindowBorderGfx_(windowId, 0x21D, 0xD0); + DrawTextBorderOuter(windowId, 0x21D, 0xD); + FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); + AddTextPrinterParameterized(windowId, 1, gText_BerryPickingRecords, GetStringCenterAlignXOffset(1, gText_BerryPickingRecords, width * 8), 1, TEXT_SPEED_FF, NULL); + for (i = 0; i < NUM_RECORD_TYPES; i++) + { + ConvertIntToDecimalStringN(gStringVar1, recordNums[i], STR_CONV_MODE_LEFT_ALIGN, sRecordNumMaxDigits[i]); + numWidth = GetStringWidth(1, gStringVar1, -1); + AddTextPrinterParameterized(windowId, 1, sRecordsTexts[i], 0, sRecordTextYCoords[i][0], TEXT_SPEED_FF, NULL); + x = (width * 8) - numWidth; + AddTextPrinterParameterized(windowId, 1, gStringVar1, x, sRecordNumYCoords[i][0], TEXT_SPEED_FF, NULL); + } + PutWindowTilemap(windowId); +} + +// Debug functions? +static const u16 sDebug_BerryResults[MAX_RFU_PLAYERS][4] = +{ + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = 0, + [BERRY_GOLD] = 90, + [BERRY_MISSED] = MAX_BERRIES + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = 70, + [BERRY_MISSED] = MAX_BERRIES + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = 0, + [BERRY_GOLD] = MAX_BERRIES, + [BERRY_MISSED] = 0 + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = 60, + [BERRY_MISSED] = 0 + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = MAX_BERRIES, + [BERRY_MISSED] = 0 + }, +}; + +static const u8 sJPText_Vowels[] = _("あいうえおかき"); +static const u8 sText_ABCDEFG[] = _("ABCDEFG"); +static const u8 sText_0123456[] = _("0123456"); + +static const u8 *const sDebug_PlayerNames[] = +{ + sJPText_Vowels, + sJPText_Vowels, + sJPText_Vowels, + sText_ABCDEFG, + sText_0123456 +}; + +static void Debug_UpdateNumPlayers(void) +{ + sGame->numPlayers = GetLinkPlayerCount(); +} + +static void Debug_SetPlayerNamesAndResults(void) +{ + u8 i, playerId; + + for (playerId = sGame->numPlayers; playerId < ARRAY_COUNT(sDebug_PlayerNames); playerId++) + StringCopy(gLinkPlayers[playerId].name, sDebug_PlayerNames[playerId]); + + sGame->numPlayers = MAX_RFU_PLAYERS; + for (i = 0; i < NUM_BERRY_TYPES; i++) + { + for (playerId = 0; playerId < sGame->numPlayers; playerId++) + sGame->berryResults[playerId][i] = sDebug_BerryResults[playerId][i]; + } +} + +struct ReadyToStartPacket +{ + u8 id; + bool8 ALIGNED(4) ready; +}; + +static void SendPacket_ReadyToStart(bool32 ready) +{ + struct ReadyToStartPacket packet; + packet.id = PACKET_READY_START; + packet.ready = ready; + Rfu_SendPacket(&packet); +} + +static u32 RecvPacket_ReadyToStart(u32 playerId) +{ + struct ReadyToStartPacket *packet; + + if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) + return FALSE; + + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_READY_START) + return packet->ready; + + return FALSE; +} + +struct GameStatePacket +{ + u8 id; + u8 fallDist_Col0:4; + u8 fallDist_Col1:4; + u16 fallDist_Col2:4; + u16 fallDist_Col3:4; + u16 fallDist_Col4:4; + u16 fallDist_Col5:4; + u16 fallDist_Col6:4; + u16 fallDist_Col7:4; + u16 fallDist_Col8:4; + u16 fallDist_Col9:4; + u16 berryId_Col0:2; + u16 berryId_Col1:2; + u16 berryId_Col2:2; + u16 berryId_Col3:2; + u16 berryId_Col4:2; + u16 berryId_Col5:2; + u16 berryId_Col6:2; + u16 berryId_Col7:2; + u8 berryId_Col8:2; + u8 berryId_Col9:2; + u8 pickState_Player1:2; + u8 pickState_Player2:2; + u8 pickState_Player3:2; + u8 pickState_Player4:2; + u8 pickState_Player5:2; + bool8 ateBerry_Player1:1; + bool8 ateBerry_Player2:1; + bool8 ateBerry_Player3:1; + bool8 ateBerry_Player4:1; + bool8 ateBerry_Player5:1; + u8 numGraySquares:5; + bool8 allReadyToEnd:1; + bool8 berriesFalling:1; + bool8 missedBerry_Player1:1; + bool8 missedBerry_Player2:1; + bool8 missedBerry_Player3:1; + bool8 missedBerry_Player4:1; + bool8 missedBerry_Player5:1; +}; + +static void SendPacket_GameState(struct DodrioGame_Player *player, + struct DodrioGame_PlayerCommData *player1, + struct DodrioGame_PlayerCommData *player2, + struct DodrioGame_PlayerCommData *player3, + struct DodrioGame_PlayerCommData *player4, + struct DodrioGame_PlayerCommData *player5, + u8 numGraySquares, + bool32 berriesFalling, + bool32 allReadyToEnd) +{ + struct GameStatePacket packet; + struct DodrioGame_Berries *berries = &player->berries; + + packet.id = PACKET_GAME_STATE; + packet.fallDist_Col0 = berries->fallDist[0]; + packet.fallDist_Col1 = berries->fallDist[1]; + packet.fallDist_Col2 = berries->fallDist[2]; + packet.fallDist_Col3 = berries->fallDist[3]; + packet.fallDist_Col4 = berries->fallDist[4]; + packet.fallDist_Col5 = berries->fallDist[5]; + packet.fallDist_Col6 = berries->fallDist[6]; + packet.fallDist_Col7 = berries->fallDist[7]; + packet.fallDist_Col8 = berries->fallDist[8]; + packet.fallDist_Col9 = berries->fallDist[9]; + + packet.berryId_Col0 = berries->ids[0]; + packet.berryId_Col1 = berries->ids[1]; + packet.berryId_Col2 = berries->ids[2]; + packet.berryId_Col3 = berries->ids[3]; + packet.berryId_Col4 = berries->ids[4]; + packet.berryId_Col5 = berries->ids[5]; + packet.berryId_Col6 = berries->ids[6]; + packet.berryId_Col7 = berries->ids[7]; + packet.berryId_Col8 = berries->ids[8]; + packet.berryId_Col9 = berries->ids[9]; + + packet.pickState_Player1 = player1->pickState; + packet.pickState_Player2 = player2->pickState; + packet.pickState_Player3 = player3->pickState; + packet.pickState_Player4 = player4->pickState; + packet.pickState_Player5 = player5->pickState; + + packet.ateBerry_Player1 = player1->ateBerry; + packet.ateBerry_Player2 = player2->ateBerry; + packet.ateBerry_Player3 = player3->ateBerry; + packet.ateBerry_Player4 = player4->ateBerry; + packet.ateBerry_Player5 = player5->ateBerry; + + packet.missedBerry_Player1 = player1->missedBerry; + packet.missedBerry_Player2 = player2->missedBerry; + packet.missedBerry_Player3 = player3->missedBerry; + packet.missedBerry_Player4 = player4->missedBerry; + packet.missedBerry_Player5 = player5->missedBerry; + + packet.numGraySquares = numGraySquares; + packet.berriesFalling = berriesFalling; + packet.allReadyToEnd = allReadyToEnd; + Rfu_SendPacket(&packet); +} + +static bool32 RecvPacket_GameState(u32 playerId, + struct DodrioGame_Player *player, + struct DodrioGame_PlayerCommData *player1, + struct DodrioGame_PlayerCommData *player2, + struct DodrioGame_PlayerCommData *player3, + struct DodrioGame_PlayerCommData *player4, + struct DodrioGame_PlayerCommData *player5, + u8 *numGraySquares, + bool32 *berriesFalling, + bool32 *allReadyToEnd) +{ + struct GameStatePacket *packet; + struct DodrioGame_Berries *berries = &player->berries; + + if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) + return FALSE; + + packet = (void *)&gRecvCmds[0][1]; + if (packet->id == PACKET_GAME_STATE) + { + berries->fallDist[0] = packet->fallDist_Col0; + berries->fallDist[1] = packet->fallDist_Col1; + berries->fallDist[2] = packet->fallDist_Col2; + berries->fallDist[3] = packet->fallDist_Col3; + berries->fallDist[4] = packet->fallDist_Col4; + berries->fallDist[5] = packet->fallDist_Col5; + berries->fallDist[6] = packet->fallDist_Col6; + berries->fallDist[7] = packet->fallDist_Col7; + berries->fallDist[8] = packet->fallDist_Col8; + berries->fallDist[9] = packet->fallDist_Col9; + berries->fallDist[10] = packet->fallDist_Col0; + + berries->ids[0] = packet->berryId_Col0; + berries->ids[1] = packet->berryId_Col1; + berries->ids[2] = packet->berryId_Col2; + berries->ids[3] = packet->berryId_Col3; + berries->ids[4] = packet->berryId_Col4; + berries->ids[5] = packet->berryId_Col5; + berries->ids[6] = packet->berryId_Col6; + berries->ids[7] = packet->berryId_Col7; + berries->ids[8] = packet->berryId_Col8; + berries->ids[9] = packet->berryId_Col9; + berries->ids[10] = packet->berryId_Col0; + + player1->pickState = packet->pickState_Player1; + player1->ateBerry = packet->ateBerry_Player1; + player1->missedBerry = packet->missedBerry_Player1; + + player2->pickState = packet->pickState_Player2; + player2->ateBerry = packet->ateBerry_Player2; + player2->missedBerry = packet->missedBerry_Player2; + + player3->pickState = packet->pickState_Player3; + player3->ateBerry = packet->ateBerry_Player3; + player3->missedBerry = packet->missedBerry_Player3; + + player4->pickState = packet->pickState_Player4; + player4->ateBerry = packet->ateBerry_Player4; + player4->missedBerry = packet->missedBerry_Player4; + + player5->pickState = packet->pickState_Player5; + player5->ateBerry = packet->ateBerry_Player5; + player5->missedBerry = packet->missedBerry_Player5; + + *numGraySquares = packet->numGraySquares; + *berriesFalling = packet->berriesFalling; + *allReadyToEnd = packet->allReadyToEnd; + return TRUE; + } + + return FALSE; +} + +struct PickStatePacket +{ + u8 id; + u8 ALIGNED(4) pickState; +}; + +static void SendPacket_PickState(u8 pickState) +{ + struct PickStatePacket packet; + packet.id = PACKET_PICK_STATE; + packet.pickState = pickState; + Rfu_SendPacket(&packet); +} + +static bool32 RecvPacket_PickState(u32 playerId, u8 *pickState) +{ + struct PickStatePacket *packet; + + if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) + return FALSE; + + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_PICK_STATE) + { + *pickState = packet->pickState; + return TRUE; + } + + return FALSE; +} + +struct ReadyToEndPacket +{ + u8 id; + bool32 ready; +}; + +static void SendPacket_ReadyToEnd(bool32 ready) +{ + struct ReadyToEndPacket packet; + packet.id = PACKET_READY_END; + packet.ready = ready; + Rfu_SendPacket(&packet); +} + +static bool32 RecvPacket_ReadyToEnd(u32 playerId) +{ + struct ReadyToEndPacket *packet; + + if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) + return FALSE; + + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_READY_END) + return packet->ready; + + return FALSE; +} + +static const struct BgTemplate sBgTemplates[] = +{ + { + .bg = BG_INTERFACE, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = BG_TREE_LEFT, + .charBaseIndex = 2, + .mapBaseIndex = 12, + .screenSize = 1, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = BG_TREE_RIGHT, + .charBaseIndex = 2, + .mapBaseIndex = 14, + .screenSize = 1, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = BG_SCENERY, + .charBaseIndex = 3, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 2, + .baseTile = 0 + }, +}; + +static const struct WindowTemplate sWindowTemplate_Dummy = DUMMY_WIN_TEMPLATE; + +static const struct WindowTemplate sWindowTemplates_Results[] = +{ + { + .bg = BG_INTERFACE, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 28, + .height = 2, + .paletteNum = 13, + .baseBlock = 0x13, + }, + { + .bg = BG_INTERFACE, + .tilemapLeft = 1, + .tilemapTop = 5, + .width = 28, + .height = 14, + .paletteNum = 13, + .baseBlock = 0x4B, + } +}; + +static const struct WindowTemplate sWindowTemplate_Prize = +{ + .bg = BG_INTERFACE, + .tilemapLeft = 1, + .tilemapTop = 5, + .width = 28, + .height = 7, + .paletteNum = 13, + .baseBlock = 0x4B, +}; + +enum { + WIN_PLAY_AGAIN, + WIN_YES_NO, +}; + +static const struct WindowTemplate sWindowTemplates_PlayAgain[] = +{ + [WIN_PLAY_AGAIN] = { + .bg = BG_INTERFACE, + .tilemapLeft = 1, + .tilemapTop = 8, + .width = 19, + .height = 3, + .paletteNum = 13, + .baseBlock = 0x13, + }, + [WIN_YES_NO] = { + .bg = BG_INTERFACE, + .tilemapLeft = 22, + .tilemapTop = 7, + .width = 6, + .height = 4, + .paletteNum = 13, + .baseBlock = 0x4C, + } +}; + +static const struct WindowTemplate sWindowTemplate_DroppedOut = +{ + .bg = BG_INTERFACE, + .tilemapLeft = 4, + .tilemapTop = 6, + .width = 22, + .height = 5, + .paletteNum = 13, + .baseBlock = 0x13, +}; + +static const struct WindowTemplate sWindowTemplate_CommStandby = +{ + .bg = BG_INTERFACE, + .tilemapLeft = 5, + .tilemapTop = 8, + .width = 19, + .height = 3, + .paletteNum = 13, + .baseBlock = 0x13, +}; + +// Unused duplicate of sActiveColumnMap +static const u8 sActiveColumnMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, @@ -297,9 +3501,10 @@ static const u8 gUnknown_082F449C[5][5][11] = {6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, {8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8}, }, -}; +}; -static const u8 gUknnown_082F45AF[5][5][3] = +// Unused duplicate of sDodrioHeadToColumnMap +static const u8 sDodrioHeadToColumnMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = { { {4, 5, 6}, @@ -328,7 +3533,8 @@ static const u8 gUknnown_082F45AF[5][5][3] = }, }; -static const u8 gUnknown_082F45FA[5][5][3] = +// Unused duplicate of sDodrioNeighborMap +static const u8 sDodrioNeighborMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = { { {1, 0, 1}, @@ -357,8 +3563,9 @@ static const u8 gUnknown_082F45FA[5][5][3] = }, }; +// Unused duplicate of sPlayerIdAtColumn ALIGNED(4) -static const u8 gUnknown_082F4648[5][11] = +static const u8 sPlayerIdAtColumn_Duplicate[MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = { {9, 9, 9, 9, 1, 1, 1, 9, 9, 9, 9}, {9, 9, 9, 0, 0, 1, 1, 0, 9, 9, 9}, @@ -367,7 +3574,8 @@ static const u8 gUnknown_082F4648[5][11] = {3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, }; -static const u8 gUnknown_082F467F[5][5] = +// Unused duplicate of sUnsharedColumns +static const u8 sUnsharedColumns_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS] = { {5}, {4, 6}, @@ -376,2765 +3584,24 @@ static const u8 gUnknown_082F467F[5][5] = {1, 3, 5, 6, 9}, }; -// Duplicate and unused gfx. Feel free to remove. -static const u32 sDuplicateGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.gbapal", - "graphics/link_games/dodrioberry_bg2.gbapal", - "graphics/link_games/dodrioberry_pkmn.gbapal", - "graphics/link_games/dodrioberry_shiny.gbapal", - "graphics/link_games/dodrioberry_status.gbapal", - "graphics/link_games/dodrioberry_berrysprites.gbapal", - "graphics/link_games/dodrioberry_berrysprites.4bpp.lz", - "graphics/link_games/dodrioberry_platform.gbapal", - "graphics/link_games/dodrioberry_bg1.4bpp.lz", - "graphics/link_games/dodrioberry_bg2.4bpp.lz", - "graphics/link_games/dodrioberry_status.4bpp.lz", - "graphics/link_games/dodrioberry_platform.4bpp.lz", - "graphics/link_games/dodrioberry_pkmn.4bpp.lz", - "graphics/link_games/dodrioberry_bg1.bin.lz", - "graphics/link_games/dodrioberry_bg2right.bin.lz", - "graphics/link_games/dodrioberry_bg2left.bin.lz"); - - -static const u8 gUnknown_082F7A88[][3] = -{ - {40, 24, 13}, - {32, 19, 10}, - {22, 13, 7}, -}; - -ALIGNED(4) -static const u8 gUnknown_082F7A94[] = {8, 5, 8, 11, 15}; - -ALIGNED(4) -static const u8 gUnknown_082F7A9C[] = {5, 10, 20, 30, 50, 70, 100}; - -ALIGNED(4) -static const u8 gUnknown_082F7AA4[][10] = -{ - {15, 16, 17, 18, 19, 19, 18, 17, 16, 15}, - {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, - {30, 31, 32, 33, 34, 34, 33, 32, 31, 30}, -}; - -static void (*const gUnknown_082F7AC4[])(void) = -{ - sub_8024DBC, - sub_8024E00, - sub_8024E38, - sub_8024F10, - sub_8024F38, - sub_8025198, - sub_8025324, - sub_8025470, - sub_8025644, - sub_80256AC, - sub_8025758, - sub_80250D4 -}; - -static void (*const gUnknown_082F7AF4[])(void) = -{ - sub_8024DBC, - sub_8024E00, - sub_8024E38, - sub_8024F10, - sub_8024FFC, - sub_8025230, - sub_8025324, - sub_8025470, - sub_8025644, - sub_80256AC, - sub_8025758, - sub_8025158 -}; - -// code -void StartDodrioBerryPicking(u16 a0, void (*callback)(void)) -{ - gUnknown_03000DB0 = FALSE; - - if (gReceivedRemoteLinkPlayers != 0 && (gUnknown_02022C98 = AllocZeroed(sizeof(*gUnknown_02022C98))) != NULL) - { - sub_8024A1C(); - sub_8024A30(gUnknown_02022C98); - gUnknown_02022C98->savedCallback = callback; - gUnknown_02022C98->multiplayerId = GetMultiplayerId(); - gUnknown_02022C98->unk32CC = gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - sub_80261F8(&gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId], &gPlayerParty[a0]); - CreateTask(sub_8024BC8, 1); - SetMainCallback2(sub_80261CC); - sub_80273F0(); - sub_8026B5C(gUnknown_02022C98->unk24, &gUnknown_02022C98->unk44, &gUnknown_02022C98->unk48); - StopMapMusic(); - PlayNewMapMusic(MUS_RG_BERRY_PICK); - } - else - { - SetMainCallback2(callback); - return; - } -} - -static void sub_8024A1C(void) -{ - ResetTasks(); - ResetSpriteData(); - FreeAllSpritePalettes(); -} - -static void sub_8024A30(struct DodrioStruct * data) -{ - u8 i; - - data->unk0C = 0; - data->unk10 = 0; - data->unk14 = 0; - data->unk18 = 0; - data->unk1C = 0; - data->unk11C = 0; - data->unk120 = 0; - data->unk30 = 0; - data->unk40 = 0; - data->unk3C = 0; - data->unk12C = 0; - - for (i = 0; i < 4; i++) - { - data->unk98[i] = 0; - } - - for (i = 0; i < 5; i++) - { - data->unkA8[i] = 0; - data->unkB0[i] = 0; - data->unk4A[i][0] = 0; - data->unk4A[i][1] = 0; - data->unk4A[i][2] = 0; - data->unk4A[i][3] = 0; - data->unk4A[i][5] = 0; - data->unk10C[i] = 0; - data->unk130[i] = 0; - } - - for (i = 0; i < 11; i++) - { - data->unkD0[i] = 0; - data->unkDC[i] = 0; - data->unkC4[i] = 0; - data->unkF4[i][0] = 0xFF; - data->unkF4[i][1] = 0xFF; - } - - data->unk20 = GetMultiplayerId() == 0 ? 1 : 0; - data->unk24 = GetLinkPlayerCount(); - data->unk34[0] = GetMultiplayerId(); - for (i = 1; i < data->unk24; i++) - { - data->unk34[i] = data->unk34[i - 1] + 1; - if (data->unk34[i] > data->unk24 - 1) - data->unk34[i] %= data->unk24; - } -} - -static void sub_8024BC8(u8 taskId) -{ - u8 r4, r5; - - switch (gUnknown_02022C98->unk0C) - { - case 0: - SetVBlankCallback(NULL); - sub_802620C(sub_8025910, 4); - gUnknown_02022C98->unk0C++; - break; - case 1: - if (!FuncIsActiveTask(sub_8025910)) - { - sub_8029274(&gUnknown_02022C98->unk160); - gUnknown_02022C98->unk0C++; - } - break; - case 2: - if (!sub_802A770()) - { - Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk0C++; - } - break; - case 3: - if (IsLinkTaskFinished()) - { - if (gReceivedRemoteLinkPlayers != 0) - { - LoadWirelessStatusIndicatorSpriteGfx(); - CreateWirelessStatusIndicatorSprite(0, 0); - } - gUnknown_02022C98->unk0C++; - } - break; - case 4: - r5 = gUnknown_02022C98->unk24; - sub_80283A8(); - for (r4 = 0; r4 < r5; r4++) - { - sub_8028408(&gUnknown_02022C98->unk318C[gUnknown_02022C98->unk34[r4]], r4, gUnknown_02022C98->unk34[r4], gUnknown_02022C98->unk24); - } - sub_802868C(FALSE, gUnknown_02022C98->unk24); - gUnknown_02022C98->unk0C++; - break; - case 5: - sub_8028A34(); - sub_8028A88(); - sub_8028D44(); - sub_8028734(); - gUnknown_02022C98->unk0C++; - break; - case 6: - BlendPalettes(PALETTES_ALL, 0x10, 0x00); - BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); - SetVBlankCallback(sub_80261E4); - gUnknown_02022C98->unk0C++; - break; - case 7: - UpdatePaletteFade(); - if (!gPaletteFade.active) - { - gUnknown_02022C98->unk0C++; - } - break; - default: - DestroyTask(taskId); - sub_802621C(sub_802589C); - break; - } -} - -static void sub_8024D4C(u8 taskId) -{ - sub_8025D04(); - gUnknown_082F7AC4[gUnknown_02022C98->unk18](); - if (!gUnknown_03000DB0) - { - sub_8026AF4(); - } - sub_8025D50(); -} - -static void sub_8024D84(u8 taskId) -{ - sub_8025E0C(); - gUnknown_082F7AF4[gUnknown_02022C98->unk18](); - if (!gUnknown_03000DB0) - { - sub_8026B28(); - } - sub_8025ED8(); -} - -static void sub_8024DBC(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - sub_8028504(1); - sub_80292E0(1); - gUnknown_02022C98->unk10++; - break; - case 1: - if (!sub_802A770()) - sub_8026240(1); - break; - } -} - -static void sub_8024E00(void) -{ - if (gUnknown_02022C98->unk10 == 0) - { - sub_80262C0(); - gUnknown_02022C98->unk10++; - } - else - { - gUnknown_02022C98->unk118 = 1; - sub_8026240(2); - } -} - -static void sub_8024E38(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - StartMinigameCountdown(7, 8, 120, 80, 0); - gUnknown_02022C98->unk10++; - break; - case 1: - Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk10++; - break; - case 2: - if (IsLinkTaskFinished()) - { - gUnknown_02022C98->unk10++; - gUnknown_02022C98->unk30 = 0; - } - break; - case 3: - if (!IsMinigameCountdownRunning()) - { - gUnknown_02022C98->unk10++; - } - break; - case 4: - if (++gUnknown_02022C98->unk30 > 5) - { - Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk10++; - } - break; - case 5: - if (IsLinkTaskFinished()) - { - sub_8026240(3); - } - break; - } -} - -static void sub_8024F10(void) -{ - if (gUnknown_02022C98->unk10 == 0) - { - if (gUnknown_02022C98->unk11C != 0) - { - sub_8026240(4); - } - } -} - -static void sub_8024F38(void) -{ - if (gUnknown_02022C98->unk10 == 0) - { - if (gUnknown_02022C98->unk40 < 10) - { - if (gUnknown_02022C98->unkA8[0] == 0) - { - if (JOY_NEW(DPAD_UP)) - { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(2); - } - } - else if (JOY_NEW(DPAD_RIGHT)) - { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(1); - } - } - else if (JOY_NEW(DPAD_LEFT)) - { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(3); - } - } - else - { - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(0); - } - } - } - else - { - sub_8026240(11); - } - sub_802671C(); - sub_8025F48(); - } -} - -static void sub_8024FFC(void) -{ - if (gUnknown_02022C98->unk40 < 10) - { - if (JOY_NEW(DPAD_UP)) - { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 2; - } - } - else if (JOY_NEW(DPAD_RIGHT)) - { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 1; - } - } - else if (JOY_NEW(DPAD_LEFT)) - { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) - { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 3; - } - } - else - { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 0; - } - } - else - { - sub_8026240(11); - } - sub_8026044(); -} - -static void sub_80250D4(void) -{ - u8 i; - - sub_802671C(); - sub_8025F48(); - if (sub_8026C50() == 1) - { - sub_80272A4(); - sub_8026240(5); - } - else - { - gUnknown_02022C98->unk12C = 1; - for (i = 1; i < gUnknown_02022C98->unk24; i++) - { - if (gUnknown_02022C98->unk130[i] != 1) - { - gUnknown_02022C98->unk12C = 0; - break; - } - } - } -} - -static void sub_8025158(void) -{ - sub_8026044(); - if (sub_8026C90() == 1) - sub_8026240(5); -} - -static bool32 sub_8025170(void) -{ - u8 recvStatus = GetBlockReceivedStatus(); - u8 playerFlags = GetLinkPlayerCountAsBitFlags(); - if (recvStatus == playerFlags) - { - ResetBlockReceivedFlags(); - return TRUE; - } - else - { - return FALSE; - } -} - -static void sub_8025198(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - if (SendBlock(0, gUnknown_02022C98->unk4A, sizeof(gUnknown_02022C98->unk4A))) - { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; - } - break; - case 1: - if (IsLinkTaskFinished()) - { - gUnknown_02022C98->unk10++; - } - break; - case 2: - if (sub_8025170()) - { - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; - } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) - { - gUnknown_02022C98->unk14++; - gUnknown_02022C98->unk10++; - } - break; - default: - if (WaitFanfare(TRUE)) - { - sub_8026240(6); - FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); - } - break; - } -} - -static void sub_8025230(void) -{ - u8 i; - - switch (gUnknown_02022C98->unk10) { - case 0: - if (SendBlock(0, gUnknown_02022C98->unk4A[gUnknown_02022C98->unk14], - sizeof(gUnknown_02022C98->unk4A))) { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; - } - break; - case 1: - if (IsLinkTaskFinished()) { - gUnknown_02022C98->unk10++; - } - break; - case 2: - if (sub_8025170()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) { - memcpy(gUnknown_02022C98->unk4A, gBlockRecvBuffer, sizeof(gUnknown_02022C98->unk4A)); - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; - } - } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - gUnknown_02022C98->unk14++; - gUnknown_02022C98->unk10++; - } - break; - default: - if (WaitFanfare(TRUE)) { - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk4A[gUnknown_02022C98->multiplayerId][5]; - sub_8026240(6); - FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); - } - break; - } -} - -static void sub_8025324(void) -{ - u8 sp00 = 1; - u8 i; - - switch (gUnknown_02022C98->unk10) - { - case 0: - sub_802749C(); - sub_80289E8(TRUE); - sub_8028DFC(); - sub_8028EC8(TRUE); - sub_80292E0(2); - gUnknown_02022C98->unk10++; - break; - case 1: - if (!sub_802A770()) - { - sub_80292E0(5); - gUnknown_02022C98->unk10++; - } - break; - case 2: - sp00 = sub_802A794(); - if (SendBlock(0, &sp00, sizeof(sp00))) - { - gUnknown_02022C98->unk10++; - } - break; - case 3: - if (IsLinkTaskFinished()) - { - gUnknown_02022C98->unk10++; - gUnknown_02022C98->unk08 = 0; - } - break; - case 4: - if (sub_8025170()) - { - for (i = 0; i < gUnknown_02022C98->unk24; i++) - { - *(gUnknown_02022C98->unk10C + i) = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; - } - } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - if (++gUnknown_02022C98->unk14 >= 120) - { - sub_80292E0(6); - gUnknown_02022C98->unk10++; - } - } - break; - default: - if (!sub_802A770()) - { - sub_8026240(7); - } - break; - } -} - -static void sub_8025470(void) -{ - u8 sp0; - u8 i; - - switch (gUnknown_02022C98->unk10) - { - case 0: - if (sub_8027748() >= 3000) - { - sub_80292E0(4); - } - gUnknown_02022C98->unk10++; - break; - case 1: - if (!sub_802A770()) - { - sub_80292E0(3); - gUnknown_02022C98->unk10++; - } - break; - case 2: - sub_8028FCC(); - sub_80272E8(); - gUnknown_02022C98->unk10++; - break; - case 3: - if ((sp0 = sub_802A794()) != 0) - { - gUnknown_02022C98->unk10++; - } - break; - case 4: - if (!sub_802A770()) - { - sub_80292E0(5); - gUnknown_02022C98->unk10++; - } - break; - case 5: - sp0 = sub_802A794(); - if (SendBlock(0, &sp0, sizeof(sp0))) - { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; - } - break; - case 6: - if (IsLinkTaskFinished()) - { - gUnknown_02022C98->unk10++; - } - break; - case 7: - if (sub_8025170()) - { - for (i = 0; i < gUnknown_02022C98->unk24; i++) - { - *(gUnknown_02022C98->unk10C + i) = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; - } - } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - if (++gUnknown_02022C98->unk14 >= 120) - { - sub_8027608(); - sub_80292E0(6); - gUnknown_02022C98->unk10++; - } - } - else - { - sub_8027554(); - } - break; - default: - if (!sub_802A770()) - { - for (i = 0; i < gUnknown_02022C98->unk24; i++) - { - if (gUnknown_02022C98->unk10C[i] == 2) - { - sub_8026240(8); - return; - } - } - sub_8026240(10); - } - break; - } -} - -static void sub_8025644(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - SetCloseLinkCallback(); - sub_80292E0(7); - gUnknown_02022C98->unk10++; - break; - case 1: - if (!sub_802A770()) - { - gUnknown_02022C98->unk10++; - } - break; - case 2: - if (sub_802A794() == 5) - { - gUnknown_02022C98->unk10++; - } - break; - default: - if (gReceivedRemoteLinkPlayers == 0) - { - sub_8026240(9); - } - break; - } -} - -static void sub_80256AC(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); - gUnknown_02022C98->unk10++; - break; - case 1: - UpdatePaletteFade(); - if (!gPaletteFade.active) - { - gUnknown_02022C98->unk10++; - } - break; - case 2: - sub_8028B80(); - sub_80287E4(); - sub_8028614(gUnknown_02022C98->unk24); - sub_8028E84(); - gUnknown_03000DB0 = TRUE; - sub_80292E0(8); - gUnknown_02022C98->unk10++; - break; - default: - if (!sub_802A770()) - { - SetMainCallback2(gUnknown_02022C98->savedCallback); - DestroyTask(gUnknown_02022C98->unk04); - Free(gUnknown_02022C98); - FreeAllWindowBuffers(); - } - break; - } -} - -static void sub_8025758(void) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - sub_80292E0(9); - BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); - gUnknown_02022C98->unk10++; - break; - case 1: - UpdatePaletteFade(); - if (!gPaletteFade.active) - { - gUnknown_02022C98->unk10++; - } - break; - case 2: - ChangeBgX(0, 0, 0); - ChangeBgY(0, 0, 0); - ChangeBgX(1, 0, 0); - ChangeBgY(1, 0, 0); - ChangeBgX(2, 0, 0); - ChangeBgY(2, 0, 0); - ChangeBgX(3, 0, 0); - ChangeBgY(3, 0, 0); - gUnknown_02022C98->unk10++; - break; - case 3: - StopMapMusic(); - gUnknown_02022C98->unk10++; - break; - case 4: - PlayNewMapMusic(MUS_RG_BERRY_PICK); - sub_8028E4C(); - gUnknown_02022C98->unk10++; - break; - case 5: - BlendPalettes(PALETTES_ALL, 16, 0); - BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); - gUnknown_02022C98->unk10++; - break; - case 6: - UpdatePaletteFade(); - if (!gPaletteFade.active) - { - gUnknown_02022C98->unk10++; - } - break; - default: - DestroyTask(gUnknown_02022C98->unk04); - sub_802621C(sub_802589C); - sub_802903C(); - sub_8024A30(gUnknown_02022C98); - if (gReceivedRemoteLinkPlayers == 0) - { - gUnknown_02022C98->unk24 = 1; - } - sub_80273F0(); - sub_8028EC8(FALSE); - break; - } -} - -static void sub_802589C(u8 taskId) -{ - switch (gUnknown_02022C98->unk10) - { - case 0: - if (sub_8026264() == 1) - { - gUnknown_02022C98->unk10++; - } - break; - case 1: - sub_80286E4(); - gUnknown_02022C98->unk10++; - break; - case 2: - if (sub_8028828() == TRUE) - { - gUnknown_02022C98->unk10++; - } - break; - default: - if (gUnknown_02022C98->unk20 != 0) - { - sub_802621C(sub_8024D4C); - } - else - { - sub_802621C(sub_8024D84); - } - DestroyTask(taskId); - break; - } -} - -static void sub_8025910(u8 taskId) -{ - s16 * data = gTasks[taskId].data; - u8 i; - - switch (data[0]) - { - case 0: - if (SendBlock(0, &gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId].isShiny, sizeof(gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId].isShiny))) - { - gUnknown_02022C98->unk08 = 0; - data[0]++; - } - break; - case 1: - if (IsLinkTaskFinished()) - { - data[0]++; - } - break; - case 2: - if (sub_8025170()) - { - for (i = 0; i < gUnknown_02022C98->unk24; i++) - { - *(u8 *)&gUnknown_02022C98->unk318C[i] = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; - } - } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) - { - DestroyTask(taskId); - sub_80292E0(6); - gUnknown_02022C98->unk10++; - } - break; - } -} - -static void sub_80259FC(void) -{ - u8 i; - u8 r7 = gUnknown_02022C98->unk24; - - gUnknown_02022C98->unk31A0[0].unk10 = sub_8028164(0, &gUnknown_02022C98->unk31A0[0], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - gUnknown_02022C98->unk128 = 1; - - for (i = 1; i < r7; i++) - { - if ( gUnknown_02022C98->unkA8[i] == 0 - && sub_8028318(i, &gUnknown_02022C98->unk31A0[i].unk2C.unk0) == 0) - { - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk128 = 0; - } - } - if (++gUnknown_02022C98->unk124 >= 60) - { - if (gUnknown_02022C98->unk128 != 0) - { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; - } - else if (gUnknown_02022C98->unk124 > 70) - { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; - } - } - - for (i = 0; i < r7; i++) - { - if ( gUnknown_02022C98->unk31A0[i].unk2C.unk0 != 0 - && gUnknown_02022C98->unkA8[i] == 0) - { - gUnknown_02022C98->unkA8[i] = 1; - } - switch (gUnknown_02022C98->unkA8[i]) - { - case 0: - default: - break; - case 1 ... 3: - if (++gUnknown_02022C98->unkB0[i] >= 6) - { - gUnknown_02022C98->unkB0[i] = 0; - gUnknown_02022C98->unkA8[i] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk8 = 0; - } - break; - case 4: - if (++gUnknown_02022C98->unkB0[i] >= 40) - { - gUnknown_02022C98->unkB0[i] = 0; - gUnknown_02022C98->unkA8[i] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk8 = 0; - } - break; - } - } -} - -static void sub_8025C0C(void) -{ - u8 i; - u8 r6 = gUnknown_02022C98->unk24; - - gUnknown_02022C98->unk31A0[0].unk10 = sub_8028164(0, &gUnknown_02022C98->unk31A0[0], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - gUnknown_02022C98->unk128 = 1; - - for (i = 1; i < r6; i++) - { - if (sub_8028374(i) != 0) - { - gUnknown_02022C98->unk130[i] = 1; - gUnknown_02022C98->unk128 = 0; - } - } - if (++gUnknown_02022C98->unk124 >= 60) - { - if (gUnknown_02022C98->unk128 != 0) - { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; - } - else if (gUnknown_02022C98->unk124 > 70) - { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; - } - } -} - -static void sub_8025D04(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 3: - if (sub_8026BB8() == TRUE) - { - sub_8026C28(); - gUnknown_02022C98->unk11C = 1; - } - break; - case 4: - sub_80259FC(); - break; - case 11: - sub_8025C0C(); - break; - } -} - -static void sub_8025D50(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 4: - sub_8027E30(&gUnknown_02022C98->unk32CC, &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, gUnknown_02022C98->unk40, gUnknown_02022C98->unk120, gUnknown_02022C98->unk12C); - break; - case 11: - sub_8027E30(&gUnknown_02022C98->unk32CC, &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, gUnknown_02022C98->unk40, gUnknown_02022C98->unk120, gUnknown_02022C98->unk12C); - break; - } -} - -static void sub_8025E0C(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 4: - sub_8028164(gUnknown_02022C98->multiplayerId, &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - break; - case 11: - sub_8028164(gUnknown_02022C98->multiplayerId, &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - break; - } -} - -static void sub_8025ED8(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 3: - sub_8027DD0(1); - gUnknown_02022C98->unk11C = 1; - break; - case 4: - if (gUnknown_02022C98->unk32CC.unk2C.unk0 != 0) - { - sub_80282EC(gUnknown_02022C98->unk32CC.unk2C.unk0); - } - break; - case 11: - if (gUnknown_02022C98->unk120 == 0 && gUnknown_02022C98->unk12C == 0) - { - sub_8028350(1); - } - break; - } -} - -static void sub_8025F48(void) -{ - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) - { - if (!IsSEPlaying()) - { - gUnknown_02022C98->unk144 = 0; - } - } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 == 1) - { - if (gUnknown_02022C98->unk144 == 0) - { - m4aSongNumStop(SE_SUCCESS); - PlaySE(SE_SUCCESS); - gUnknown_02022C98->unk144 = 1; - } - } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 == 1) - { - if (gUnknown_02022C98->unk144 == 0 && !IsSEPlaying()) - { - PlaySE(SE_BOO); - sub_80284CC(1); - gUnknown_02022C98->unk144 = 1; - } - } - - if (gUnknown_02022C98->unk154 == 0 && gUnknown_02022C98->unk40 >= 10) - { - StopMapMusic(); - gUnknown_02022C98->unk154 = 1; - } - else if (gUnknown_02022C98->unk154 == 1) - { - PlayFanfareByFanfareNum(11); // MUS_TOO_BAD - gUnknown_02022C98->unk154 = 2; - } -} - -static void sub_8026044(void) -{ - u8 r8 = gUnknown_02022C98->unk44; - u8 r7 = gUnknown_02022C98->unk48; - u8 r4; - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) - { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 != 1 && gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 != 1) - { - gUnknown_02022C98->unk144 = 0; - } - } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 == 1) - { - if (gUnknown_02022C98->unk144 == 0) - { - m4aSongNumStop(SE_SUCCESS); - PlaySE(SE_SUCCESS); - gUnknown_02022C98->unk144 = 1; - } - } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 == 1) - { - if (gUnknown_02022C98->unk144 == 0 && !IsSEPlaying()) - { - PlaySE(SE_BOO); - sub_80284CC(1); - gUnknown_02022C98->unk144 = 1; - } - } - for (r4 = r8; r4 < r7; r4++) - { - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk14; - if (ptr->unkB[r4] >= 10) - { - if (gUnknown_02022C98->unk148[r4] == 0) - { - PlaySE(SE_BALLOON_RED + ptr->unk0[r4]); - gUnknown_02022C98->unk148[r4] = 1; - } - } - else - { - gUnknown_02022C98->unk148[r4] = 0; - } - } - if (gUnknown_02022C98->unk154 == 0 && gUnknown_02022C98->unk40 >= 10) - { - StopMapMusic(); - gUnknown_02022C98->unk154 = 1; - } - else if (gUnknown_02022C98->unk154 == 1) - { - PlayFanfareByFanfareNum(11); // MUS_TOO_BAD - gUnknown_02022C98->unk154 = 2; - } -} - -static void sub_80261CC(void) -{ - RunTasks(); - AnimateSprites(); - BuildOamBuffer(); - UpdatePaletteFade(); -} - -static void sub_80261E4(void) -{ - TransferPlttBuffer(); - LoadOam(); - ProcessSpriteCopyRequests(); -} - -static void sub_80261F8(struct DodrioSubstruct_318C * a0, struct Pokemon * a1) -{ - a0->isShiny = IsMonShiny(a1); -} - -static void sub_802620C(TaskFunc func, u8 priority) -{ - CreateTask(func, priority); -} - -static void sub_802621C(TaskFunc func) -{ - gUnknown_02022C98->unk04 = CreateTask(func, 1); - gUnknown_02022C98->unk10 = 0; - gUnknown_02022C98->unk0C = 0; - gUnknown_02022C98->unk14 = 0; -} - -static void sub_8026240(u8 a0) -{ - gUnknown_02022C98->unk1C = gUnknown_02022C98->unk18; - gUnknown_02022C98->unk18 = a0; - gUnknown_02022C98->unk10 = 0; - gUnknown_02022C98->unk14 = 0; -} - -static bool32 sub_8026264(void) -{ - u8 r2 = gUnknown_02022C98->unk14 / 4; - gUnknown_02022C98->unk14++; - if (r2 != 0 && gUnknown_02022C98->unk14 % 4 == 0) - { - if (r2 < gUnknown_082F7A94[gUnknown_02022C98->unk24 - 1]) - { - SetGpuReg(REG_OFFSET_BG1HOFS, (r2 * 8)); - SetGpuReg(REG_OFFSET_BG2HOFS, -(r2 * 8)); - return FALSE; - } - else - { - return TRUE; - } - } - else - { - return FALSE; - } -} - -static void sub_80262C0(void) -{ - u8 i; - u8 start = gUnknown_02022C98->unk44; - u8 finish = gUnknown_02022C98->unk48; - - for (i = start; i < finish; i++) - { - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk32CC.unk14; - ptr->unkB[i] = (i % 2 == 0) ? 1 : 0; - ptr->unk0[i] = 0; - } -} - -static void sub_8026324(void) -{ - u8 sp0 = gUnknown_02022C98->unk44; - u8 sp4 = gUnknown_02022C98->unk48; - u8 sp8 = gUnknown_02022C98->unk24; - u8 i, j, k, r5; - - if (gUnknown_02022C98->unk40 >= 10) - return; - - for (i = 0; i < sp8; i++) - { - u8 *ptr = &gUnknown_02022C98->unk31A0[i].unk2C.unk0; - if (*ptr != 0 && gUnknown_02022C98->unkA8[i] == 1) - { - for (j = sp0; j < sp4; j++) - { - r5 = gUnknown_082F449C[0][0][j]; - if (gUnknown_02022C98->unkF4[r5][0] == i || gUnknown_02022C98->unkF4[r5][1] == i) - break; - if (sub_8026634(i, *ptr, r5) == TRUE) - { - for (k = 0; k < 2; k++) - { - if (gUnknown_02022C98->unkF4[r5][k] == 0xFF) - { - gUnknown_02022C98->unkF4[r5][k] = i; - gUnknown_02022C98->unkA8[i] = 2; - gUnknown_02022C98->unkC4[r5] = 1; - break; - } - } - break; - } - if (gUnknown_02022C98->unk31A0[i].unk2C.unk8 == 1) - break; - } - } - } - - for (j = sp0; j < sp4; j++) - { - u8 id = 0xFF; - r5 = gUnknown_082F449C[0][0][j]; - if (gUnknown_02022C98->unkC4[r5] == 1) - { - s32 r2; - u8 r4, r3 = gUnknown_02022C98->unk90[sub_8026D8C(r5)] / 7; - if (r3 >= ARRAY_COUNT(gUnknown_082F7A88) - 1) - r3 = ARRAY_COUNT(gUnknown_082F7A88) - 1; - - r2 = gUnknown_082F7A88[r3][gUnknown_02022C98->unk31A0[0].unk14.unk0[r5]] - gUnknown_02022C98->unkD0[r5]; - if (r2 < 6) - gUnknown_02022C98->unk9C[r5] += r2; - - if (++gUnknown_02022C98->unk9C[r5] >= 6) - { - gUnknown_02022C98->unk9C[r5] = 0; - if (gUnknown_02022C98->unkF4[r5][0] == 0xFF && gUnknown_02022C98->unkF4[r5][1] == 0xFF) - { - continue; - } - else if (gUnknown_02022C98->unkF4[r5][0] != 0xFF && gUnknown_02022C98->unkF4[r5][1] == 0xFF) - { - r4 = gUnknown_02022C98->unkF4[r5][0]; - } - else - { - u8 unk0 = gUnknown_02022C98->unkF4[r5][0]; - i = gUnknown_02022C98->unkF4[r5][1]; // Have to re-use the variable to match. - if (!(Random() & 1)) - { - r4 = unk0; - id = i; - } - else - { - r4 = i; - id = unk0; - } - } - gUnknown_02022C98->unk32CC.unk14.unkB[r5] = 7; - gUnknown_02022C98->unkC4[r5] = 2; - gUnknown_02022C98->unkA8[r4] = 3; - gUnknown_02022C98->unkB8[r5] = r4; - gUnknown_02022C98->unk31A0[r4].unk2C.unk4 = 1; - gUnknown_02022C98->unk31A0[id].unk2C.unk8 = 1; - gUnknown_02022C98->unk86[r4]++; - sub_8026F1C(0, r5, r4); - sub_8027234(TRUE); - sub_8026D1C(r4); - gUnknown_02022C98->unkE8[r5] = gUnknown_02022C98->unk32CC.unk14.unk0[r5]; - gUnknown_02022C98->unk32CC.unk14.unk0[r5] = 3; - gUnknown_02022C98->unkF4[r5][0] = 0xFF; - gUnknown_02022C98->unkF4[r5][1] = 0xFF; - } - } - } -} - -static bool32 sub_8026634(u8 a0, u8 a1, u8 a2) -{ - s32 r7 = 0; - u8 r5 = gUnknown_02022C98->unk24 - 1; - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk32CC.unk14; - - switch (a1) - { - case 3: - default: - r7 = 0; - break; - case 2: - r7 = 1; - break; - case 1: - r7 = 2; - break; - } - if (ptr->unkB[a2] == 6 || ptr->unkB[a2] == 7) - { - if (a2 == gUknnown_082F45AF[r5][a0][r7]) - { - if (gUnknown_02022C98->unkC4[a2] == 1 || gUnknown_02022C98->unkC4[a2] == 2) - { - gUnknown_02022C98->unk31A0[a0].unk2C.unk8 = 1; - return FALSE; - } - else - { - return TRUE; - } - } - } - else - { - if (a2 == gUknnown_082F45AF[r5][a0][r7]) - { - gUnknown_02022C98->unkA8[a0] = 4; - gUnknown_02022C98->unk31A0[a0].unk2C.unk8 = 1; - } - } - return FALSE; -} - -static void sub_802671C(void) -{ - u8 r1 = gUnknown_02022C98->unk44; - u8 r9 = gUnknown_02022C98->unk48; - u8 r3 = 0; - u8 r10 = 0; - u8 i; - u8 r2; - struct DodrioStruct *ptr; - - gUnknown_02022C98->unk120 = 0; - - for (i = r1; i < r9 - 1; i++) - { - ptr = gUnknown_02022C98; - - if (gUnknown_02022C98->unkC4[i] == 0 || gUnknown_02022C98->unkC4[i] == 1) - { - gUnknown_02022C98->unk120 = 1; - if (ptr->unk32CC.unk14.unkB[i] >= 10) - { - ptr->unk32CC.unk14.unkB[i] = 10; - gUnknown_02022C98->unkC4[i] = 3; - if (gUnknown_02022C98->unk148[i] == 0) - { - gUnknown_02022C98->unk148[i] = 1; - PlaySE(SE_BALLOON_RED + ptr->unk32CC.unk14.unk0[i]); - } - if (gUnknown_02022C98->unk40 < 10 || r10 == 1) - { - r10 = 1; - gUnknown_02022C98->unk148[i] = 0; - if (gUnknown_02022C98->unk40 < 10) - { - gUnknown_02022C98->unk40++; - } - sub_8026F1C(3, i, 0); - sub_8027234(FALSE); - } - } - else - { - r3 = gUnknown_02022C98->unk90[sub_8026D8C(i)] / 7; - if (r3 >= 2) - { - r3 = 2; - } - r2 = gUnknown_082F7A88[r3][ptr->unk32CC.unk14.unk0[i]]; - if (++gUnknown_02022C98->unkD0[i] >= r2) - { - ptr->unk32CC.unk14.unkB[i]++; - gUnknown_02022C98->unkD0[i] = 0; - } - sub_8026324(); - } - } - else if (gUnknown_02022C98->unkC4[i] == 2) - { - gUnknown_02022C98->unk120 = 1; - if (++gUnknown_02022C98->unkDC[i] >= 20) - { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->unkB8[i]].unk2C.unk4 = 0; - gUnknown_02022C98->unkDC[i] = 0; - gUnknown_02022C98->unkD0[i] = 0; - gUnknown_02022C98->unkC4[i] = 0; - ptr->unk32CC.unk14.unkB[i] = 1; - ptr->unk32CC.unk14.unk0[i] = sub_8026DB0(sub_8026D8C(i), i); - } - } - else if (gUnknown_02022C98->unkC4[i] == 3) - { - if (++gUnknown_02022C98->unkDC[i] >= 20) - { - if (gUnknown_02022C98->unk40 < 10) - { - gUnknown_02022C98->unkDC[i] = 0; - gUnknown_02022C98->unkD0[i] = 0; - gUnknown_02022C98->unkC4[i] = 0; - ptr->unk32CC.unk14.unkB[i] = 1; - gUnknown_02022C98->unkE8[i] = ptr->unk32CC.unk14.unk0[i]; - ptr->unk32CC.unk14.unk0[i] = sub_8026DB0(sub_8026D8C(i), i); - } - } - } - } -} - -static void sub_8026988(void) -{ - u8 i, first, count; - - first = gUnknown_02022C98->unk44; - count = gUnknown_02022C98->unk48; - for (i = first; i < count; i++) - { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - u8 var = gUnknown_082F449C[gUnknown_02022C98->unk24 - 1][gUnknown_02022C98->multiplayerId][i]; - - if (ptr->unk14.unkB[var] != 0) - sub_8028BF8(i, FALSE); - else - sub_8028BF8(i, TRUE); - - if (ptr->unk14.unkB[var] > 9) - { - sub_8028CA4(i, ptr->unk14.unk0[var] + 3); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2 - 1); - } - else if (ptr->unk14.unk0[var] == 3) - { - ptr->unk14.unkB[var] = 7; - sub_8028CA4(i, 6); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2 - 1); - } - else - { - sub_8028CA4(i, ptr->unk14.unk0[var]); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2); - } - } -} - -static void sub_8026A88(void) -{ - u8 i, count; - - count = gUnknown_02022C98->unk24; - for (i = 0; i < count; i++) - { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[i]; - sub_80286B4(i, ptr->unk2C.unk0); - } -} - -static void sub_8026AC8(void) -{ - u8 i, count; - - count = gUnknown_02022C98->unk24; - for (i = 0; i < count; i++) - sub_80286B4(i, 4); -} - -static void sub_8026AF4(void) -{ - sub_8026988(); - if (gUnknown_02022C98->unk40 > 9) - sub_8026AC8(); - else - sub_8026A88(); - - sub_80288D4(gUnknown_02022C98->unk40); -} - -// This function is literally the same as the one above...Why? -static void sub_8026B28(void) -{ - sub_8026988(); - if (gUnknown_02022C98->unk40 > 9) - sub_8026AC8(); - else - sub_8026A88(); - - sub_80288D4(gUnknown_02022C98->unk40); -} - -static void sub_8026B5C(u8 arg0, u8 *arg1, u8 *arg2) -{ - switch (arg0) - { - case 1: - *arg1 = 4, *arg2 = 7; - break; - case 2: - *arg1 = 3, *arg2 = 8; - break; - case 3: - *arg1 = 2, *arg2 = 9; - break; - case 4: - *arg1 = 1, *arg2 = 10; - break; - case 5: - *arg1 = 0, *arg2 = 11; - break; - } -} - -static bool32 sub_8026BB8(void) -{ - u8 i, count; - - count = gUnknown_02022C98->unk24; - for (i = 1; i < count; i++) - { - if (gUnknown_02022C98->unk158[i] == 0) - gUnknown_02022C98->unk158[i] = sub_8027DFC(i); - } - - // This loop won't ever run, the seemingly poitnless assingment below is to make the compiler - // generate code for it. - count = count; - for (; i < count; i++) - { - if (gUnknown_02022C98->unk158[i] == 0) - return FALSE; - } - - return TRUE; -} - -static void sub_8026C28(void) -{ - u8 i; - - for (i = 0; i < 5; i++) - gUnknown_02022C98->unk158[i] = 0; -} - -static bool32 sub_8026C50(void) -{ - if (gUnknown_02022C98->unk40 > 9 && gUnknown_02022C98->unk120 == 0) - { - gUnknown_02022C98->unk40 = 10; - if (gUnknown_02022C98->unk12C != 0) - return TRUE; - } - - return FALSE; -} - -static bool32 sub_8026C90(void) -{ - u8 i, first, count; - - if (gUnknown_02022C98->unk40 > 9) - { - first = gUnknown_02022C98->unk44; - count = gUnknown_02022C98->unk48; - gUnknown_02022C98->unk40 = 10; - if (gUnknown_02022C98->unk12C != 0) - { - for (i = first; i < count; i++) - { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - u8 var = gUnknown_082F449C[gUnknown_02022C98->unk24 - 1][gUnknown_02022C98->multiplayerId][i]; - - if (ptr->unk14.unkB[var] != 10) - return FALSE; - } - return TRUE; - } - } - - return FALSE; -} - -static void sub_8026D1C(u8 arg0) -{ - u8 var = gUnknown_082F7A9C[gUnknown_02022C98->unk90[arg0] % 7] + (gUnknown_02022C98->unk90[arg0] / 7) * 100; - if (gUnknown_02022C98->unk86[arg0] >= var) - gUnknown_02022C98->unk90[arg0]++; -} - -static u8 sub_8026D8C(u8 arg0) -{ - return gUnknown_082F4648[gUnknown_02022C98->unk24 - 1][arg0]; -} - -static u8 sub_8026DB0(u8 arg0, u8 arg1) -{ - u8 i, var3; - u8 count = gUnknown_02022C98->unk24 - 1; - u8 var0 = gUnknown_082F45FA[count][arg0][0]; - u8 var1 = gUnknown_082F45FA[count][arg0][1]; - u8 var2 = gUnknown_082F45FA[count][arg0][2]; - - for (i = 0; gUnknown_082F467F[count][i] != 0; i++) - { - if (arg1 == gUnknown_082F467F[count][i]) - return sub_8026E70(gUnknown_02022C98->unk90[var1], arg1); - } - - // Gets the highest of the three. - if (gUnknown_02022C98->unk90[var0] > gUnknown_02022C98->unk90[var1]) - var3 = gUnknown_02022C98->unk90[var0]; - else - var3 = gUnknown_02022C98->unk90[var1]; - - if (gUnknown_02022C98->unk90[var2] > var3) - var3 = gUnknown_02022C98->unk90[var2]; - - return sub_8026E70(var3, arg1); -} - -static u8 sub_8026E70(u8 arg0, u8 arg1) -{ - u8 var = gUnknown_02022C98->unkE8[arg1]; - switch (arg0 % 7) - { - default: return 0; - case 0: return 0; - case 1: return 1; - case 2: return 2; - case 3: - if (var == 0) - return 1; - else - return 0; - case 4: - if (var == 0) - return 2; - else - return 0; - case 5: - if (var == 2) - return 1; - else - return 2; - case 6: - if (var == 0) - return 1; - else if (var == 1) - return 2; - else - return 0; - } -} - -static bool32 sub_8026EEC(u16 arg0[5][6]) -{ - int sum, i; - for (sum = 0, i = 0; i < GetLinkPlayerCount(); sum += arg0[i][3], i++) - ; - - if (sum >= 11) - return TRUE; - else - return FALSE; -} - -static void sub_8026F1C(u8 arg0, u8 arg1, u8 arg2) -{ - u8 var; - u8 count = gUnknown_02022C98->unk24; - switch (arg0) - { - case 0: - case 1: - case 2: - var = gUnknown_02022C98->unk31A0[0].unk14.unk0[arg1]; - gUnknown_02022C98->unk4A[arg2][var] = IncrementWithLimit(gUnknown_02022C98->unk4A[arg2][var], 20000); - break; - case 3: - if (sub_8026EEC(gUnknown_02022C98->unk4A)) - break; - switch (count) - { - case 5: - switch (arg1) - { - case 0: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[3][3]++; - break; - case 1: - gUnknown_02022C98->unk4A[3][3]++; - break; - case 2: - gUnknown_02022C98->unk4A[3][3]++; - gUnknown_02022C98->unk4A[4][3]++; - break; - case 3: - gUnknown_02022C98->unk4A[4][3]++; - break; - case 4: - gUnknown_02022C98->unk4A[4][3]++; - gUnknown_02022C98->unk4A[0][3]++; - break; - case 5: - gUnknown_02022C98->unk4A[0][3]++; - break; - case 6: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; - break; - case 7: - gUnknown_02022C98->unk4A[1][3]++; - break; - case 8: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; - break; - case 9: - gUnknown_02022C98->unk4A[2][3]++; - break; - } - break; - case 4: - switch (arg1) - { - case 1: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[3][3]++; - break; - case 2: - gUnknown_02022C98->unk4A[3][3]++; - break; - case 3: - gUnknown_02022C98->unk4A[3][3]++; - gUnknown_02022C98->unk4A[0][3]++; - break; - case 4: - gUnknown_02022C98->unk4A[0][3]++; - break; - case 5: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; - break; - case 6: - gUnknown_02022C98->unk4A[1][3]++; - break; - case 7: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; - break; - case 8: - gUnknown_02022C98->unk4A[2][3]++; - break; - } - break; - case 3: - switch (arg1) - { - case 2: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; - break; - case 3: - gUnknown_02022C98->unk4A[2][3]++; - break; - case 4: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[0][3]++; - break; - case 5: - gUnknown_02022C98->unk4A[0][3]++; - break; - case 6: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; - break; - case 7: - gUnknown_02022C98->unk4A[1][3]++; - break; - } - break; - case 2: - switch (arg1) - { - case 3: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; - break; - case 4: - gUnknown_02022C98->unk4A[0][3]++; - break; - case 5: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; - break; - case 6: - gUnknown_02022C98->unk4A[1][3]++; - break; - } - break; - } - break; - } -} - -static void sub_8027234(bool32 arg0) -{ - if (gUnknown_02022C98->unk24 != 5) - return; - - if (arg0 == TRUE) - { - if (++gUnknown_02022C98->unk112 > gUnknown_02022C98->unk114) - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk112; - if (gUnknown_02022C98->unk112 > 9999) - gUnknown_02022C98->unk112 = 9999; - } - else - { - if (gUnknown_02022C98->unk112 > gUnknown_02022C98->unk114) - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk112; - gUnknown_02022C98->unk112 = 0; - } -} - -static void sub_80272A4(void) -{ - u8 i; - for (i = 0; i < gUnknown_02022C98->unk24; i++) - gUnknown_02022C98->unk4A[i][5] = gUnknown_02022C98->unk114; -} - -static void sub_80272E8(void) -{ - u8 i, j; - - for (i = 0; i < 5; i++) - { - for (j = 0; j < 11; j++) - gUnknown_02022C98->unk31A0[i].unk14.unkB[j] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk90[i] = 0; - gUnknown_02022C98->unk86[i] = 0; - gUnknown_02022C98->unk3308[i].unk0 = 0; - gUnknown_02022C98->unk3308[i].unk4 = 0; - gUnknown_02022C98->unk4A[i][0] = 0; - gUnknown_02022C98->unk4A[i][1] = 0; - gUnknown_02022C98->unk4A[i][2] = 0; - gUnknown_02022C98->unk4A[i][3] = 0; - gUnknown_02022C98->unk4A[i][4] = 0; - gUnknown_02022C98->unk4A[i][5] = 0; - } - gUnknown_02022C98->unk154 = 0; - gUnknown_02022C98->unk112 = 0; - gUnknown_02022C98->unk40 = 0; - sub_8026A88(); - sub_8026988(); -} - -static const s16 gUnknown_082F7B24[] = {10, 30, 50, 50}; - -static void sub_80273F0(void) -{ - u8 i, var = 0, var2 = 0; - - switch (gUnknown_02022C98->unk24) - { - case 4: var = 1; break; - case 5: var = 2; break; - } - - var2 = Random() % 10; - for (i = 0; i < 5; i++) - gUnknown_02022C98->unk4A[i][4] = gUnknown_082F7AA4[var][var2]; -} - -static u32 sub_802745C(u8 arg0) -{ - u32 sum = gUnknown_02022C98->unk4A[arg0][0] - + gUnknown_02022C98->unk4A[arg0][1] - + gUnknown_02022C98->unk4A[arg0][2]; - return min(sum, 9999); -} - -static void sub_802749C(void) -{ - u32 berriesPicked = Min(sub_802745C(gUnknown_02022C98->multiplayerId), 9999); - u32 score = Min(sub_80276C0(gUnknown_02022C98->multiplayerId), 999990); - - if (gSaveBlock2Ptr->berryPick.bestScore < score) - gSaveBlock2Ptr->berryPick.bestScore = score; - if (gSaveBlock2Ptr->berryPick.berriesPicked < berriesPicked) - gSaveBlock2Ptr->berryPick.berriesPicked = berriesPicked; - if (gSaveBlock2Ptr->berryPick.berriesPickedInRow < gUnknown_02022C98->unk114) - gSaveBlock2Ptr->berryPick.berriesPickedInRow = gUnknown_02022C98->unk114; -} - -static u8 sub_8027518(u8 arg0) -{ - u8 i, saved; - - saved = gUnknown_02022C98->unk98[3]; - for (i = 3; i != 0; i--) - gUnknown_02022C98->unk98[i] = gUnknown_02022C98->unk98[i - 1]; - gUnknown_02022C98->unk98[0] = arg0; - return saved; -} - -static void sub_8027554(void) -{ - if (gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] == 0) - { - if (JOY_NEW(DPAD_UP)) - { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 2; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; - PlaySE(SE_M_CHARM); - } - else if (JOY_NEW(DPAD_LEFT)) - { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 3; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; - PlaySE(SE_M_CHARM); - } - else if (JOY_NEW(DPAD_RIGHT)) - { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 1; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; - PlaySE(SE_M_CHARM); - } - else - { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 0; - } - } - else - { - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId]--; - } -} - -static void sub_8027608(void) -{ - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 0; -} - -static u16 sub_802762C(void) -{ - return gUnknown_02022C98->unk4A[gUnknown_02022C98->multiplayerId][4] + FIRST_BERRY_INDEX; -} - -static u8 sub_8027650(void) -{ - return gUnknown_02022C98->unk24; -} - -static u8 *sub_8027660(u8 id) -{ - if (gReceivedRemoteLinkPlayers) - return gLinkPlayers[id].name; - else - return gUnknown_02022C98->unk31A0[id].name; -} - -static u16 sub_80276A0(u8 arg0, u8 arg1) -{ - return gUnknown_02022C98->unk4A[arg0][arg1]; -} - -static u32 sub_80276C0(u8 arg0) -{ - u8 i; - u32 var, sum = 0; - - for (i = 0; i < 3; i++) - sum += gUnknown_02022C98->unk4A[arg0][i] * gUnknown_082F7B24[i]; - - var = gUnknown_02022C98->unk4A[arg0][3] * gUnknown_082F7B24[3]; - if (sum <= var) - return 0; - else - return sum - var; -} - -static u32 sub_8027748(void) -{ - u8 i, count = gUnknown_02022C98->unk24; - u32 maxVar = sub_80276C0(0); - - for (i = 1; i < count; i++) - { - u32 var = sub_80276C0(i); - if (var > maxVar) - maxVar = var; - } - return Min(maxVar, 999990); -} - -static u32 sub_802778C(u8 arg0) -{ - u8 i, count = gUnknown_02022C98->unk24; - u16 maxVar = gUnknown_02022C98->unk4A[0][arg0]; - - for (i = 0; i < count; i++) - { - u16 var = gUnknown_02022C98->unk4A[i][arg0]; - if (var > maxVar) - maxVar = var; - } - return maxVar; -} - -static u32 sub_80277D0(u8 arg0) -{ - u32 vals[5], temp; - s16 r6 = TRUE; - u8 i, count = gUnknown_02022C98->unk24; - - for (i = 0; i < count; i++) - vals[i] = temp = sub_80276C0(i); - - while (r6) - { - r6 = FALSE; - for (i = 0; i < count - 1; i++) - { - if (vals[i] < vals[i + 1]) - { - SWAP(vals[i], vals[i + 1], temp); - r6 = TRUE; - } - } - } - - return vals[arg0]; -} - -static u32 sub_802784C(void) -{ - u8 i, r10 = 0, r8 = 0, r9 = 0, count = gUnknown_02022C98->unk24; - - // Function called two times for some reason. - sub_8027748(); - if (sub_8027748() == 0) - { - for (i = 0; i < count; i++) - { - gUnknown_02022C98->unk3308[i].unk0 = 4; - gUnknown_02022C98->unk3308[i].unk4 = 0; - } - } - - for (i = 0; i < count; i++) - gUnknown_02022C98->unk3308[i].unk4 = Min(sub_80276C0(i), 999990); - - do - { - u32 r6 = sub_80277D0(r10); - u8 r3 = r8; - for (i = 0; i < count; i++) - { - if (r6 == gUnknown_02022C98->unk3308[i].unk4) - { - gUnknown_02022C98->unk3308[i].unk0 = r3; - r8++; - r9++; - } - } - r10 = r8; - } while (r9 < count); - - return 0; -} - -static void sub_802793C(struct DodrioSubstruct_3308 *dst, u8 id) -{ - *dst = gUnknown_02022C98->unk3308[id]; -} - -// Unused function -static u8 sub_802795C(u8 arg0) -{ - u8 i, ret = 0, count = gUnknown_02022C98->unk24; - u32 var, vars[5] = {0}; - - for (i = 0; i < count; i++) - vars[i] = sub_80276C0(i); - - var = vars[arg0]; - for (i = 0; i < 5; i++) - { - if (i != arg0 && var < vars[i]) - ret++; - } - - return ret; -} - -static u8 sub_80279C8(void) -{ - u8 multiplayerId = gUnknown_02022C98->multiplayerId; - u16 itemId = sub_802762C(); - - if (sub_80276C0(multiplayerId) != sub_8027748()) - return 3; - if (!CheckBagHasSpace(itemId, 1)) - return 2; - - AddBagItem(itemId, 1); - if (!CheckBagHasSpace(itemId, 1)) - return 1; - return 0; -} - -// Really? What next, u32 Add(u32 a)return a+1;? -static u32 IncrementWithLimit(u32 a, u32 max) -{ - if (a < max) - return a + 1; - else - return max; -} - -// Gamefreak pls, min(a, b) ((a) < (b) ? (a) : (b)) is a well-known macro -static u32 Min(u32 a, u32 b) -{ - if (a < b) - return a; - else - return b; -} - -static u8 sub_8027A48(u8 id) -{ - return gUnknown_02022C98->unk34[id]; -} - -void IsDodrioInParty(void) -{ - int i; - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_HAS_SPECIES) - && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_DODRIO) - { - gSpecialVar_Result = TRUE; - return; - } - } - - gSpecialVar_Result = FALSE; -} - -void ShowDodrioBerryPickingRecords(void) -{ - u8 taskId = CreateTask(Task_ShowDodrioBerryPickingRecords, 0); - Task_ShowDodrioBerryPickingRecords(taskId); -} - -// Data related to printing saved results. -static const struct WindowTemplate gUnknown_082F7B2C = -{ - .bg = 0, - .tilemapLeft = 5, - .tilemapTop = 1, - .width = 20, - .height = 11, - .paletteNum = 15, - .baseBlock = 0x1, -}; - -static const u8 *const gUnknown_082F7B34[3] = {gText_BerriesPicked, gText_BestScore, gText_BerriesInRowFivePlayers}; -static const u8 gUnknown_082F7B40[] = {4, 7, 4}; - -ALIGNED(4) -static const u8 gUnknown_082F7B44[][2] = {{25}, {41}, {57}}; -static const u8 gUnknown_082F7B4A[][2] = {{25}, {41}, {73}}; - -static void Task_ShowDodrioBerryPickingRecords(u8 taskId) -{ - struct WindowTemplate window; - s32 i, width, widthCurr; - s16 *data = gTasks[taskId].data; - - switch (data[0]) - { - case 0: - window = gUnknown_082F7B2C; - width = GetStringWidth(1, gText_BerryPickingRecords, 0); - for (i = 0; i < ARRAY_COUNT(gUnknown_082F7B34); i++) - { - widthCurr = GetStringWidth(1, gUnknown_082F7B34[i], 0) + 50; - if (widthCurr > width) - width = widthCurr; - } - width = (width + 7) / 8; - if (width & 1) - width++; - window.tilemapLeft = (30 - width) / 2; - window.width = width; - data[1] = AddWindow(&window); - sub_8027BEC(data[1], width); - CopyWindowToVram(data[1], 3); - data[0]++; - break; - case 1: - if (!IsDma3ManagerBusyWithBgCopy()) - data[0]++; - break; - case 2: - if (JOY_NEW(A_BUTTON | B_BUTTON)) - { - rbox_fill_rectangle(data[1]); - CopyWindowToVram(data[1], 1); - data[0]++; - } - break; - case 3: - if (!IsDma3ManagerBusyWithBgCopy()) - { - RemoveWindow(data[1]); - DestroyTask(taskId); - EnableBothScriptContexts(); - } - break; - } -} - -static void sub_8027BEC(u8 windowId, s32 width) -{ - s32 i, x, numWidth; - s32 results[3]; - results[0] = gSaveBlock2Ptr->berryPick.berriesPicked; - results[1] = gSaveBlock2Ptr->berryPick.bestScore; - results[2] = gSaveBlock2Ptr->berryPick.berriesPickedInRow; - - LoadUserWindowBorderGfx_(windowId, 0x21D, 0xD0); - DrawTextBorderOuter(windowId, 0x21D, 0xD); - FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); - AddTextPrinterParameterized(windowId, 1, gText_BerryPickingRecords, GetStringCenterAlignXOffset(1, gText_BerryPickingRecords, width * 8), 1, TEXT_SPEED_FF, NULL); - for (i = 0; i < 3; i++) - { - ConvertIntToDecimalStringN(gStringVar1, results[i], STR_CONV_MODE_LEFT_ALIGN, gUnknown_082F7B40[i]); - numWidth = GetStringWidth(1, gStringVar1, -1); - AddTextPrinterParameterized(windowId, 1, gUnknown_082F7B34[i], 0, gUnknown_082F7B44[i][0], TEXT_SPEED_FF, NULL); - x = (width * 8) - numWidth; - AddTextPrinterParameterized(windowId, 1, gStringVar1, x, gUnknown_082F7B4A[i][0], TEXT_SPEED_FF, NULL); - } - PutWindowTilemap(windowId); -} - -// Debug functions? -static const u16 gUnknown_082F7B50[][4] = -{ - {9999, 0, 90, 9999}, - {9999, 9999, 70, 9999}, - {9999, 0, 9999, 0}, - {9999, 9999, 60, 0}, - {9999, 9999, 9999, 0}, -}; - -static const u8 sJPText_Vowels[] = _("あいうえおかき"); -static const u8 sText_ABCDEFG[] = _("ABCDEFG"); -static const u8 sText_0123456[] = _("0123456"); - -static const u8 *const sPlaceholderPlayerNames[] = -{ - sJPText_Vowels, - sJPText_Vowels, - sJPText_Vowels, - sText_ABCDEFG, - sText_0123456 -}; - -static void sub_8027D20(void) -{ - gUnknown_02022C98->unk24 = GetLinkPlayerCount(); -} - -static void sub_8027D38(void) -{ - u8 i, playerId; - - for (playerId = gUnknown_02022C98->unk24; playerId < ARRAY_COUNT(sPlaceholderPlayerNames); playerId++) - StringCopy(gLinkPlayers[playerId].name, sPlaceholderPlayerNames[playerId]); - - gUnknown_02022C98->unk24 = 5; - for (i = 0; i < 4; i++) - { - for (playerId = 0; playerId < gUnknown_02022C98->unk24; playerId++) - gUnknown_02022C98->unk4A[playerId][i] = gUnknown_082F7B50[playerId][i]; - } -} - -struct UnkPacket1 -{ - u8 id; - u8 ALIGNED(4) unk4; -}; - -static void sub_8027DD0(u32 arg0) -{ - struct UnkPacket1 packet; - packet.id = 1; - packet.unk4 = arg0; - Rfu_SendPacket(&packet); -} - -static u32 sub_8027DFC(u32 arg0) -{ - struct UnkPacket1 *packet; - - if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; - - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 1) - return packet->unk4; - - return 0; -} - -struct UnkPacket2 -{ - u8 id; - u8 unk1_0:4; - u8 unk1_1:4; - u16 unk2_0:4; - u16 unk2_1:4; - u16 unk3_0:4; - u16 unk3_1:4; - u16 unk4_0:4; - u16 unk4_1:4; - u16 unk5_0:4; - u16 unk5_1:4; - u16 unk6_0:2; - u16 unk6_1:2; - u16 unk6_2:2; - u16 unk6_3:2; - u16 unk7_0:2; - u16 unk7_1:2; - u16 unk7_2:2; - u16 unk7_3:2; - u8 unk8_0:2; - u8 unk8_1:2; - u8 unk8_2:2; - u8 unk8_3:2; - u8 unk9_0:2; - u8 unk9_1:2; - u8 unk9_2:2; - u8 unk9_3:1; - u8 unk9_4:1; - u8 unkA_0:1; - u8 unkA_1:1; - u8 unkA_2:1; - u8 unkA_3:5; - u8 unkB_0:1; - u8 unkB_1:1; - u8 unkB_2:1; - u8 unkB_3:1; - u8 unkB_4:1; - u8 unkB_5:1; - u8 unkB_6:1; -}; - -static void sub_8027E30(struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 arg6, u32 arg7, u32 arg8) -{ - struct UnkPacket2 packet; - struct DodrioSubstruct_31A0_14 *ptr = &arg0->unk14; - - packet.id = 2; - packet.unk1_0 = ptr->unkB[0]; - packet.unk1_1 = ptr->unkB[1]; - packet.unk2_0 = ptr->unkB[2]; - packet.unk2_1 = ptr->unkB[3]; - packet.unk3_0 = ptr->unkB[4]; - packet.unk3_1 = ptr->unkB[5]; - packet.unk4_0 = ptr->unkB[6]; - packet.unk4_1 = ptr->unkB[7]; - packet.unk5_0 = ptr->unkB[8]; - packet.unk5_1 = ptr->unkB[9]; - - packet.unk6_0 = ptr->unk0[0]; - packet.unk6_1 = ptr->unk0[1]; - packet.unk6_2 = ptr->unk0[2]; - packet.unk6_3 = ptr->unk0[3]; - packet.unk7_0 = ptr->unk0[4]; - packet.unk7_1 = ptr->unk0[5]; - packet.unk7_2 = ptr->unk0[6]; - packet.unk7_3 = ptr->unk0[7]; - packet.unk8_0 = ptr->unk0[8]; - packet.unk8_1 = ptr->unk0[9]; - - packet.unk8_2 = arg1->unk0; - packet.unk8_3 = arg2->unk0; - packet.unk9_0 = arg3->unk0; - packet.unk9_1 = arg4->unk0; - packet.unk9_2 = arg5->unk0; - - packet.unk9_3 = arg1->unk4; - packet.unk9_4 = arg2->unk4; - packet.unkA_0 = arg3->unk4; - packet.unkA_1 = arg4->unk4; - packet.unkA_2 = arg5->unk4; - - packet.unkB_2 = arg1->unk8; - packet.unkB_3 = arg2->unk8; - packet.unkB_4 = arg3->unk8; - packet.unkB_5 = arg4->unk8; - packet.unkB_6 = arg5->unk8; - - packet.unkA_3 = arg6; - packet.unkB_1 = arg7; - packet.unkB_0 = arg8; - Rfu_SendPacket(&packet); -} - -static u32 sub_8028164(u32 unused, struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 *arg6, u32 *arg7, u32 *arg8) -{ - struct UnkPacket2 *packet; - struct DodrioSubstruct_31A0_14 *ptr = &arg0->unk14; - - if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; - - packet = (void *)&gRecvCmds[0][1]; - if (packet->id == 2) - { - ptr->unkB[0] = packet->unk1_0; - ptr->unkB[1] = packet->unk1_1; - ptr->unkB[2] = packet->unk2_0; - ptr->unkB[3] = packet->unk2_1; - ptr->unkB[4] = packet->unk3_0; - ptr->unkB[5] = packet->unk3_1; - ptr->unkB[6] = packet->unk4_0; - ptr->unkB[7] = packet->unk4_1; - ptr->unkB[8] = packet->unk5_0; - ptr->unkB[9] = packet->unk5_1; - ptr->unkB[10] = packet->unk1_0; - - ptr->unk0[0] = packet->unk6_0; - ptr->unk0[1] = packet->unk6_1; - ptr->unk0[2] = packet->unk6_2; - ptr->unk0[3] = packet->unk6_3; - ptr->unk0[4] = packet->unk7_0; - ptr->unk0[5] = packet->unk7_1; - ptr->unk0[6] = packet->unk7_2; - ptr->unk0[7] = packet->unk7_3; - ptr->unk0[8] = packet->unk8_0; - ptr->unk0[9] = packet->unk8_1; - ptr->unk0[10] = packet->unk6_0; - - arg1->unk0 = packet->unk8_2; - arg1->unk4 = packet->unk9_3; - arg1->unk8 = packet->unkB_2; - - arg2->unk0 = packet->unk8_3; - arg2->unk4 = packet->unk9_4; - arg2->unk8 = packet->unkB_3; - - arg3->unk0 = packet->unk9_0; - arg3->unk4 = packet->unkA_0; - arg3->unk8 = packet->unkB_4; - - arg4->unk0 = packet->unk9_1; - arg4->unk4 = packet->unkA_1; - arg4->unk8 = packet->unkB_5; - - arg5->unk0 = packet->unk9_2; - arg5->unk4 = packet->unkA_2; - arg5->unk8 = packet->unkB_6; - - *arg6 = packet->unkA_3; - *arg7 = packet->unkB_1; - *arg8 = packet->unkB_0; - return 1; - } - - return 0; -} - -struct UnkPacket3 -{ - u8 id; - u8 ALIGNED(4) unk4; -}; - -static void sub_80282EC(u8 arg0) -{ - struct UnkPacket3 packet; - packet.id = 3; - packet.unk4 = arg0; - Rfu_SendPacket(&packet); -} - -static u32 sub_8028318(u32 arg0, u8 *arg1) -{ - struct UnkPacket3 *packet; - - if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; - - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 3) - { - *arg1 = packet->unk4; - return 1; - } - - return 0; -} - -struct UnkPacket4 -{ - u8 id; - u32 unk4; -}; - -static void sub_8028350(u32 arg0) -{ - struct UnkPacket4 packet; - packet.id = 4; - packet.unk4 = arg0; - Rfu_SendPacket(&packet); -} - -static u32 sub_8028374(u32 arg0) -{ - struct UnkPacket4 *packet; - - if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; - - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 4) - return packet->unk4; - - return 0; -} - -// Large chunk of data -static const struct BgTemplate gUnknown_082F7BA4[] = -{ - { - .bg = 0, - .charBaseIndex = 0, - .mapBaseIndex = 30, - .screenSize = 0, - .paletteMode = 0, - .priority = 0, - .baseTile = 0 - }, - { - .bg = 1, - .charBaseIndex = 2, - .mapBaseIndex = 12, - .screenSize = 1, - .paletteMode = 0, - .priority = 1, - .baseTile = 0 - }, - { - .bg = 2, - .charBaseIndex = 2, - .mapBaseIndex = 14, - .screenSize = 1, - .paletteMode = 0, - .priority = 1, - .baseTile = 0 - }, - { - .bg = 3, - .charBaseIndex = 3, - .mapBaseIndex = 31, - .screenSize = 0, - .paletteMode = 0, - .priority = 2, - .baseTile = 0 - }, -}; - -// Unknown unreferenced data, feel free to remove. -static const u32 sUnused[] = {255, 0}; - -static const struct WindowTemplate gUnknown_082F7BBC[] = -{ - { - .bg = 0, - .tilemapLeft = 1, - .tilemapTop = 1, - .width = 28, - .height = 2, - .paletteNum = 13, - .baseBlock = 0x13, - }, - { - .bg = 0, - .tilemapLeft = 1, - .tilemapTop = 5, - .width = 28, - .height = 14, - .paletteNum = 13, - .baseBlock = 0x4B, - } -}; -static const struct WindowTemplate gUnknown_082F7BCC = -{ - .bg = 0, - .tilemapLeft = 1, - .tilemapTop = 5, - .width = 28, - .height = 7, - .paletteNum = 13, - .baseBlock = 0x4B, -}; -static const struct WindowTemplate gUnknown_082F7BD4[] = -{ - { - .bg = 0, - .tilemapLeft = 1, - .tilemapTop = 8, - .width = 19, - .height = 3, - .paletteNum = 13, - .baseBlock = 0x13, - }, - { - .bg = 0, - .tilemapLeft = 22, - .tilemapTop = 7, - .width = 6, - .height = 4, - .paletteNum = 13, - .baseBlock = 0x4C, - } -}; -static const struct WindowTemplate gUnknown_082F7BE4 = -{ - .bg = 0, - .tilemapLeft = 4, - .tilemapTop = 6, - .width = 22, - .height = 5, - .paletteNum = 13, - .baseBlock = 0x13, -}; -static const struct WindowTemplate gUnknown_082F7BEC = -{ - .bg = 0, - .tilemapLeft = 5, - .tilemapTop = 8, - .width = 19, - .height = 3, - .paletteNum = 13, - .baseBlock = 0x13, -}; - -// This is an unused copy of the tables from the top of the file. Feel free to remove. -static const u8 sDuplicateArray[] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0, 0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 2, 9, - 0, 0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0, 0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0, 0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0, 0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0, 0, 7, - 8, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0, - 1, 2, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 4, 5, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 5, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 6, 7, 2, 2, 3, 4, 0, 0, 0, 0, 0, 0, - 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2, 3, 0, 0, 0, 4, 5, 6, 6, 7, 8, 8, 9, 0, 0, 1, 2, 2, 3, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 1, - 2, 1, 2, 3, 2, 3, 0, 0, 0, 0, 4, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 0, 0, 0, 0, 9, 9, 9, 9, 1, 1, 1, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 1, 1, 0, 9, 9, 9, 9, 9, 2, 2, 0, 0, 1, 1, 1, 9, 9, 9, 3, 3, 0, 0, 1, 1, 2, 2, 3, 9, 3, 3, 4, 4, 0, 0, 1, 1, - 2, 2, 3, 5, 0, 0, 0, 0, 4, 6, 0, 0, 0, 3, 5, 7, 0, 0, 2, 4, 6, 8, 0, 1, 3, 5, 6, 9 -}; - -static const u16 gDodrioBerryBgPal1[] = INCBIN_U16("graphics/link_games/dodrioberry_bg1.gbapal", - "graphics/link_games/dodrioberry_bg2.gbapal"); -static const u16 gDodrioBerryPkmnPal[] = INCBIN_U16("graphics/link_games/dodrioberry_pkmn.gbapal"); -static const u16 gDodrioBerryShinyPal[] = INCBIN_U16("graphics/link_games/dodrioberry_shiny.gbapal"); -static const u16 gDodrioBerryStatusPal[] = INCBIN_U16("graphics/link_games/dodrioberry_status.gbapal"); -static const u16 gDodrioBerrySpritesPal[] = INCBIN_U16("graphics/link_games/dodrioberry_berrysprites.gbapal"); -static const u32 gDodrioBerrySpritesGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_berrysprites.4bpp.lz"); -static const u16 gDodrioBerryPlatformPal[] = INCBIN_U16("graphics/link_games/dodrioberry_platform.gbapal"); -static const u32 gDodrioBerryBgGfx1[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.4bpp.lz"); -static const u32 gDodrioBerryBgGfx2[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2.4bpp.lz"); -static const u32 gDodrioBerryStatusGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_status.4bpp.lz"); -static const u32 gDodrioBerryPlatformGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_platform.4bpp.lz"); -static const u32 gDodrioBerryPkmnGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_pkmn.4bpp.lz"); -static const u32 gDodrioBerryBgTilemap1[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.bin.lz"); -static const u32 gDodrioBerryBgTilemap2Right[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2right.bin.lz"); -static const u32 gDodrioBerryBgTilemap2Left[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2left.bin.lz"); - -static const struct OamData sOamData_82FB1E0 = +static const u16 sBg_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/bg.gbapal", + "graphics/dodrio_berry_picking/tree_border.gbapal"); +static const u16 sDodrioNormal_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/dodrio.gbapal"); +static const u16 sDodrioShiny_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/shiny.gbapal"); +static const u16 sStatus_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/status.gbapal"); +static const u16 sBerries_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/berries.gbapal"); +static const u32 sBerries_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/berries.4bpp.lz"); +static const u16 sCloud_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/cloud.gbapal"); +static const u32 sBg_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.4bpp.lz"); +static const u32 sTreeBorder_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border.4bpp.lz"); +static const u32 sStatus_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/status.4bpp.lz"); +static const u32 sCloud_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/cloud.4bpp.lz"); +static const u32 sDodrio_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/dodrio.4bpp.lz"); +static const u32 sBg_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.bin.lz"); +static const u32 sTreeBorderRight_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border_right.bin.lz"); +static const u32 sTreeBorderLeft_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border_left.bin.lz"); + +static const struct OamData sOamData_Dodrio = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3151,7 +3618,8 @@ static const struct OamData sOamData_82FB1E0 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1E8 = +// Used by the status bar and the results screen berry icons +static const struct OamData sOamData_16x16_Priority0 = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3168,7 +3636,7 @@ static const struct OamData sOamData_82FB1E8 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1F0 = +static const struct OamData sOamData_Berry = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3185,7 +3653,7 @@ static const struct OamData sOamData_82FB1F0 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1F8 = +static const struct OamData sOamData_Cloud = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3202,533 +3670,589 @@ static const struct OamData sOamData_82FB1F8 = .affineParam = 0 }; -static const union AnimCmd sSpriteAnim_82FB200[] = +static const union AnimCmd sAnim_Dodrio_Normal[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB208[] = +static const union AnimCmd sAnim_Dodrio_PickRight[] = { ANIMCMD_FRAME(64, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB210[] = +static const union AnimCmd sAnim_Dodrio_PickMiddle[] = { ANIMCMD_FRAME(128, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB218[] = +static const union AnimCmd sAnim_Dodrio_PickLeft[] = { ANIMCMD_FRAME(192, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB220[] = +static const union AnimCmd sAnim_Dodrio_Down[] = { ANIMCMD_FRAME(256, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB228[] = +static const union AnimCmd *const sAnims_Dodrio[] = { - sSpriteAnim_82FB200, - sSpriteAnim_82FB208, - sSpriteAnim_82FB210, - sSpriteAnim_82FB218, - sSpriteAnim_82FB220 + [PICK_NONE] = sAnim_Dodrio_Normal, + [PICK_RIGHT] = sAnim_Dodrio_PickRight, + [PICK_MIDDLE] = sAnim_Dodrio_PickMiddle, + [PICK_LEFT] = sAnim_Dodrio_PickLeft, + [PICK_DISABLED] = sAnim_Dodrio_Down, + // There is an unused 6th frame of Dodrio's graphic }; -static const union AnimCmd sSpriteAnim_82FB23C[] = +static const union AnimCmd sAnims_StatusBar_Yellow[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB244[] = +static const union AnimCmd sAnims_StatusBar_Gray[] = { ANIMCMD_FRAME(4, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB24C[] = +static const union AnimCmd sAnims_StatusBar_Red[] = { ANIMCMD_FRAME(8, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB254[] = +static const union AnimCmd *const sAnims_StatusBar[] = { - sSpriteAnim_82FB23C, - sSpriteAnim_82FB244, - sSpriteAnim_82FB24C + [STATUS_YELLOW] = sAnims_StatusBar_Yellow, + [STATUS_GRAY] = sAnims_StatusBar_Gray, + [STATUS_RED] = sAnims_StatusBar_Red }; -static const union AnimCmd sSpriteAnim_82FB260[] = +static const union AnimCmd sAnim_Berry_Blue[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB268[] = +static const union AnimCmd sAnim_Berry_Green[] = { ANIMCMD_FRAME(4, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB270[] = +static const union AnimCmd sAnim_Berry_Gold[] = { ANIMCMD_FRAME(8, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB278[] = +static const union AnimCmd sAnim_Berry_BlueSquished[] = { ANIMCMD_FRAME(12, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB280[] = +static const union AnimCmd sAnim_Berry_GreenSquished[] = { ANIMCMD_FRAME(16, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB288[] = +static const union AnimCmd sAnim_Berry_GoldSquished[] = { ANIMCMD_FRAME(20, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB290[] = +static const union AnimCmd sAnim_Berry_Eaten[] = { ANIMCMD_FRAME(24, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB298[] = +static const union AnimCmd sAnim_Berry_Empty1[] = { ANIMCMD_FRAME(28, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB2A0[] = +static const union AnimCmd sAnim_Berry_Empty2[] = { ANIMCMD_FRAME(32, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB2A8[] = +static const union AnimCmd *const sAnims_Berry[] = { - sSpriteAnim_82FB260, - sSpriteAnim_82FB268, - sSpriteAnim_82FB270, - sSpriteAnim_82FB278, - sSpriteAnim_82FB280, - sSpriteAnim_82FB288, - sSpriteAnim_82FB290, - sSpriteAnim_82FB298, - sSpriteAnim_82FB2A0 + [BERRY_BLUE] = sAnim_Berry_Blue, + [BERRY_GREEN] = sAnim_Berry_Green, + [BERRY_GOLD] = sAnim_Berry_Gold, + + [BERRY_BLUE + BERRY_MISSED] = sAnim_Berry_BlueSquished, + [BERRY_GREEN + BERRY_MISSED] = sAnim_Berry_GreenSquished, + [BERRY_GOLD + BERRY_MISSED] = sAnim_Berry_GoldSquished, + + [ANIM_EATEN] = sAnim_Berry_Eaten, + + sAnim_Berry_Empty1, + sAnim_Berry_Empty2 }; -static const union AnimCmd sSpriteAnim_82FB2CC[] = +static const union AnimCmd sAnim_Cloud[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB2D4[] = +static const union AnimCmd *const sAnims_Cloud[] = { - sSpriteAnim_82FB2CC + sAnim_Cloud }; -static void sub_80283A8(void) +static void LoadDodrioGfx(void) { void *ptr = AllocZeroed(0x3000); - struct SpritePalette pal1 = {gDodrioBerryPkmnPal, 0}; - struct SpritePalette pal2 = {gDodrioBerryShinyPal, 1}; + struct SpritePalette normal = {sDodrioNormal_Pal, PALTAG_DODRIO_NORMAL}; + struct SpritePalette shiny = {sDodrioShiny_Pal, PALTAG_DODRIO_SHINY}; - LZ77UnCompWram(gDodrioBerryPkmnGfx, ptr); - // This check should be one line up. - if (ptr != NULL) + LZ77UnCompWram(sDodrio_Gfx, ptr); + if (ptr) { - struct SpriteSheet sheet = {ptr, 0x3000, 0}; + struct SpriteSheet sheet = {ptr, 0x3000, GFXTAG_DODRIO}; LoadSpriteSheet(&sheet); Free(ptr); } - LoadSpritePalette(&pal1); - LoadSpritePalette(&pal2); + LoadSpritePalette(&normal); + LoadSpritePalette(&shiny); } -static void sub_8028408(struct DodrioSubstruct_318C *arg0, u8 arg1, u8 id, u8 arg3) +static void CreateDodrioSprite(struct DodrioGame_MonInfo * monInfo, u8 playerId, u8 id, u8 numPlayers) { - struct SpriteTemplate sprTemplate = + struct SpriteTemplate template = { - .tileTag = 0, - .paletteTag = arg0->isShiny, - .oam = &sOamData_82FB1E0, - .anims = sSpriteAnimTable_82FB228, + .tileTag = GFXTAG_DODRIO, + .paletteTag = monInfo->isShiny, // PALTAG_DODRIO_NORMAL / PALTAG_DODRIO_SHINY + .oam = &sOamData_Dodrio, + .anims = sAnims_Dodrio, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_80284A8, + .callback = SpriteCB_Dodrio, }; - gUnknown_02022C9C[id] = AllocZeroed(4); - *gUnknown_02022C9C[id] = CreateSprite(&sprTemplate, sub_8028F14(arg1, arg3), 136, 3); - sub_8028654(TRUE, id); + sDodrioSpriteIds[id] = AllocZeroed(4); + *sDodrioSpriteIds[id] = CreateSprite(&template, GetDodrioXPos(playerId, numPlayers), 136, 3); + SetDodrioInvisibility(TRUE, id); } -static void sub_80284A8(struct Sprite *sprite) +#define sState data[0] +#define sTimer data[1] +#define sUnused1 data[2] +#define sUnused2 data[3] +#define sUnused3 data[4] + +static void SpriteCB_Dodrio(struct Sprite *sprite) { - switch (sprite->data[0]) + switch (sprite->sState) { case 0: break; case 1: - sub_802853C(sprite); + DoDodrioMissedAnim(sprite); break; case 2: - sub_80285AC(sprite); + DoDodrioIntroAnim(sprite); break; } } -static void sub_80284CC(u8 unused) +static void StartDodrioMissedAnim(u8 unused) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[GetMultiplayerId()]]; - sprite->data[0] = 1; - sprite->data[1] = 0; - sprite->data[2] = 0; - sprite->data[3] = 0; - sprite->data[4] = 0; + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[GetMultiplayerId()]]; + sprite->sState = 1; + sprite->sTimer = 0; + sprite->sUnused1 = 0; + sprite->sUnused2 = 0; + sprite->sUnused3 = 0; } -static void sub_8028504(u8 unused) +static void StartDodrioIntroAnim(u8 unused) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[GetMultiplayerId()]]; - sprite->data[0] = 2; - sprite->data[1] = 0; - sprite->data[2] = 0; - sprite->data[3] = 0; - sprite->data[4] = 0; + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[GetMultiplayerId()]]; + sprite->sState = 2; + sprite->sTimer = 0; + sprite->sUnused1 = 0; + sprite->sUnused2 = 0; + sprite->sUnused3 = 0; } -static u32 sub_802853C(struct Sprite *sprite) +// Do animation where Dodrio shakes horizontally after reaching for a berry and missing +static u32 DoDodrioMissedAnim(struct Sprite *sprite) { - s8 var; - u8 mod = (++sprite->data[1] / 2) % 4; + s8 x; + u8 state = (++sprite->sTimer / 2) % 4; - if (sprite->data[1] >= 3) + if (sprite->sTimer >= 3) { - switch (mod) + switch (state) { default: - var = 1; + x = 1; break; case 1: case 2: - var = -1; + x = -1; break; } - sprite->pos1.x += var; - if (++sprite->data[1] >= 40) + sprite->pos1.x += x; + if (++sprite->sTimer >= 40) { - sprite->data[0] = 0; - sprite->pos1.x = sub_8028F14(0, sub_8027650()); + sprite->sState = 0; + sprite->pos1.x = GetDodrioXPos(0, GetNumPlayers()); } } return 0; } -static u32 sub_80285AC(struct Sprite *sprite) -{ - u8 mod = (++sprite->data[1] / 13) % 4; +// Does the intro animation where the player's Dodrio +// cycles through extending each head twice +#define FRAMES_PER_STATE 13 +#define NUM_INTRO_PICK_STATES PICK_DISABLED // Cycle through 'Normal' and each head, but exclude the Disabled state - if (sprite->data[1] % 13 == 0 && mod != 0) +static u32 DoDodrioIntroAnim(struct Sprite *sprite) +{ + u8 pickState = (++sprite->sTimer / FRAMES_PER_STATE) % NUM_INTRO_PICK_STATES; + + // Play a sound effect at the start of each head extension + if (sprite->sTimer % FRAMES_PER_STATE == 0 && pickState != PICK_NONE) PlaySE(SE_M_CHARM); - if (sprite->data[1] >= 104) + + if (sprite->sTimer >= FRAMES_PER_STATE * NUM_INTRO_PICK_STATES * 2) { - sprite->data[0] = 0; - mod = 0; + // End animation + sprite->sState = 0; + pickState = PICK_NONE; } - sub_80286B4(GetMultiplayerId(), mod); + SetDodrioAnim(GetMultiplayerId(), pickState); return 0; } -static void sub_8028614(u8 count) +#undef sState +#undef sTimer +#undef sUnused1 +#undef sUnused2 +#undef sUnused3 + +static void FreeDodrioSprites(u8 numPlayers) { u8 i; - for (i = 0; i < count; i++) + for (i = 0; i < numPlayers; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[i]]; - if (sprite != NULL) + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[i]]; + if (sprite) DestroySpriteAndFreeResources(sprite); - // Memory should be freed here but is not. +#ifdef BUGFIX + FREE_AND_SET_NULL(sDodrioSpriteIds[i]); // Memory should be freed here but is not. +#endif } } -static void sub_8028654(bool8 invisible, u8 id) +static void SetDodrioInvisibility(bool8 invisible, u8 id) { - gSprites[*gUnknown_02022C9C[id]].invisible = invisible; + gSprites[*sDodrioSpriteIds[id]].invisible = invisible; } -static void sub_802868C(bool8 invisible, u8 count) +static void SetAllDodrioInvisibility(bool8 invisible, u8 count) { u8 i; for (i = 0; i < count; i++) - sub_8028654(invisible, i); + SetDodrioInvisibility(invisible, i); } -static void sub_80286B4(u8 id, u8 frameNum) +static void SetDodrioAnim(u8 id, u8 pickState) { - StartSpriteAnim(&gSprites[*gUnknown_02022C9C[id]], frameNum); + StartSpriteAnim(&gSprites[*sDodrioSpriteIds[id]], pickState); } -static void nullsub_15(struct Sprite *sprite) +static void SpriteCB_Status(struct Sprite *sprite) { } -static void sub_80286E4(void) +static void InitStatusBarPos(void) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; sprite->pos1.x = (i * 16) + 48; sprite->pos1.y = -8 - (i * 8); - gUnknown_02022CF4->unkC[i] = 0; + sStatusBar->entered[i] = FALSE; } } -static void sub_8028734(void) +static void CreateStatusBarSprites(void) { u8 i; void *ptr = AllocZeroed(0x180); - struct SpritePalette spPal = {gDodrioBerryStatusPal, 2}; + struct SpritePalette pal = {sStatus_Pal, PALTAG_STATUS}; - LZ77UnCompWram(gDodrioBerryStatusGfx, ptr); + LZ77UnCompWram(sStatus_Gfx, ptr); // This check should be one line up. - if (ptr != NULL) + if (ptr) { - struct SpriteSheet spSheet = {ptr, 0x180, 1}; - struct SpriteTemplate spTemplate = + struct SpriteSheet sheet = {ptr, 0x180, GFXTAG_STATUS}; + struct SpriteTemplate template = { - .tileTag = 1, - .paletteTag = 2, - .oam = &sOamData_82FB1E8, - .anims = sSpriteAnimTable_82FB254, + .tileTag = GFXTAG_STATUS, + .paletteTag = PALTAG_STATUS, + .oam = &sOamData_16x16_Priority0, + .anims = sAnims_StatusBar, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = nullsub_15, + .callback = SpriteCB_Status, }; - gUnknown_02022CF4 = AllocZeroed(sizeof(*gUnknown_02022CF4)); - LoadSpriteSheet(&spSheet); - LoadSpritePalette(&spPal); - for (i = 0; i < 10; i++) - gUnknown_02022CF4->unk2A[i] = CreateSprite(&spTemplate, (i * 16) + 48, -8 - (i * 8), 0); + sStatusBar = AllocZeroed(sizeof(*sStatusBar)); + LoadSpriteSheet(&sheet); + LoadSpritePalette(&pal); + for (i = 0; i < NUM_STATUS_SQUARES; i++) + sStatusBar->spriteIds[i] = CreateSprite(&template, (i * 16) + 48, -8 - (i * 8), 0); } Free(ptr); } -static void sub_80287E4(void) +static void FreeStatusBar(void) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; - if (sprite != NULL) + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; + if (sprite) DestroySpriteAndFreeResources(sprite); } - FREE_AND_SET_NULL(gUnknown_02022CF4); + FREE_AND_SET_NULL(sStatusBar); } -static bool32 sub_8028828(void) +// Progress an animation where each square of the +// status bar drops down into view, bounces up, +// then settles into position. +// Returns TRUE if the animation is complete +static bool32 DoStatusBarIntro(void) { u8 i; - bool32 r3 = FALSE; - for (i = 0; i < 10; i++) + bool32 animActive = FALSE; + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; - gUnknown_02022CF4->unk16[i] = 2; - if (gUnknown_02022CF4->unkC[i] != 0 && sprite->pos1.y == 8) + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; + sStatusBar->yChange[i] = 2; + if (sStatusBar->entered[i] && sprite->pos1.y == 8) continue; - r3 = TRUE; + + animActive = TRUE; if (sprite->pos1.y == 8) { - if (gUnknown_02022CF4->unkC[i] != 0) + if (sStatusBar->entered[i]) continue; - gUnknown_02022CF4->unkC[i] = 1; - gUnknown_02022CF4->unk16[i] = -16; + + // Square has entered screen, play click + // sound and reverse direction + sStatusBar->entered[i] = TRUE; + sStatusBar->yChange[i] = -16; PlaySE(SE_CLICK); } - sprite->pos1.y += gUnknown_02022CF4->unk16[i]; + sprite->pos1.y += sStatusBar->yChange[i]; } - if (r3) + if (animActive) return FALSE; else return TRUE; } -static void sub_80288D4(u8 arg0) +// The status bar at the top changes color depending on the game performance. +// The squares start out yellow. For every berry missed, a square is colored gray. +// If there are 4 or fewer yellow squares left they also flash red +static void UpdateStatusBarAnim(u8 numEmpty) { u8 i; - if (arg0 > 10) + if (numEmpty > NUM_STATUS_SQUARES) { - for (i = 0; i < 10; i++) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 1); + // All squares gray + for (i = 0; i < NUM_STATUS_SQUARES; i++) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_GRAY); } else { - for (i = 0; i < 10 - arg0; i++) + // At least 1 square is yellow + for (i = 0; i < NUM_STATUS_SQUARES - numEmpty; i++) { - if (arg0 > 6) + if (numEmpty > 6) { - gUnknown_02022CF4->unk3E += arg0 - 6; - if (gUnknown_02022CF4->unk3E > 30) - gUnknown_02022CF4->unk3E = 0; - else if (gUnknown_02022CF4->unk3E > 10) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 2); + // Flash the yellow squares red + // The flash cycles faster the fewer yellow squares remain + sStatusBar->flashTimer += numEmpty - 6; + if (sStatusBar->flashTimer > 30) + sStatusBar->flashTimer = 0; + else if (sStatusBar->flashTimer > 10) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_RED); else - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 0); + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_YELLOW); } else { - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 0); + // Set yellow squares, no flash + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_YELLOW); } } - for (; i < 10; i++) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 1); + + // Set remaining squares gray + for (; i < NUM_STATUS_SQUARES; i++) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_GRAY); } } -static void sub_80289E8(bool8 invisible) +static void SetStatusBarInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 10; i++) - gSprites[gUnknown_02022CF4->unk2A[i]].invisible = invisible; + for (i = 0; i < NUM_STATUS_SQUARES; i++) + gSprites[sStatusBar->spriteIds[i]].invisible = invisible; } -// Unknown unused data, feel free to remove. -static const u8 sUnused2[] = {0xD4, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0xFB, 0x0, 0x0}; +static const u8 sUnusedSounds[] = { + SE_M_CHARM, + SE_NOTE_C, + SE_NOTE_D, + SE_NOTE_E, + SE_NOTE_F, + SE_NOTE_G, + SE_NOTE_A, + SE_NOTE_B, + SE_NOTE_C_HIGH, + SE_RG_CARD_OPEN +}; -static void sub_8028A34(void) +static void LoadBerryGfx(void) { void *ptr = AllocZeroed(0x480); - struct SpritePalette sprPal = {gDodrioBerrySpritesPal, 3}; + struct SpritePalette pal = {sBerries_Pal, PALTAG_BERRIES}; - LZ77UnCompWram(gDodrioBerrySpritesGfx, ptr); - if (ptr != NULL) + LZ77UnCompWram(sBerries_Gfx, ptr); + if (ptr) { - struct SpriteSheet sprSheet = {ptr, 0x480, 2}; - LoadSpriteSheet(&sprSheet); + struct SpriteSheet sheet = {ptr, 0x480, GFXTAG_BERRIES}; + LoadSpriteSheet(&sheet); } - LoadSpritePalette(&sprPal); + LoadSpritePalette(&pal); Free(ptr); } -static const s16 gUnknown_082FB31C[] = {88, 128, 168, 208}; +static const s16 sBerryIconXCoords[] = {88, 128, 168, 208}; -static void sub_8028A88(void) +static void CreateBerrySprites(void) { u8 i; s16 x; - struct SpriteTemplate sprTemplate1 = + struct SpriteTemplate berry = { - .tileTag = 2, - .paletteTag = 3, - .oam = &sOamData_82FB1F0, - .anims = sSpriteAnimTable_82FB2A8, + .tileTag = GFXTAG_BERRIES, + .paletteTag = PALTAG_BERRIES, + .oam = &sOamData_Berry, + .anims = sAnims_Berry, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; - struct SpriteTemplate sprTemplate2 = + struct SpriteTemplate berryIcon = { - .tileTag = 2, - .paletteTag = 3, - .oam = &sOamData_82FB1E8, - .anims = sSpriteAnimTable_82FB2A8, + .tileTag = GFXTAG_BERRIES, + .paletteTag = PALTAG_BERRIES, + .oam = &sOamData_16x16_Priority0, + .anims = sAnims_Berry, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; - for (i = 0; i < 11; i++) + // Create berry sprites that fall during gameplay + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - gUnknown_02022CB8[i] = AllocZeroed(4); + sBerrySpriteIds[i] = AllocZeroed(4); x = i * 16; - *gUnknown_02022CB8[i] = CreateSprite(&sprTemplate1, x + (i * 8), 8, 1); - sub_8028BF8(i, TRUE); - } - for (i = 0; i < 4; i++) - { - gUnknown_02022CE4[i] = AllocZeroed(4); - if (i == 3) - *gUnknown_02022CE4[i] = CreateSprite(&sprTemplate2, gUnknown_082FB31C[i], 49, 0); - else - *gUnknown_02022CE4[i] = CreateSprite(&sprTemplate2, gUnknown_082FB31C[i], 52, 0); - StartSpriteAnim(&gSprites[*gUnknown_02022CE4[i]], i); + *sBerrySpriteIds[i] = CreateSprite(&berry, x + (i * 8), 8, 1); + SetBerryInvisibility(i, TRUE); } - sub_8028C30(TRUE); + // Create berry icon sprites for results screen + for (i = 0; i < NUM_BERRY_TYPES; i++) + { + sBerryIconSpriteIds[i] = AllocZeroed(4); + if (i == BERRY_MISSED) + *sBerryIconSpriteIds[i] = CreateSprite(&berryIcon, sBerryIconXCoords[i], 49, 0); + else + *sBerryIconSpriteIds[i] = CreateSprite(&berryIcon, sBerryIconXCoords[i], 52, 0); + StartSpriteAnim(&gSprites[*sBerryIconSpriteIds[i]], i); + } + SetBerryIconsInvisibility(TRUE); } -static void sub_8028B80(void) +static void FreeBerrySprites(void) { struct Sprite *sprite; u8 i; - for (i = 0; i < 11; i++) + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - sprite = &gSprites[*gUnknown_02022CB8[i]]; - if (sprite != NULL) + sprite = &gSprites[*sBerrySpriteIds[i]]; + if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CB8[i]); + FREE_AND_SET_NULL(sBerrySpriteIds[i]); } - for (i = 0; i < 4; i++) + for (i = 0; i < NUM_BERRY_TYPES; i++) { - sprite = &gSprites[*gUnknown_02022CE4[i]]; - if (sprite != NULL) + sprite = &gSprites[*sBerryIconSpriteIds[i]]; + if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CE4[i]); + FREE_AND_SET_NULL(sBerryIconSpriteIds[i]); } } -static void sub_8028BF8(u8 id, bool8 invisible) +static void SetBerryInvisibility(u8 id, bool8 invisible) { - gSprites[*gUnknown_02022CB8[id]].invisible = invisible; + gSprites[*sBerrySpriteIds[id]].invisible = invisible; } -static void sub_8028C30(bool8 invisible) +static void SetBerryIconsInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 4; i++) - gSprites[*gUnknown_02022CE4[i]].invisible = invisible; + for (i = 0; i < NUM_BERRY_TYPES; i++) + gSprites[*sBerryIconSpriteIds[i]].invisible = invisible; } -static void sub_8028C7C(u8 id, u8 y) +static void SetBerryYPos(u8 id, u8 y) { - gSprites[*gUnknown_02022CB8[id]].pos1.y = y * 8; + gSprites[*sBerrySpriteIds[id]].pos1.y = y * 8; } -static void sub_8028CA4(u16 id, u8 frameNum) +static void SetBerryAnim(u16 id, u8 animNum) { - StartSpriteAnim(&gSprites[*gUnknown_02022CB8[id]], frameNum); + StartSpriteAnim(&gSprites[*sBerrySpriteIds[id]], animNum); } // Unused -static void sub_8028CD0(u8 spriteId) +static void UnusedSetSpritePos(u8 spriteId) { gSprites[spriteId].pos1.x = 20 * spriteId + 50; gSprites[spriteId].pos1.y = 50; @@ -3736,125 +4260,129 @@ static void sub_8028CD0(u8 spriteId) // Gamefreak made a mistake there and goes out of bounds for the data array as it holds 8 elements // in turn overwriting sprite's subpriority and subsprites fields. -#if defined(NONMATCHING) || MODERN - #define sKeepPosX data[1] +#ifdef UBFIX + #define sFrozen data[1] #else - #define sKeepPosX data[10] -#endif // NONMATCHING + #define sFrozen data[10] +#endif // UBFIX -static void sub_8028CF4(struct Sprite *sprite) +static void SpriteCB_Cloud(struct Sprite *sprite) { u8 i; - static const u8 array[] = {30, 20}; + static const u8 moveDelays[] = {30, 20}; - if (sprite->sKeepPosX != TRUE) + if (sprite->sFrozen != TRUE) { - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - if (++gUnknown_02022CB0[i][1] > array[i]) + if (++sCloudSpriteIds[i][1] > moveDelays[i]) { sprite->pos1.x--; - gUnknown_02022CB0[i][1] = 0; + sCloudSpriteIds[i][1] = 0; } } } } -static const s16 gUnknown_082FB356[][2] = {{230, 55}, {30, 74}}; +static const s16 sCloudStartCoords[NUM_CLOUDS][2] = +{ + {230, 55}, + { 30, 74} +}; -static void sub_8028D44(void) +static void CreateCloudSprites(void) { u8 i; void *ptr = AllocZeroed(0x400); - struct SpritePalette sprPal = {gDodrioBerryPlatformPal, 6}; + struct SpritePalette pal = {sCloud_Pal, PALTAG_CLOUD}; - LZ77UnCompWram(gDodrioBerryPlatformGfx, ptr); - if (ptr != NULL) + LZ77UnCompWram(sCloud_Gfx, ptr); + if (ptr) { - struct SpriteSheet sprSheet = {ptr, 0x400, 5}; - struct SpriteTemplate sprTemplate = + struct SpriteSheet sheet = {ptr, 0x400, GFXTAG_CLOUD}; + struct SpriteTemplate template = { - .tileTag = 5, - .paletteTag = 6, - .oam = &sOamData_82FB1F8, - .anims = sSpriteAnimTable_82FB2D4, + .tileTag = GFXTAG_CLOUD, + .paletteTag = PALTAG_CLOUD, + .oam = &sOamData_Cloud, + .anims = sAnims_Cloud, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8028CF4, + .callback = SpriteCB_Cloud, }; - LoadSpriteSheet(&sprSheet); - LoadSpritePalette(&sprPal); - for (i = 0; i < 2; i++) + LoadSpriteSheet(&sheet); + LoadSpritePalette(&pal); + for (i = 0; i < NUM_CLOUDS; i++) { - gUnknown_02022CB0[i] = AllocZeroed(4); - *gUnknown_02022CB0[i] = CreateSprite(&sprTemplate, gUnknown_082FB356[i][0], gUnknown_082FB356[i][1], 4); + sCloudSpriteIds[i] = AllocZeroed(4); + *sCloudSpriteIds[i] = CreateSprite(&template, sCloudStartCoords[i][0], sCloudStartCoords[i][1], 4); } } Free(ptr); } -static void sub_8028DFC(void) +static void ResetCloudPos(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; - sprite->sKeepPosX = TRUE; - sprite->pos1.x = gUnknown_082FB356[i][0]; - sprite->pos1.y = gUnknown_082FB356[i][1]; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; + sprite->sFrozen = TRUE; + sprite->pos1.x = sCloudStartCoords[i][0]; + sprite->pos1.y = sCloudStartCoords[i][1]; } } -static void sub_8028E4C(void) +static void StartCloudMovement(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; - sprite->sKeepPosX = FALSE; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; + sprite->sFrozen = FALSE; } } -static void sub_8028E84(void) +static void FreeCloudSprites(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CB0[i]); + FREE_AND_SET_NULL(sCloudSpriteIds[i]); } } -static void sub_8028EC8(bool8 invisible) +static void SetCloudInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 2; i++) - gSprites[*gUnknown_02022CB0[i]].invisible = invisible; + for (i = 0; i < NUM_CLOUDS; i++) + gSprites[*sCloudSpriteIds[i]].invisible = invisible; } -#undef sKeepPosX +#undef sFrozen -static s16 sub_8028F14(u8 arg0, u8 arg1) +static s16 GetDodrioXPos(u8 playerId, u8 numPlayers) { s16 x = 0; - switch (arg1) + switch (numPlayers) { case 1: x = 15; break; case 2: - switch (arg0) + switch (playerId) { case 0: x = 12; break; case 1: x = 18; break; } break; case 3: - switch (arg0) + switch (playerId) { case 0: x = 15; break; case 1: x = 21; break; @@ -3862,7 +4390,7 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) } break; case 4: - switch (arg0) + switch (playerId) { case 0: x = 12; break; case 1: x = 18; break; @@ -3871,7 +4399,7 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) } break; case 5: - switch (arg0) + switch (playerId) { case 0: x = 15; break; case 1: x = 21; break; @@ -3885,78 +4413,79 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) return x * 8; } -static void sub_8028FCC(void) +static void ResetBerryAndStatusBarSprites(void) { u8 i; - for (i = 0; i < 11; i++) + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - sub_8028BF8(i, TRUE); - sub_8028C7C(i, 1); + SetBerryInvisibility(i, TRUE); + SetBerryYPos(i, 1); } - sub_80289E8(FALSE); + SetStatusBarInvisibility(FALSE); } -static void sub_8028FF8(u8 frameId) +static void LoadWindowFrameGfx(u8 frameId) { - LoadBgTiles(0, GetWindowFrameTilesPal(frameId)->tiles, 0x120, 1); + LoadBgTiles(BG_INTERFACE, GetWindowFrameTilesPal(frameId)->tiles, 0x120, 1); LoadPalette(GetWindowFrameTilesPal(frameId)->pal, 0xA0, 0x20); } -static void sub_802902C(void) +static void LoadUserWindowFrameGfx(void) { LoadUserWindowBorderGfx_(0, 0xA, 0xB0); } -static void sub_802903C(void) +static void ResetGfxState(void) { - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->unk3018 = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + sGfx->finished = FALSE; + sGfx->state = 0; + sGfx->loadState = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; } -static void sub_8029074(const struct WindowTemplate *winTempl) +static void DrawYesNoMessageWindow(const struct WindowTemplate *template) { - u8 pal = 0xA; + u8 pal = 10; - FillBgTilemapBufferRect(0, 1, winTempl->tilemapLeft - 1, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 2, winTempl->tilemapLeft, winTempl->tilemapTop - 1, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 3, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 4, winTempl->tilemapLeft - 1, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 6, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 7, winTempl->tilemapLeft - 1, winTempl->tilemapTop + winTempl->height, 1, 1, pal); - FillBgTilemapBufferRect(0, 8, winTempl->tilemapLeft, winTempl->tilemapTop + winTempl->height, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 9, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop + winTempl->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 1, template->tilemapLeft - 1, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 2, template->tilemapLeft, template->tilemapTop - 1, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 3, template->tilemapLeft + template->width, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 4, template->tilemapLeft - 1, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 6, template->tilemapLeft + template->width, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 7, template->tilemapLeft - 1, template->tilemapTop + template->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 8, template->tilemapLeft, template->tilemapTop + template->height, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 9, template->tilemapLeft + template->width, template->tilemapTop + template->height, 1, 1, pal); } -static void sub_8029174(const struct WindowTemplate *winTempl) +static void DrawMessageWindow(const struct WindowTemplate *template) { - u8 pal = 0xB; + u8 pal = 11; - FillBgTilemapBufferRect(0, 10, winTempl->tilemapLeft - 1, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 11, winTempl->tilemapLeft, winTempl->tilemapTop - 1, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 12, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 13, winTempl->tilemapLeft - 1, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 15, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 16, winTempl->tilemapLeft - 1, winTempl->tilemapTop + winTempl->height, 1, 1, pal); - FillBgTilemapBufferRect(0, 17, winTempl->tilemapLeft, winTempl->tilemapTop + winTempl->height, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 18, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop + winTempl->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 10, template->tilemapLeft - 1, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 11, template->tilemapLeft, template->tilemapTop - 1, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 12, template->tilemapLeft + template->width, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 13, template->tilemapLeft - 1, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 15, template->tilemapLeft + template->width, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 16, template->tilemapLeft - 1, template->tilemapTop + template->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 17, template->tilemapLeft, template->tilemapTop + template->height, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 18, template->tilemapLeft + template->width, template->tilemapTop + template->height, 1, 1, pal); } -static void sub_8029274(struct DodrioSubstruct_0160 *ptr) +static void InitGameGfx(struct DodrioGame_Gfx *ptr) { - gUnknown_02022CF8 = ptr; - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->unk3018 = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; - gUnknown_02022CF8->unk3004 = CreateTask(sub_8029314, 3); - sub_802A72C(sub_8029338); + sGfx = ptr; + sGfx->finished = FALSE; + sGfx->state = 0; + sGfx->loadState = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; + sGfx->taskId = CreateTask(Task_TryRunGfxFunc, 3); + SetGfxFunc(LoadGfx); } -static void sub_80292D4(void) +// Unused +static void FreeAllWindowBuffers_(void) { FreeAllWindowBuffers(); } @@ -3968,30 +4497,37 @@ struct WinCoords u8 top; }; +enum { + COLORID_GREY, + COLORID_RED, + COLORID_BLUE, + COLORID_GREEN, // Unused +}; + static const u8 sTextColorTable[][3] = { - {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, - {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, - {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, - {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, + [COLORID_GREY] = {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, + [COLORID_RED] = {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, + [COLORID_BLUE] = {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, + [COLORID_GREEN] = {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, }; -static const struct WinCoords gUnknown_082FB38C[] = {{12, 6}}; -static const struct WinCoords gUnknown_082FB390[] = {{9, 10}, {15, 6}}; -static const struct WinCoords gUnknown_082FB398[] = {{12, 6}, {18, 10}, {6, 10}}; -static const struct WinCoords gUnknown_082FB3A4[] = {{9, 10}, {15, 6}, {21, 10}, {3, 6}}; -static const struct WinCoords gUnknown_082FB3B4[] = {{12, 6}, {18, 10}, {23, 6}, {1, 6}, {6, 10}}; +static const struct WinCoords sNameWindowCoords_1Player[] = {{12, 6}}; +static const struct WinCoords sNameWindowCoords_2Players[] = {{9, 10}, {15, 6}}; +static const struct WinCoords sNameWindowCoords_3Players[] = {{12, 6}, {18, 10}, {6, 10}}; +static const struct WinCoords sNameWindowCoords_4Players[] = {{9, 10}, {15, 6}, {21, 10}, {3, 6}}; +static const struct WinCoords sNameWindowCoords_5Players[] = {{12, 6}, {18, 10}, {23, 6}, {1, 6}, {6, 10}}; -static const struct WinCoords *const gUnknown_082FB3C8[] = +static const struct WinCoords *const sNameWindowCoords[MAX_RFU_PLAYERS] = { - gUnknown_082FB38C, - gUnknown_082FB390, - gUnknown_082FB398, - gUnknown_082FB3A4, - gUnknown_082FB3B4, + sNameWindowCoords_1Player, + sNameWindowCoords_2Players, + sNameWindowCoords_3Players, + sNameWindowCoords_4Players, + sNameWindowCoords_5Players, }; -static const u8 *const gUnknown_082FB3DC[] = +static const u8 *const sRankingTexts[MAX_RFU_PLAYERS] = { gText_1Colon, gText_2Colon, @@ -4000,625 +4536,640 @@ static const u8 *const gUnknown_082FB3DC[] = gText_5Colon, }; -static const u16 gUnknown_082FB3F0[] = {92, 132, 172, 212}; -static const u16 gUnknown_082FB3F8[] = {33, 49, 65, 81, 97}; -static const u16 gUnknown_082FB402[] = {17, 33, 49, 65, 81}; +static const u16 sResultsXCoords[] = {92, 132, 172, 212}; +static const u16 sResultsYCoords[] = {33, 49, 65, 81, 97}; +static const u16 sRankingYCoords[] = {17, 33, 49, 65, 81}; struct { u8 id; void (*func)(void); -} const gUnknown_082FB40C[] = +} const sGfxFuncs[] = { - {0, sub_8029338}, - {1, sub_8029440}, - {2, sub_802988C}, - {3, sub_802A010}, - {4, sub_802A380}, - {5, sub_802A454}, - {6, sub_802A534}, - {7, sub_802A588}, - {8, sub_802A6FC}, - {9, nullsub_16}, + {GFXFUNC_LOAD, LoadGfx}, // Element not used, LoadGfx is passed directly to SetGfxFunc + {GFXFUNC_SHOW_NAMES, ShowNames}, + {GFXFUNC_SHOW_RESULTS, ShowResults}, + {GFXFUNC_MSG_PLAY_AGAIN, Msg_WantToPlayAgain}, + {GFXFUNC_MSG_SAVING, Msg_SavingDontTurnOff}, + {GFXFUNC_MSG_COMM_STANDBY, Msg_CommunicationStandby}, + {GFXFUNC_ERASE_MSG, EraseMessage}, + {GFXFUNC_MSG_PLAYER_DROPPED, Msg_SomeoneDroppedOut}, + {GFXFUNC_STOP, StopGfxFuncs}, + {GFXFUNC_IDLE, GfxIdle}, }; -static void sub_80292E0(u8 arg0) +static void SetGfxFuncById(u8 funcId) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < ARRAY_COUNT(sGfxFuncs); i++) { - if (gUnknown_082FB40C[i].id == arg0) - sub_802A72C(gUnknown_082FB40C[i].func); + if (sGfxFuncs[i].id == funcId) + SetGfxFunc(sGfxFuncs[i].func); } } -static void sub_8029314(u8 taskId) +static void Task_TryRunGfxFunc(u8 taskId) { - if (!gUnknown_02022CF8->finished) - sub_802A75C()(); + // Continue calling function until it + // has reached its finished state. + // Another will not be called until + // readied by SetGfxFunc + if (!sGfx->finished) + GetGfxFunc()(); } -static void sub_8029338(void) +static void LoadGfx(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - sub_802A7A8(); - gUnknown_02022CF8->state++; + InitBgs(); + sGfx->state++; break; case 1: - if (sub_802A8E8() == TRUE) - gUnknown_02022CF8->state++; + if (LoadBgGfx() == TRUE) + sGfx->state++; break; case 2: - CopyToBgTilemapBuffer(3, gDodrioBerryBgTilemap1, 0, 0); - CopyToBgTilemapBuffer(1, gDodrioBerryBgTilemap2Left, 0, 0); - CopyToBgTilemapBuffer(2, gDodrioBerryBgTilemap2Right, 0, 0); - CopyBgTilemapBufferToVram(3); - CopyBgTilemapBufferToVram(1); - CopyBgTilemapBufferToVram(2); - gUnknown_02022CF8->state++; + CopyToBgTilemapBuffer(BG_SCENERY, sBg_Tilemap, 0, 0); + CopyToBgTilemapBuffer(BG_TREE_LEFT, sTreeBorderLeft_Tilemap, 0, 0); + CopyToBgTilemapBuffer(BG_TREE_RIGHT, sTreeBorderRight_Tilemap, 0, 0); + CopyBgTilemapBufferToVram(BG_SCENERY); + CopyBgTilemapBufferToVram(BG_TREE_LEFT); + CopyBgTilemapBufferToVram(BG_TREE_RIGHT); + sGfx->state++; break; case 3: - ShowBg(0); - ShowBg(3); - ShowBg(1); - ShowBg(2); - gUnknown_02022CF8->state++; + ShowBg(BG_INTERFACE); + ShowBg(BG_SCENERY); + ShowBg(BG_TREE_LEFT); + ShowBg(BG_TREE_RIGHT); + sGfx->state++; break; case 4: - sub_8028FF8(gSaveBlock2Ptr->optionsWindowFrameType); - sub_802902C(); - gUnknown_02022CF8->state++; + LoadWindowFrameGfx(gSaveBlock2Ptr->optionsWindowFrameType); + LoadUserWindowFrameGfx(); + sGfx->state++; break; default: - gUnknown_02022CF8->finished = TRUE; + sGfx->finished = TRUE; break; } } -static void sub_8029440(void) +static void ShowNames(void) { - u8 i, playersCount, id, colorsId, *name; + u8 i, numPlayers, playerId, colorsId, *name; u32 left; struct WindowTemplate window; - const struct WinCoords *ptr; + const struct WinCoords *coords; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - playersCount = sub_8027650(); - ptr = gUnknown_082FB3C8[playersCount - 1]; - window.bg = 0; + numPlayers = GetNumPlayers(); + coords = sNameWindowCoords[numPlayers - 1]; + window.bg = BG_INTERFACE; window.width = 7; window.height = 2; - window.paletteNum = 0xD; + window.paletteNum = 13; window.baseBlock = 0x13; - for (i = 0; i < playersCount; ptr++, i++) + for (i = 0; i < numPlayers; coords++, i++) { - colorsId = 0; - id = sub_8027A48(i); - left = (56 - GetStringWidth(1, sub_8027660(id), -1)) / 2u; - window.tilemapLeft = ptr->left; - window.tilemapTop = ptr->top; - gUnknown_02022CF8->unk3008[i] = AddWindow(&window); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[i]); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[i], PIXEL_FILL(1)); - if (id == GetMultiplayerId()) - colorsId = 2; - name = sub_8027660(id); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[i], 1, left, 1, sTextColorTable[colorsId], -1, name); - CopyWindowToVram(gUnknown_02022CF8->unk3008[i], 2); + colorsId = COLORID_GREY; + playerId = GetPlayerIdByPos(i); + left = (56 - GetStringWidth(1, GetPlayerName(playerId), -1)) / 2u; + window.tilemapLeft = coords->left; + window.tilemapTop = coords->top; + sGfx->windowIds[i] = AddWindow(&window); + ClearWindowTilemap(sGfx->windowIds[i]); + FillWindowPixelBuffer(sGfx->windowIds[i], PIXEL_FILL(1)); + if (playerId == GetMultiplayerId()) + colorsId = COLORID_BLUE; + name = GetPlayerName(playerId); + AddTextPrinterParameterized3(sGfx->windowIds[i], 1, left, 1, sTextColorTable[colorsId], -1, name); + CopyWindowToVram(sGfx->windowIds[i], 2); window.baseBlock += 0xE; - sub_8029174(&window); + DrawMessageWindow(&window); } - gUnknown_02022CF8->state++; + sGfx->state++; break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) { - playersCount = sub_8027650(); - for (i = 0; i < playersCount; i++) - PutWindowTilemap(gUnknown_02022CF8->unk3008[i]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + numPlayers = GetNumPlayers(); + for (i = 0; i < numPlayers; i++) + PutWindowTilemap(sGfx->windowIds[i]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; } break; default: - if (++gUnknown_02022CF8->state > 180) + if (++sGfx->state > 180) { - playersCount = sub_8027650(); - for (i = 0; i < playersCount; i++) + numPlayers = GetNumPlayers(); + for (i = 0; i < numPlayers; i++) { - ClearWindowTilemap(gUnknown_02022CF8->unk3008[i]); - RemoveWindow(gUnknown_02022CF8->unk3008[i]); + ClearWindowTilemap(sGfx->windowIds[i]); + RemoveWindow(sGfx->windowIds[i]); } - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; } break; } } -static void sub_80296A8(u8 playersCount_) +static void PrintRankedScores(u8 numPlayers_) { - u8 i, r8 = 0, r6 = 0; - u8 playersCount = playersCount_; // Pointless variable, I know, but it's needed to match. + u8 i, ranking = 0, rankedPlayers = 0; + u8 numPlayers = numPlayers_; // Needed to match u8 *name; u32 x, numWidth; u8 numString[32]; - u8 array[5] = {0, 1, 2, 3, 4}; - struct DodrioSubstruct_3308 temp, structArray[5]; + u8 playersByRanking[MAX_RFU_PLAYERS] = {0, 1, 2, 3, 4}; + struct DodrioGame_ScoreResults temp, scoreResults[MAX_RFU_PLAYERS]; - for (i = 0; i < playersCount; i++) + // Get all players scores and rankings + for (i = 0; i < numPlayers; i++) { - array[i] = i; - sub_802793C(&temp, i); - structArray[i] = temp; + playersByRanking[i] = i; + GetScoreResults(&temp, i); + scoreResults[i] = temp; } - if (sub_8027748() != 0) + // Sort player ids by ranking + if (GetHighestScore() != 0) { do { - for (i = 0; i < playersCount; i++) + for (i = 0; i < numPlayers; i++) { - if (structArray[i].unk0 == r8) + if (scoreResults[i].ranking == ranking) { - array[r6] = i; - r6++; + playersByRanking[rankedPlayers] = i; + rankedPlayers++; } } - r8 = r6; - } while (r6 < playersCount); + ranking = rankedPlayers; + } while (rankedPlayers < numPlayers); } - for (i = 0; i < playersCount; i++) + // Put any player with a score of 0 at lowest ranking + for (i = 0; i < numPlayers; i++) { - if (structArray[i].unk4 == 0) - structArray[i].unk0 = playersCount - 1; + if (scoreResults[i].score == 0) + scoreResults[i].ranking = numPlayers - 1; } + // Print text x = 216 - GetStringWidth(1, gText_SpacePoints, 0); - for (i = 0; i < playersCount; i++) + for (i = 0; i < numPlayers; i++) { - u8 colorsId = 0; - u8 id = array[i]; - u32 points = structArray[id].unk4; + u8 colorsId = COLORID_GREY; + u8 playerId = playersByRanking[i]; + u32 points = scoreResults[playerId].score; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gUnknown_082FB3DC[structArray[id].unk0], 8, gUnknown_082FB402[i], -1, NULL); - if (id == GetMultiplayerId()) - colorsId = 2; - name = sub_8027660(id); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, 28, gUnknown_082FB402[i], sTextColorTable[colorsId], -1, name); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, sRankingTexts[scoreResults[playerId].ranking], 8, sRankingYCoords[i], -1, NULL); + if (playerId == GetMultiplayerId()) + colorsId = COLORID_BLUE; + name = GetPlayerName(playerId); + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, 28, sRankingYCoords[i], sTextColorTable[colorsId], -1, name); ConvertIntToDecimalStringN(numString, points, STR_CONV_MODE_LEFT_ALIGN, 7); numWidth = GetStringWidth(1, numString, -1); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, numString, x - numWidth, gUnknown_082FB402[i], -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SpacePoints, x, gUnknown_082FB402[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, numString, x - numWidth, sRankingYCoords[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gText_SpacePoints, x, sRankingYCoords[i], -1, NULL); } } -static void sub_802988C(void) +static void ShowResults(void) { - u8 i, j, itemGiveRet, playersCount = sub_8027650(); + u8 i, j, prizeState, numPlayers = GetNumPlayers(); u8 *name; u32 strWidth, x; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - sub_802784C(); - gUnknown_02022CF8->unk301C = 0; - gUnknown_02022CF8->state++; + SetScoreResults(); + sGfx->timer = 0; + sGfx->state++; break; case 1: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BBC[0]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BBC[1]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BBC[0]); - sub_8029174(&gUnknown_082F7BBC[1]); - gUnknown_02022CF8->state++; + sGfx->windowIds[0] = AddWindow(&sWindowTemplates_Results[0]); + sGfx->windowIds[1] = AddWindow(&sWindowTemplates_Results[1]); + ClearWindowTilemap(sGfx->windowIds[0]); + ClearWindowTilemap(sGfx->windowIds[1]); + DrawMessageWindow(&sWindowTemplates_Results[0]); + DrawMessageWindow(&sWindowTemplates_Results[1]); + sGfx->state++; break; case 2: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_BerryPickingResults, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_BerryPickingResults, x, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_10P30P50P50P, 68, 17, -1, NULL); - for (i = 0; i < playersCount; i++) + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_BerryPickingResults, x, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gText_10P30P50P50P, 68, 17, -1, NULL); + for (i = 0; i < numPlayers; i++) { - u8 colorsId = 0; + u8 colorsId = COLORID_GREY; if (i == GetMultiplayerId()) - colorsId = 2; + colorsId = COLORID_BLUE; - name = sub_8027660(i); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, 0, gUnknown_082FB3F8[i], sTextColorTable[colorsId], -1, name); + name = GetPlayerName(i); + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, 0, sResultsYCoords[i], sTextColorTable[colorsId], -1, name); for (j = 0; j < 4; j++) { u32 width; - u16 result1 = Min(sub_80276A0(i, j), 9999); - u16 result2 = Min(sub_802778C(j), 9999); + u16 berriesPicked = Min(GetBerryResult(i, j), MAX_BERRIES); + u16 maxBerriesPicked = Min(GetHighestBerryResult(j), MAX_BERRIES); - ConvertIntToDecimalStringN(gStringVar4, result1, STR_CONV_MODE_LEFT_ALIGN, 4); + ConvertIntToDecimalStringN(gStringVar4, berriesPicked, STR_CONV_MODE_LEFT_ALIGN, 4); width = GetStringWidth(1, gStringVar4, -1); - if (result2 == result1 && result2 != 0) - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, gUnknown_082FB3F0[j] - width, gUnknown_082FB3F8[i], sTextColorTable[1], -1, gStringVar4); + + // If player got the most of a berry type, highlight their number in red + if (maxBerriesPicked == berriesPicked && maxBerriesPicked != 0) + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, sResultsXCoords[j] - width, sResultsYCoords[i], sTextColorTable[COLORID_RED], -1, gStringVar4); else - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, gUnknown_082FB3F0[j] - width, gUnknown_082FB3F8[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, sResultsXCoords[j] - width, sResultsYCoords[i], -1, NULL); } } - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 3: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); - sub_8028C30(FALSE); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + SetBerryIconsInvisibility(FALSE); + sGfx->state++; break; case 4: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - sub_8028C30(TRUE); - gUnknown_02022CF8->state++; + SetBerryIconsInvisibility(TRUE); + sGfx->state++; } break; case 5: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_AnnouncingRankings, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_AnnouncingRankings, x, 1, -1, NULL); - gUnknown_02022CF8->state++; + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_AnnouncingRankings, x, 1, -1, NULL); + sGfx->state++; break; case 6: - sub_80296A8(playersCount); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + PrintRankedScores(numPlayers); + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 7: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 8: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - if (sub_8027748() < 3000) + if (GetHighestScore() < PRIZE_SCORE) { - gUnknown_02022CF8->state = 127; + sGfx->state = 127; // Skip to end, past giving prize } else { StopMapMusic(); - gUnknown_02022CF8->state++; + sGfx->state++; } - FillBgTilemapBufferRect_Palette0(0, 0, 0, 5, 30, 15); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BCC); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BCC); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 5, 30, 15); + RemoveWindow(sGfx->windowIds[1]); + sGfx->windowIds[1] = AddWindow(&sWindowTemplate_Prize); + ClearWindowTilemap(sGfx->windowIds[1]); + DrawMessageWindow(&sWindowTemplate_Prize); } break; case 9: PlayNewMapMusic(MUS_LEVEL_UP); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_AnnouncingPrizes, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_AnnouncingPrizes, x, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_AnnouncingPrizes, x, 1, -1, NULL); DynamicPlaceholderTextUtil_Reset(); - CopyItemName(sub_802762C(), gStringVar1); + CopyItemName(GetPrizeItemId(), gStringVar1); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1); DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_FirstPlacePrize); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, 0, 1, -1, NULL); - itemGiveRet = sub_80279C8(); - if (itemGiveRet != 0 && itemGiveRet != 3) + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, 0, 1, -1, NULL); + prizeState = TryGivePrize(); + if (prizeState != PRIZE_RECEIVED && prizeState != NO_PRIZE) { DynamicPlaceholderTextUtil_Reset(); - CopyItemName(sub_802762C(), gStringVar1); + CopyItemName(GetPrizeItemId(), gStringVar1); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1); - if (itemGiveRet == 2) + if (prizeState == PRIZE_NO_ROOM) DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_CantHoldAnyMore); - else if (itemGiveRet == 1) + else if (prizeState == PRIZE_FILLED_BAG) DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_FilledStorageSpace); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, 0, 41, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, 0, 41, -1, NULL); } - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 10: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); + CopyBgTilemapBufferToVram(BG_INTERFACE); FadeOutAndFadeInNewMapMusic(MUS_RG_VICTORY_WILD, 20, 10); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 11: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - gUnknown_02022CF8->state++; + sGfx->state++; } break; default: - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + ClearWindowTilemap(sGfx->windowIds[0]); + ClearWindowTilemap(sGfx->windowIds[1]); + RemoveWindow(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[1]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A010(void) +static void Msg_WantToPlayAgain(void) { u8 y; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BD4[0]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BD4[1]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BD4[0]); - sub_8029074(&gUnknown_082F7BD4[1]); - gUnknown_02022CF8->state++; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + // Create windows + sGfx->windowIds[WIN_PLAY_AGAIN] = AddWindow(&sWindowTemplates_PlayAgain[WIN_PLAY_AGAIN]); + sGfx->windowIds[WIN_YES_NO] = AddWindow(&sWindowTemplates_PlayAgain[WIN_YES_NO]); + ClearWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + ClearWindowTilemap(sGfx->windowIds[WIN_YES_NO]); + DrawMessageWindow(&sWindowTemplates_PlayAgain[WIN_PLAY_AGAIN]); + DrawYesNoMessageWindow(&sWindowTemplates_PlayAgain[WIN_YES_NO]); + sGfx->state++; + sGfx->cursorSelection = PLAY_AGAIN_NONE; + sGfx->playAgainState = PLAY_AGAIN_NONE; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_WantToPlayAgain, 0, 5, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_Yes, 8, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_No, 8, 17, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SelectorArrow2, 0, 1, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + // Print text + FillWindowPixelBuffer(sGfx->windowIds[WIN_PLAY_AGAIN], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[WIN_YES_NO], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[WIN_PLAY_AGAIN], 1, gText_WantToPlayAgain, 0, 5, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_Yes, 8, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_No, 8, 17, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_SelectorArrow2, 0, 1, -1, NULL); + CopyWindowToVram(sGfx->windowIds[WIN_PLAY_AGAIN], 2); + CopyWindowToVram(sGfx->windowIds[WIN_YES_NO], 2); + sGfx->state++; break; case 2: + // Draw windows if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + PutWindowTilemap(sGfx->windowIds[WIN_YES_NO]); } - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 3: - y = gUnknown_02022CF8->unk3020; - if (y == 0) - y = 1; - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_Yes, 8, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_No, 8, 17, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SelectorArrow2, 0, ((y - 1) * 16) + 1, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 3); + // Handle input + y = sGfx->cursorSelection; + if (y == PLAY_AGAIN_NONE) + y = PLAY_AGAIN_YES; + FillWindowPixelBuffer(sGfx->windowIds[WIN_YES_NO], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_Yes, 8, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_No, 8, 17, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_SelectorArrow2, 0, ((y - 1) * 16) + 1, -1, NULL); + CopyWindowToVram(sGfx->windowIds[WIN_YES_NO], 3); + // Increment state only if A or B button have been pressed. if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); - if (gUnknown_02022CF8->unk3020 == 0) - gUnknown_02022CF8->unk3020 = 1; - gUnknown_02022CF8->state++; + if (sGfx->cursorSelection == PLAY_AGAIN_NONE) + sGfx->cursorSelection = PLAY_AGAIN_YES; + sGfx->state++; } else if (JOY_NEW(DPAD_UP | DPAD_DOWN)) { PlaySE(SE_SELECT); - switch (gUnknown_02022CF8->unk3020) + switch (sGfx->cursorSelection) { - case 0: - gUnknown_02022CF8->unk3020 = 2; + case PLAY_AGAIN_NONE: + sGfx->cursorSelection = PLAY_AGAIN_NO; break; - case 1: - gUnknown_02022CF8->unk3020 = 2; + case PLAY_AGAIN_YES: + sGfx->cursorSelection = PLAY_AGAIN_NO; break; - case 2: - gUnknown_02022CF8->unk3020 = 1; + case PLAY_AGAIN_NO: + sGfx->cursorSelection = PLAY_AGAIN_YES; break; } } else if (JOY_NEW(B_BUTTON)) { PlaySE(SE_SELECT); - gUnknown_02022CF8->unk3020 = 2; - gUnknown_02022CF8->state++; + sGfx->cursorSelection = PLAY_AGAIN_NO; + sGfx->state++; } break; default: - gUnknown_02022CF8->unk3024 = gUnknown_02022CF8->unk3020; - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + sGfx->playAgainState = sGfx->cursorSelection; + ClearWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + ClearWindowTilemap(sGfx->windowIds[WIN_YES_NO]); + RemoveWindow(sGfx->windowIds[WIN_PLAY_AGAIN]); + RemoveWindow(sGfx->windowIds[WIN_YES_NO]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A380(void) +static void Msg_SavingDontTurnOff(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: DrawDialogueFrame(0, FALSE); AddTextPrinterParameterized2(0, 1, gText_SavingDontTurnOffPower, 0, NULL, 2, 1, 3); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 1: CopyWindowToVram(0, 3); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) { CreateTask(Task_LinkSave, 0); - gUnknown_02022CF8->state++; + sGfx->state++; } break; case 3: if (!FuncIsActiveTask(Task_LinkSave)) - gUnknown_02022CF8->state++; + sGfx->state++; break; default: - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A454(void) +static void Msg_CommunicationStandby(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BEC); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - sub_8029174(&gUnknown_082F7BEC); - gUnknown_02022CF8->state++; + sGfx->windowIds[0] = AddWindow(&sWindowTemplate_CommStandby); + ClearWindowTilemap(sGfx->windowIds[0]); + DrawMessageWindow(&sWindowTemplate_CommStandby); + sGfx->state++; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_CommunicationStandby3, 0, 5, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - gUnknown_02022CF8->state++; + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_CommunicationStandby3, 0, 5, -1, NULL); + CopyWindowToVram(sGfx->windowIds[0], 2); + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + PutWindowTilemap(sGfx->windowIds[0]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; default: - gUnknown_02022CF8->finished = TRUE; + sGfx->finished = TRUE; break; } } -static void sub_802A534(void) +static void EraseMessage(void) { - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + ClearWindowTilemap(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[0]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; } -static void sub_802A588(void) +static void Msg_SomeoneDroppedOut(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BE4); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - sub_8029174(&gUnknown_082F7BE4); - gUnknown_02022CF8->state++; - gUnknown_02022CF8->unk301C = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + sGfx->windowIds[0] = AddWindow(&sWindowTemplate_DroppedOut); + ClearWindowTilemap(sGfx->windowIds[0]); + DrawMessageWindow(&sWindowTemplate_DroppedOut); + sGfx->state++; + sGfx->timer = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_SomeoneDroppedOut, 0, 5, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - gUnknown_02022CF8->state++; + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_SomeoneDroppedOut, 0, 5, -1, NULL); + CopyWindowToVram(sGfx->windowIds[0], 2); + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + PutWindowTilemap(sGfx->windowIds[0]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 3: - if (++gUnknown_02022CF8->unk301C >= 120) - gUnknown_02022CF8->state++; + if (++sGfx->timer >= 120) + sGfx->state++; break; default: - gUnknown_02022CF8->unk3024 = 5; - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + sGfx->playAgainState = PLAY_AGAIN_DROPPED; + ClearWindowTilemap(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[0]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A6FC(void) +static void StopGfxFuncs(void) { - DestroyTask(gUnknown_02022CF8->unk3004); - gUnknown_02022CF8->finished = TRUE; + DestroyTask(sGfx->taskId); + sGfx->finished = TRUE; } -static void nullsub_16(void) +static void GfxIdle(void) { } -static void sub_802A72C(void (*func)(void)) +static void SetGfxFunc(void (*func)(void)) { - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->unk3028 = func; + sGfx->state = 0; + sGfx->finished = FALSE; + sGfx->func = func; } -static void (*sub_802A75C(void))(void) +static void (*GetGfxFunc(void))(void) { - return gUnknown_02022CF8->unk3028; + return sGfx->func; } -static bool32 sub_802A770(void) +static bool32 IsGfxFuncActive(void) { - if (gUnknown_02022CF8->finished == TRUE) + if (sGfx->finished == TRUE) return FALSE; else return TRUE; } -static u8 sub_802A794(void) +static u8 GetPlayAgainState(void) { - return gUnknown_02022CF8->unk3024; + return sGfx->playAgainState; } -static void sub_802A7A8(void) +static void InitBgs(void) { DmaClearLarge16(3, (void *)VRAM, VRAM_SIZE, 0x1000); DmaClear32(3,(void *)OAM, OAM_SIZE); DmaClear16(3, (void *)PLTT, PLTT_SIZE); SetGpuReg(REG_OFFSET_DISPCNT, 0); ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, gUnknown_082F7BA4, ARRAY_COUNT(gUnknown_082F7BA4)); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); @@ -4630,26 +5181,26 @@ static void sub_802A7A8(void) InitStandardTextBoxWindows(); InitTextBoxGfxAndPrinters(); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); - SetBgTilemapBuffer(3, gUnknown_02022CF8->tilemapBuffers[0]); - SetBgTilemapBuffer(1, gUnknown_02022CF8->tilemapBuffers[1]); - SetBgTilemapBuffer(2, gUnknown_02022CF8->tilemapBuffers[2]); + SetBgTilemapBuffer(BG_SCENERY, sGfx->tilemapBuffers[0]); + SetBgTilemapBuffer(BG_TREE_LEFT, sGfx->tilemapBuffers[1]); + SetBgTilemapBuffer(BG_TREE_RIGHT, sGfx->tilemapBuffers[2]); } -static bool32 sub_802A8E8(void) +static bool32 LoadBgGfx(void) { - switch (gUnknown_02022CF8->unk3018) + switch (sGfx->loadState) { case 0: - LoadPalette(gDodrioBerryBgPal1, 0, sizeof(gDodrioBerryBgPal1)); + LoadPalette(sBg_Pal, 0, sizeof(sBg_Pal)); break; case 1: ResetTempTileDataBuffers(); break; case 2: - DecompressAndCopyTileDataToVram(3, gDodrioBerryBgGfx1, 0, 0, 0); + DecompressAndCopyTileDataToVram(BG_SCENERY, sBg_Gfx, 0, 0, 0); break; case 3: - DecompressAndCopyTileDataToVram(1, gDodrioBerryBgGfx2, 0, 0, 0); + DecompressAndCopyTileDataToVram(BG_TREE_LEFT, sTreeBorder_Gfx, 0, 0, 0); break; case 4: if (FreeTempTileDataBuffersIfPossible() == TRUE) @@ -4659,10 +5210,10 @@ static bool32 sub_802A8E8(void) LoadPalette(GetTextWindowPalette(3), 0xD0, 0x20); break; default: - gUnknown_02022CF8->unk3018 = 0; + sGfx->loadState = 0; return TRUE; } - gUnknown_02022CF8->unk3018++; + sGfx->loadState++; return FALSE; } diff --git a/src/link.c b/src/link.c index e151bfa28..9f0ac6654 100644 --- a/src/link.c +++ b/src/link.c @@ -168,7 +168,7 @@ static const u32 sWirelessLinkDisplayTilemap[] = INCBIN_U32("graphics/interface/ static const u16 sLinkTestDigitsPal[] = INCBIN_U16("graphics/interface/link_test_digits.gbapal"); static const u16 sLinkTestDigitsGfx[] = INCBIN_U16("graphics/interface/link_test_digits.4bpp"); static const u8 sUnusedTransparentWhite[] = _("{HIGHLIGHT TRANSPARENT}{COLOR WHITE}"); -static const u16 s2BlankTilesGfx[] = INCBIN_U16("graphics/interface/blank_1x2.4bpp"); +static const u16 sCommErrorBg_Gfx[] = INCBIN_U16("graphics/interface/comm_error_bg.4bpp"); static const struct BlockRequest sBlockRequests[] = { {gBlockSendBuffer, 200}, {gBlockSendBuffer, 200}, @@ -1680,9 +1680,9 @@ void CB2_LinkError(void) } } -static void sub_800B080(void) +static void ErrorMsg_MoveCloserToPartner(void) { - LoadBgTiles(0, s2BlankTilesGfx, 0x20, 0); + LoadBgTiles(0, sCommErrorBg_Gfx, 0x20, 0); DecompressAndLoadBgGfxUsingHeap(1, sWirelessLinkDisplayGfx, FALSE, 0, 0); CopyToBgTilemapBuffer(1, sWirelessLinkDisplayTilemap, 0, 0); CopyBgTilemapBufferToVram(1); @@ -1697,9 +1697,9 @@ static void sub_800B080(void) CopyWindowToVram(2, 3); } -static void sub_800B138(void) +static void ErrorMsg_CheckConnections(void) { - LoadBgTiles(0, s2BlankTilesGfx, 0x20, 0); + LoadBgTiles(0, sCommErrorBg_Gfx, 0x20, 0); FillWindowPixelBuffer(1, PIXEL_FILL(0)); FillWindowPixelBuffer(2, PIXEL_FILL(0)); AddTextPrinterParameterized3(1, 3, 2, 0, sTextColors, 0, gText_CommErrorCheckConnections); @@ -1715,20 +1715,14 @@ static void CB2_PrintErrorMessage(void) { case 00: if (sLinkErrorBuffer.unk_06) - { - sub_800B080(); - } + ErrorMsg_MoveCloserToPartner(); else - { - sub_800B138(); - } + ErrorMsg_CheckConnections(); break; case 02: ShowBg(0); if (sLinkErrorBuffer.unk_06) - { ShowBg(1); - } break; case 30: PlaySE(SE_BOO); @@ -1741,13 +1735,9 @@ static void CB2_PrintErrorMessage(void) break; case 130: if (gWirelessCommType == 2) - { AddTextPrinterParameterized3(0, 3, 2, 20, sTextColors, 0, gText_ABtnTitleScreen); - } else if (gWirelessCommType == 1) - { AddTextPrinterParameterized3(0, 3, 2, 20, sTextColors, 0, gText_ABtnRegistrationCounter); - } break; } if (gMain.state == 160) diff --git a/src/link_rfu_2.c b/src/link_rfu_2.c index 3b49ae4b1..54f21ed9f 100644 --- a/src/link_rfu_2.c +++ b/src/link_rfu_2.c @@ -2472,7 +2472,7 @@ void RfuVSync(void) rfu_LMAN_syncVBlank(); } -void sub_8011AC8(void) +void ClearRecvCommands(void) { CpuFill32(0, gRecvCmds, sizeof(gRecvCmds)); } diff --git a/src/party_menu.c b/src/party_menu.c index fc547e96d..7b77a1067 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4904,7 +4904,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) else { gPartyMenuUseExitCallback = TRUE; - PlayFanfareByFanfareNum(0); + PlayFanfareByFanfareNum(FANFARE_LEVEL_UP); UpdateMonDisplayInfoAfterRareCandy(gPartyMenu.slotId, mon); RemoveBagItem(gSpecialVar_ItemId, 1); GetMonNickname(mon, gStringVar1); diff --git a/src/sound.c b/src/sound.c index ee1753bb3..42f507b7c 100644 --- a/src/sound.c +++ b/src/sound.c @@ -41,24 +41,24 @@ static void Task_DuckBGMForPokemonCry(u8 taskId); static void RestoreBGMVolumeAfterPokemonCry(void); static const struct Fanfare sFanfares[] = { - { MUS_LEVEL_UP, 80 }, - { MUS_OBTAIN_ITEM, 160 }, - { MUS_EVOLVED, 220 }, - { MUS_OBTAIN_TMHM, 220 }, - { MUS_HEAL, 160 }, - { MUS_OBTAIN_BADGE, 340 }, - { MUS_MOVE_DELETED, 180 }, - { MUS_OBTAIN_BERRY, 120 }, - { MUS_AWAKEN_LEGEND, 710 }, - { MUS_SLOTS_JACKPOT, 250 }, - { MUS_SLOTS_WIN, 150 }, - { MUS_TOO_BAD, 160 }, - { MUS_RG_POKE_FLUTE, 450 }, - { MUS_RG_OBTAIN_KEY_ITEM, 170 }, - { MUS_RG_DEX_RATING, 196 }, - { MUS_OBTAIN_B_POINTS, 313 }, - { MUS_OBTAIN_SYMBOL, 318 }, - { MUS_REGISTER_MATCH_CALL, 135 }, + [FANFARE_LEVEL_UP] = { MUS_LEVEL_UP, 80 }, + [FANFARE_OBTAIN_ITEM] = { MUS_OBTAIN_ITEM, 160 }, + [FANFARE_EVOLVED] = { MUS_EVOLVED, 220 }, + [FANFARE_OBTAIN_TMHM] = { MUS_OBTAIN_TMHM, 220 }, + [FANFARE_HEAL] = { MUS_HEAL, 160 }, + [FANFARE_OBTAIN_BADGE] = { MUS_OBTAIN_BADGE, 340 }, + [FANFARE_MOVE_DELETED] = { MUS_MOVE_DELETED, 180 }, + [FANFARE_OBTAIN_BERRY] = { MUS_OBTAIN_BERRY, 120 }, + [FANFARE_AWAKEN_LEGEND] = { MUS_AWAKEN_LEGEND, 710 }, + [FANFARE_SLOTS_JACKPOT] = { MUS_SLOTS_JACKPOT, 250 }, + [FANFARE_SLOTS_WIN] = { MUS_SLOTS_WIN, 150 }, + [FANFARE_TOO_BAD] = { MUS_TOO_BAD, 160 }, + [FANFARE_RG_POKE_FLUTE] = { MUS_RG_POKE_FLUTE, 450 }, + [FANFARE_RG_OBTAIN_KEY_ITEM] = { MUS_RG_OBTAIN_KEY_ITEM, 170 }, + [FANFARE_RG_DEX_RATING] = { MUS_RG_DEX_RATING, 196 }, + [FANFARE_OBTAIN_B_POINTS] = { MUS_OBTAIN_B_POINTS, 313 }, + [FANFARE_OBTAIN_SYMBOL] = { MUS_OBTAIN_SYMBOL, 318 }, + [FANFARE_REGISTER_MATCH_CALL] = { MUS_REGISTER_MATCH_CALL, 135 }, }; #define CRY_VOLUME 120 // was 125 in R/S @@ -212,6 +212,7 @@ bool8 WaitFanfare(bool8 stop) } } +// Unused void StopFanfareByFanfareNum(u8 fanfareNum) { m4aSongNumStop(sFanfares[fanfareNum].songNum); @@ -220,7 +221,7 @@ void StopFanfareByFanfareNum(u8 fanfareNum) void PlayFanfare(u16 songNum) { s32 i; - for (i = 0; (u32)i < 18; i++) + for (i = 0; (u32)i < ARRAY_COUNT(sFanfares); i++) { if (sFanfares[i].songNum == songNum) { @@ -230,6 +231,8 @@ void PlayFanfare(u16 songNum) } } + // songNum is not in sFanfares + // Play first fanfare in table instead PlayFanfareByFanfareNum(0); CreateFanfareTask(); }