summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgolem galvanize <golemgalvanize@github.com>2018-02-12 14:00:47 -0500
committergolem galvanize <golemgalvanize@github.com>2018-02-12 14:00:47 -0500
commit4ac064bbaf54966082a860e6b6723c5ec654c436 (patch)
treeb419b2bb1a7fe7d17c440d58e5000c21e832386c /src
parentf81c52b56e865d8ecc753a69a31a5148548320a6 (diff)
parenta4787bc06a323071d32d3e0705e9cd39d9221452 (diff)
Merge branch 'master' of https://github.com/pret/pokeemerald into decompile_item_menu
Diffstat (limited to 'src')
-rw-r--r--src/battle_ai_switch_items.c1
-rw-r--r--src/battle_controller_link_opponent.c24
-rw-r--r--src/battle_controller_link_partner.c1
-rw-r--r--src/battle_controller_opponent.c1
-rw-r--r--src/battle_controller_player.c4
-rw-r--r--src/battle_controller_player_partner.c1
-rw-r--r--src/battle_controller_recorded_opponent.c1
-rw-r--r--src/battle_controller_recorded_player.c1
-rw-r--r--src/battle_controller_safari.c1
-rw-r--r--src/battle_controller_wally.c2
-rw-r--r--src/battle_controllers.c622
-rw-r--r--src/battle_gfx_sfx_util.c1
-rw-r--r--src/battle_interface.c2
-rw-r--r--src/battle_main.c54
-rw-r--r--src/battle_message.c2
-rw-r--r--src/battle_script_commands.c11
-rw-r--r--src/battle_setup.c1
-rw-r--r--src/battle_util.c1
-rw-r--r--src/berry_blender.c22
-rw-r--r--src/bg.c6
-rw-r--r--src/braille_puzzles.c2
-rw-r--r--src/calculate_base_damage.c275
-rw-r--r--src/clear_save_data_screen.c2
-rw-r--r--src/decompress.c2
-rw-r--r--src/decoration.c2
-rw-r--r--src/egg_hatch.c11
-rw-r--r--src/evolution_scene.c10
-rwxr-xr-xsrc/item_use.c3
-rw-r--r--src/librfu_rfu.c32
-rw-r--r--src/lilycove_lady.c2
-rw-r--r--src/link.c2428
-rw-r--r--src/link_rfu.c4940
-rw-r--r--src/main.c92
-rw-r--r--src/mystery_event_menu.c2
-rw-r--r--src/pokeblock_feed.c3
-rw-r--r--src/pokemon.c6094
-rw-r--r--src/pokemon_1.c457
-rw-r--r--src/pokemon_2.c1365
-rw-r--r--src/pokemon_3.c1749
-rw-r--r--src/pokemon_summary_screen.c40
-rw-r--r--src/recorded_battle.c3
-rw-r--r--src/reshow_battle_screen.c5
-rw-r--r--src/rom_8011DC0.c18
-rw-r--r--src/scrcmd.c3
-rw-r--r--src/text.c7
-rw-r--r--src/tv.c4
-rw-r--r--src/util.c2
-rw-r--r--src/window.c7
48 files changed, 13914 insertions, 4405 deletions
diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c
index b0fcc2e29..c3bb0d422 100644
--- a/src/battle_ai_switch_items.c
+++ b/src/battle_ai_switch_items.c
@@ -8,7 +8,6 @@
#include "random.h"
#include "util.h"
#include "constants/items.h"
-#include "pokemon_item_effects.h"
extern const struct BattleMove gBattleMoves[];
extern const u8 gTypeEffectiveness[];
diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c
index 290236f4a..a399adf25 100644
--- a/src/battle_controller_link_opponent.c
+++ b/src/battle_controller_link_opponent.c
@@ -26,7 +26,6 @@
#include "data2.h"
#include "battle_setup.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
@@ -34,7 +33,6 @@ extern struct UnusedControllerStruct gUnknown_02022D0C;
extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[];
extern const struct BattleMove gBattleMoves[];
-extern const u8 gFacilityClassToPicIndex[];
extern void sub_8172EF0(u8 bank, struct Pokemon *mon);
extern void sub_806A068(u16, u8);
@@ -1246,7 +1244,7 @@ static void LinkOpponentHandleDrawTrainerPic(void)
if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
{
- if (gActiveBattler == 1)
+ if (gActiveBattler == B_POSITION_OPPONENT_LEFT)
trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A);
else
trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B);
@@ -1256,18 +1254,18 @@ static void LinkOpponentHandleDrawTrainerPic(void)
if ((gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_FIRE_RED
|| (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_LEAF_GREEN)
{
- if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != 0)
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_10];
+ if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != MALE)
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_LEAF];
else
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_9];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RED];
}
else if ((gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_RUBY
|| (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_SAPPHIRE)
{
- if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != 0)
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_12];
+ if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != MALE)
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_MAY];
else
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_11];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_BRENDAN];
}
else
{
@@ -1286,17 +1284,17 @@ static void LinkOpponentHandleDrawTrainerPic(void)
|| (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_LEAF_GREEN)
{
if (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].gender != 0)
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_10];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_LEAF];
else
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_9];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RED];
}
else if ((gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_RUBY
|| (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_SAPPHIRE)
{
if (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].gender != 0)
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_12];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_MAY];
else
- trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_11];
+ trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_BRENDAN];
}
else
{
diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c
index 9d2c79922..1734abe62 100644
--- a/src/battle_controller_link_partner.c
+++ b/src/battle_controller_link_partner.c
@@ -25,7 +25,6 @@
#include "data2.h"
#include "battle_setup.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern struct UnusedControllerStruct gUnknown_02022D0C;
diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c
index 5a3732f8b..26e0191cb 100644
--- a/src/battle_controller_opponent.c
+++ b/src/battle_controller_opponent.c
@@ -29,7 +29,6 @@
#include "data2.h"
#include "battle_setup.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index 897122ddd..8847715f6 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -872,7 +872,7 @@ static void HandleMoveSwitchting(void)
static void sub_80586F8(void)
{
- if (gLinkVSyncDisabled == 0)
+ if (gWirelessCommType == 0)
{
if (gReceivedRemoteLinkPlayers == 0)
{
@@ -908,7 +908,7 @@ void sub_80587B0(void)
{
if (sub_800A520())
{
- if (gLinkVSyncDisabled == 0)
+ if (gWirelessCommType == 0)
sub_800AC34();
else
sub_800ADF8();
diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c
index 159fdb2ff..d2f85f85e 100644
--- a/src/battle_controller_player_partner.c
+++ b/src/battle_controller_player_partner.c
@@ -25,7 +25,6 @@
#include "battle_setup.h"
#include "item_use.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern struct UnusedControllerStruct gUnknown_02022D0C;
diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c
index 855dfc554..2295c4a75 100644
--- a/src/battle_controller_recorded_opponent.c
+++ b/src/battle_controller_recorded_opponent.c
@@ -27,7 +27,6 @@
#include "item_use.h"
#include "battle_setup.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c
index 4efe5babf..0d06e26eb 100644
--- a/src/battle_controller_recorded_player.c
+++ b/src/battle_controller_recorded_player.c
@@ -25,7 +25,6 @@
#include "data2.h"
#include "item_use.h"
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern u32 gTransformedPersonalities[MAX_BATTLERS_COUNT];
diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c
index f65d11a84..39eab24ee 100644
--- a/src/battle_controller_safari.c
+++ b/src/battle_controller_safari.c
@@ -24,7 +24,6 @@
#include "item_use.h"
extern struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT];
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c
index ad028b719..445feaf7a 100644
--- a/src/battle_controller_wally.c
+++ b/src/battle_controller_wally.c
@@ -30,8 +30,6 @@
#include "battle_setup.h"
#include "item_use.h"
-extern struct MusicPlayerInfo gMPlayInfo_BGM;
-extern struct SpriteTemplate gUnknown_0202499C;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG0_Y;
extern s32 gUnknown_0203CD70;
diff --git a/src/battle_controllers.c b/src/battle_controllers.c
index cbb4fff69..3c8b1563f 100644
--- a/src/battle_controllers.c
+++ b/src/battle_controllers.c
@@ -12,13 +12,29 @@
#include "constants/abilities.h"
#include "battle_message.h"
-extern u8 gBattleBuffersTransferData[0x100];
-extern u8 gUnknown_0202428C;
-extern u32 gUnknown_02022FF4;
-extern u8 gUnknown_0203C7B4;
+extern u32 gBattleExecBuffer;
+extern void (*gBattleBankFunc[4])(void);
+extern u8 gBanksByIdentity[4];
+extern u8 gActionSelectionCursor[4];
+extern u8 gMoveSelectionCursor[4];
+extern u8 gNoOfAllBanks;
+extern u8 gActiveBank;
+extern u16 gBattlePartyID[4];
+extern u8 gBattleBufferA[4][0x200];
+extern u8 gBattleBufferB[4][0x200];
extern u8 gUnknown_02022D08;
extern u8 gUnknown_02022D09;
extern u8 gUnknown_02022D0A;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gAbsentBankFlags;
+extern u8 gEffectBank;
+extern struct BattlePokemon gBattleMons[4];
+extern u16 gLastUsedMove;
+extern u8 gStringBank;
+extern u8 gBattleBuffersTransferData[0x100];
+
+static EWRAM_DATA u8 sBattleBuffersTransferData[0x100] = {};
extern const struct BattleMove gBattleMoves[];
@@ -37,7 +53,7 @@ void HandleLinkBattleSetup(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800B488();
if (!gReceivedRemoteLinkPlayers)
OpenLink();
@@ -758,7 +774,7 @@ static void Task_HandleSendLinkBuffersData(u8 taskId)
gTasks[taskId].data[11]++;
break;
case 2:
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
{
gTasks[taskId].data[11]++;
}
@@ -917,171 +933,171 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId)
void BtlController_EmitGetMonData(u8 bufferId, u8 requestId, u8 monToCheck)
{
- gBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA;
- gBattleBuffersTransferData[1] = requestId;
- gBattleBuffersTransferData[2] = monToCheck;
- gBattleBuffersTransferData[3] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA;
+ sBattleBuffersTransferData[1] = requestId;
+ sBattleBuffersTransferData[2] = monToCheck;
+ sBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitGetRawMonData(u8 bufferId, u8 monId, u8 bytes)
{
- gBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA;
- gBattleBuffersTransferData[1] = monId;
- gBattleBuffersTransferData[2] = bytes;
- gBattleBuffersTransferData[3] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA;
+ sBattleBuffersTransferData[1] = monId;
+ sBattleBuffersTransferData[2] = bytes;
+ sBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitSetMonData(u8 bufferId, u8 requestId, u8 monToCheck, u8 bytes, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA;
- gBattleBuffersTransferData[1] = requestId;
- gBattleBuffersTransferData[2] = monToCheck;
+ sBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA;
+ sBattleBuffersTransferData[1] = requestId;
+ sBattleBuffersTransferData[2] = monToCheck;
for (i = 0; i < bytes; i++)
- gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 3 + bytes);
+ sBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 3 + bytes);
}
void BtlController_EmitSetRawMonData(u8 bufferId, u8 monId, u8 bytes, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA;
- gBattleBuffersTransferData[1] = monId;
- gBattleBuffersTransferData[2] = bytes;
+ sBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA;
+ sBattleBuffersTransferData[1] = monId;
+ sBattleBuffersTransferData[2] = bytes;
for (i = 0; i < bytes; i++)
- gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, bytes + 3);
+ sBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, bytes + 3);
}
void BtlController_EmitLoadMonSprite(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE;
- gBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE;
- gBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE;
- gBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE;
+ sBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE;
+ sBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE;
+ sBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitSwitchInAnim(u8 bufferId, u8 partyId, bool8 dontClearSubstituteBit)
{
- gBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM;
- gBattleBuffersTransferData[1] = partyId;
- gBattleBuffersTransferData[2] = dontClearSubstituteBit;
- gBattleBuffersTransferData[3] = 5;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM;
+ sBattleBuffersTransferData[1] = partyId;
+ sBattleBuffersTransferData[2] = dontClearSubstituteBit;
+ sBattleBuffersTransferData[3] = 5;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitReturnMonToBall(u8 bufferId, u8 arg1)
{
- gBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL;
- gBattleBuffersTransferData[1] = arg1;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL;
+ sBattleBuffersTransferData[1] = arg1;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitDrawTrainerPic(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC;
- gBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC;
- gBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC;
- gBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC;
+ sBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC;
+ sBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC;
+ sBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitTrainerSlide(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE;
- gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE;
- gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE;
- gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE;
+ sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE;
+ sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE;
+ sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitTrainerSlideBack(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK;
- gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK;
- gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK;
- gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK;
+ sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK;
+ sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK;
+ sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitFaintAnimation(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION;
- gBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION;
- gBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION;
- gBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION;
+ sBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION;
+ sBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION;
+ sBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitPaletteFade(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE;
- gBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE;
- gBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE;
- gBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE;
+ sBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE;
+ sBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE;
+ sBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitSuccessBallThrowAnim(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM;
- gBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM;
- gBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM;
- gBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM;
+ sBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM;
+ sBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM;
+ sBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitBallThrowAnim(u8 bufferId, u8 caseId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM;
- gBattleBuffersTransferData[1] = caseId;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM;
+ sBattleBuffersTransferData[1] = caseId;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitPause(u8 bufferId, u8 toWait, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_PAUSE;
- gBattleBuffersTransferData[1] = toWait;
+ sBattleBuffersTransferData[0] = CONTROLLER_PAUSE;
+ sBattleBuffersTransferData[1] = toWait;
for (i = 0; i < toWait * 3; i++)
- gBattleBuffersTransferData[2 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, toWait * 3 + 2);
+ sBattleBuffersTransferData[2 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, toWait * 3 + 2);
}
void BtlController_EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit)
{
- gBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION;
- gBattleBuffersTransferData[1] = move;
- gBattleBuffersTransferData[2] = (move & 0xFF00) >> 8;
- gBattleBuffersTransferData[3] = turnOfMove;
- gBattleBuffersTransferData[4] = movePower;
- gBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8;
- gBattleBuffersTransferData[6] = dmg;
- gBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8;
- gBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16;
- gBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24;
- gBattleBuffersTransferData[10] = friendship;
- gBattleBuffersTransferData[11] = multihit;
+ sBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION;
+ sBattleBuffersTransferData[1] = move;
+ sBattleBuffersTransferData[2] = (move & 0xFF00) >> 8;
+ sBattleBuffersTransferData[3] = turnOfMove;
+ sBattleBuffersTransferData[4] = movePower;
+ sBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8;
+ sBattleBuffersTransferData[6] = dmg;
+ sBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8;
+ sBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16;
+ sBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24;
+ sBattleBuffersTransferData[10] = friendship;
+ sBattleBuffersTransferData[11] = multihit;
if (WEATHER_HAS_EFFECT2)
{
- gBattleBuffersTransferData[12] = gBattleWeather;
- gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8;
+ sBattleBuffersTransferData[12] = gBattleWeather;
+ sBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8;
}
else
{
- gBattleBuffersTransferData[12] = 0;
- gBattleBuffersTransferData[13] = 0;
+ sBattleBuffersTransferData[12] = 0;
+ sBattleBuffersTransferData[13] = 0;
}
- gBattleBuffersTransferData[14] = 0;
- gBattleBuffersTransferData[15] = 0;
- memcpy(&gBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct));
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 16 + sizeof(struct DisableStruct));
+ sBattleBuffersTransferData[14] = 0;
+ sBattleBuffersTransferData[15] = 0;
+ memcpy(&sBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct));
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 16 + sizeof(struct DisableStruct));
}
void BtlController_EmitPrintString(u8 bufferId, u16 stringID)
@@ -1089,12 +1105,12 @@ void BtlController_EmitPrintString(u8 bufferId, u16 stringID)
s32 i;
struct StringInfoBattle* stringInfo;
- gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING;
- gBattleBuffersTransferData[1] = gBattleOutcome;
- gBattleBuffersTransferData[2] = stringID;
- gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING;
+ sBattleBuffersTransferData[1] = gBattleOutcome;
+ sBattleBuffersTransferData[2] = stringID;
+ sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
- stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]);
stringInfo->currentMove = gCurrentMove;
stringInfo->originallyUsedMove = gChosenMove;
stringInfo->lastItem = gLastUsedItem;
@@ -1113,7 +1129,7 @@ void BtlController_EmitPrintString(u8 bufferId, u16 stringID)
stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
}
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
}
void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID)
@@ -1121,12 +1137,12 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID)
s32 i;
struct StringInfoBattle *stringInfo;
- gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY;
- gBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY;
- gBattleBuffersTransferData[2] = stringID;
- gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY;
+ sBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY;
+ sBattleBuffersTransferData[2] = stringID;
+ sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
- stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]);
+ stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]);
stringInfo->currentMove = gCurrentMove;
stringInfo->originallyUsedMove = gChosenMove;
stringInfo->lastItem = gLastUsedItem;
@@ -1142,386 +1158,386 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID)
stringInfo->textBuffs[1][i] = gBattleTextBuff2[i];
stringInfo->textBuffs[2][i] = gBattleTextBuff3[i];
}
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4);
}
void BtlController_EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2)
{
- gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION;
- gBattleBuffersTransferData[1] = arg1;
- gBattleBuffersTransferData[2] = arg2;
- gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION;
+ sBattleBuffersTransferData[1] = arg1;
+ sBattleBuffersTransferData[2] = arg2;
+ sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitUnknownYesNoBox(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX;
- gBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX;
- gBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX;
- gBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX;
+ sBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX;
+ sBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX;
+ sBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE;
- gBattleBuffersTransferData[1] = isDoubleBattle;
- gBattleBuffersTransferData[2] = NoPpNumber;
- gBattleBuffersTransferData[3] = 0;
+ sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE;
+ sBattleBuffersTransferData[1] = isDoubleBattle;
+ sBattleBuffersTransferData[2] = NoPpNumber;
+ sBattleBuffersTransferData[3] = 0;
for (i = 0; i < sizeof(*movePpData); i++)
- gBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(*movePpData) + 4);
+ sBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(*movePpData) + 4);
}
void BtlController_EmitChooseItem(u8 bufferId, u8 *arg1)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_OPENBAG;
+ sBattleBuffersTransferData[0] = CONTROLLER_OPENBAG;
for (i = 0; i < 3; i++)
- gBattleBuffersTransferData[1 + i] = arg1[i];
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[1 + i] = arg1[i];
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8* arg4)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON;
- gBattleBuffersTransferData[1] = caseId;
- gBattleBuffersTransferData[2] = arg2;
- gBattleBuffersTransferData[3] = abilityId;
+ sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON;
+ sBattleBuffersTransferData[1] = caseId;
+ sBattleBuffersTransferData[2] = arg2;
+ sBattleBuffersTransferData[3] = abilityId;
for (i = 0; i < 3; i++)
- gBattleBuffersTransferData[4 + i] = arg4[i];
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 8); // but only 7 bytes were written
+ sBattleBuffersTransferData[4 + i] = arg4[i];
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 8); // but only 7 bytes were written
}
void BtlController_EmitCmd23(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_23;
- gBattleBuffersTransferData[1] = CONTROLLER_23;
- gBattleBuffersTransferData[2] = CONTROLLER_23;
- gBattleBuffersTransferData[3] = CONTROLLER_23;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_23;
+ sBattleBuffersTransferData[1] = CONTROLLER_23;
+ sBattleBuffersTransferData[2] = CONTROLLER_23;
+ sBattleBuffersTransferData[3] = CONTROLLER_23;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
// why is the argument u16 if it's being cast to s16 anyway?
void BtlController_EmitHealthBarUpdate(u8 bufferId, u16 hpValue)
{
- gBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE;
- gBattleBuffersTransferData[1] = 0;
- gBattleBuffersTransferData[2] = (s16)hpValue;
- gBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE;
+ sBattleBuffersTransferData[1] = 0;
+ sBattleBuffersTransferData[2] = (s16)hpValue;
+ sBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
// why is the argument u16 if it's being cast to s16 anyway?
void BtlController_EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints)
{
- gBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE;
- gBattleBuffersTransferData[1] = partyId;
- gBattleBuffersTransferData[2] = (s16)expPoints;
- gBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE;
+ sBattleBuffersTransferData[1] = partyId;
+ sBattleBuffersTransferData[2] = (s16)expPoints;
+ sBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2)
{
- gBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE;
- gBattleBuffersTransferData[1] = status1;
- gBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8;
- gBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16;
- gBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24;
- gBattleBuffersTransferData[5] = status2;
- gBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8;
- gBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16;
- gBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 9);
+ sBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE;
+ sBattleBuffersTransferData[1] = status1;
+ sBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8;
+ sBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16;
+ sBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24;
+ sBattleBuffersTransferData[5] = status2;
+ sBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8;
+ sBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16;
+ sBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 9);
}
void BtlController_EmitStatusAnimation(u8 bufferId, bool8 status2, u32 status)
{
- gBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION;
- gBattleBuffersTransferData[1] = status2;
- gBattleBuffersTransferData[2] = status;
- gBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8;
- gBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16;
- gBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 6);
+ sBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION;
+ sBattleBuffersTransferData[1] = status2;
+ sBattleBuffersTransferData[2] = status;
+ sBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8;
+ sBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16;
+ sBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 6);
}
void BtlController_EmitStatusXor(u8 bufferId, u8 b)
{
- gBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR;
- gBattleBuffersTransferData[1] = b;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR;
+ sBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitDataTransfer(u8 bufferId, u16 size, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER;
- gBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER;
- gBattleBuffersTransferData[2] = size;
- gBattleBuffersTransferData[3] = (size & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER;
+ sBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER;
+ sBattleBuffersTransferData[2] = size;
+ sBattleBuffersTransferData[3] = (size & 0xFF00) >> 8;
for (i = 0; i < size; i++)
- gBattleBuffersTransferData[4 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 4);
+ sBattleBuffersTransferData[4 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 4);
}
void BtlController_EmitDMA3Transfer(u8 bufferId, void *dst, u16 size, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER;
- gBattleBuffersTransferData[1] = (u32)(dst);
- gBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8;
- gBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16;
- gBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24;
- gBattleBuffersTransferData[5] = size;
- gBattleBuffersTransferData[6] = (size & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER;
+ sBattleBuffersTransferData[1] = (u32)(dst);
+ sBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8;
+ sBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16;
+ sBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24;
+ sBattleBuffersTransferData[5] = size;
+ sBattleBuffersTransferData[6] = (size & 0xFF00) >> 8;
for (i = 0; i < size; i++)
- gBattleBuffersTransferData[7 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 7);
+ sBattleBuffersTransferData[7 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 7);
}
void BtlController_EmitPlayBGM(u8 bufferId, u16 songId, void *unusedDumbDataParameter)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_31;
- gBattleBuffersTransferData[1] = songId;
- gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_31;
+ sBattleBuffersTransferData[1] = songId;
+ sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
for (i = 0; i < songId; i++) // ????
- gBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, songId + 3);
+ sBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, songId + 3);
}
void BtlController_EmitCmd32(u8 bufferId, u16 size, void *data)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_32;
- gBattleBuffersTransferData[1] = size;
- gBattleBuffersTransferData[2] = (size & 0xFF00) >> 8;
+ sBattleBuffersTransferData[0] = CONTROLLER_32;
+ sBattleBuffersTransferData[1] = size;
+ sBattleBuffersTransferData[2] = (size & 0xFF00) >> 8;
for (i = 0; i < size; i++)
- gBattleBuffersTransferData[3 + i] = *(u8*)(data++);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 3);
+ sBattleBuffersTransferData[3 + i] = *(u8*)(data++);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 3);
}
void BtlController_EmitTwoReturnValues(u8 bufferId, u8 arg1, u16 arg2)
{
- gBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES;
- gBattleBuffersTransferData[1] = arg1;
- gBattleBuffersTransferData[2] = arg2;
- gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES;
+ sBattleBuffersTransferData[1] = arg1;
+ sBattleBuffersTransferData[2] = arg2;
+ sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitChosenMonReturnValue(u8 bufferId, u8 b, u8 *c)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE;
- gBattleBuffersTransferData[1] = b;
+ sBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE;
+ sBattleBuffersTransferData[1] = b;
for (i = 0; i < 3; i++)
- gBattleBuffersTransferData[2 + i] = c[i];
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 5);
+ sBattleBuffersTransferData[2 + i] = c[i];
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 5);
}
void BtlController_EmitOneReturnValue(u8 bufferId, u16 arg1)
{
- gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE;
- gBattleBuffersTransferData[1] = arg1;
- gBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8;
- gBattleBuffersTransferData[3] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE;
+ sBattleBuffersTransferData[1] = arg1;
+ sBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8;
+ sBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitOneReturnValue_Duplicate(u8 bufferId, u16 b)
{
- gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE;
- gBattleBuffersTransferData[1] = b;
- gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
- gBattleBuffersTransferData[3] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE;
+ sBattleBuffersTransferData[1] = b;
+ sBattleBuffersTransferData[2] = (b & 0xFF00) >> 8;
+ sBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitCmd37(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_37;
- gBattleBuffersTransferData[1] = CONTROLLER_37;
- gBattleBuffersTransferData[2] = CONTROLLER_37;
- gBattleBuffersTransferData[3] = CONTROLLER_37;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_37;
+ sBattleBuffersTransferData[1] = CONTROLLER_37;
+ sBattleBuffersTransferData[2] = CONTROLLER_37;
+ sBattleBuffersTransferData[3] = CONTROLLER_37;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitCmd38(u8 bufferId, u8 b)
{
- gBattleBuffersTransferData[0] = CONTROLLER_38;
- gBattleBuffersTransferData[1] = b;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_38;
+ sBattleBuffersTransferData[1] = b;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitCmd39(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_39;
- gBattleBuffersTransferData[1] = CONTROLLER_39;
- gBattleBuffersTransferData[2] = CONTROLLER_39;
- gBattleBuffersTransferData[3] = CONTROLLER_39;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_39;
+ sBattleBuffersTransferData[1] = CONTROLLER_39;
+ sBattleBuffersTransferData[2] = CONTROLLER_39;
+ sBattleBuffersTransferData[3] = CONTROLLER_39;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitCmd40(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_40;
- gBattleBuffersTransferData[1] = CONTROLLER_40;
- gBattleBuffersTransferData[2] = CONTROLLER_40;
- gBattleBuffersTransferData[3] = CONTROLLER_40;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_40;
+ sBattleBuffersTransferData[1] = CONTROLLER_40;
+ sBattleBuffersTransferData[2] = CONTROLLER_40;
+ sBattleBuffersTransferData[3] = CONTROLLER_40;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitHitAnimation(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION;
- gBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION;
- gBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION;
- gBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION;
+ sBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION;
+ sBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION;
+ sBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitCmd42(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_42;
- gBattleBuffersTransferData[1] = CONTROLLER_42;
- gBattleBuffersTransferData[2] = CONTROLLER_42;
- gBattleBuffersTransferData[3] = CONTROLLER_42;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_42;
+ sBattleBuffersTransferData[1] = CONTROLLER_42;
+ sBattleBuffersTransferData[2] = CONTROLLER_42;
+ sBattleBuffersTransferData[3] = CONTROLLER_42;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitPlaySE(u8 bufferId, u16 songId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND;
- gBattleBuffersTransferData[1] = songId;
- gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
- gBattleBuffersTransferData[3] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND;
+ sBattleBuffersTransferData[1] = songId;
+ sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ sBattleBuffersTransferData[3] = 0;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitPlayFanfareOrBGM(u8 bufferId, u16 songId, bool8 playBGM)
{
- gBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM;
- gBattleBuffersTransferData[1] = songId;
- gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
- gBattleBuffersTransferData[3] = playBGM;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM;
+ sBattleBuffersTransferData[1] = songId;
+ sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8;
+ sBattleBuffersTransferData[3] = playBGM;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitFaintingCry(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY;
- gBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY;
- gBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY;
- gBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY;
+ sBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY;
+ sBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY;
+ sBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitIntroSlide(u8 bufferId, u8 terrainId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE;
- gBattleBuffersTransferData[1] = terrainId;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE;
+ sBattleBuffersTransferData[1] = terrainId;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitIntroTrainerBallThrow(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW;
- gBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW;
- gBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW;
- gBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW;
+ sBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW;
+ sBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW;
+ sBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitDrawPartyStatusSummary(u8 bufferId, struct HpAndStatus* hpAndStatus, u8 arg2)
{
s32 i;
- gBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY;
- gBattleBuffersTransferData[1] = arg2 & 0x7F;
- gBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7;
- gBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY;
+ sBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY;
+ sBattleBuffersTransferData[1] = arg2 & 0x7F;
+ sBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7;
+ sBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY;
for (i = 0; i < (s32)(sizeof(struct HpAndStatus) * 6); i++)
- gBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus));
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4);
+ sBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus));
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4);
}
void BtlController_EmitCmd49(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_49;
- gBattleBuffersTransferData[1] = CONTROLLER_49;
- gBattleBuffersTransferData[2] = CONTROLLER_49;
- gBattleBuffersTransferData[3] = CONTROLLER_49;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_49;
+ sBattleBuffersTransferData[1] = CONTROLLER_49;
+ sBattleBuffersTransferData[2] = CONTROLLER_49;
+ sBattleBuffersTransferData[3] = CONTROLLER_49;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitCmd50(u8 bufferId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_50;
- gBattleBuffersTransferData[1] = CONTROLLER_50;
- gBattleBuffersTransferData[2] = CONTROLLER_50;
- gBattleBuffersTransferData[3] = CONTROLLER_50;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_50;
+ sBattleBuffersTransferData[1] = CONTROLLER_50;
+ sBattleBuffersTransferData[2] = CONTROLLER_50;
+ sBattleBuffersTransferData[3] = CONTROLLER_50;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitSpriteInvisibility(u8 bufferId, bool8 isInvisible)
{
- gBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY;
- gBattleBuffersTransferData[1] = isInvisible;
- gBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY;
- gBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY;
+ sBattleBuffersTransferData[1] = isInvisible;
+ sBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY;
+ sBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitBattleAnimation(u8 bufferId, u8 animationId, u16 argument)
{
- gBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION;
- gBattleBuffersTransferData[1] = animationId;
- gBattleBuffersTransferData[2] = argument;
- gBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4);
+ sBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION;
+ sBattleBuffersTransferData[1] = animationId;
+ sBattleBuffersTransferData[2] = argument;
+ sBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitLinkStandbyMsg(u8 bufferId, u8 arg1, bool32 arg2)
{
bool8 arg2_ = arg2;
- gBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG;
- gBattleBuffersTransferData[1] = arg1;
+ sBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG;
+ sBattleBuffersTransferData[1] = arg1;
if (arg2_)
- gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = sub_81850DC(&gBattleBuffersTransferData[4]);
+ sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = sub_81850DC(&sBattleBuffersTransferData[4]);
else
- gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = 0;
+ sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = 0;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[2] + 4);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[2] + 4);
}
void BtlController_EmitResetActionMoveSelection(u8 bufferId, u8 caseId)
{
- gBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION;
- gBattleBuffersTransferData[1] = caseId;
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2);
+ sBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION;
+ sBattleBuffersTransferData[1] = caseId;
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2);
}
void BtlController_EmitCmd55(u8 bufferId, u8 arg1)
{
- gBattleBuffersTransferData[0] = CONTROLLER_55;
- gBattleBuffersTransferData[1] = arg1;
- gBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b;
- gBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b;
- gBattleBuffersTransferData[5] = gBattleBuffersTransferData[4] = sub_81850DC(&gBattleBuffersTransferData[6]);
- PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[4] + 6);
+ sBattleBuffersTransferData[0] = CONTROLLER_55;
+ sBattleBuffersTransferData[1] = arg1;
+ sBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b;
+ sBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b;
+ sBattleBuffersTransferData[5] = sBattleBuffersTransferData[4] = sub_81850DC(&sBattleBuffersTransferData[6]);
+ PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[4] + 6);
}
diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c
index 803b3eeab..4dc88ab6a 100644
--- a/src/battle_gfx_sfx_util.c
+++ b/src/battle_gfx_sfx_util.c
@@ -39,7 +39,6 @@ extern const struct CompressedSpriteSheet gTrainerBackPicTable[];
extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[];
extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[];
extern const union AnimCmd* const * const gMonAnimationsSpriteAnimsPtrTable[];
-extern const struct SpriteTemplate gUnknown_08329D98[4];
extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow;
extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow;
extern const u8 gEnemyMonElevation[];
diff --git a/src/battle_interface.c b/src/battle_interface.c
index bc6ff1122..96462ec04 100644
--- a/src/battle_interface.c
+++ b/src/battle_interface.c
@@ -650,7 +650,7 @@ static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2)
}
#else
-__attribute__((naked))
+ASM_DIRECT
static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2)
{
asm(".syntax unified\n\
diff --git a/src/battle_main.c b/src/battle_main.c
index 3c4a61600..78b69212d 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -20,6 +20,7 @@
#include "constants/hold_effects.h"
#include "constants/trainers.h"
#include "link.h"
+#include "link_rfu.h"
#include "bg.h"
#include "dma3.h"
#include "string_util.h"
@@ -50,7 +51,7 @@
#include "international_string_util.h"
#include "pokeball.h"
-struct UnknownPokemonStruct2
+struct UnknownPokemonStruct4
{
/*0x00*/ u16 species;
/*0x02*/ u16 heldItem;
@@ -85,7 +86,6 @@ extern const u16 gBattleTextboxPalette[]; // battle textbox palette
extern const struct BgTemplate gUnknown_0831AA08[];
extern const struct WindowTemplate * const gUnknown_0831ABA0[];
extern const u8 gUnknown_0831ACE0[];
-extern const u8 gStatStageRatios[][2];
extern const u8 * const gBattleScriptsForMoveEffects[];
extern const u8 * const gBattlescriptsForBallThrow[];
extern const u8 * const gBattlescriptsForRunningByItem[];
@@ -198,8 +198,8 @@ EWRAM_DATA static u32 sUnusedUnknownArray[25] = {0};
EWRAM_DATA u32 gBattleTypeFlags = 0;
EWRAM_DATA u8 gBattleTerrain = 0;
EWRAM_DATA u32 gUnknown_02022FF4 = 0;
-EWRAM_DATA struct UnknownPokemonStruct2 gUnknown_02022FF8[3] = {0}; // what is it used for?
-EWRAM_DATA struct UnknownPokemonStruct2* gUnknown_02023058 = NULL; // what is it used for?
+EWRAM_DATA struct UnknownPokemonStruct4 gUnknown_02022FF8[3] = {0}; // what is it used for?
+EWRAM_DATA struct UnknownPokemonStruct4* gUnknown_02023058 = NULL; // what is it used for?
EWRAM_DATA u8 *gUnknown_0202305C = NULL;
EWRAM_DATA u8 *gUnknown_02023060 = NULL;
EWRAM_DATA u8 gBattleBufferA[MAX_BATTLERS_COUNT][0x200] = {0};
@@ -738,7 +738,7 @@ static void CB2_HandleStartBattle(void)
sub_805EF14();
gBattleCommunication[MULTIUSE_STATE] = 1;
}
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800E0E8();
break;
case 1:
@@ -762,8 +762,8 @@ static void CB2_HandleStartBattle(void)
SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32);
gBattleCommunication[MULTIUSE_STATE] = 2;
}
- if (gLinkVSyncDisabled)
- sub_800DFB4(0, 0);
+ if (gWirelessCommType)
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
}
else
@@ -790,7 +790,7 @@ static void CB2_HandleStartBattle(void)
gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1];
sub_8185F90(gBlockRecvBuffer[playerMultiplayerId][1]);
sub_8185F90(gBlockRecvBuffer[enemyMultiplayerId][1]);
- sub_8068AA4();
+ SetDeoxysStats();
gBattleCommunication[MULTIUSE_STATE]++;
}
break;
@@ -933,7 +933,7 @@ static void CB2_HandleStartMultiPartnerBattle(void)
sub_805EF14();
gBattleCommunication[MULTIUSE_STATE] = 1;
}
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800E0E8();
// fall through
case 1:
@@ -964,8 +964,8 @@ static void CB2_HandleStartMultiPartnerBattle(void)
gBattleCommunication[MULTIUSE_STATE] = 2;
}
- if (gLinkVSyncDisabled)
- sub_800DFB4(0, 0);
+ if (gWirelessCommType)
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
}
else
@@ -1202,9 +1202,9 @@ static void CB2_PreInitMultiBattle(void)
case 0:
if (gReceivedRemoteLinkPlayers != 0 && sub_800A520())
{
- gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3);
+ gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct4) * 3);
sub_80379F8(0);
- SendBlock(bitmask_all_link_players_but_self(), gUnknown_02023058, sizeof(struct UnknownPokemonStruct2) * 3);
+ SendBlock(bitmask_all_link_players_but_self(), gUnknown_02023058, sizeof(struct UnknownPokemonStruct4) * 3);
gBattleCommunication[MULTIUSE_STATE]++;
}
break;
@@ -1222,12 +1222,12 @@ static void CB2_PreInitMultiBattle(void)
if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[playerMultiplierId].lp_field_18 & 1))
|| (gLinkPlayers[i].lp_field_18 & 1 && gLinkPlayers[playerMultiplierId].lp_field_18 & 1))
{
- memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3);
+ memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct4) * 3);
}
}
else
{
- memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3);
+ memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct4) * 3);
}
}
gBattleCommunication[MULTIUSE_STATE]++;
@@ -1241,14 +1241,14 @@ static void CB2_PreInitMultiBattle(void)
if (sub_800A520() && !gPaletteFade.active)
{
gBattleCommunication[MULTIUSE_STATE]++;
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800ADF8();
else
sub_800AC34();
}
break;
case 3:
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
{
if (sub_8010500())
{
@@ -1286,7 +1286,7 @@ static void CB2_PreInitIngamePlayerPartnerBattle(void)
switch (gBattleCommunication[MULTIUSE_STATE])
{
case 0:
- gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3);
+ gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct4) * 3);
sub_80379F8(3);
gBattleCommunication[MULTIUSE_STATE]++;
*savedCallback = gMain.savedCallback;
@@ -1333,7 +1333,7 @@ static void CB2_HandleStartMultiBattle(void)
sub_805EF14();
gBattleCommunication[MULTIUSE_STATE] = 1;
}
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800E0E8();
break;
case 1:
@@ -1351,8 +1351,8 @@ static void CB2_HandleStartMultiBattle(void)
SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32);
gBattleCommunication[MULTIUSE_STATE]++;
}
- if (gLinkVSyncDisabled)
- sub_800DFB4(0, 0);
+ if (gWirelessCommType)
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
}
else
@@ -1369,7 +1369,7 @@ static void CB2_HandleStartMultiBattle(void)
ResetBlockReceivedFlags();
sub_8036EB8(4, playerMultiplayerId);
SetAllPlayersBerryData();
- sub_8068AA4();
+ SetDeoxysStats();
var = CreateTask(sub_8035D74, 0);
gTasks[var].data[1] = 0x10E;
gTasks[var].data[2] = 0x5A;
@@ -2136,12 +2136,12 @@ static void sub_8038F34(void)
}
break;
case 8:
- if (!gLinkVSyncDisabled)
+ if (!gWirelessCommType)
sub_800AC34();
gBattleCommunication[MULTIUSE_STATE]++;
break;
case 9:
- if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1)
+ if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1)
{
gMain.field_439_x4 = 0;
SetMainCallback2(gMain.savedCallback);
@@ -2320,13 +2320,13 @@ static void sub_803939C(void)
case 8:
if (--gBattleCommunication[1] == 0)
{
- if (gMain.field_439_x4 && !gLinkVSyncDisabled)
+ if (gMain.field_439_x4 && !gWirelessCommType)
sub_800AC34();
gBattleCommunication[MULTIUSE_STATE]++;
}
break;
case 9:
- if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1)
+ if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1)
{
gMain.field_439_x4 = 0;
if (!gPaletteFade.active)
@@ -3389,7 +3389,7 @@ static void BattleIntroOpponent1SendsOutMonAnimation(void)
}
#else
-__attribute__((naked))
+ASM_DIRECT
static void BattleIntroOpponent1SendsOutMonAnimation(void)
{
asm(".syntax unified\n\
diff --git a/src/battle_message.c b/src/battle_message.c
index 2b9783f1a..9a4a062ad 100644
--- a/src/battle_message.c
+++ b/src/battle_message.c
@@ -1968,7 +1968,7 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst)
break;
case B_TXT_TRAINER1_CLASS: // trainer class name
if (gBattleTypeFlags & BATTLE_TYPE_SECRET_BASE)
- toCpy = gTrainerClassNames[GetSecretBaseTrainerNameIndex()];
+ toCpy = gTrainerClassNames[GetSecretBaseTrainerClass()];
else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00)
toCpy = gTrainerClassNames[sub_8068BB0()];
else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_3FE)
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 4d40d83a8..75f05e86f 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -12,7 +12,6 @@
#include "constants/hold_effects.h"
#include "util.h"
#include "pokemon.h"
-#include "calculate_base_damage.h"
#include "random.h"
#include "battle_controllers.h"
#include "battle_interface.h"
@@ -32,7 +31,6 @@
#include "bg.h"
#include "string_util.h"
#include "pokemon_icon.h"
-#include "pokemon_item_effects.h"
#include "m4a.h"
#include "mail.h"
#include "event_data.h"
@@ -3649,7 +3647,7 @@ static void atk24(void)
}
}
#else
-__attribute__((naked))
+ASM_DIRECT
static void atk24(void)
{
asm("\n\
@@ -4529,7 +4527,7 @@ static void atk48_playstatchangeanimation(void)
}
}
#else
-__attribute__((naked))
+ASM_DIRECT
static void atk48_playstatchangeanimation(void)
{
asm("\n\
@@ -6882,8 +6880,7 @@ static void atk74_hpthresholds2(void)
static void atk75_useitemonopponent(void)
{
gBattlerInMenuId = gBattlerAttacker;
- ExecuteTableBasedItemEffect(&gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]], gLastUsedItem, gBattlerPartyIndexes[gBattlerAttacker], 0, 1);
-
+ PokemonUseItemEffects(&gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]], gLastUsedItem, gBattlerPartyIndexes[gBattlerAttacker], 0, 1);
gBattlescriptCurrInstr += 1;
}
@@ -9422,7 +9419,7 @@ static void atkC1_hiddenpowercalc(void)
}
#else
-__attribute__((naked))
+ASM_DIRECT
static void atkC1_hiddenpowercalc(void)
{
asm(".syntax unified\n\
diff --git a/src/battle_setup.c b/src/battle_setup.c
index 52ed99b21..fdf6e77b6 100644
--- a/src/battle_setup.c
+++ b/src/battle_setup.c
@@ -5,7 +5,6 @@
#include "battle_transition.h"
#include "main.h"
#include "task.h"
-#include "pokemon_3.h"
#include "safari_zone.h"
#include "script.h"
#include "constants/game_stat.h"
diff --git a/src/battle_util.c b/src/battle_util.c
index ddd61ae19..a457ce15d 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -20,7 +20,6 @@
#include "battle_ai_script_commands.h"
#include "battle_controllers.h"
#include "event_data.h"
-#include "calculate_base_damage.h"
#include "link.h"
#include "berry.h"
diff --git a/src/berry_blender.c b/src/berry_blender.c
index 45e3acd24..23594ba46 100644
--- a/src/berry_blender.c
+++ b/src/berry_blender.c
@@ -160,7 +160,7 @@ extern void sub_809882C(u8, u16, u8);
extern void copy_textbox_border_tile_patterns_to_vram(u8, u16, u8);
extern void sub_81AABF0(void (*callback)(void));
extern void sub_800B4C0(void);
-extern void sub_8009F8C(void);
+extern void ClearLinkCallback(void);
extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void);
extern void sub_8153430(void);
extern bool8 sub_8153474(void);
@@ -952,10 +952,10 @@ static void sub_807FAC8(void)
sBerryBlenderData->syncArrowSpriteIds[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1);
StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[i]], i + 8);
}
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
{
sub_800E0E8();
- sub_800DFB4(0, 0);
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
SetVBlankCallback(VBlankCB0_BerryBlender);
sBerryBlenderData->mainState++;
@@ -1158,10 +1158,10 @@ static void sub_8080018(void)
sBerryBlenderData->syncArrowSprite2Ids[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1);
StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSprite2Ids[i]], i + 8);
}
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
{
sub_800E0E8();
- sub_800DFB4(0, 0);
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
sBerryBlenderData->mainState++;
break;
@@ -1874,7 +1874,7 @@ static void sub_8081370(u16 a0)
static bool32 sub_80814B0(u16 arg0, u16 arg1, u16 arg2)
{
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
{
if ((arg0 & 0xFF00) == arg2)
return TRUE;
@@ -2316,7 +2316,7 @@ static void sub_8081E20(void)
static void sub_8081F94(u16 *a0)
{
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
*a0 = 0x2F00;
else
*a0 = 0x2FFF;
@@ -2345,7 +2345,7 @@ static void CB2_HandleBlenderEndGame(void)
sBerryBlenderData->field_4C -= 32;
if (sBerryBlenderData->field_4C <= 0)
{
- sub_8009F8C();
+ ClearLinkCallback();
sBerryBlenderData->field_4C = 0;
if (gReceivedRemoteLinkPlayers != 0)
@@ -2365,7 +2365,7 @@ static void CB2_HandleBlenderEndGame(void)
}
else if (sub_800A520())
{
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
{
sBerryBlenderData->gameBlock.timeRPM.time = sBerryBlenderData->gameFrameTime;
sBerryBlenderData->gameBlock.timeRPM.max_RPM = sBerryBlenderData->max_RPM;
@@ -2394,7 +2394,7 @@ static void CB2_HandleBlenderEndGame(void)
ResetBlockReceivedFlags();
sBerryBlenderData->gameEndState++;
- if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled)
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
{
struct BlenderGameBlock *receivedBlock = (struct BlenderGameBlock*)(&gBlockRecvBuffer);
@@ -2871,7 +2871,7 @@ static void sub_8082D28(void)
if (gReceivedRemoteLinkPlayers != 0)
playerId = GetMultiplayerId();
- if (gLinkVSyncDisabled && gReceivedRemoteLinkPlayers != 0)
+ if (gWirelessCommType && gReceivedRemoteLinkPlayers != 0)
{
if (playerId == 0)
{
diff --git a/src/bg.c b/src/bg.c
index b699a0b1f..22861b64d 100644
--- a/src/bg.c
+++ b/src/bg.c
@@ -463,7 +463,7 @@ bool8 IsDma3ManagerBusyWithBgCopy(void)
return FALSE;
}
#else
-__attribute__((naked))
+ASM_DIRECT
bool8 IsDma3ManagerBusyWithBgCopy(void)
{
asm("push {r4-r7,lr}\n\
@@ -1048,7 +1048,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8
}
}
}*/
-__attribute__((naked))
+ASM_DIRECT
void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8 srcWidth, u8 srcHeight, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, u8 palette1, u16 tileOffset, u16 palette2)
{
asm("push {r4-r7,lr}\n\
@@ -1495,7 +1495,7 @@ void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 pal
*dest = test;
}
#else
-__attribute__((naked))
+ASM_DIRECT
void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 palette2)
{
asm("push {r4-r6,lr}\n\
diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c
index d6924de9f..55e75bfbf 100644
--- a/src/braille_puzzles.c
+++ b/src/braille_puzzles.c
@@ -421,7 +421,7 @@ bool8 ShouldDoBrailleRegicePuzzle(void)
return FALSE;
}
#else
-__attribute__((naked))
+ASM_DIRECT
bool8 ShouldDoBrailleRegicePuzzle(void)
{
asm(".syntax unified\n\
diff --git a/src/calculate_base_damage.c b/src/calculate_base_damage.c
deleted file mode 100644
index 98468caa2..000000000
--- a/src/calculate_base_damage.c
+++ /dev/null
@@ -1,275 +0,0 @@
-#include "global.h"
-#include "constants/abilities.h"
-#include "battle.h"
-#include "battle_setup.h"
-#include "constants/hold_effects.h"
-#include "event_data.h"
-#include "item.h"
-#include "constants/items.h"
-#include "pokemon.h"
-#include "constants/species.h"
-#include "constants/moves.h"
-#include "constants/battle_move_effects.h"
-
-bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank);
-
-extern const struct BattleMove gBattleMoves[];
-extern const u8 gHoldEffectToType[][2];
-extern const u8 gStatStageRatios[][2];
-
-#define APPLY_STAT_MOD(var, mon, stat, statIndex) \
-{ \
- (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \
- (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \
-}
-
-s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef)
-{
- u32 i;
- s32 damage = 0;
- s32 damageHelper;
- u8 type;
- u16 attack, defense;
- u16 spAttack, spDefense;
- u8 defenderHoldEffect;
- u8 defenderHoldEffectParam;
- u8 attackerHoldEffect;
- u8 attackerHoldEffectParam;
-
- if (!powerOverride)
- gBattleMovePower = gBattleMoves[move].power;
- else
- gBattleMovePower = powerOverride;
-
- if (!typeOverride)
- type = gBattleMoves[move].type;
- else
- type = typeOverride & 0x3F;
-
- attack = attacker->attack;
- defense = defender->defense;
- spAttack = attacker->spAttack;
- spDefense = defender->spDefense;
-
- if (attacker->item == ITEM_ENIGMA_BERRY)
- {
- attackerHoldEffect = gEnigmaBerries[bankAtk].holdEffect;
- attackerHoldEffectParam = gEnigmaBerries[bankAtk].holdEffectParam;
- }
- else
- {
- attackerHoldEffect = ItemId_GetHoldEffect(attacker->item);
- attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item);
- }
-
- if (defender->item == ITEM_ENIGMA_BERRY)
- {
- defenderHoldEffect = gEnigmaBerries[bankDef].holdEffect;
- defenderHoldEffectParam = gEnigmaBerries[bankDef].holdEffectParam;
- }
- else
- {
- defenderHoldEffect = ItemId_GetHoldEffect(defender->item);
- defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item);
- }
-
- if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER)
- attack *= 2;
-
- if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, bankAtk))
- attack = (110 * attack) / 100;
- if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, bankDef))
- defense = (110 * defense) / 100;
- if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankAtk))
- spAttack = (110 * spAttack) / 100;
- if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankDef))
- spDefense = (110 * spDefense) / 100;
-
- for (i = 0; i < 17; i++)
- {
- if (attackerHoldEffect == gHoldEffectToType[i][0]
- && type == gHoldEffectToType[i][1])
- {
- if (type <= 8)
- attack = (attack * (attackerHoldEffectParam + 100)) / 100;
- else
- spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100;
- break;
- }
- }
-
- if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND)
- attack = (150 * attack) / 100;
- if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS))
- spAttack = (150 * spAttack) / 100;
- if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS))
- spDefense = (150 * spDefense) / 100;
- if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL)
- spAttack *= 2;
- if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL)
- spDefense *= 2;
- if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU)
- spAttack *= 2;
- if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO)
- defense *= 2;
- if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK))
- attack *= 2;
- if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE))
- spAttack /= 2;
- if (attacker->ability == ABILITY_HUSTLE)
- attack = (150 * attack) / 100;
- if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0))
- spAttack = (150 * spAttack) / 100;
- if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0))
- spAttack = (150 * spAttack) / 100;
- if (attacker->ability == ABILITY_GUTS && attacker->status1)
- attack = (150 * attack) / 100;
- if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1)
- defense = (150 * defense) / 100;
- if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0))
- gBattleMovePower /= 2;
- if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0))
- gBattleMovePower /= 2;
- if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3))
- gBattleMovePower = (150 * gBattleMovePower) / 100;
- if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3))
- gBattleMovePower = (150 * gBattleMovePower) / 100;
- if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3))
- gBattleMovePower = (150 * gBattleMovePower) / 100;
- if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3))
- gBattleMovePower = (150 * gBattleMovePower) / 100;
- if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION)
- defense /= 2;
-
- if (IS_MOVE_PHYSICAL(type))
- {
- if (gCritMultiplier == 2)
- {
- if (attacker->statStages[STAT_ATK] > 6)
- APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
- else
- damage = attack;
- }
- else
- APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
-
- damage = damage * gBattleMovePower;
- damage *= (2 * attacker->level / 5 + 2);
-
- if (gCritMultiplier == 2)
- {
- if (defender->statStages[STAT_DEF] < 6)
- APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
- else
- damageHelper = defense;
- }
- else
- APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
-
- damage = damage / damageHelper;
- damage /= 50;
-
- if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS)
- damage /= 2;
-
- if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1)
- {
- if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2)
- damage = 2 * (damage / 3);
- else
- damage /= 2;
- }
-
- if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2)
- damage /= 2;
-
- // moves always do at least 1 damage.
- if (damage == 0)
- damage = 1;
- }
-
- if (type == TYPE_MYSTERY)
- damage = 0; // is ??? type. does 0 damage.
-
- if (IS_MOVE_SPECIAL(type))
- {
- if (gCritMultiplier == 2)
- {
- if (attacker->statStages[STAT_SPATK] > 6)
- APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
- else
- damage = spAttack;
- }
- else
- APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
-
- damage = damage * gBattleMovePower;
- damage *= (2 * attacker->level / 5 + 2);
-
- if (gCritMultiplier == 2)
- {
- if (defender->statStages[STAT_SPDEF] < 6)
- APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
- else
- damageHelper = spDefense;
- }
- else
- APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
-
- damage = (damage / damageHelper);
- damage /= 50;
-
- if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1)
- {
- if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2)
- damage = 2 * (damage / 3);
- else
- damage /= 2;
- }
-
- if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2)
- damage /= 2;
-
- // are effects of weather negated with cloud nine or air lock
- if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0)
- && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0))
- {
- if (gBattleWeather & WEATHER_RAIN_TEMPORARY)
- {
- switch (type)
- {
- case TYPE_FIRE:
- damage /= 2;
- break;
- case TYPE_WATER:
- damage = (15 * damage) / 10;
- break;
- }
- }
-
- // any weather except sun weakens solar beam
- if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM)
- damage /= 2;
-
- // sunny
- if (gBattleWeather & WEATHER_SUN_ANY)
- {
- switch (type)
- {
- case TYPE_FIRE:
- damage = (15 * damage) / 10;
- break;
- case TYPE_WATER:
- damage /= 2;
- break;
- }
- }
- }
-
- // flash fire triggered
- if ((gBattleResources->flags->flags[bankAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE)
- damage = (15 * damage) / 10;
- }
-
- return damage + 2;
-}
diff --git a/src/clear_save_data_screen.c b/src/clear_save_data_screen.c
index 6d6a1545b..ca2037d2f 100644
--- a/src/clear_save_data_screen.c
+++ b/src/clear_save_data_screen.c
@@ -14,8 +14,6 @@
extern u8 gText_ClearAllSaveData[];
extern u8 gText_ClearingData[];
-extern u16 gUnknown_0860F074[];
-
static void Task_DoClearSaveDataScreenYesNo(u8);
static void Task_ClearSaveDataScreenYesNoChoice(u8);
static void Task_ClearSaveData(u8);
diff --git a/src/decompress.c b/src/decompress.c
index 8e8827194..fb288bf4a 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -117,7 +117,7 @@ void Unused_LZDecompressWramIndirect(const void **src, void *dest)
}
// This one (unused) function is really challenging, won't even try to decompile it.
-__attribute__((naked))
+ASM_DIRECT
void sub_803471C()
{
asm(".syntax unified\n\
diff --git a/src/decoration.c b/src/decoration.c
index db19ff4c6..8eb875560 100644
--- a/src/decoration.c
+++ b/src/decoration.c
@@ -2542,7 +2542,7 @@ void sub_812A0E8(u8 taskId)
}
}
#else
-__attribute__((naked)) void sub_812A0E8(u8 taskId)
+ASM_DIRECT void sub_812A0E8(u8 taskId)
{
asm_unified("\tpush {r4-r7,lr}\n"
"\tlsls r0, 24\n"
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
index 5a2fe5ca2..b78b9433e 100644
--- a/src/egg_hatch.c
+++ b/src/egg_hatch.c
@@ -44,7 +44,6 @@ struct EggHatchData
u8 textColor[3];
};
-extern struct SpriteTemplate gUnknown_0202499C;
extern void (*gFieldCallback)(void);
extern const struct CompressedSpriteSheet gMonFrontPicTable[];
@@ -58,20 +57,14 @@ extern const u8 gText_HatchedFromEgg[];
extern const u8 gText_NickHatchPrompt[];
extern u8 sav1_map_get_name(void);
-extern s8 ProcessMenuInputNoWrap_(void);
extern void TVShowConvertInternationalString(u8* str1, u8* str2, u8);
extern void sub_806A068(u16, u8);
extern void FadeScreen(u8, u8);
extern void overworld_free_bg_tilemaps(void);
extern void sub_80AF168(void);
-extern void AllocateMonSpritesGfx(void);
-extern void FreeMonSpritesGfx(void);
extern void ScanlineEffect_Stop(void);
-extern void reset_temp_tile_data_buffers(void);
extern void c2_exit_to_overworld_2_switch(void);
extern void play_some_sound(void);
-extern void copy_decompressed_tile_data_to_vram_autofree(u8 bg_id, const void* src, u16 size, u16 offset, u8 mode);
-extern void CreateYesNoMenu(const struct WindowTemplate*, u16, u8, u8);
extern void DoNamingScreen(u8, const u8*, u16, u8, u32, MainCallback);
extern u16 sub_80D22D0(void);
extern u8 CountPartyAliveNonEggMonsExcept(u8);
@@ -440,12 +433,12 @@ static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
gMonSpritesGfxPtr->sprites[(a0 * 2) + 1],
species, pid);
- LoadCompressedObjectPalette(sub_806E794(mon));
+ LoadCompressedObjectPalette(GetMonSpritePalStruct(mon));
*speciesLoc = species;
}
break;
case 1:
- sub_806A068(sub_806E794(mon)->tag, r5);
+ sub_806A068(GetMonSpritePalStruct(mon)->tag, r5);
spriteID = CreateSprite(&gUnknown_0202499C, 120, 75, 6);
gSprites[spriteID].invisible = 1;
gSprites[spriteID].callback = SpriteCallbackDummy;
diff --git a/src/evolution_scene.c b/src/evolution_scene.c
index f38f9f19c..1b929c9bd 100644
--- a/src/evolution_scene.c
+++ b/src/evolution_scene.c
@@ -48,7 +48,6 @@ extern u16 gBattle_BG2_X;
extern u16 gBattle_BG2_Y;
extern u16 gBattle_BG3_X;
extern u16 gBattle_BG3_Y;
-extern struct SpriteTemplate gUnknown_0202499C;
extern bool8 gAffineAnimsDisabled;
extern u16 gMoveToLearn;
extern const u8 gSpeciesNames[][11];
@@ -67,9 +66,6 @@ extern const u8 gText_PkmnStoppedEvolving[];
extern const u8 gText_EllipsisQuestionMark[];
extern const u8 gText_CommunicationStandby5[];
-extern void copy_decompressed_tile_data_to_vram_autofree(u8 arg0, const void *arg1, bool32 arg2, u16 arg3, u8 arg4);
-extern u32 sub_80391E0(u8, u8);
-extern void SpriteCallbackDummy_2(struct Sprite *sprite);
extern void sub_80356D0(void);
extern void sub_807B154(void);
extern void sub_806A068(u16, u8);
@@ -471,10 +467,10 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void)
}
break;
case 6:
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
{
sub_800E0E8();
- sub_800DFB4(0, 0);
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
BlendPalettes(-1,0x10, 0);
gMain.state++;
@@ -1255,7 +1251,7 @@ static void Task_TradeEvolutionScene(u8 taskID)
case 5:
if (!gPaletteFade.active)
{
- if (gLinkVSyncDisabled)
+ if (gWirelessCommType)
sub_800E084();
Free(GetBgTilemapBuffer(3));
diff --git a/src/item_use.c b/src/item_use.c
index 11dca12fb..2e47e6f14 100755
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -87,7 +87,6 @@ extern void sub_81ABA88(u8);
extern void sub_80B7CC8(void);
extern void flagmods_08054D70(void);
extern u8* sub_806CF78(u16);
-extern bool8 ExecuteTableBasedItemEffect_(struct Pokemon*, u16, u8, u8);
extern void sub_81B89F0(void);
extern u8 GetItemEffectType(u16);
extern struct MapConnection *sub_8088A8C(s16, s16);
@@ -984,7 +983,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId)
{
u16 partyId = gBattlerPartyIndexes[gBattlerInMenuId];
- if (ExecuteTableBasedItemEffect_(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE)
+ if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE)
{
if (!InBattlePyramid())
DisplayItemMessage(taskId, 1, gText_WontHaveEffect, bag_menu_inits_lists_menu);
diff --git a/src/librfu_rfu.c b/src/librfu_rfu.c
index cf3fe12ad..c5aa25c10 100644
--- a/src/librfu_rfu.c
+++ b/src/librfu_rfu.c
@@ -3,38 +3,6 @@
#include "librfu.h"
-struct RfuUnk1
-{
- u8 unk_0[0x14];
- u32 unk_14;
- u32 unk_18;
- struct RfuIntrStruct unk_1c;
-};
-
-struct RfuUnk2
-{
- u8 unk_0[0x68];
- u32 unk_68;
- u32 unk_6c;
- u8 unk_70[0x70];
-};
-
-struct RfuUnk3
-{
- u32 unk_0;
- u32 unk_4;
- u8 unk_8[0xD4];
- u32 unk_dc;
-};
-
-extern u32 *gUnknown_03007890;
-extern u32 *gUnknown_03007894;
-extern struct RfuUnk3* gUnknown_03007898;
-extern struct RfuUnk2* gUnknown_03007880[4];
-extern struct RfuUnk1* gUnknown_03007870[4];
-extern void* sub_82E53F4;
-extern void rfu_STC_clearAPIVariables(void);
-
// Nonmatching, only register differences
/*u16 rfu_initializeAPI(u32 *unk0, u16 unk1, IntrFunc *interrupt, bool8 copyInterruptToRam)
{
diff --git a/src/lilycove_lady.c b/src/lilycove_lady.c
index 927b87c72..dcdf9b45a 100644
--- a/src/lilycove_lady.c
+++ b/src/lilycove_lady.c
@@ -641,7 +641,7 @@ static u8 sub_818E13C(void)
return retval;
}
#else
-__attribute__((naked)) static u8 sub_818E13C(void)
+ASM_DIRECT static u8 sub_818E13C(void)
{
asm_unified("\tpush {r4-r7,lr}\n"
"\tmovs r7, 0x1\n"
diff --git a/src/link.c b/src/link.c
index ae2cd1992..8f7aa71b6 100644
--- a/src/link.c
+++ b/src/link.c
@@ -1,6 +1,32 @@
// Includes
#include "global.h"
+#include "m4a.h"
+#include "malloc.h"
+#include "reset_save_heap.h"
+#include "save.h"
+#include "bg.h"
+#include "window.h"
+#include "librfu.h"
+#include "random.h"
+#include "decompress.h"
+#include "string_util.h"
+#include "event_data.h"
+#include "item_menu.h"
+#include "overworld.h"
+#include "gpu_regs.h"
+#include "palette.h"
+#include "task.h"
+#include "scanline_effect.h"
+#include "menu.h"
+#include "text.h"
+#include "strings.h"
+#include "constants/songs.h"
+#include "sound.h"
+#include "trade.h"
+#include "battle.h"
+#include "link.h"
+#include "link_rfu.h"
// Static type declarations
@@ -8,7 +34,7 @@ struct BlockTransfer
{
u16 pos;
u16 size;
- void *src;
+ const u8 *src;
bool8 active;
u8 multiplayerId;
};
@@ -23,34 +49,2392 @@ struct LinkTestBGInfo
// Static RAM declarations
-IWRAM_DATA struct BlockTransfer gUnknown_03000D10;
+IWRAM_DATA struct BlockTransfer sBlockSend;
IWRAM_DATA u32 link_c_unused_03000d1c;
-IWRAM_DATA struct BlockTransfer gUnknown_03000D20[4];
-IWRAM_DATA u32 gUnknown_03000D50;
+IWRAM_DATA struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS];
+IWRAM_DATA u32 sBlockSendDelayCounter;
IWRAM_DATA u32 gUnknown_03000D54;
IWRAM_DATA u8 gUnknown_03000D58;
-IWRAM_DATA u32 gUnknown_03000D5C;
+IWRAM_DATA u32 sPlayerDataExchangeStatus;
IWRAM_DATA u32 gUnknown_03000D60;
-IWRAM_DATA u8 gUnknown_03000D64[4]; // not really, but won't match otherwise
-IWRAM_DATA u8 gUnknown_03000D68[4];
-IWRAM_DATA u8 gUnknown_03000D6C;
-IWRAM_DATA bool8 gUnknown_03000D6D;
-IWRAM_DATA u16 gUnknown_03000D6E;
-IWRAM_DATA u16 gUnknown_03000D70;
-IWRAM_DATA u8 gUnknown_03000D72;
-IWRAM_DATA u8 gUnknown_03000D73;
-IWRAM_DATA u8 gUnknown_03000D74[4]; // not really, but won't match otherwise
-IWRAM_DATA u8 gUnknown_03000D78[8]; // not really, but won't match otherwise
-IWRAM_DATA u8 gUnknown_03000D80[16];
-IWRAM_DATA u16 gUnknown_03000D90[8];
-IWRAM_DATA u32 gUnknown_03000DA0;
-IWRAM_DATA u32 gUnknown_03000DA4;
-IWRAM_DATA void *gUnknown_03000DA8;
-IWRAM_DATA void *gUnknown_03000DAC;
-IWRAM_DATA bool32 gUnknown_03000DB0;
+IWRAM_DATA u8 sLinkTestLastBlockSendPos;
+ALIGNED() IWRAM_DATA u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS];
+IWRAM_DATA u8 sNumVBlanksWithoutSerialIntr;
+IWRAM_DATA bool8 sSendBufferEmpty;
+IWRAM_DATA u16 sSendNonzeroCheck;
+IWRAM_DATA u16 sRecvNonzeroCheck;
+IWRAM_DATA u8 sChecksumAvailable;
+IWRAM_DATA u8 sHandshakePlayerCount;
+
+u16 gLinkPartnersHeldKeys[6];
+u32 gLinkDebugSeed;
+struct LinkPlayerBlock gLocalLinkPlayerBlock;
+bool8 gLinkErrorOccurred;
+u32 gLinkDebugFlags;
+u32 gFiller_03003074;
+bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS];
+u8 gBlockReceivedStatus[MAX_LINK_PLAYERS];
+u32 gFiller_03003080;
+u16 gLinkHeldKeys;
+u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH];
+u32 gLinkStatus;
+bool8 gUnknown_030030E4;
+bool8 gUnknown_030030E8;
+bool8 gUnknown_030030EC[MAX_LINK_PLAYERS];
+bool8 gUnknown_030030F0[MAX_LINK_PLAYERS];
+u16 gUnknown_030030F4;
+u8 gSuppressLinkErrorMessage;
+bool8 gWirelessCommType;
+bool8 gSavedLinkPlayerCount;
+u16 gSendCmd[CMD_LENGTH];
+u8 gSavedMultiplayerId;
+bool8 gReceivedRemoteLinkPlayers;
+struct LinkTestBGInfo gLinkTestBGInfo;
+void (*gLinkCallback)(void);
+u8 gShouldAdvanceLinkState;
+u16 gLinkTestBlockChecksums[MAX_LINK_PLAYERS];
+u8 gBlockRequestType;
+u32 gFiller_03003154;
+u32 gFiller_03003158;
+u32 gFiller_0300315c;
+u8 gLastSendQueueCount;
+struct Link gLink;
+u8 gLastRecvQueueCount;
+u16 gLinkSavedIme;
+u32 gFiller_03004138;
+u32 gFiller_0300413C;
+
+EWRAM_DATA u8 gLinkTestDebugValuesEnabled = 0;
+EWRAM_DATA u8 gUnknown_020223BD = 0;
+EWRAM_DATA u32 gUnknown_020223C0 = 0;
+EWRAM_DATA u16 gBlockRecvBuffer[MAX_RFU_PLAYERS][BLOCK_BUFFER_SIZE / 2] = {};
+EWRAM_DATA u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE] = {};
+EWRAM_DATA bool8 gLinkOpen = FALSE;
+EWRAM_DATA u16 gLinkType = 0;
+EWRAM_DATA u16 gLinkTimeOutCounter = 0;
+EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {};
+EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {};
+EWRAM_DATA struct LinkPlayer gSavedLinkPlayers[MAX_RFU_PLAYERS] = {};
+EWRAM_DATA struct {
+ u32 status;
+ u8 lastRecvQueueCount;
+ u8 lastSendQueueCount;
+ u8 unk_06;
+} sLinkErrorBuffer = {};
+EWRAM_DATA u16 gUnknown_02022B08 = 0;
+EWRAM_DATA void *gUnknown_02022B0C = NULL;
// Static ROM declarations
+static void InitLocalLinkPlayer(void);
+static void sub_80096BC(void);
+static void CB2_LinkTest(void);
+static void ProcessRecvCmds(u8 unused);
+static void sub_8009F70(void);
+static void ResetBlockSend(void);
+static bool32 InitBlockSend(const void *src, size_t size);
+static void LinkCB_BlockSendBegin(void);
+static void LinkCB_BlockSend(void);
+static void LinkCB_BlockSendEnd(void);
+static void SetBlockReceivedFlag(u8 who);
+static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size);
+static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2);
+static void LinkCB_RequestPlayerDataExchange(void);
+static void Task_PrintTestData(u8 taskId);
+
+static void sub_800AC80(void);
+static void sub_800ACAC(void);
+static void sub_800AD5C(void);
+static void sub_800AD88(void);
+static void sub_800AE30(void);
+static void sub_800AE5C(void);
+
+static void CheckErrorStatus(void);
+static void CB2_PrintErrorMessage(void);
+static bool8 IsSioMultiMaster(void);
+static void sub_800B4A4(void);
+static void DisableSerial(void);
+static void EnableSerial(void);
+static void CheckMasterOrSlave(void);
+static void InitTimer(void);
+static void EnqueueSendCmd(u16 *sendCmd);
+static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH]);
+
+static void StartTransfer(void);
+static bool8 DoHandshake(void);
+static void DoRecv(void);
+static void DoSend(void);
+static void StopTimer(void);
+static void SendRecvDone(void);
+
// .rodata
+ALIGNED(4) const u16 gWirelessLinkDisplayPal[] = INCBIN_U16("graphics/interface/wireless_link_display.gbapal");
+const u8 gWirelessLinkDisplayGfx[] = INCBIN_U8("graphics/interface/wireless_link_display.4bpp.lz");
+const u8 gWirelessLinkDisplayTilemap[] = INCBIN_U8("graphics/interface/wireless_link_display.bin.lz");
+const u16 gLinkTestDigitsPal[] = INCBIN_U16("graphics/interface/link_test_digits.gbapal");
+const u16 gLinkTestDigitsGfx[] = INCBIN_U16("graphics/interface/link_test_digits.4bpp");
+const u8 unkstring_82ed160[] = _("{HIGHLIGHT TRANSPARENT}{COLOR WHITE}");
+const u16 g2BlankTilesGfx[] = INCBIN_U16("graphics/interface/blank_1x2.4bpp");
+const struct BlockRequest gUnknown_082ED1A8[] = {
+ {gBlockSendBuffer, 200},
+ {gBlockSendBuffer, 200},
+ {gBlockSendBuffer, 100},
+ {gBlockSendBuffer, 220},
+ {gBlockSendBuffer, 40}
+};
+const u8 gBGControlRegs[] = {
+ REG_OFFSET_BG0CNT,
+ REG_OFFSET_BG1CNT,
+ REG_OFFSET_BG2CNT,
+ REG_OFFSET_BG3CNT
+};
+const char gASCIIGameFreakInc[] = "GameFreak inc.";
+const char gASCIITestPrint[] = "TEST PRINT\nP0\nP1\nP2\nP3";
+const struct BgTemplate gUnknown_082ED1FC[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .priority = 0
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .priority = 1
+ }
+};
+const struct WindowTemplate gUnknown_082ED204[] = {
+ {0x00, 0x00, 0x00, 0x1E, 0x05, 0x0F, 0x0002},
+ {0x00, 0x00, 0x06, 0x1E, 0x07, 0x0F, 0x0098},
+ {0x00, 0x00, 0x0D, 0x1E, 0x07, 0x0F, 0x016A},
+ DUMMY_WIN_TEMPLATE
+};
+const u8 gUnknown_082ED224[] = {
+ 0x00, 0x01, 0x02, 0x00,
+ 0xff, 0xfe, 0xff, 0x00
+};
+
// .text
+
+bool8 sub_80093CC(void)
+{
+ sub_800B488();
+ sub_800E700();
+ if (sub_800BEC0() == 0x8001)
+ {
+ rfu_REQ_stopMode();
+ rfu_waitREQComplete();
+ return TRUE;
+ }
+ sub_800B4A4();
+ CloseLink();
+ RestoreSerialTimer3IntrHandlers();
+ return FALSE;
+}
+
+void Task_DestroySelf(u8 taskId)
+{
+ DestroyTask(taskId);
+}
+
+static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock, u16 a4)
+{
+ LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20);
+ DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock) + (16 * a4), sizeof gLinkTestDigitsGfx);
+ gLinkTestBGInfo.screenBaseBlock = screenBaseBlock;
+ gLinkTestBGInfo.paletteNum = paletteNum;
+ gLinkTestBGInfo.dummy_8 = a4;
+ switch (bgNum)
+ {
+ case 1:
+ SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock));
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock));
+ break;
+ case 3:
+ SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock));
+ break;
+ }
+ SetGpuReg(REG_OFFSET_BG0HOFS + bgNum * 4, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS + bgNum * 4, 0);
+}
+
+void sub_80094EC(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock)
+{
+ LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20);
+ DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock), sizeof gLinkTestDigitsGfx);
+ gLinkTestBGInfo.screenBaseBlock = screenBaseBlock;
+ gLinkTestBGInfo.paletteNum = paletteNum;
+ gLinkTestBGInfo.dummy_8 = 0;
+ SetGpuReg(gBGControlRegs[bgNum], BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_CHARBASE(charBaseBlock));
+}
+
+void LinkTestScreen(void)
+{
+ int i;
+
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ SetVBlankCallback(sub_80096BC);
+ ResetBlockSend();
+ gLinkType = 0x1111;
+ OpenLink();
+ SeedRng(gMain.vblankCounter2);
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ gSaveBlock2Ptr->playerTrainerId[i] = Random() % 256;
+ }
+ InitLinkTestBG(0, 2, 4, 0, 0);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON);
+ CreateTask(Task_DestroySelf, 0);
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ gUnknown_03000D60 = 0;
+ InitLocalLinkPlayer();
+ CreateTask(Task_PrintTestData, 0);
+ SetMainCallback2(CB2_LinkTest);
+}
+
+void sub_8009628(u8 a0)
+{
+ gLocalLinkPlayer.lp_field_18 = a0;
+}
+
+static void InitLocalLinkPlayer(void)
+{
+ gLocalLinkPlayer.trainerId = gSaveBlock2Ptr->playerTrainerId[0] | (gSaveBlock2Ptr->playerTrainerId[1] << 8) | (gSaveBlock2Ptr->playerTrainerId[2] << 16) | (gSaveBlock2Ptr->playerTrainerId[3] << 24);
+ StringCopy(gLocalLinkPlayer.name, gSaveBlock2Ptr->playerName);
+ gLocalLinkPlayer.gender = gSaveBlock2Ptr->playerGender;
+ gLocalLinkPlayer.linkType = gLinkType;
+ gLocalLinkPlayer.language = gGameLanguage;
+ gLocalLinkPlayer.version = gGameVersion + 0x4000;
+ gLocalLinkPlayer.lp_field_2 = 0x8000;
+ gLocalLinkPlayer.name[8] = IsNationalPokedexEnabled();
+ if (FlagGet(FLAG_0x87F))
+ {
+ gLocalLinkPlayer.name[8] |= 0x10;
+ }
+}
+
+static void sub_80096BC(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void InitLink(void)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ gSendCmd[i] = 0xefff;
+ }
+ gLinkOpen = TRUE;
+ EnableSerial();
+}
+
+static void Task_TriggerHandshake(u8 taskId)
+{
+ if (++gTasks[taskId].data[0] == 5)
+ {
+ gShouldAdvanceLinkState = 1;
+ DestroyTask(taskId);
+ }
+}
+
+void OpenLink(void)
+{
+ int i;
+
+ if (!gWirelessCommType)
+ {
+ ResetSerial();
+ InitLink();
+ gLinkCallback = LinkCB_RequestPlayerDataExchange;
+ gLinkVSyncDisabled = FALSE;
+ gLinkErrorOccurred = FALSE;
+ gSuppressLinkErrorMessage = FALSE;
+ ResetBlockReceivedFlags();
+ ResetBlockSend();
+ gUnknown_03000D54 = 0;
+ gUnknown_030030E8 = FALSE;
+ gUnknown_030030E4 = FALSE;
+ gUnknown_030030F4 = 0;
+ CreateTask(Task_TriggerHandshake, 2);
+ }
+ else
+ {
+ sub_800E700();
+ }
+ gReceivedRemoteLinkPlayers = 0;
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ gRemoteLinkPlayersNotReceived[i] = TRUE;
+ gUnknown_030030F0[i] = FALSE;
+ gUnknown_030030EC[i] = FALSE;
+ }
+}
+
+void CloseLink(void)
+{
+ gReceivedRemoteLinkPlayers = FALSE;
+ if (gWirelessCommType)
+ {
+ sub_800EDD4();
+ }
+ gLinkOpen = FALSE;
+ DisableSerial();
+}
+
+static void TestBlockTransfer(u8 nothing, u8 is, u8 used)
+{
+ u8 i;
+ u8 status;
+
+ if (sLinkTestLastBlockSendPos != sBlockSend.pos)
+ {
+ LinkTest_prnthex(sBlockSend.pos, 2, 3, 2);
+ sLinkTestLastBlockSendPos = sBlockSend.pos;
+ }
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ if (sLinkTestLastBlockRecvPos[i] != sBlockRecv[i].pos)
+ {
+ LinkTest_prnthex(sBlockRecv[i].pos, 2, i + 4, 2);
+ sLinkTestLastBlockRecvPos[i] = sBlockRecv[i].pos;
+ }
+ }
+ status = GetBlockReceivedStatus();
+ if (status == 0xF) // 0b1111
+ {
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ if ((status >> i) & 1)
+ {
+ gLinkTestBlockChecksums[i] = LinkTestCalcBlockChecksum(gBlockRecvBuffer[i], sBlockRecv[i].size);
+ ResetBlockReceivedFlag(i);
+ if (gLinkTestBlockChecksums[i] != 0x0342)
+ {
+ gLinkTestDebugValuesEnabled = FALSE;
+ gUnknown_020223BD = FALSE;
+ }
+ }
+ }
+ }
+}
+
+static void LinkTestProcessKeyInput(void)
+{
+ if (gMain.newKeys & A_BUTTON)
+ {
+ gShouldAdvanceLinkState = 1;
+ }
+ if (gMain.heldKeys & B_BUTTON)
+ {
+ InitBlockSend(gHeap + 0x4000, 0x00002004);
+ }
+ if (gMain.newKeys & L_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 16, 0, 2);
+ }
+ if (gMain.newKeys & START_BUTTON)
+ {
+ SetSuppressLinkErrorMessage(TRUE);
+ }
+ if (gMain.newKeys & R_BUTTON)
+ {
+ TrySavingData(1);
+ }
+ if (gMain.newKeys & SELECT_BUTTON)
+ {
+ sub_800AC34();
+ }
+ if (gLinkTestDebugValuesEnabled)
+ {
+ SetLinkDebugValues(gMain.vblankCounter2, gLinkCallback ? gLinkVSyncDisabled : gLinkVSyncDisabled | 0x10);
+ }
+}
+
+static void CB2_LinkTest(void)
+{
+ LinkTestProcessKeyInput();
+ TestBlockTransfer(1, 1, 0);
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+u16 LinkMain2(const u16 *heldKeys)
+{
+ u8 i;
+
+ if (!gLinkOpen)
+ {
+ return 0;
+ }
+ for (i = 0; i < 8; i++)
+ {
+ gSendCmd[i] = 0;
+ }
+ gLinkHeldKeys = *heldKeys;
+ if (gLinkStatus & LINK_STAT_CONN_ESTABLISHED)
+ {
+ ProcessRecvCmds(SIO_MULTI_CNT->id);
+ if (gLinkCallback != NULL)
+ {
+ gLinkCallback();
+ }
+ CheckErrorStatus();
+ }
+ return gLinkStatus;
+}
+
+static void HandleReceiveRemoteLinkPlayer(u8 who)
+{
+ int i;
+ int count;
+
+ count = 0;
+ gRemoteLinkPlayersNotReceived[who] = FALSE;
+ for (i = 0; i < GetLinkPlayerCount_2(); i++)
+ {
+ count += gRemoteLinkPlayersNotReceived[i];
+ }
+ if (count == 0 && gReceivedRemoteLinkPlayers == 0)
+ {
+ gReceivedRemoteLinkPlayers = 1;
+ }
+}
+
+static void ProcessRecvCmds(u8 unused)
+{
+ u16 i;
+
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ gLinkPartnersHeldKeys[i] = 0;
+ if (gRecvCmds[i][0] == 0)
+ {
+ continue;
+ }
+ switch (gRecvCmds[i][0])
+ {
+ case LINKCMD_SEND_LINK_TYPE:
+ {
+ struct LinkPlayerBlock *block;
+
+ InitLocalLinkPlayer();
+ block = &gLocalLinkPlayerBlock;
+ block->linkPlayer = gLocalLinkPlayer;
+ memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1);
+ memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1);
+ InitBlockSend(block, sizeof(*block));
+ break;
+ }
+ case LINKCMD_SEND_HELD_KEYS:
+ gLinkPartnersHeldKeys[i] = gRecvCmds[i][1];
+ break;
+ case LINKCMD_0x5555:
+ gUnknown_030030E8 = TRUE;
+ break;
+ case LINKCMD_0x5566:
+ gUnknown_030030E8 = TRUE;
+ break;
+ case LINKCMD_INIT_BLOCK:
+ {
+ struct BlockTransfer *blockRecv;
+
+ blockRecv = &sBlockRecv[i];
+ blockRecv->pos = 0;
+ blockRecv->size = gRecvCmds[i][1];
+ blockRecv->multiplayerId = gRecvCmds[i][2];
+ break;
+ }
+ case LINKCMD_CONT_BLOCK:
+ {
+ if (sBlockRecv[i].size > BLOCK_BUFFER_SIZE)
+ {
+ u16 *buffer;
+ u16 j;
+
+ buffer = (u16 *)gDecompressionBuffer;
+ for (j = 0; j < CMD_LENGTH - 1; j++)
+ {
+ buffer[(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1];
+ }
+ }
+ else
+ {
+ u16 j;
+
+ for (j = 0; j < CMD_LENGTH - 1; j++)
+ {
+ gBlockRecvBuffer[i][(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1];
+ }
+ }
+
+ sBlockRecv[i].pos += (CMD_LENGTH - 1) * 2;
+
+ if (sBlockRecv[i].pos >= sBlockRecv[i].size)
+ {
+ if (gRemoteLinkPlayersNotReceived[i] == TRUE)
+ {
+ struct LinkPlayerBlock *block;
+ struct LinkPlayer *linkPlayer;
+
+ block = (struct LinkPlayerBlock *)&gBlockRecvBuffer[i];
+ linkPlayer = &gLinkPlayers[i];
+ *linkPlayer = block->linkPlayer;
+ if ((linkPlayer->version & 0xFF) == VERSION_RUBY || (linkPlayer->version & 0xFF) == VERSION_SAPPHIRE)
+ {
+ linkPlayer->name[10] = 0;
+ linkPlayer->name[9] = 0;
+ linkPlayer->name[8] = 0;
+ }
+ sub_800B524(linkPlayer);
+ if (strcmp(block->magic1, gASCIIGameFreakInc) != 0
+ || strcmp(block->magic2, gASCIIGameFreakInc) != 0)
+ {
+ SetMainCallback2(CB2_LinkError);
+ }
+ else
+ {
+ HandleReceiveRemoteLinkPlayer(i);
+ }
+ }
+ else
+ {
+ SetBlockReceivedFlag(i);
+ }
+ }
+ }
+ break;
+ case LINKCMD_0x5FFF:
+ gUnknown_030030F0[i] = TRUE;
+ break;
+ case LINKCMD_0x2FFE:
+ gUnknown_030030EC[i] = TRUE;
+ break;
+ case LINKCMD_0xAAAA:
+ sub_800A418();
+ break;
+ case LINKCMD_0xCCCC:
+ SendBlock(0, gUnknown_082ED1A8[gRecvCmds[i][1]].address, gUnknown_082ED1A8[gRecvCmds[i][1]].size);
+ break;
+ case LINKCMD_SEND_HELD_KEYS_2:
+ gLinkPartnersHeldKeys[i] = gRecvCmds[i][1];
+ break;
+ }
+ }
+}
+
+static void BuildSendCmd(u16 command)
+{
+ switch (command)
+ {
+ case LINKCMD_SEND_LINK_TYPE:
+ gSendCmd[0] = LINKCMD_SEND_LINK_TYPE;
+ gSendCmd[1] = gLinkType;
+ break;
+ case LINKCMD_0x2FFE:
+ gSendCmd[0] = LINKCMD_0x2FFE;
+ break;
+ case LINKCMD_SEND_HELD_KEYS:
+ gSendCmd[0] = LINKCMD_SEND_HELD_KEYS;
+ gSendCmd[1] = gMain.heldKeys;
+ break;
+ case LINKCMD_0x5555:
+ gSendCmd[0] = LINKCMD_0x5555;
+ break;
+ case LINKCMD_0x6666:
+ gSendCmd[0] = LINKCMD_0x6666;
+ gSendCmd[1] = 0;
+ break;
+ case LINKCMD_0x7777:
+ {
+ u8 i;
+
+ gSendCmd[0] = LINKCMD_0x7777;
+ for (i = 0; i < 5; i++)
+ {
+ gSendCmd[i + 1] = 0xEE;
+ }
+ break;
+ }
+ case LINKCMD_INIT_BLOCK:
+ gSendCmd[0] = LINKCMD_INIT_BLOCK;
+ gSendCmd[1] = sBlockSend.size;
+ gSendCmd[2] = sBlockSend.multiplayerId + 0x80;
+ break;
+ case LINKCMD_0xAAAA:
+ gSendCmd[0] = LINKCMD_0xAAAA;
+ break;
+ case LINKCMD_0xAAAB:
+ gSendCmd[0] = LINKCMD_0xAAAB;
+ gSendCmd[1] = gSpecialVar_ItemId;
+ break;
+ case LINKCMD_0xCCCC:
+ gSendCmd[0] = LINKCMD_0xCCCC;
+ gSendCmd[1] = gBlockRequestType;
+ break;
+ case LINKCMD_0x5FFF:
+ gSendCmd[0] = LINKCMD_0x5FFF;
+ gSendCmd[1] = gUnknown_030030F4;
+ break;
+ case LINKCMD_0x5566:
+ gSendCmd[0] = LINKCMD_0x5566;
+ break;
+ case LINKCMD_SEND_HELD_KEYS_2:
+ if (gUnknown_03005DA8 == 0 || gLinkTransferringData)
+ {
+ break;
+ }
+ gSendCmd[0] = LINKCMD_SEND_HELD_KEYS_2;
+ gSendCmd[1] = gUnknown_03005DA8;
+ break;
+ }
+}
+
+void sub_8009F18(void)
+{
+ if (gWirelessCommType)
+ {
+ sub_800F804();
+ }
+ gLinkCallback = sub_8009F70;
+}
+
+bool32 sub_8009F3C(void)
+{
+ if (gWirelessCommType)
+ {
+ return sub_800F7E4();
+ }
+ if (gLinkCallback == sub_8009F70)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_8009F70(void)
+{
+ if (gReceivedRemoteLinkPlayers == TRUE)
+ {
+ BuildSendCmd(LINKCMD_SEND_HELD_KEYS_2);
+ }
+}
+
+void ClearLinkCallback(void)
+{
+ if (gWirelessCommType)
+ {
+ Rfu_set_zero();
+ }
+ else
+ {
+ gLinkCallback = NULL;
+ }
+}
+
+void ClearLinkCallback_2(void)
+{
+ if (gWirelessCommType)
+ {
+ Rfu_set_zero();
+ }
+ else
+ {
+ gLinkCallback = NULL;
+ }
+}
+
+u8 GetLinkPlayerCount(void)
+{
+ if (gWirelessCommType)
+ {
+ return sub_80104F4();
+ }
+ return EXTRACT_PLAYER_COUNT(gLinkStatus);
+}
+
+static int sub_8009FF8(u32 version1, u32 version2)
+{
+ int i;
+ u8 nPlayers;
+
+ nPlayers = GetLinkPlayerCount();
+ for (i = 0; i < nPlayers; i++)
+ {
+ if ((gLinkPlayers[i].version & 0xFF) == version1 || (gLinkPlayers[i].version & 0xFF) == version2)
+ {
+ return 1;
+ }
+ }
+ return -1;
+}
+
+u32 sub_800A03C(void)
+{
+ return 2;
+}
+
+bool32 sub_800A040(void)
+{
+ if (GetLinkPlayerCount() != 4 || sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) < 0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool32 sub_800A064(void)
+{
+ if (sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) >= 0)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool32 sub_800A07C(void)
+{
+ int i;
+
+ i = sub_8009FF8(VERSION_FIRE_RED, VERSION_LEAF_GREEN);
+ if (i >= 0 && gLinkPlayers[i].language == LANGUAGE_JAPANESE)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void OpenLinkTimed(void)
+{
+ sPlayerDataExchangeStatus = EXCHANGE_NOT_STARTED;
+ gLinkTimeOutCounter = 0;
+ OpenLink();
+}
+
+u8 GetLinkPlayerDataExchangeStatusTimed(int lower, int upper)
+{
+ int i;
+ int count;
+ u32 index;
+ u8 cmpVal;
+ u32 linkType1;
+ u32 linkType2;
+
+ count = 0;
+ if (gReceivedRemoteLinkPlayers == TRUE)
+ {
+ cmpVal = GetLinkPlayerCount_2();
+ if (lower > cmpVal || cmpVal > upper)
+ {
+ sPlayerDataExchangeStatus = EXCHANGE_STAT_6;
+ return 6;
+ }
+ else
+ {
+ if (GetLinkPlayerCount() == 0)
+ {
+ gLinkErrorOccurred = TRUE;
+ CloseLink();
+ }
+ for (i = 0, index = 0; i < GetLinkPlayerCount(); index++, i++)
+ {
+ if (gLinkPlayers[index].linkType == gLinkPlayers[0].linkType)
+ {
+ count++;
+ }
+ }
+ if (count == GetLinkPlayerCount())
+ {
+ if (gLinkPlayers[0].linkType == 0x1133)
+ {
+ switch (sub_807A728())
+ {
+ case 1:
+ sPlayerDataExchangeStatus = EXCHANGE_STAT_4;
+ break;
+ case 2:
+ sPlayerDataExchangeStatus = EXCHANGE_STAT_5;
+ break;
+ case 0:
+ sPlayerDataExchangeStatus = EXCHANGE_COMPLETE;
+ break;
+ }
+ }
+ else
+ {
+ sPlayerDataExchangeStatus = EXCHANGE_COMPLETE;
+ }
+ }
+ else
+ {
+ sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS;
+ linkType1 = gLinkPlayers[GetMultiplayerId()].linkType;
+ linkType2 = gLinkPlayers[GetMultiplayerId() ^ 1].linkType;
+ if ((linkType1 == 0x2266 && linkType2 == 0x2277) || (linkType1 == 0x2277 && linkType2 == 0x2266))
+ {
+ gSpecialVar_0x8005 = 3;
+ }
+ }
+ }
+ }
+ else if (++gLinkTimeOutCounter > 600)
+ {
+ sPlayerDataExchangeStatus = EXCHANGE_TIMED_OUT;
+ }
+ return sPlayerDataExchangeStatus;
+}
+
+bool8 IsLinkPlayerDataExchangeComplete(void)
+{
+ u8 i;
+ u8 count;
+ bool8 retval;
+
+ count = 0;
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ if (gLinkPlayers[i].linkType == gLinkPlayers[0].linkType)
+ {
+ count++;
+ }
+ }
+ if (count == GetLinkPlayerCount())
+ {
+ retval = TRUE;
+ sPlayerDataExchangeStatus = EXCHANGE_COMPLETE;
+ }
+ else
+ {
+ retval = FALSE;
+ sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS;
+ }
+ return retval;
+}
+
+u32 GetLinkPlayerTrainerId(u8 who)
+{
+ return gLinkPlayers[who].trainerId;
+}
+
+void ResetLinkPlayers(void)
+{
+ int i;
+
+ for (i = 0; i <= MAX_LINK_PLAYERS; i++)
+ {
+ gLinkPlayers[i] = (struct LinkPlayer){};
+ }
+}
+
+static void ResetBlockSend(void)
+{
+ sBlockSend.active = FALSE;
+ sBlockSend.pos = 0;
+ sBlockSend.size = 0;
+ sBlockSend.src = NULL;
+}
+
+static bool32 InitBlockSend(const void *src, size_t size)
+{
+ if (sBlockSend.active)
+ {
+ return FALSE;
+ }
+ sBlockSend.multiplayerId = GetMultiplayerId();
+ sBlockSend.active = TRUE;
+ sBlockSend.size = size;
+ sBlockSend.pos = 0;
+ if (size > 0x100)
+ {
+ sBlockSend.src = src;
+ }
+ else
+ {
+ if (src != gBlockSendBuffer)
+ {
+ memcpy(gBlockSendBuffer, src, size);
+ }
+ sBlockSend.src = gBlockSendBuffer;
+ }
+ BuildSendCmd(LINKCMD_INIT_BLOCK);
+ gLinkCallback = LinkCB_BlockSendBegin;
+ sBlockSendDelayCounter = 0;
+ return TRUE;
+}
+
+static void LinkCB_BlockSendBegin(void)
+{
+ if (++sBlockSendDelayCounter > 2)
+ {
+ gLinkCallback = LinkCB_BlockSend;
+ }
+}
+
+static void LinkCB_BlockSend(void)
+{
+ int i;
+ const u8 *src;
+
+ src = sBlockSend.src;
+ gSendCmd[0] = LINKCMD_CONT_BLOCK;
+ for (i = 0; i < 7; i++)
+ {
+ gSendCmd[i + 1] = (src[sBlockSend.pos + i * 2 + 1] << 8) | src[sBlockSend.pos + i * 2];
+ }
+ sBlockSend.pos += 14;
+ if (sBlockSend.size <= sBlockSend.pos)
+ {
+ sBlockSend.active = FALSE;
+ gLinkCallback = LinkCB_BlockSendEnd;
+ }
+}
+
+static void LinkCB_BlockSendEnd(void)
+{
+ gLinkCallback = NULL;
+}
+
+static void sub_800A3F8(void)
+{
+ GetMultiplayerId();
+ BuildSendCmd(LINKCMD_SEND_HELD_KEYS);
+ gUnknown_020223C0++;
+}
+
+void sub_800A418(void)
+{
+ gUnknown_020223C0 = 0;
+ if (gWirelessCommType)
+ {
+ sub_800F850();
+ }
+ else
+ {
+ gLinkCallback = sub_800A3F8;
+ }
+}
+
+u32 sub_800A44C(void)
+{
+ return gUnknown_020223C0;
+}
+
+void sub_800A458(void)
+{
+ BuildSendCmd(LINKCMD_0xAAAA);
+}
+
+u8 GetMultiplayerId(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ return rfu_get_multiplayer_id();
+ }
+ return SIO_MULTI_CNT->id;
+}
+
+u8 bitmask_all_link_players_but_self(void)
+{
+ u8 mpId;
+
+ mpId = GetMultiplayerId();
+ return ((1 << MAX_LINK_PLAYERS) - 1) ^ (1 << mpId);
+}
+
+bool8 SendBlock(u8 unused, const void *src, u16 size)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ return sub_800FE84(src, size);
+ }
+ return InitBlockSend(src, size);
+}
+
+bool8 sub_800A4D8(u8 a0)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ return sub_8010100(a0);
+ }
+ if (gLinkCallback == NULL)
+ {
+ gBlockRequestType = a0;
+ BuildSendCmd(LINKCMD_0xCCCC);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_800A520(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ return sub_8010500();
+ }
+ return gLinkCallback == NULL;
+}
+
+u8 GetBlockReceivedStatus(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ return sub_800FCD8();
+ }
+ return (gBlockReceivedStatus[3] << 3) | (gBlockReceivedStatus[2] << 2) | (gBlockReceivedStatus[1] << 1) | (gBlockReceivedStatus[0] << 0);
+}
+
+static void SetBlockReceivedFlag(u8 who)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ sub_800F6FC(who);
+ }
+ else
+ {
+ gBlockReceivedStatus[who] = TRUE;
+ }
+}
+
+void ResetBlockReceivedFlags(void)
+{
+ int i;
+
+ if (gWirelessCommType == TRUE)
+ {
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ sub_800F728(i);
+ }
+ }
+ else
+ {
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ gBlockReceivedStatus[i] = FALSE;
+ }
+ }
+}
+
+void ResetBlockReceivedFlag(u8 who)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ sub_800F728(who);
+ }
+ else if (gBlockReceivedStatus[who])
+ {
+ gBlockReceivedStatus[who] = FALSE;
+ }
+}
+
+void sub_800A620(void)
+{
+ if ((gLinkStatus & LINK_STAT_MASTER) && EXTRACT_PLAYER_COUNT(gLinkStatus) > 1)
+ {
+ gShouldAdvanceLinkState = 1;
+ }
+}
+
+static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size)
+{
+ u16 chksum;
+ u16 i;
+
+ chksum = 0;
+ for (i = 0; i < size / 2; i++)
+ {
+ chksum += src[i];
+ }
+ return chksum;
+}
+
+static void LinkTest_prnthexchar(char a0, u8 a1, u8 a2)
+{
+ u16 *vAddr;
+
+ vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock);
+ vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + 1 + gLinkTestBGInfo.dummy_8);
+}
+
+static void LinkTest_prntchar(char a0, u8 a1, u8 a2)
+{
+ u16 *vAddr;
+
+ vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock);
+ vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + gLinkTestBGInfo.dummy_8);
+}
+
+static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2)
+{
+ char sp[32 / 2];
+ int i;
+
+ for (i = 0; i < a2; i++)
+ {
+ sp[i] = pos & 0xf;
+ pos >>= 4;
+ }
+ for (i = a2 - 1; i >= 0; i--)
+ {
+ LinkTest_prnthexchar(sp[i], a0, a1);
+ a0++;
+ }
+}
+
+static void LinkTest_prntint(int a0, u8 a1, u8 a2, u8 a3)
+{
+ char sp[32 / 2];
+ int sp10;
+ int i;
+
+ sp10 = -1;
+ if (a0 < 0)
+ {
+ sp10 = a1;
+ a0 = -a0;
+ }
+ for (i = 0; i < a3; i++)
+ {
+ sp[i] = a0 % 10;
+ a0 /= 10;
+ }
+ for (i = a3 - 1; i >= 0; i--)
+ {
+ LinkTest_prnthexchar(sp[i], a1, a2);
+ a1++;
+ }
+ if (sp10 != -1)
+ {
+ LinkTest_prnthexchar(*"\n", sp10, a2);
+ }
+}
+
+static void LinkTest_prntstr(const char *a0, u8 a1, u8 a2)
+{
+ int r6;
+ int i;
+ int r5;
+
+ r5 = 0;
+ r6 = 0;
+ for (i = 0; a0[i] != 0; a0++)
+ {
+ if (a0[i] == *"\n")
+ {
+ r5++;
+ r6 = 0;
+ }
+ else
+ {
+ LinkTest_prntchar(a0[i], a1 + r6, a2 + r5);
+ r6++;
+ }
+ }
+}
+
+static void LinkCB_RequestPlayerDataExchange(void)
+{
+ if (gLinkStatus & LINK_STAT_MASTER)
+ {
+ BuildSendCmd(LINKCMD_SEND_LINK_TYPE);
+ }
+ gLinkCallback = NULL;
+}
+
+static void Task_PrintTestData(u8 taskId)
+{
+ char sp[32];
+ int i;
+
+ strcpy(sp, gASCIITestPrint);
+ LinkTest_prntstr(sp, 5, 2);
+ LinkTest_prnthex(gShouldAdvanceLinkState, 2, 1, 2);
+ LinkTest_prnthex(gLinkStatus, 15, 1, 8);
+ LinkTest_prnthex(gLink.state, 2, 10, 2);
+ LinkTest_prnthex(EXTRACT_PLAYER_COUNT(gLinkStatus), 15, 10, 2);
+ LinkTest_prnthex(GetMultiplayerId(), 15, 12, 2);
+ LinkTest_prnthex(gLastSendQueueCount, 25, 1, 2);
+ LinkTest_prnthex(gLastRecvQueueCount, 25, 2, 2);
+ LinkTest_prnthex(GetBlockReceivedStatus(), 15, 5, 2);
+ LinkTest_prnthex(gLinkDebugSeed, 2, 12, 8);
+ LinkTest_prnthex(gLinkDebugFlags, 2, 13, 8);
+ LinkTest_prnthex(GetSioMultiSI(), 25, 5, 1);
+ LinkTest_prnthex(IsSioMultiMaster(), 25, 6, 1);
+ LinkTest_prnthex(IsLinkConnectionEstablished(), 25, 7, 1);
+ LinkTest_prnthex(HasLinkErrorOccurred(), 25, 8, 1);
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ LinkTest_prnthex(gLinkTestBlockChecksums[i], 10, 4 + i, 4);
+ }
+}
+
+void SetLinkDebugValues(u32 seed, u32 flags)
+{
+ gLinkDebugSeed = seed;
+ gLinkDebugFlags = flags;
+}
+
+u8 sub_800A9A8(void)
+{
+ int i;
+ u8 flags;
+
+ flags = 0;
+ for (i = 0; i < gSavedLinkPlayerCount; i++)
+ {
+ flags |= (1 << i);
+ }
+ return flags;
+}
+
+u8 sub_800A9D8(void)
+{
+ int i;
+ u8 flags;
+
+ flags = 0;
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ flags |= (1 << i);
+ }
+ return flags;
+}
+
+void sub_800AA04(u8 a0)
+{
+ int i;
+
+ gSavedLinkPlayerCount = a0;
+ gSavedMultiplayerId = GetMultiplayerId();
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ gSavedLinkPlayers[i] = gLinkPlayers[i];
+ }
+}
+
+u8 sub_800AA48(void)
+{
+ return gSavedLinkPlayerCount;
+}
+
+u8 sub_800AA54(void)
+{
+ return gSavedMultiplayerId;
+}
+
+bool8 sub_800AA60(void)
+{
+ int i;
+ unsigned count;
+
+ count = 0;
+ for (i = 0; i < gSavedLinkPlayerCount; i++)
+ {
+ if (gLinkPlayers[i].trainerId == gSavedLinkPlayers[i].trainerId)
+ {
+ if (gLinkType == 0x2288)
+ {
+ if (gLinkType == gLinkPlayers[i].linkType)
+ {
+ count++;
+ }
+ }
+ else
+ {
+ count++;
+ }
+ }
+ }
+ if (count == gSavedLinkPlayerCount)
+ {
+ if (GetLinkPlayerCount_2() == gSavedLinkPlayerCount)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_800AAF4(void)
+{
+ int i;
+
+ // Clearly not what was meant to be written, but here it is anyway.
+ for (i = 0; i < 4; i++)
+ {
+ CpuSet(&gSavedLinkPlayers[i], NULL, sizeof(struct LinkPlayer));
+ }
+}
+
+void sub_800AB18(void)
+{
+ u8 i;
+
+ for (i = 0; i < gSavedLinkPlayerCount; i++)
+ {
+ if (gSavedLinkPlayers[i].trainerId != gLinkPlayers[i].trainerId || StringCompare(gSavedLinkPlayers[i].name, gLinkPlayers[i].name) != 0)
+ {
+ gLinkErrorOccurred = TRUE;
+ CloseLink();
+ SetMainCallback2(CB2_LinkError);
+ }
+ }
+}
+
+void sub_800AB98(void)
+{
+ gSavedLinkPlayerCount = 0;
+ gSavedMultiplayerId = 0;
+}
+
+u8 GetLinkPlayerCount_2(void)
+{
+ return EXTRACT_PLAYER_COUNT(gLinkStatus);
+}
+
+bool8 IsLinkMaster(void)
+{
+ if (gWirelessCommType)
+ {
+ return Rfu_IsMaster();
+ }
+ return EXTRACT_MASTER(gLinkStatus);
+}
+
+u8 sub_800ABE8(void)
+{
+ return gUnknown_03000D58;
+}
+
+void sub_800ABF4(u16 a0)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ }
+ else
+ {
+ if (gLinkCallback == NULL)
+ {
+ gLinkCallback = sub_800AC80;
+ gUnknown_030030E4 = FALSE;
+ gUnknown_030030F4 = a0;
+ }
+ }
+}
+
+void sub_800AC34(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ }
+ else
+ {
+ if (gLinkCallback != NULL)
+ {
+ gUnknown_02022B08++;
+ }
+ else
+ {
+ gLinkCallback = sub_800AC80;
+ gUnknown_030030E4 = FALSE;
+ gUnknown_030030F4 = 0;
+ }
+ }
+}
+
+static void sub_800AC80(void)
+{
+ if (gLastRecvQueueCount == 0)
+ {
+ BuildSendCmd(LINKCMD_0x5FFF);
+ gLinkCallback = sub_800ACAC;
+ }
+}
+
+static void sub_800ACAC(void)
+{
+ int i;
+ unsigned count;
+ u8 linkPlayerCount;
+
+ linkPlayerCount = GetLinkPlayerCount();
+ count = 0;
+ for (i = 0; i < linkPlayerCount; i++)
+ {
+ if (gUnknown_030030F0[i])
+ {
+ count++;
+ }
+ }
+ if (count == linkPlayerCount)
+ {
+ gBattleTypeFlags &= ~BATTLE_TYPE_20;
+ gLinkVSyncDisabled = TRUE;
+ CloseLink();
+ gLinkCallback = NULL;
+ gUnknown_030030E4 = TRUE;
+ }
+}
+
+void sub_800AD10(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ }
+ else
+ {
+ if (gLinkCallback != NULL)
+ {
+ gUnknown_02022B08++;
+ }
+ else
+ {
+ gLinkCallback = sub_800AD5C;
+ gUnknown_030030E4 = FALSE;
+ gUnknown_030030F4 = 0;
+ }
+ }
+}
+
+static void sub_800AD5C(void)
+{
+ if (gLastRecvQueueCount == 0)
+ {
+ BuildSendCmd(LINKCMD_0x5FFF);
+ gLinkCallback = sub_800AD88;
+ }
+}
+
+static void sub_800AD88(void)
+{
+ int i;
+ unsigned count;
+ u8 linkPlayerCount;
+
+ linkPlayerCount = GetLinkPlayerCount();
+ count = 0;
+ for (i = 0; i < linkPlayerCount; i++)
+ {
+ if (gLinkPlayers[i].language == LANGUAGE_JAPANESE)
+ {
+ count++;
+ }
+ else if (gUnknown_030030F0[i])
+ {
+ count++;
+ }
+ }
+ if (count == linkPlayerCount)
+ {
+ gBattleTypeFlags &= ~BATTLE_TYPE_20;
+ gLinkVSyncDisabled = TRUE;
+ CloseLink();
+ gLinkCallback = NULL;
+ gUnknown_030030E4 = TRUE;
+ }
+}
+
+void sub_800ADF8(void)
+{
+ if (gWirelessCommType == TRUE)
+ {
+ sub_8010434();
+ }
+ else
+ {
+ if (gLinkCallback == NULL)
+ {
+ gLinkCallback = sub_800AE30;
+ }
+ gUnknown_030030E4 = FALSE;
+ }
+}
+
+static void sub_800AE30(void)
+{
+ if (gLastRecvQueueCount == 0)
+ {
+ BuildSendCmd(LINKCMD_0x2FFE);
+ gLinkCallback = sub_800AE5C;
+ }
+}
+
+static void sub_800AE5C(void)
+{
+ u8 i;
+ u8 linkPlayerCount;
+
+ linkPlayerCount = GetLinkPlayerCount();
+ for (i = 0; i < linkPlayerCount; i++)
+ {
+ if (!gUnknown_030030EC[i])
+ {
+ break;
+ }
+ }
+ if (i == linkPlayerCount)
+ {
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ gUnknown_030030EC[i] = FALSE;
+ }
+ gLinkCallback = NULL;
+ }
+}
+
+static void CheckErrorStatus(void)
+{
+ if (gLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus))
+ {
+ if (!gSuppressLinkErrorMessage)
+ {
+ sLinkErrorBuffer.status = gLinkStatus;
+ sLinkErrorBuffer.lastRecvQueueCount = gLastRecvQueueCount;
+ sLinkErrorBuffer.lastSendQueueCount = gLastSendQueueCount;
+ SetMainCallback2(CB2_LinkError);
+ }
+ gLinkErrorOccurred = TRUE;
+ CloseLink();
+ }
+}
+
+void sub_800AF18(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, u8 unk_06)
+{
+ sLinkErrorBuffer.status = status;
+ sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount;
+ sLinkErrorBuffer.lastRecvQueueCount = lastRecvQueueCount;
+ sLinkErrorBuffer.unk_06 = unk_06;
+}
+
+void CB2_LinkError(void)
+{
+ u8 *tilemapBuffer;
+
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ m4aMPlayStop(&gMPlayInfo_SE1);
+ m4aMPlayStop(&gMPlayInfo_SE2);
+ m4aMPlayStop(&gMPlayInfo_SE3);
+ InitHeap(gHeap, HEAP_SIZE);
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetPaletteFadeControl();
+ FillPalette(0, 0, 2);
+ ResetTasks();
+ ScanlineEffect_Stop();
+ if (gWirelessCommType)
+ {
+ if (!sLinkErrorBuffer.unk_06)
+ {
+ gWirelessCommType = 3;
+ }
+ sub_800E604();
+ }
+ SetVBlankCallback(sub_80096BC);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_082ED1FC, 2);
+ gUnknown_02022B0C = tilemapBuffer = malloc(0x800);
+ SetBgTilemapBuffer(1, tilemapBuffer);
+ if (InitWindows(gUnknown_082ED204))
+ {
+ DeactivateAllTextPrinters();
+ reset_temp_tile_data_buffers();
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON);
+ LoadPalette(gUnknown_0860F074, 0xf0, 0x20);
+ gSoftResetDisabled = FALSE;
+ CreateTask(Task_DestroySelf, 0);
+ StopMapMusic();
+ gMain.callback1 = NULL;
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ SetMainCallback2(CB2_PrintErrorMessage);
+ }
+}
+
+static void sub_800B080(void)
+{
+ LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0);
+ copy_decompressed_tile_data_to_vram_autofree(1, gWirelessLinkDisplayGfx, FALSE, 0, 0);
+ CopyToBgTilemapBuffer(1, gWirelessLinkDisplayTilemap, 0, 0);
+ CopyBgTilemapBufferToVram(1);
+ LoadPalette(gWirelessLinkDisplayPal, 0, 0x20);
+ FillWindowPixelBuffer(0, 0x00);
+ FillWindowPixelBuffer(2, 0x00);
+ box_print(0, 3, 2, 6, gUnknown_082ED224, 0, gText_CommErrorEllipsis);
+ box_print(2, 3, 2, 1, gUnknown_082ED224, 0, gText_MoveCloserToLinkPartner);
+ PutWindowTilemap(0);
+ PutWindowTilemap(2);
+ CopyWindowToVram(0, 0);
+ CopyWindowToVram(2, 3);
+}
+
+static void sub_800B138(void)
+{
+ LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0);
+ FillWindowPixelBuffer(1, 0x00);
+ FillWindowPixelBuffer(2, 0x00);
+ box_print(1, 3, 2, 0, gUnknown_082ED224, 0, gText_CommErrorCheckConnections);
+ PutWindowTilemap(1);
+ PutWindowTilemap(2);
+ CopyWindowToVram(1, 0);
+ CopyWindowToVram(2, 3);
+}
+
+static void CB2_PrintErrorMessage(void)
+{
+ switch (gMain.state)
+ {
+ case 00:
+ if (sLinkErrorBuffer.unk_06)
+ {
+ sub_800B080();
+ }
+ else
+ {
+ sub_800B138();
+ }
+ break;
+ case 02:
+ ShowBg(0);
+ if (sLinkErrorBuffer.unk_06)
+ {
+ ShowBg(1);
+ }
+ break;
+ case 30:
+ PlaySE(SE_BOO);
+ break;
+ case 60:
+ PlaySE(SE_BOO);
+ break;
+ case 90:
+ PlaySE(SE_BOO);
+ break;
+ case 130:
+ if (gWirelessCommType == 2)
+ {
+ box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnTitleScreen);
+ }
+ else if (gWirelessCommType == 1)
+ {
+ box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnRegistrationCounter);
+ }
+ break;
+ }
+ if (gMain.state == 160)
+ {
+ if (gWirelessCommType == 1)
+ {
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_PIN);
+ gWirelessCommType = 0;
+ sLinkErrorBuffer.unk_06 = 0;
+ sub_81700F8();
+ }
+ }
+ else if (gWirelessCommType == 2)
+ {
+ if (gMain.newKeys & A_BUTTON)
+ {
+ rfu_REQ_stopMode();
+ rfu_waitREQComplete();
+ DoSoftReset();
+ }
+ }
+ }
+ if (gMain.state != 160)
+ {
+ gMain.state++;
+ }
+}
+
+// TODO: there might be a file boundary here, let's name it
+
+bool8 GetSioMultiSI(void)
+{
+ return (REG_SIOCNT & 0x04) != 0;
+}
+
+static bool8 IsSioMultiMaster(void)
+{
+ return (REG_SIOCNT & 0x8) && !(REG_SIOCNT & 0x04);
+}
+
+bool8 IsLinkConnectionEstablished(void)
+{
+ return EXTRACT_CONN_ESTABLISHED(gLinkStatus);
+}
+
+void SetSuppressLinkErrorMessage(bool8 flag)
+{
+ gSuppressLinkErrorMessage = flag;
+}
+
+bool8 HasLinkErrorOccurred(void)
+{
+ return gLinkErrorOccurred;
+}
+
+void sub_800B348(void)
+{
+ struct LinkPlayerBlock *block;
+
+ InitLocalLinkPlayer();
+ block = &gLocalLinkPlayerBlock;
+ block->linkPlayer = gLocalLinkPlayer;
+ memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1);
+ memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1);
+ memcpy(gBlockSendBuffer, block, sizeof(*block));
+}
+
+void sub_800B3A4(u32 who)
+{
+ u8 who_ = who;
+ struct LinkPlayerBlock *block;
+ struct LinkPlayer *player;
+
+ block = (struct LinkPlayerBlock *)gBlockRecvBuffer[who_];
+ player = &gLinkPlayers[who_];
+ *player = block->linkPlayer;
+ sub_800B524(player);
+ if (strcmp(block->magic1, gASCIIGameFreakInc) != 0 || strcmp(block->magic2, gASCIIGameFreakInc) != 0)
+ {
+ SetMainCallback2(CB2_LinkError);
+ }
+}
+
+bool8 HandleLinkConnection(void)
+{
+ bool32 r4;
+ bool32 r5;
+
+ if (gWirelessCommType == 0)
+ {
+ gLinkStatus = LinkMain1(&gShouldAdvanceLinkState, gSendCmd, gRecvCmds);
+ LinkMain2(&gMain.heldKeys);
+ if ((gLinkStatus & LINK_STAT_RECEIVED_NOTHING) && sub_808766C() == TRUE)
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ r4 = sub_8010EC0();
+ r5 = sub_8010F1C();
+ if (sub_808766C() == TRUE)
+ {
+ if (r4 == TRUE || sub_800F0B8() || r5)
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void sub_800B488(void)
+{
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gWirelessCommType = 1;
+ }
+}
+
+static void sub_800B4A4(void)
+{
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gWirelessCommType = 0;
+ }
+}
+
+void sub_800B4C0(void)
+{
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gWirelessCommType = 0;
+ }
+}
+
+u32 sub_800B4DC(void)
+{
+ if (gWirelessCommType != 0)
+ {
+ return sub_80124D4();
+ }
+ return gLink.recvQueue.count;
+}
+
+bool8 sub_800B504(void)
+{
+ if (sub_800B4DC() > 2)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+u8 sub_800B518(void)
+{
+ return gWirelessCommType;
+}
+
+void sub_800B524(struct LinkPlayer *player)
+{
+ player->name[10] = player->name[8];
+ ConvertInternationalString(player->name, player->language);
+}
+
+static void DisableSerial(void)
+{
+ DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ REG_SIOCNT = SIO_MULTI_MODE;
+ REG_TMCNT_H(3) = 0;
+ REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL;
+ REG_SIOMLT_SEND = 0;
+ REG_SIOMLT_RECV = 0;
+ CpuFill32(0, &gLink, sizeof(gLink));
+}
+
+static void EnableSerial(void)
+{
+ DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ REG_RCNT = 0;
+ REG_SIOCNT = SIO_MULTI_MODE;
+ REG_SIOCNT |= SIO_115200_BPS | SIO_INTR_ENABLE;
+ EnableInterrupts(INTR_FLAG_SERIAL);
+ REG_SIOMLT_SEND = 0;
+ CpuFill32(0, &gLink, sizeof(gLink));
+ sNumVBlanksWithoutSerialIntr = 0;
+ sSendNonzeroCheck = 0;
+ sRecvNonzeroCheck = 0;
+ sChecksumAvailable = 0;
+ sHandshakePlayerCount = 0;
+ gLastSendQueueCount = 0;
+ gLastRecvQueueCount = 0;
+}
+
+void ResetSerial(void)
+{
+ EnableSerial();
+ DisableSerial();
+}
+
+// link_main1.c
+
+u32 LinkMain1(u8 *shouldAdvanceLinkState, u16 *sendCmd, u16 (*recvCmds)[CMD_LENGTH])
+{
+ u32 retVal;
+ u32 retVal2;
+
+ switch (gLink.state)
+ {
+ case LINK_STATE_START0:
+ DisableSerial();
+ gLink.state = 1;
+ break;
+ case LINK_STATE_START1:
+ if (*shouldAdvanceLinkState == 1)
+ {
+ EnableSerial();
+ gLink.state = 2;
+ }
+ break;
+ case LINK_STATE_HANDSHAKE:
+ switch (*shouldAdvanceLinkState)
+ {
+ default:
+ CheckMasterOrSlave();
+ break;
+ case 1:
+ if (gLink.isMaster == LINK_MASTER && gLink.playerCount > 1)
+ {
+ gLink.handshakeAsMaster = TRUE;
+ }
+ break;
+ case 2:
+ gLink.state = LINK_STATE_START0;
+ REG_SIOMLT_SEND = 0;
+ break;
+ }
+ break;
+ case LINK_STATE_INIT_TIMER:
+ InitTimer();
+ gLink.state = LINK_STATE_CONN_ESTABLISHED;
+ // fallthrough
+ case LINK_STATE_CONN_ESTABLISHED:
+ EnqueueSendCmd(sendCmd);
+ DequeueRecvCmds(recvCmds);
+ break;
+ }
+ *shouldAdvanceLinkState = 0;
+ retVal = gLink.localId;
+ retVal |= (gLink.playerCount << LINK_STAT_PLAYER_COUNT_SHIFT);
+ if (gLink.isMaster == LINK_MASTER)
+ {
+ retVal |= LINK_STAT_MASTER;
+ }
+ {
+ u32 receivedNothing = gLink.receivedNothing << LINK_STAT_RECEIVED_NOTHING_SHIFT;
+ u32 link_field_F = gLink.link_field_F << LINK_STAT_UNK_FLAG_9_SHIFT;
+ u32 hardwareError = gLink.hardwareError << LINK_STAT_ERROR_HARDWARE_SHIFT;
+ u32 badChecksum = gLink.badChecksum << LINK_STAT_ERROR_CHECKSUM_SHIFT;
+ u32 queueFull = gLink.queueFull << LINK_STAT_ERROR_QUEUE_FULL_SHIFT;
+ u32 val;
+
+ if (gLink.state == LINK_STATE_CONN_ESTABLISHED)
+ {
+ val = LINK_STAT_CONN_ESTABLISHED;
+ val |= receivedNothing;
+ val |= retVal;
+ val |= link_field_F;
+ val |= hardwareError;
+ val |= badChecksum;
+ val |= queueFull;
+ }
+ else
+ {
+ val = retVal;
+ val |= receivedNothing;
+ val |= link_field_F;
+ val |= hardwareError;
+ val |= badChecksum;
+ val |= queueFull;
+ }
+
+ retVal = val;
+ }
+
+ if (gLink.lag == LAG_MASTER)
+ {
+ retVal |= LINK_STAT_ERROR_LAG_MASTER;
+ }
+
+ if (gLink.localId >= MAX_LINK_PLAYERS)
+ {
+ retVal |= LINK_STAT_ERROR_INVALID_ID;
+ }
+
+ retVal2 = retVal;
+ if (gLink.lag == LAG_SLAVE)
+ {
+ retVal2 |= LINK_STAT_ERROR_LAG_SLAVE;
+ }
+
+ return retVal2;
+}
+
+static void CheckMasterOrSlave(void)
+{
+ u32 terminals;
+
+ terminals = *(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SD | SIO_MULTI_SI);
+ if (terminals == SIO_MULTI_SD && gLink.localId == 0)
+ {
+ gLink.isMaster = LINK_MASTER;
+ }
+ else
+ {
+ gLink.isMaster = LINK_SLAVE;
+ }
+}
+
+static void InitTimer(void)
+{
+ if (gLink.isMaster)
+ {
+ REG_TM3CNT_L = -197;
+ REG_TM3CNT_H = TIMER_64CLK | TIMER_INTR_ENABLE;
+ EnableInterrupts(INTR_FLAG_TIMER3);
+ }
+}
+
+static void EnqueueSendCmd(u16 *sendCmd)
+{
+ u8 i;
+ u8 offset;
+
+ gLinkSavedIme = REG_IME;
+ REG_IME = 0;
+ if (gLink.sendQueue.count < QUEUE_CAPACITY)
+ {
+ offset = gLink.sendQueue.pos + gLink.sendQueue.count;
+ if (offset >= QUEUE_CAPACITY)
+ {
+ offset -= QUEUE_CAPACITY;
+ }
+ for (i = 0; i < CMD_LENGTH; i++)
+ {
+ sSendNonzeroCheck |= *sendCmd;
+ gLink.sendQueue.data[i][offset] = *sendCmd;
+ *sendCmd = 0;
+ sendCmd++;
+ }
+ }
+ else
+ {
+ gLink.queueFull = QUEUE_FULL_SEND;
+ }
+ if (sSendNonzeroCheck)
+ {
+ gLink.sendQueue.count++;
+ sSendNonzeroCheck = 0;
+ }
+ REG_IME = gLinkSavedIme;
+ gLastSendQueueCount = gLink.sendQueue.count;
+}
+
+
+static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH])
+{
+ u8 i;
+ u8 j;
+
+ gLinkSavedIme = REG_IME;
+ REG_IME = 0;
+ if (gLink.recvQueue.count == 0)
+ {
+ for (i = 0; i < gLink.playerCount; i++)
+ {
+ for (j = 0; j < CMD_LENGTH; j++)
+ {
+ recvCmds[i][j] = 0;
+ }
+ }
+
+ gLink.receivedNothing = TRUE;
+ }
+ else
+ {
+ for (i = 0; i < gLink.playerCount; i++)
+ {
+ for (j = 0; j < CMD_LENGTH; j++)
+ {
+ recvCmds[i][j] = gLink.recvQueue.data[i][j][gLink.recvQueue.pos];
+ }
+ }
+ gLink.recvQueue.count--;
+ gLink.recvQueue.pos++;
+ if (gLink.recvQueue.pos >= QUEUE_CAPACITY)
+ {
+ gLink.recvQueue.pos = 0;
+ }
+ gLink.receivedNothing = FALSE;
+ }
+ REG_IME = gLinkSavedIme;
+}
+
+// link_intr.c
+
+void LinkVSync(void)
+{
+ if (gLink.isMaster)
+ {
+ switch (gLink.state)
+ {
+ case LINK_STATE_CONN_ESTABLISHED:
+ if (gLink.serialIntrCounter < 9)
+ {
+ if (gLink.hardwareError != TRUE)
+ {
+ gLink.lag = LAG_MASTER;
+ }
+ else
+ {
+ StartTransfer();
+ }
+ }
+ else if (gLink.lag != LAG_MASTER)
+ {
+ gLink.serialIntrCounter = 0;
+ StartTransfer();
+ }
+ break;
+ case LINK_STATE_HANDSHAKE:
+ StartTransfer();
+ break;
+ }
+ }
+ else if (gLink.state == LINK_STATE_CONN_ESTABLISHED || gLink.state == LINK_STATE_HANDSHAKE)
+ {
+ if (++sNumVBlanksWithoutSerialIntr > 10)
+ {
+ if (gLink.state == LINK_STATE_CONN_ESTABLISHED)
+ {
+ gLink.lag = LAG_SLAVE;
+ }
+ if (gLink.state == LINK_STATE_HANDSHAKE)
+ {
+ gLink.playerCount = 0;
+ gLink.link_field_F = FALSE;
+ }
+ }
+ }
+}
+
+void Timer3Intr(void)
+{
+ StopTimer();
+ StartTransfer();
+}
+
+void SerialCB(void)
+{
+ gLink.localId = SIO_MULTI_CNT->id;
+ switch (gLink.state)
+ {
+ case LINK_STATE_CONN_ESTABLISHED:
+ gLink.hardwareError = SIO_MULTI_CNT->error;
+ DoRecv();
+ DoSend();
+ SendRecvDone();
+ break;
+ case LINK_STATE_HANDSHAKE:
+ if (DoHandshake())
+ {
+ if (gLink.isMaster)
+ {
+ gLink.state = LINK_STATE_INIT_TIMER;
+ gLink.serialIntrCounter = 8;
+ }
+ else
+ {
+ gLink.state = LINK_STATE_CONN_ESTABLISHED;
+ }
+ }
+ break;
+ }
+ gLink.serialIntrCounter++;
+ sNumVBlanksWithoutSerialIntr = 0;
+ if (gLink.serialIntrCounter == 8)
+ {
+ gLastRecvQueueCount = gLink.recvQueue.count;
+ }
+}
+
+static void StartTransfer(void)
+{
+ REG_SIOCNT |= SIO_START;
+}
+
+static bool8 DoHandshake(void)
+{
+ u8 i;
+ u8 playerCount;
+ u16 minRecv;
+
+ playerCount = 0;
+ minRecv = 0xFFFF;
+ if (gLink.handshakeAsMaster == TRUE)
+ {
+ REG_SIOMLT_SEND = MASTER_HANDSHAKE;
+ }
+ else
+ {
+ REG_SIOMLT_SEND = SLAVE_HANDSHAKE;
+ }
+ *(u64 *)gLink.tempRecvBuffer = REG_SIOMLT_RECV;
+ REG_SIOMLT_RECV = 0;
+ gLink.handshakeAsMaster = FALSE;
+ for (i = 0; i < 4; i++)
+ {
+ if ((gLink.tempRecvBuffer[i] & ~0x3) == SLAVE_HANDSHAKE || gLink.tempRecvBuffer[i] == MASTER_HANDSHAKE)
+ {
+ playerCount++;
+ if (minRecv > gLink.tempRecvBuffer[i] && gLink.tempRecvBuffer[i] != 0)
+ {
+ minRecv = gLink.tempRecvBuffer[i];
+ }
+ }
+ else
+ {
+ if (gLink.tempRecvBuffer[i] != 0xFFFF)
+ {
+ playerCount = 0;
+ }
+ break;
+ }
+ }
+ gLink.playerCount = playerCount;
+ if (gLink.playerCount > 1 && gLink.playerCount == sHandshakePlayerCount && gLink.tempRecvBuffer[0] == MASTER_HANDSHAKE)
+ {
+ return TRUE;
+ }
+ if (gLink.playerCount > 1)
+ {
+ gLink.link_field_F = (minRecv & 3) + 1;
+ }
+ else
+ {
+ gLink.link_field_F = 0;
+ }
+ sHandshakePlayerCount = gLink.playerCount;
+ return FALSE;
+}
+
+static void DoRecv(void)
+{
+ u16 recv[4];
+ u8 i;
+ u8 index;
+
+ *(u64 *)recv = REG_SIOMLT_RECV;
+ if (gLink.sendCmdIndex == 0)
+ {
+ for (i = 0; i < gLink.playerCount; i++)
+ {
+ if (gLink.checksum != recv[i] && sChecksumAvailable)
+ {
+ gLink.badChecksum = TRUE;
+ }
+ }
+ gLink.checksum = 0;
+ sChecksumAvailable = TRUE;
+ }
+ else
+ {
+ index = gLink.recvQueue.pos + gLink.recvQueue.count;
+ if (index >= QUEUE_CAPACITY)
+ {
+ index -= QUEUE_CAPACITY;
+ }
+ if (gLink.recvQueue.count < QUEUE_CAPACITY)
+ {
+ for (i = 0; i < gLink.playerCount; i++)
+ {
+ gLink.checksum += recv[i];
+ sRecvNonzeroCheck |= recv[i];
+ gLink.recvQueue.data[i][gLink.recvCmdIndex][index] = recv[i];
+ }
+ }
+ else
+ {
+ gLink.queueFull = QUEUE_FULL_RECV;
+ }
+ gLink.recvCmdIndex++;
+ if (gLink.recvCmdIndex == CMD_LENGTH && sRecvNonzeroCheck)
+ {
+ gLink.recvQueue.count++;
+ sRecvNonzeroCheck = 0;
+ }
+ }
+}
+
+static void DoSend(void)
+{
+ if (gLink.sendCmdIndex == CMD_LENGTH)
+ {
+ REG_SIOMLT_SEND = gLink.checksum;
+ if (!sSendBufferEmpty)
+ {
+ gLink.sendQueue.count--;
+ gLink.sendQueue.pos++;
+ if (gLink.sendQueue.pos >= QUEUE_CAPACITY)
+ {
+ gLink.sendQueue.pos = 0;
+ }
+ }
+ else
+ {
+ sSendBufferEmpty = FALSE;
+ }
+ }
+ else
+ {
+ if (!sSendBufferEmpty && gLink.sendQueue.count == 0)
+ {
+ sSendBufferEmpty = TRUE;
+ }
+ if (sSendBufferEmpty)
+ {
+ REG_SIOMLT_SEND = 0;
+ }
+ else
+ {
+ REG_SIOMLT_SEND = gLink.sendQueue.data[gLink.sendCmdIndex][gLink.sendQueue.pos];
+ }
+ gLink.sendCmdIndex++;
+ }
+}
+
+static void StopTimer(void)
+{
+ if (gLink.isMaster)
+ {
+ REG_TM3CNT_H &= ~TIMER_ENABLE;
+ REG_TM3CNT_L = -197;
+ }
+}
+
+static void SendRecvDone(void)
+{
+ if (gLink.recvCmdIndex == CMD_LENGTH)
+ {
+ gLink.sendCmdIndex = 0;
+ gLink.recvCmdIndex = 0;
+ }
+ else if (gLink.isMaster)
+ {
+ REG_TM3CNT_H |= TIMER_ENABLE;
+ }
+}
+
+void ResetSendBuffer(void)
+{
+ u8 i;
+ u8 j;
+
+ gLink.sendQueue.count = 0;
+ gLink.sendQueue.pos = 0;
+ for (i = 0; i < CMD_LENGTH; i++)
+ {
+ for (j = 0; j < QUEUE_CAPACITY; j++)
+ {
+ gLink.sendQueue.data[i][j] = 0xEFFF;
+ }
+ }
+}
+
+void ResetRecvBuffer(void)
+{
+ u8 i;
+ u8 j;
+ u8 k;
+
+ gLink.recvQueue.count = 0;
+ gLink.recvQueue.pos = 0;
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
+ {
+ for (j = 0; j < CMD_LENGTH; j++)
+ {
+ for (k = 0; k < QUEUE_CAPACITY; k++)
+ {
+ gLink.recvQueue.data[i][j][k] = 0xEFFF;
+ }
+ }
+ }
+}
diff --git a/src/link_rfu.c b/src/link_rfu.c
new file mode 100644
index 000000000..186d54fd3
--- /dev/null
+++ b/src/link_rfu.c
@@ -0,0 +1,4940 @@
+
+// Includes
+#include "global.h"
+#include "malloc.h"
+#include "battle.h"
+#include "berry_blender.h"
+#include "task.h"
+#include "random.h"
+#include "decompress.h"
+#include "text.h"
+#include "string_util.h"
+#include "event_data.h"
+#include "overworld.h"
+#include "link.h"
+#include "librfu.h"
+#include "rom_8011DC0.h"
+#include "link_rfu.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+struct UnkRfuStruct_1 gUnknown_03004140;
+struct UnkRfuStruct_2 gUnknown_03005000;
+
+IWRAM_DATA u8 gUnknown_03000D74;
+ALIGNED(4) IWRAM_DATA u8 gUnknown_03000D78[8];
+IWRAM_DATA u8 gUnknown_03000D80[16];
+IWRAM_DATA u16 gUnknown_03000D90[8];
+
+EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0;
+EWRAM_DATA ALIGNED(4) struct UnkLinkRfuStruct_02022B14 gUnknown_02022B14 = {};
+EWRAM_DATA ALIGNED(2) u8 gUnknown_02022B22[8] = {};
+EWRAM_DATA struct UnkLinkRfuStruct_02022B2C gUnknown_02022B2C = {};
+EWRAM_DATA struct UnkLinkRfuStruct_02022B44 gUnknown_02022B44 = {};
+
+// Static ROM declarations
+
+static void sub_800C000(void);
+static void sub_800C7B4(u16 r8, u16 r6);
+static void sub_800C744(u32 a0);
+static void sub_800CEB0(u16 r6);
+static void sub_800CF34(void);
+static void sub_800D158(void);
+static void sub_800D20C(void);
+static void sub_800D268(void);
+static u8 sub_800D294(void);
+static void sub_800D30C(u8 a0, u8 a1);
+static void sub_800D334(u8 a0);
+static void sub_800D358(u8 a0);
+static void sub_800D434(void);
+static void sub_800D610(void);
+void sub_800D630(void);
+static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2);
+static void sub_800EAB4(void);
+static void sub_800EAFC(void);
+void sub_800ED34(u16 unused);
+static void sub_800EDBC(u16 unused);
+static void sub_800F048(void);
+static void sub_800F86C(u8 unused);
+static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data);
+void sub_800FD14(u16 command);
+static void rfufunc_80F9F44(void);
+static void sub_800FFB0(void);
+static void rfufunc_80FA020(void);
+bool32 sub_8010454(u32 a0);
+static void sub_8010528(void);
+void sub_8010750(void);
+int sub_80107A0(void);
+void sub_801084C(u8 taskId);
+void sub_80109E8(u16 a0);
+void sub_8010A70(void *a0);
+void sub_8010AAC(u8 taskId);
+void sub_8010D0C(u8 taskId);
+void sub_80115EC(u16 a0);
+u8 sub_8011CE4(const u8 *a0, u16 a1);
+void sub_8011D6C(u8 a0);
+void sub_8011E94(u8 a0, u8 a1);
+u8 sub_8012224(void);
+void sub_801227C(void);
+
+// .rodata
+
+const u16 gWirelessLinkIconPalette[] = INCBIN_U16("graphics/interface/wireless_link_icon.gbapal");
+const u8 gWirelessLinkIconPic[] = INCBIN_U8("graphics/interface/wireless_link_icon.4bpp.lz");
+const u8 sWireless_ASCIItoRSETable[] = {
+ 0xff, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x00, 0xab, 0xb5, 0xb6, 0xb1, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb2, 0xf1, 0x00, 0xae, 0xad, 0xba,
+ 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0x00, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1,
+ 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1,
+ 0xd2, 0xd3, 0xd4, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+ 0x00, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
+ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0x2d, 0x2f, 0x30, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x50, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+ 0x1b, 0xad, 0xb3, 0xb4, 0x00, 0xaf, 0x7d, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xa0,
+ 0xae, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7e, 0xb0, 0xac,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2e, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
+ 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94
+};
+const u8 sWireless_RSEtoASCIITable[] = {
+ 0x20, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
+ 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
+ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c,
+ 0x9d, 0x9e, 0x9f, 0xa0, 0xe0, 0xe1, 0xe2, 0xe3,
+ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0x7b, 0xf1, 0x7c,
+ 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x84, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xa6, 0xdd, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xf2,
+ 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
+ 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0xaf, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x21, 0xdf, 0xa1, 0xb0, 0xa5,
+ 0xde, 0x24, 0x2a, 0xa2, 0xa3, 0x22, 0x23, 0x20,
+ 0xa4, 0x20, 0x2f, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
+ 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
+ 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x20,
+ 0x20, 0x2b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00
+};
+const struct OamData sWirelessStatusIndicatorOamData = {
+ .size = 1
+};
+static const union AnimCmd sWirelessStatusIndicatorAnim0[] = {
+ // 3 bars
+ ANIMCMD_FRAME( 4, 5),
+ ANIMCMD_FRAME( 8, 5),
+ ANIMCMD_FRAME(12, 5),
+ ANIMCMD_FRAME(16, 10),
+ ANIMCMD_FRAME(12, 5),
+ ANIMCMD_FRAME( 8, 5),
+ ANIMCMD_JUMP(0)
+};
+static const union AnimCmd sWirelessStatusIndicatorAnim1[] = {
+ // 2 bars
+ ANIMCMD_FRAME( 4, 5),
+ ANIMCMD_FRAME( 8, 5),
+ ANIMCMD_FRAME(12, 10),
+ ANIMCMD_FRAME( 8, 5),
+ ANIMCMD_JUMP(0)
+};
+static const union AnimCmd sWirelessStatusIndicatorAnim2[] = {
+ // 1 bar
+ ANIMCMD_FRAME(4, 5),
+ ANIMCMD_FRAME(8, 5),
+ ANIMCMD_JUMP(0)
+};
+static const union AnimCmd sWirelessStatusIndicatorAnim3[] = {
+ // searching
+ ANIMCMD_FRAME( 4, 10),
+ ANIMCMD_FRAME(20, 10),
+ ANIMCMD_JUMP(0)
+};
+static const union AnimCmd sWirelessStatusIndicatorAnim4[] = {
+ // error
+ ANIMCMD_FRAME(24, 10),
+ ANIMCMD_FRAME( 4, 10),
+ ANIMCMD_JUMP(0)
+};
+static const union AnimCmd *const sWirelessStatusIndicatorAnims[] = {
+ sWirelessStatusIndicatorAnim0,
+ sWirelessStatusIndicatorAnim1,
+ sWirelessStatusIndicatorAnim2,
+ sWirelessStatusIndicatorAnim3,
+ sWirelessStatusIndicatorAnim4
+};
+const struct CompressedSpriteSheet sWirelessStatusIndicatorSpriteSheet = {
+ gWirelessLinkIconPic, 0x0380, 0xD431
+};
+const struct SpritePalette sWirelessStatusIndicatorSpritePalette = {
+ gWirelessLinkIconPalette, 0xD432
+};
+static const struct SpriteTemplate sWirelessStatusIndicatorSpriteTemplate = {
+ 0xD431,
+ 0xD432,
+ &sWirelessStatusIndicatorOamData,
+ sWirelessStatusIndicatorAnims,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCallbackDummy
+};
+
+const struct UnkLinkRfuStruct_02022B2C gUnknown_082ED608 = {
+ 0x04, 0x20, 0x00, 0x00, 0x02,
+ &gUnknown_02022B14,
+ gUnknown_02022B22,
+ 0x01, 0x00, 0x258, 0x12c
+};
+const u8 gUnknown_082ED620[] = {
+ 0, 3, 2, 1, 0
+};
+const u32 gUnknown_082ED628[] = {
+ 0x000000,
+ 0x000001,
+ 0x000003,
+ 0x000007,
+ 0x00000f,
+ 0x00001f,
+ 0x00003f,
+ 0x00007f,
+ 0x0000ff,
+ 0x0001ff,
+ 0x0003ff,
+ 0x0007ff,
+ 0x000fff,
+ 0x001fff,
+ 0x003fff,
+ 0x007fff,
+ 0x00ffff,
+ 0x01ffff,
+ 0x03ffff,
+ 0x07ffff,
+ 0x0fffff,
+ 0x1fffff,
+ 0x3fffff,
+ 0x7fffff,
+ 0xffffff
+};
+const u8 gUnknown_082ED68C[] = {
+ 0, 0, 1,
+ 1, 2, 2,
+ 2, 2, 3
+};
+const u8 gUnknown_082ED695[] = {
+ 0, 1, 1, 2,
+ 1, 2, 2, 3,
+ 1, 2, 2, 3,
+ 2, 3, 3, 4
+};
+const u8 gUnknown_082ED6A5[] = {
+ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+const struct {
+ u8 *buffer;
+ u32 size;
+} gUnknown_082ED6B8[] = {
+ { gBlockSendBuffer, 200 },
+ { gBlockSendBuffer, 200 },
+ { gBlockSendBuffer, 100 },
+ { gBlockSendBuffer, 220 },
+ { gBlockSendBuffer, 40 }
+};
+const u16 gUnknown_082ED6E0[] = {
+ 0x0002, 0x7f7d, 0x0000, 0xffff
+};
+
+const char sUnref_082ED6E8[][15] = {
+ "RFU WAIT",
+ "RFU BOOT",
+ "RFU ERROR",
+ "RFU RESET",
+ "RFU CONFIG",
+ "RFU START",
+ "RFU SC POLL",
+ "RFU SP POLL",
+ "RFU START",
+ "RFU SEND ERR",
+ "RFU CP POLL"
+};
+const char sUnref_082ED6E9[][16] = {
+ " ",
+ "RECOVER START ",
+ "DISSCONECT ",
+ "RECOVER SUUSES",
+ "RECOVER FAILED"
+};
+const TaskFunc gUnknown_082ED7E0[] = {
+ sub_801084C,
+ sub_8010AAC,
+ sub_8010D0C
+};
+const char gUnknown_082ED7EC[] = "PokemonSioInfo";
+const char gUnknown_082ED7FC[] = "LINK LOSS DISCONNECT!";
+const char gUnknown_082ED814[] = "LINK LOSS RECOVERY NOW";
+
+// .text
+
+u32 sub_800BEC0(void)
+{
+ u32 r4;
+
+ r4 = rfu_REQBN_softReset_and_checkID();
+ if (r4 == 0x8001)
+ {
+ gUnknown_03004140.unk_08 = 1;
+ }
+ if (gUnknown_03004140.unk_04 != 0x17 && gUnknown_03004140.unk_04 != 0x01)
+ {
+ gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_04 = 0;
+ }
+ gUnknown_03004140.unk_07 = 0;
+ gUnknown_03004140.unk_0d = 0;
+ gUnknown_03004140.unk_01 = 0;
+ gUnknown_03004140.unk_00 = 0;
+ gUnknown_03004140.unk_06 = -1;
+ sub_800D610();
+ return r4;
+}
+
+void rfu_REQ_sendData_wrapper(u8 r2)
+{
+ u8 val;
+ if (!gUnknown_03007890->unk_00)
+ {
+ val = gUnknown_03004140.unk_02;
+ r2 = 0;
+ if (val == 1)
+ {
+ r2 = 1;
+ }
+ }
+ else
+ {
+ gUnknown_03004140.unk_03 = 0;
+ }
+ rfu_REQ_sendData(r2);
+}
+
+int sub_800BF4C(void (*func1)(u8, u8), void (*func2)(u16))
+{
+ if (func1 == NULL)
+ {
+ return 4;
+ }
+ CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, filler_48));
+ gUnknown_03004140.unk_06 = -1;
+ gUnknown_03004140.unk_40 = func1;
+ gUnknown_03004140.unk_44 = func2;
+ rfu_setMSCCallback(sub_800CEB0);
+ rfu_setREQCallback(sub_800C7B4);
+ return 0;
+}
+
+void sub_800BFA0(void)
+{
+ CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, unk_40));
+ gUnknown_03004140.unk_06 = -1;
+}
+
+void sub_800BFCC(const struct UnkLinkRfuStruct_02022B2C *unk0)
+{
+ sub_800C000();
+ gUnknown_03004140.unk_04 = 1;
+ gUnknown_03004140.unk_05 = 2;
+ gUnknown_03004140.unk_3c = unk0;
+ gUnknown_03004140.unk_09 = unk0->unk_11;
+ gUnknown_03004140.unk_32 = unk0->unk_12;
+ gUnknown_03004140.unk_18 = unk0->unk_14;
+ if (unk0->unk_10)
+ {
+ gUnknown_03004140.unk_0b = 1;
+ }
+}
+
+static void sub_800C000(void)
+{
+ u8 i;
+
+ gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_04 = 0;
+ gUnknown_03004140.unk_06 = -1;
+ gUnknown_03004140.unk_07 = 0;
+ gUnknown_03004140.unk_10 = 0;
+ gUnknown_03004140.unk_0c = 0;
+ gUnknown_03004140.unk_24 = 0;
+ gUnknown_03004140.unk_30 = 0;
+ for (i = 0; i < 4; i++)
+ {
+ gUnknown_03004140.unk_28[i] = 0;
+ gUnknown_03004140.unk_34[i] = 0;
+ }
+}
+
+void sub_800C048(void)
+{
+ gUnknown_03004140.unk_04 = 0x15;
+}
+
+u8 sub_800C054(u8 r5, u16 r7, u16 r8, const u16 *r6)
+{
+ u8 i;
+ const u16 *buffer;
+
+ if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 != 0x08 || r5 != 1))
+ {
+ gUnknown_03004140.unk_14 = 1;
+ sub_800D30C(0xf3, 0x01);
+ return 1;
+ }
+ if (!rfu_getMasterSlave())
+ {
+ gUnknown_03004140.unk_14 = 2;
+ sub_800D30C(0xf3, 0x01);
+ return 2;
+ }
+ for (i = 0, buffer = r6; i < 16; i++)
+ {
+ if (*buffer++ == 0xFFFF)
+ {
+ break;
+ }
+ }
+ if (i == 16)
+ {
+ gUnknown_03004140.unk_14 = 4;
+ sub_800D30C(0xf3, 0x01);
+ return 4;
+ }
+ if (r5 > 1)
+ {
+ gUnknown_03004140.unk_07 = 1;
+ r5 = 1;
+ r7 = 0;
+ }
+ else
+ {
+ gUnknown_03004140.unk_07 = 0;
+ }
+ if (r5 != 0)
+ {
+ gUnknown_03004140.unk_04 = 5;
+ }
+ else
+ {
+ gUnknown_03004140.unk_04 = 9;
+ if (gUnknown_03004140.unk_0b)
+ {
+ gUnknown_03004140.unk_0b = 2;
+ }
+ }
+ gUnknown_03004140.unk_06 = r5;
+ gUnknown_03004140.unk_1a = r7;
+ gUnknown_03004140.unk_26 = r8;
+ gUnknown_03004140.unk_20 = r6;
+ return 0;
+}
+
+u8 sub_800C12C(u16 r6, u16 r8)
+{
+ u8 i;
+ struct RfuUnk5 *tmp;
+
+ if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 < 9 || gUnknown_03004140.unk_04 > 11))
+ {
+ gUnknown_03004140.unk_14 = 1;
+ sub_800D30C(0xF3, 0x01);
+ return 1;
+ }
+ if (!rfu_getMasterSlave())
+ {
+ gUnknown_03004140.unk_14 = 2;
+ sub_800D30C(0xF3, 0x01);
+ return 2;
+ }
+ for (i = 0; i < gUnknown_03007890->unk_08; i++)
+ {
+ if (gUnknown_03007890->unk_14[i].unk_00 == r6)
+ {
+ break;
+ }
+ }
+ if (gUnknown_03007890->unk_08 == 0 || i == gUnknown_03007890->unk_08)
+ {
+ gUnknown_03004140.unk_14 = 3;
+ sub_800D30C(0xF3, 0x01);
+ return 3;
+ }
+ if (gUnknown_03004140.unk_04 == 0 || gUnknown_03004140.unk_04 == 9)
+ {
+ gUnknown_03004140.unk_04 = 12;
+ gUnknown_03004140.unk_05 = 13;
+ }
+ else
+ {
+ gUnknown_03004140.unk_04 = 11;
+ gUnknown_03004140.unk_05 = 12;
+ }
+ gUnknown_03004140.unk_1e = r6;
+ gUnknown_03004140.unk_1a = r8;
+ if (gUnknown_03004140.unk_07 != 0)
+ {
+ gUnknown_03004140.unk_07 = 7;
+ }
+ return 0;
+}
+
+void sub_800C210(u8 a0)
+{
+ u8 i;
+
+ if (a0 & gUnknown_03004140.unk_30)
+ {
+ gUnknown_03004140.unk_30 &= ~a0;
+ for (i = 0; i < 4; i++)
+ {
+ if ((a0 >> i) & 1)
+ {
+ gUnknown_03004140.unk_34[i] = 0;
+ }
+ }
+ i = gUnknown_03007890->unk_03 & a0;
+ if (i)
+ {
+ sub_800D334(i);
+ }
+ gUnknown_03004140.unk_14 = i;
+ sub_800D30C(0x33, i);
+ }
+}
+
+void sub_800C27C(bool8 a0)
+{
+ u8 r2;
+
+ r2 = 0;
+ gUnknown_03004140.unk_07 = 0;
+ if (a0)
+ {
+ sub_800C000();
+ gUnknown_03004140.unk_04 = 23;
+ }
+ else
+ {
+ switch (gUnknown_03004140.unk_04)
+ {
+ case 5:
+ gUnknown_03004140.unk_04 = 8;
+ gUnknown_03004140.unk_05 = 0;
+ r2 = 0x13;
+ break;
+ case 6:
+ gUnknown_03004140.unk_04 = 7;
+ gUnknown_03004140.unk_05 = 8;
+ break;
+ case 7:
+ gUnknown_03004140.unk_04 = 7;
+ gUnknown_03004140.unk_05 = 8;
+ break;
+ case 8:
+ break;
+ case 9:
+ gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_04 = 0;
+ r2 = 0x21;
+ break;
+ case 10:
+ gUnknown_03004140.unk_04 = 11;
+ gUnknown_03004140.unk_05 = 0;
+ break;
+ case 11:
+ gUnknown_03004140.unk_04 = 11;
+ gUnknown_03004140.unk_05 = 0;
+ break;
+ case 12:
+ gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_04 = 0;
+ r2 = 0x23;
+ break;
+ case 13:
+ gUnknown_03004140.unk_04 = 14;
+ break;
+ case 14:
+ gUnknown_03004140.unk_04 = 14;
+ break;
+ case 15:
+ break;
+ case 16:
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11;
+ gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12;
+ sub_800D334(gUnknown_03007890->unk_03);
+ gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03;
+ sub_800D30C(0x33, 0x01);
+ return;
+ case 17:
+ gUnknown_03004140.unk_04 = 18;
+ break;
+ case 18:
+ gUnknown_03004140.unk_04 = 18;
+ break;
+ default:
+ gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_04 = 0;
+ r2 = 0x43;
+ break;
+ }
+ if (gUnknown_03004140.unk_04 == 0)
+ {
+ sub_800D30C(r2, 0);
+ }
+ }
+}
+
+bool8 sub_800C36C(u16 a0)
+{
+ bool8 retVal;
+ u8 i;
+ u8 sp0;
+ u8 sp1;
+ u8 sp2;
+ u8 flags;
+
+ retVal = FALSE;
+ rfu_REQBN_watchLink(a0, &sp0, &sp1, &sp2);
+ if (sp0)
+ {
+ gUnknown_03004140.unk_14 = sp0;
+ gUnknown_03004140.unk_16 = sp1;
+ if (gUnknown_03004140.unk_09)
+ {
+ gUnknown_03004140.unk_0a = 1;
+ if (gUnknown_03004140.unk_06 == 0 && sp1 == 0)
+ {
+ gUnknown_03004140.unk_0a = 4;
+ }
+ if (gUnknown_03004140.unk_0a == 1)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if ((sp0 >> i) & 1)
+ {
+ gUnknown_03004140.unk_30 |= (1 << i);
+ gUnknown_03004140.unk_34[i] = gUnknown_03004140.unk_32;
+ }
+ }
+ sub_800D30C(0x31, 0x01);
+ }
+ else
+ {
+ gUnknown_03004140.unk_0a = 0;
+ sub_800D334(sp0);
+ retVal = TRUE;
+ sub_800D30C(0x33, 0x01);
+ }
+ }
+ else
+ {
+ sub_800D334(sp0);
+ retVal = TRUE;
+ sub_800D30C(0x30, 0x02);
+ }
+ sub_800D610();
+ }
+ if (gUnknown_03007890->unk_00 == 1)
+ {
+ if (sp2)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03004140.unk_30 >> i) & 1 && (sp2 >> i) & 1)
+ {
+ gUnknown_03004140.unk_34[i] = 0;
+ }
+ }
+ gUnknown_03004140.unk_30 &= ~sp2;
+ gUnknown_03004140.unk_14 = sp2;
+ sub_800D30C(0x32, 0x01);
+ }
+ if (gUnknown_03004140.unk_30)
+ {
+ flags = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03004140.unk_30 >> i) & 1 && gUnknown_03004140.unk_34[i] && --gUnknown_03004140.unk_34[i] == 0)
+ {
+ gUnknown_03004140.unk_30 &= ~(1 << i);
+ flags |= (1 << i);
+ }
+ }
+ if (flags)
+ {
+ sub_800D334(flags);
+ retVal = TRUE;
+ gUnknown_03004140.unk_14 = flags;
+ sub_800D30C(0x33, 0x01);
+ }
+ }
+ if (!gUnknown_03004140.unk_30)
+ {
+ gUnknown_03004140.unk_0a = 0;
+ }
+ }
+ return retVal;
+}
+
+void rfu_syncVBlank_(void)
+{
+ if (rfu_syncVBlank())
+ {
+ sub_800D30C(0xF1, 0x00);
+ sub_800D610();
+ }
+}
+
+void sub_800C54C(u32 a0)
+{
+ u8 r2;
+
+ if (gUnknown_03004140.unk_40 == NULL && gUnknown_03004140.unk_04 != 0)
+ {
+ gUnknown_03004140.unk_04 = 0;
+ }
+ else
+ {
+ if (gUnknown_03004140.unk_07 != 0)
+ {
+ sub_800C744(a0);
+ }
+ do
+ {
+ if (gUnknown_03004140.unk_04 != 0)
+ {
+ rfu_waitREQComplete();
+ gUnknown_03004140.unk_0e = 1;
+ switch (gUnknown_03004140.unk_04)
+ {
+ case 23:
+ r2 = sub_800BEC0() == 0x8001 ? 0x44 : 0xFF;
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D30C(r2, 0);
+ break;
+ case 1:
+ if (sub_800BEC0() == 0x8001)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_05 = 3;
+ }
+ else
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D30C(0xFF, 0);
+ }
+ break;
+ case 2:
+ rfu_REQ_reset();
+ break;
+ case 3:
+ rfu_REQ_configSystem(gUnknown_03004140.unk_3c->unk_02, gUnknown_03004140.unk_3c->unk_00, gUnknown_03004140.unk_3c->unk_01);
+ break;
+ case 4:
+ rfu_REQ_configGameData(gUnknown_03004140.unk_3c->unk_04, gUnknown_03004140.unk_3c->unk_06, gUnknown_03004140.unk_3c->unk_08, gUnknown_03004140.unk_3c->unk_0c);
+ break;
+ case 5:
+ rfu_REQ_startSearchChild();
+ break;
+ case 6:
+ rfu_REQ_pollSearchChild();
+ break;
+ case 7:
+ rfu_REQ_endSearchChild();
+ break;
+ case 8:
+ break;
+ case 9:
+ rfu_REQ_startSearchParent();
+ break;
+ case 10:
+ rfu_REQ_pollSearchParent();
+ break;
+ case 11:
+ rfu_REQ_endSearchParent();
+ break;
+ case 12:
+ rfu_REQ_startConnectParent(gUnknown_03004140.unk_1e);
+ break;
+ case 13:
+ rfu_REQ_pollConnectParent();
+ break;
+ case 14:
+ rfu_REQ_endConnectParent();
+ break;
+ case 15:
+ break;
+ case 16:
+ rfu_REQ_CHILD_startConnectRecovery(gUnknown_03007890->unk_03);
+ break;
+ case 17:
+ rfu_REQ_CHILD_pollConnectRecovery();
+ break;
+ case 18:
+ rfu_REQ_CHILD_endConnectRecovery();
+ break;
+ case 19:
+ rfu_REQ_changeMasterSlave();
+ break;
+ case 20:
+ break;
+ case 21:
+ rfu_REQ_stopMode();
+ break;
+ case 22:
+ break;
+ }
+ rfu_waitREQComplete();
+ gUnknown_03004140.unk_0e = 0;
+ }
+ } while (gUnknown_03004140.unk_04 == 18 || gUnknown_03004140.unk_04 == 19);
+ if (gUnknown_03007890->unk_00 != 1 || !sub_800C36C(0))
+ {
+ sub_800CF34();
+ sub_800D158();
+ sub_800D268();
+ sub_800D434();
+ }
+ }
+}
+
+static void sub_800C744(u32 a0)
+{
+ if (gUnknown_03004140.unk_07 == 5)
+ {
+ gUnknown_03004140.unk_06 = 1;
+ gUnknown_03004140.unk_04 = 5;
+ gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c;
+ if (gUnknown_03004140.unk_1a)
+ {
+ gUnknown_03004140.unk_07 = 6;
+ }
+ else
+ {
+ gUnknown_03004140.unk_07 = 1;
+ }
+ }
+ if (gUnknown_03004140.unk_07 == 1)
+ {
+ gUnknown_03004140.unk_06 = 1;
+ gUnknown_03004140.unk_04 = 5;
+ gUnknown_03004140.unk_1a = a0 % 140;
+ gUnknown_03004140.unk_1c = 140 - gUnknown_03004140.unk_1a;
+ if (gUnknown_03004140.unk_1a)
+ {
+ gUnknown_03004140.unk_07 = 2;
+ }
+ else
+ {
+ gUnknown_03004140.unk_07 = 3;
+ }
+ }
+ if (gUnknown_03004140.unk_07 == 3)
+ {
+ gUnknown_03004140.unk_06 = 0;
+ gUnknown_03004140.unk_1a = 40;
+ gUnknown_03004140.unk_07 = 4;
+ gUnknown_03004140.unk_04 = 9;
+ }
+}
+
+static void sub_800C7B4(u16 r8, u16 r6)
+{
+ u8 sp0;
+ register u8 *stwiRecvBuffer asm("r0");
+ u8 *tmp;
+ u8 i;
+
+ if (gUnknown_03004140.unk_0e != 0)
+ {
+ gUnknown_03004140.unk_0e = 0;
+ switch (r8)
+ {
+ case 16:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_05 = 4;
+ }
+ break;
+ case 23:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_05 = 0;
+ }
+ break;
+ case 22:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D30C(0x00, 0x00);
+ }
+ break;
+ case 25:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 6;
+ }
+ break;
+ case 26:
+ if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0)
+ {
+ gUnknown_03004140.unk_04 = 7;
+ gUnknown_03004140.unk_05 = 8;
+ }
+ break;
+ case 27:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_05 = 0;
+ if (gUnknown_03004140.unk_07 == 0)
+ {
+ sub_800D30C(0x13, 0x00);
+ }
+ }
+ break;
+ case 28:
+ if (r6 == 0)
+ {
+ if (gUnknown_03004140.unk_0b == 1 && gUnknown_03004140.unk_1a > 1)
+ {
+ gUnknown_03004140.unk_1a--;
+ }
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 10;
+ }
+ break;
+ case 29:
+ if (r6 == 0)
+ {
+ sp0 = sub_800D294();
+ gUnknown_03004140.unk_14 = sp0;
+ if (sp0)
+ {
+ sub_800D30C(0x20, 0x01);
+ }
+ if (gUnknown_03004140.unk_0b && gUnknown_03004140.unk_1a != 1 && gUnknown_03007890->unk_08 == 4)
+ {
+ rfu_REQ_endSearchParent();
+ rfu_waitREQComplete();
+ gUnknown_03004140.unk_04 = 9;
+ gUnknown_03004140.unk_0b = 1;
+ }
+ }
+ if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0)
+ {
+ gUnknown_03004140.unk_04 = 11;
+ gUnknown_03004140.unk_05 = 0;
+ }
+ break;
+ case 30:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ if (gUnknown_03004140.unk_07 == 0)
+ {
+ if (gUnknown_03004140.unk_04 == 0)
+ {
+ sub_800D30C(0x21, 0x00);
+ }
+ }
+ else if (gUnknown_03004140.unk_07 != 7)
+ {
+ gUnknown_03004140.unk_04 = 5;
+ gUnknown_03004140.unk_07 = 5;
+ }
+ }
+ break;
+ case 31:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 13;
+ }
+ break;
+ case 32:
+ if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10) && !sp0)
+ {
+ gUnknown_03004140.unk_04 = 14;
+ }
+ if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0)
+ {
+ gUnknown_03004140.unk_04 = 14;
+ }
+ break;
+ case 33:
+ if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10))
+ {
+ if (!sp0)
+ {
+ gUnknown_03004140.unk_04 = 19;
+ gUnknown_03004140.unk_05 = 15;
+ gUnknown_03004140.unk_1e = 0x22;
+ gUnknown_03004140.unk_14 = gUnknown_03004140.unk_10;
+ }
+ else
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ gUnknown_03004140.unk_1e = 0x23;
+ gUnknown_03004140.unk_14 = sp0;
+ if (gUnknown_03004140.unk_07)
+ {
+ gUnknown_03004140.unk_07 = 3;
+ gUnknown_03004140.unk_04 = 9;
+ }
+ }
+ sub_800D30C(gUnknown_03004140.unk_1e, 0x01);
+ gUnknown_03004140.unk_1e = 0;
+ }
+ break;
+ case 50:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03;
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 17;
+ for (gUnknown_03004140.unk_10 = 0; gUnknown_03004140.unk_10 < 4; gUnknown_03004140.unk_10 ++)
+ {
+ if ((gUnknown_03007890->unk_03 >> gUnknown_03004140.unk_10) & 1)
+ {
+ break;
+ }
+ }
+ }
+ break;
+ case 51:
+ if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0) && sp0 < 2)
+ {
+ gUnknown_03004140.unk_04 = 18;
+ }
+ if (gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] && --gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] == 0)
+ {
+ gUnknown_03004140.unk_04 = 18;
+ }
+ break;
+ case 52:
+ if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0))
+ {
+ if (!sp0)
+ {
+ gUnknown_03004140.unk_04 = 19;
+ gUnknown_03004140.unk_05 = 22;
+ gUnknown_03004140.unk_1e = 0x32;
+ }
+ else
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D334(gUnknown_03007890->unk_03);
+ gUnknown_03004140.unk_1e = 0x33;
+ }
+ gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] = 0;
+ gUnknown_03004140.unk_30 = 0;
+ gUnknown_03004140.unk_0a = 0;
+ sub_800D30C(gUnknown_03004140.unk_1e, 0x01);
+ gUnknown_03004140.unk_1e = 0;
+ }
+ break;
+ case 39:
+ if (r6 == 0)
+ {
+ if (gUnknown_03004140.unk_05 == 22)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11;
+ gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12;
+ gUnknown_03004140.unk_02 = 1;
+ sub_800D30C(0x41, 0x00);
+ }
+ else if (gUnknown_03004140.unk_05 == 15)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_02 = 1;
+ sub_800D30C(0x41, 0x00);
+ gUnknown_03004140.unk_24 |= 1 << gUnknown_03004140.unk_10;
+ gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = gUnknown_03004140.unk_26;
+ rfu_clearSlot(4, gUnknown_03004140.unk_10);
+ tmp = &sp0;
+ *tmp = rfu_NI_CHILD_setSendGameName(gUnknown_03004140.unk_10, 0x0e);
+ if (*tmp)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D610();
+ sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03);
+ gUnknown_03004140.unk_14 = sp0;
+ sub_800D30C(0x25, 0x01);
+ }
+ }
+ }
+ break;
+ case 61:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D30C(0x42, 0x00);
+ }
+ break;
+ }
+ gUnknown_03004140.unk_0e = 1;
+ }
+ else if (r6 == 3 && gUnknown_03004140.unk_0f && (r8 == 0x24 || r8 == 0x26 || r8 == 0x27))
+ {
+ rfu_REQ_RFUStatus();
+ rfu_waitREQComplete();
+ rfu_getRFUStatus(&sp0);
+ if (sp0 == 0 && gUnknown_03007890->unk_00 == 0)
+ {
+ stwiRecvBuffer = rfu_getSTWIRecvBuffer();
+ stwiRecvBuffer[4] = gUnknown_03007890->unk_02;
+ stwiRecvBuffer[5] = 1;
+ sub_800C36C(0x29);
+ r6 = 0;
+ }
+ }
+ switch (r8)
+ {
+ case 48:
+ if (r6 == 0)
+ {
+ stwiRecvBuffer = rfu_getSTWIRecvBuffer();
+ gUnknown_03004140.unk_14 = stwiRecvBuffer[8];
+ sub_800D358(gUnknown_03004140.unk_14);
+ if (gUnknown_03004140.unk_30)
+ {
+ gUnknown_03004140.unk_30 &= ~gUnknown_03004140.unk_14;
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03004140.unk_14 >> i) & 1)
+ {
+ gUnknown_03004140.unk_34[i] = 0;
+ }
+ }
+ if (gUnknown_03004140.unk_06 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ }
+ }
+ sp0 = gUnknown_03004140.unk_00 & gUnknown_03004140.unk_14;
+ for (i = 0; i < 4; i++)
+ {
+ if ((sp0 >> i) & 1 && gUnknown_03004140.unk_01)
+ {
+ gUnknown_03004140.unk_01--;
+ }
+ }
+ gUnknown_03004140.unk_00 &= ~gUnknown_03004140.unk_14;
+ if (gUnknown_03004140.unk_07)
+ {
+ if (gUnknown_03007890->unk_00 == 0xFF)
+ {
+ if (gUnknown_03004140.unk_07 == 8)
+ {
+ gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c;
+ gUnknown_03004140.unk_07 = 6;
+ gUnknown_03004140.unk_04 = 6;
+ }
+ else if (gUnknown_03004140.unk_04 != 6 && gUnknown_03004140.unk_04 != 7)
+ {
+ gUnknown_03004140.unk_07 = 1;
+ gUnknown_03004140.unk_04 = 5;
+ }
+ }
+ }
+ if (gUnknown_03007890->unk_00 == 0xFF)
+ {
+ if (gUnknown_03004140.unk_04 == 0)
+ {
+ gUnknown_03004140.unk_06 = -1;
+ }
+ }
+ if (gUnknown_03004140.unk_0e == 0)
+ {
+ sub_800D30C(0x40, 0x01);
+ }
+ }
+ break;
+ case 38:
+ sub_800D20C();
+ if (gUnknown_03007890->unk_00 != 0xFF)
+ {
+ sub_800D30C(0x50, 0x00);
+ }
+ break;
+ case 16:
+ case 61:
+ if (r6 == 0)
+ {
+ gUnknown_03004140.unk_0d = 0;
+ gUnknown_03004140.unk_01 = 0;
+ gUnknown_03004140.unk_00 = 0;;
+ gUnknown_03004140.unk_06 = -1;
+ sub_800D610();
+ if (r8 == 61)
+ {
+ sub_800BFA0();
+ }
+ }
+ break;
+ }
+ if (r6 != 0)
+ {
+ if (r8 == 28 && r6 != 0 && gUnknown_03004140.unk_07 == 4)
+ {
+ gUnknown_03007890->unk_00 = 1;
+ gUnknown_03007890->unk_02 = 15;
+ sub_800D334(15);
+ rfu_waitREQComplete();
+ return;
+ }
+ else
+ {
+ gUnknown_03004140.unk_14 = r8;
+ gUnknown_03004140.unk_16 = r6;
+ if (gUnknown_03004140.unk_0e)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ }
+ sub_800D30C(0xf0, 0x02);
+ sub_800D610();
+ }
+ }
+ if (r8 == 0xFF)
+ {
+ sub_800D30C(0xf2, 0x00);
+ sub_800D610();
+ }
+}
+
+static void sub_800CEB0(u16 r6)
+{
+ u8 r7;
+ u8 sp0;
+
+ r7 = gUnknown_03004140.unk_0e;
+ gUnknown_03004140.unk_0e = 0;
+ gUnknown_03004140.unk_0f = 1;
+ if (gUnknown_03007890->unk_00 == 0)
+ {
+ sub_800C36C(r6);
+ if (gUnknown_03004140.unk_02 != 1)
+ {
+ sub_800D610();
+ gUnknown_03004140.unk_0f = 0;
+ gUnknown_03004140.unk_0e = r7;
+ return;
+ }
+ }
+ else
+ {
+ if (!rfu_UNI_PARENT_getDRAC_ACK(&sp0))
+ {
+ gUnknown_03004140.unk_03 |= sp0;
+ }
+ }
+ if (gUnknown_03004140.unk_44 != NULL)
+ {
+ gUnknown_03004140.unk_44(r6);
+ rfu_waitREQComplete();
+ if (gUnknown_03004140.unk_02 == 2)
+ {
+ sub_800D610();
+ }
+ }
+ gUnknown_03004140.unk_0f = 0;
+ gUnknown_03004140.unk_0e = r7;
+}
+
+static void sub_800CF34(void)
+{
+ u8 flags;
+ u8 sp0;
+ u8 i;
+ u8 r5;
+ u8 r4;
+ const u16 *ptr;
+
+ if (gUnknown_03004140.unk_04 == 5 || gUnknown_03004140.unk_04 == 6 || gUnknown_03004140.unk_04 == 7 || gUnknown_03004140.unk_04 == 8)
+ {
+ flags = ((gUnknown_03007890->unk_02 ^ gUnknown_03004140.unk_0c) & gUnknown_03007890->unk_02) & ~gUnknown_03007890->unk_07;
+ gUnknown_03004140.unk_0c = gUnknown_03007890->unk_02;
+ if (flags)
+ {
+ gUnknown_03004140.unk_14 = flags;
+ sub_800D30C(0x10, 0x01);
+ }
+ sp0 = 0x00;
+ for (i = 0; i < 4; i++)
+ {
+ r4 = 1 << i;
+ r5 = 0x00;
+ if (flags & r4)
+ {
+ gUnknown_03004140.unk_28[i] = gUnknown_03004140.unk_26;
+ gUnknown_03004140.unk_24 |= r4;
+ }
+ else if (gUnknown_03004140.unk_24 & r4)
+ {
+ if (gUnknown_03007880[i]->unk_34 == 0x46)
+ {
+ if (gUnknown_03007880[i]->unk_61 == 1)
+ {
+ r5 = 0x02;
+ for (ptr = gUnknown_03004140.unk_20; *ptr != 0xFFFF; ptr++)
+ {
+ if (gUnknown_03007890->unk_14[i].unk_04 == *ptr)
+ {
+ gUnknown_03004140.unk_00 |= r4;
+ gUnknown_03004140.unk_01++;
+ sp0 |= r4;
+ r5 |= 0x01;
+ break;
+ }
+ }
+ if (!(r5 & 0x01))
+ {
+ r5 |= 0x04;
+ }
+ }
+ }
+ else if (--gUnknown_03004140.unk_28[i] == 0)
+ {
+ r5 = 0x06;
+ }
+ if (r5 & 0x02)
+ {
+ gUnknown_03004140.unk_24 &= ~r4;
+ gUnknown_03004140.unk_28[i] = 0;
+ rfu_clearSlot(0x08, i);
+ }
+ if (r5 & 0x04)
+ {
+ gUnknown_03004140.unk_0d |= r4;
+ }
+ }
+ }
+ if (sp0)
+ {
+ gUnknown_03004140.unk_14 = sp0;
+ sub_800D30C(0x11, 0x01);
+ }
+ if (gUnknown_03004140.unk_0d)
+ {
+ r5 = 0x01;
+ if (gUnknown_03007890->unk_06 && ((gUnknown_03004140.unk_03 & gUnknown_03004140.unk_00) != gUnknown_03004140.unk_00))
+ {
+ r5 = 0x00;
+ }
+ if (r5)
+ {
+ sub_800D334(gUnknown_03004140.unk_0d);
+ gUnknown_03004140.unk_14 = gUnknown_03004140.unk_0d;
+ gUnknown_03004140.unk_0d = 0;
+ sub_800D30C(0x12, 0x01);
+ }
+ }
+ if (gUnknown_03004140.unk_24 == 0 && gUnknown_03004140.unk_04 == 8)
+ {
+ if (gUnknown_03004140.unk_07 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D30C(0x14, 0x00);
+ }
+ else
+ {
+ if (gUnknown_03004140.unk_07 == 2)
+ {
+ gUnknown_03004140.unk_07 = 3;
+ gUnknown_03004140.unk_04 = 9;
+ }
+ else
+ {
+ gUnknown_03004140.unk_07 = 1;
+ gUnknown_03004140.unk_04 = 5;
+ }
+ if (gUnknown_03004140.unk_00)
+ {
+ gUnknown_03004140.unk_1a = 0;
+ gUnknown_03004140.unk_07 = 8;
+ gUnknown_03004140.unk_04 = 5;
+ }
+ }
+ }
+ }
+}
+
+static void sub_800D158(void)
+{
+ u16 imeBak = REG_IME;
+ REG_IME = 0;
+ if (gUnknown_03004140.unk_04 == 15)
+ {
+ if (--gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] == 0 || gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x27)
+ {
+ sub_800D630();
+ gUnknown_03004140.unk_04 = 24;
+ rfu_clearSlot(4, gUnknown_03004140.unk_10);
+ gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10);
+ gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0;
+ }
+ }
+ REG_IME = imeBak;
+ if (gUnknown_03004140.unk_04 == 24)
+ {
+ if (gUnknown_03004140.unk_02 == 1)
+ {
+ sub_800D630();
+ }
+ if (gUnknown_03004140.unk_02 == 0)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03);
+ gUnknown_03004140.unk_14 = 0;
+ sub_800D30C(0x25, 0x01);
+ }
+ }
+}
+
+static void sub_800D20C(void)
+{
+ if (gUnknown_03004140.unk_04 == 15 && gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x26)
+ {
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ rfu_clearSlot(4, gUnknown_03004140.unk_10);
+ gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10);
+ gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0;
+ sub_800D30C(0x24, 0x00);
+ }
+}
+
+static void sub_800D268(void)
+{
+ if (gUnknown_03004140.unk_06 == 0 && gUnknown_03004140.unk_0a == 1)
+ {
+ gUnknown_03004140.unk_11 = gUnknown_03004140.unk_04;
+ gUnknown_03004140.unk_12 = gUnknown_03004140.unk_05;
+ gUnknown_03004140.unk_04 = 16;
+ gUnknown_03004140.unk_05 = 17;
+ gUnknown_03004140.unk_0a = 2;
+ }
+}
+
+static u8 sub_800D294(void)
+{
+ u8 i;
+ const u16 *ptr;
+ u8 flags = 0x00;
+
+ for (i = 0; i < gUnknown_03007890->unk_08; i++)
+ {
+ for (ptr = gUnknown_03004140.unk_20; *ptr != 0xffff; ptr++)
+ {
+ if (gUnknown_03007890->unk_14[i].unk_04 == *ptr)
+ {
+ flags |= (1 << i);
+ }
+ }
+ }
+ return flags;
+}
+
+static void sub_800D30C(u8 a0, u8 a1)
+{
+ if (gUnknown_03004140.unk_40 != NULL)
+ {
+ gUnknown_03004140.unk_40(a0, a1);
+ }
+ gUnknown_03004140.unk_14 = gUnknown_03004140.unk_16 = 0;
+}
+
+static void sub_800D334(u8 a0)
+{
+ u8 unk_0e_bak = gUnknown_03004140.unk_0e;
+ gUnknown_03004140.unk_0e = 1;
+ rfu_REQ_disconnect(a0);
+ rfu_waitREQComplete();
+ gUnknown_03004140.unk_0e = unk_0e_bak;
+}
+
+static void sub_800D358(u8 a0)
+{
+ u8 i;
+
+ if (gUnknown_03007890->unk_04)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03007880[i]->unk_0 & 0x8000 && gUnknown_03007880[i]->unk_1a & a0)
+ {
+ rfu_changeSendTarget(0x20, i, gUnknown_03007880[i]->unk_1a & ~a0);
+ }
+ }
+ }
+ if (gUnknown_03007890->unk_05)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_4e & a0)
+ {
+ rfu_NI_stopReceivingData(i);
+ }
+ }
+ }
+ if (gUnknown_03007890->unk_06)
+ {
+ gUnknown_03007890->unk_06 &= ~a0;
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03007870[i]->unk_0 == 0x8024 && a0 & gUnknown_03007870[i]->unk_3)
+ {
+ gUnknown_03007870[i]->unk_3 &= ~a0;
+ }
+ }
+ }
+}
+
+static void sub_800D434(void)
+{
+ u8 i;
+ u8 j;
+ u8 flags;
+
+ if (gUnknown_03004140.unk_18)
+ {
+ if (gUnknown_03007890->unk_04)
+ {
+ for (i = 0; i < 4; i ++)
+ {
+ if (gUnknown_03007880[i]->unk_0 & 0x8000)
+ {
+ flags = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if ((gUnknown_03007880[i]->unk_1a >> j) & 1 && gUnknown_03007880[j]->unk_2 > gUnknown_03004140.unk_18)
+ {
+ flags |= (1 << j);
+ }
+ if (flags)
+ {
+ rfu_changeSendTarget(0x20, i, flags ^ gUnknown_03007880[i]->unk_1a);
+ }
+ }
+ }
+ }
+ }
+ if (gUnknown_03007890->unk_05)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_36 > gUnknown_03004140.unk_18)
+ {
+ rfu_NI_stopReceivingData(i);
+ }
+ }
+ }
+ }
+}
+
+void sub_800D52C(void (*func)(u16))
+{
+ gUnknown_03004140.unk_44 = func;
+ rfu_setMSCCallback(sub_800CEB0);
+}
+
+void sub_800D544(void (*func)(u8, u8))
+{
+ gUnknown_03004140.unk_40 = func;
+}
+
+u8 sub_800D550(u8 a0, u16 a1)
+{
+ u16 imeBak;
+ if (gUnknown_03004140.unk_09 && a0 == 0 && gUnknown_03004140.unk_30)
+ {
+ return 5;
+ }
+ imeBak = REG_IME;
+ REG_IME = 0;
+ gUnknown_03004140.unk_09 = a0;
+ gUnknown_03004140.unk_32 = a1;
+ REG_IME = imeBak;
+ return 0;
+}
+
+u8 sub_800D594(u16 a0)
+{
+ if (gUnknown_03007890->unk_04 | gUnknown_03007890->unk_05)
+ {
+ gUnknown_03004140.unk_14 = 6;
+ sub_800D30C(0xf3, 0x01);
+ return 6;
+ }
+ gUnknown_03004140.unk_18 = a0;
+ return 0;
+}
+
+u8 sub_800D5D0(u8 a0)
+{
+ if (gUnknown_03004140.unk_04 == 9 || gUnknown_03004140.unk_04 == 10 || gUnknown_03004140.unk_04 == 11)
+ {
+ gUnknown_03004140.unk_14 = 7;
+ sub_800D30C(0xf3, 0x01);
+ return 7;
+ }
+ if (a0)
+ {
+ gUnknown_03004140.unk_0b = 1;
+ }
+ else
+ {
+ gUnknown_03004140.unk_0b = 0;
+ }
+ return 0;
+}
+
+static void sub_800D610(void)
+{
+ if (gUnknown_03004140.unk_02)
+ {
+ gUnknown_03004140.unk_02 = 0;
+ sub_800D30C(0x45, 0x00);
+ }
+}
+
+void sub_800D630(void)
+{
+ if (gUnknown_03004140.unk_02 == 0)
+ {
+ sub_800D30C(0x45, 0x00);
+ }
+ else if (gUnknown_03004140.unk_02 == 1)
+ {
+ gUnknown_03004140.unk_02 = 2;
+ }
+}
+
+void sub_800D658(void)
+{
+ if (gUnknown_03004140.unk_07)
+ {
+ switch (gUnknown_03004140.unk_04)
+ {
+ case 5:
+ gUnknown_03004140.unk_07 = 3;
+ gUnknown_03004140.unk_04 = 9;
+ break;
+ case 6:
+ gUnknown_03004140.unk_07 = 2;
+ gUnknown_03004140.unk_1a = 1;
+ break;
+ case 7:
+ case 8:
+ gUnknown_03004140.unk_07 = 2;
+ break;
+ case 9:
+ case 10:
+ gUnknown_03004140.unk_1a = 40;
+ break;
+ case 11:
+ gUnknown_03004140.unk_1a = 40;
+ gUnknown_03004140.unk_04 = 10;
+ break;
+ }
+ }
+}
+
+// TODO: Is there a file boundary here?
+
+void sub_800D6C8(struct UnkRfuStruct_2_Sub_124 *ptr)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < 32; i++)
+ {
+ for (j = 0; j < 70; j++)
+ {
+ ptr->unk_00[i][j] = 0;
+ }
+ }
+ ptr->unk_8c1 = 0;
+ ptr->unk_8c0 = 0;
+ ptr->unk_8c2 = 0;
+ ptr->unk_8c3 = 0;
+}
+
+void sub_800D724(struct UnkRfuStruct_2_Sub_9e8 *ptr)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < 40; i++)
+ {
+ for (j = 0; j < 14; j++)
+ {
+ ptr->unk_00[i][j] = 0;
+ }
+ }
+ ptr->unk_231 = 0;
+ ptr->unk_230 = 0;
+ ptr->unk_232 = 0;
+ ptr->unk_233 = 0;
+}
+
+void sub_800D780(struct UnkRfuStruct_Sub_Unused *ptr)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 256; j++)
+ {
+ ptr->unk_00[i][j] = 0;
+ }
+ }
+ ptr->unk_201 = 0;
+ ptr->unk_200 = 0;
+ ptr->unk_202 = 0;
+ ptr->unk_203 = 0;
+}
+
+void sub_800D7D8(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2)
+{
+ int i;
+ u16 imeBak;
+ u8 count;
+
+ if (q1->unk_8c2 < 32)
+ {
+ imeBak = REG_IME;
+ REG_IME = 0;
+ count = 0;
+ for (i = 0; i < 70; i += 14)
+ {
+ if (q2[i] == 0 && q2[i + 1] == 0)
+ {
+ count++;
+ }
+ }
+ if (count != 5)
+ {
+ for (i = 0; i < 70; i++)
+ {
+ q1->unk_00[q1->unk_8c0][i] = q2[i];
+ }
+ q1->unk_8c0++;
+ q1->unk_8c0 %= 32;
+ q1->unk_8c2++;
+ for (i = 0; i < 70; i++)
+ {
+ q2[i] = 0;
+ }
+ }
+ REG_IME = imeBak;
+ }
+ else
+ {
+ q1->unk_8c3 = 1;
+ }
+}
+
+void sub_800D888(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2)
+{
+ int i;
+ u16 imeBak;
+
+ if (q1->unk_232 < 40)
+ {
+ imeBak = REG_IME;
+ REG_IME = 0;
+ for (i = 0; i < 14; i++)
+ {
+ if (q2[i] != 0)
+ {
+ break;
+ }
+ }
+ if (i != 14)
+ {
+ for (i = 0; i < 14; i++)
+ {
+ q1->unk_00[q1->unk_230][i] = q2[i];
+ }
+ q1->unk_230++;
+ q1->unk_230 %= 40;
+ q1->unk_232++;
+ for (i = 0; i < 14; i++)
+ {
+ q2[i] = 0;
+ }
+ }
+ REG_IME = imeBak;
+ }
+ else
+ {
+ q1->unk_233 = 1;
+ }
+}
+
+bool8 sub_800D934(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2)
+{
+ u16 imeBak;
+ int i;
+
+ imeBak = REG_IME;
+ REG_IME = 0;
+ if (q1->unk_8c0 == q1->unk_8c1 || q1->unk_8c3 != 0)
+ {
+ for (i = 0; i < 70; i++)
+ {
+ q2[i] = 0;
+ }
+ REG_IME = imeBak;
+ return FALSE;
+ }
+ for (i = 0; i < 70; i++)
+ {
+ q2[i] = q1->unk_00[q1->unk_8c1][i];
+ }
+ q1->unk_8c1++;
+ q1->unk_8c1 %= 32;
+ q1->unk_8c2--;
+ REG_IME = imeBak;
+ return TRUE;
+}
+
+bool8 sub_800D9DC(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2)
+{
+ int i;
+ u16 imeBak;
+
+ if (q1->unk_230 == q1->unk_231 || q1->unk_233 != 0)
+ {
+ return FALSE;
+ }
+ imeBak = REG_IME;
+ REG_IME = 0;
+ for (i = 0; i < 14; i++)
+ {
+ q2[i] = q1->unk_00[q1->unk_231][i];
+ }
+ q1->unk_231++;
+ q1->unk_231 %= 40;
+ q1->unk_232--;
+ REG_IME = imeBak;
+ return TRUE;
+}
+
+void sub_800DA68(struct UnkRfuStruct_2_Sub_c1c *q1, const u8 *q2)
+{
+ int i;
+
+ if (q2[1] == 0)
+ {
+ sub_800DAC8(q1, NULL);
+ }
+ else
+ {
+ for (i = 0; i < 14; i++)
+ {
+ q1->unk_00[q1->unk_1c][i] = q2[i];
+ }
+ q1->unk_1c++;
+ q1->unk_1c %= 2;
+ if (q1->unk_1e < 2)
+ {
+ q1->unk_1e++;
+ }
+ else
+ {
+ q1->unk_1d = q1->unk_1c;
+ }
+ }
+}
+
+static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2)
+{
+ int i;
+
+ if (q1->unk_1e == 0)
+ {
+ return FALSE;
+ }
+ if (q2 != NULL)
+ {
+ for (i = 0; i < 14; i++)
+ {
+ q2[i] = q1->unk_00[q1->unk_1d][i];
+ }
+ }
+ q1->unk_1d++;
+ q1->unk_1d %= 2;
+ q1->unk_1e--;
+ return TRUE;
+}
+
+void sub_800DB18(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2)
+{
+ int i;
+
+ if (q1->unk_202 < 2)
+ {
+ for (i = 0; i < 256; i++)
+ {
+ q1->unk_00[q1->unk_200][i] = q2[i];
+ }
+ q1->unk_200++;
+ q1->unk_200 %= 2;
+ q1->unk_202++;
+ }
+ else
+ {
+ q1->unk_203 = 1;
+ }
+}
+
+bool8 sub_800DB84(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2)
+{
+ int i;
+
+ if (q1->unk_200 == q1->unk_201 || q1->unk_203)
+ {
+ return FALSE;
+ }
+ for (i = 0; i < 256; i++)
+ {
+ q2[i] = q1->unk_00[q1->unk_201][i];
+ }
+ q1->unk_201++;
+ q1->unk_201 %= 2;
+ q1->unk_202--;
+ return TRUE;
+}
+
+void sub_800DBF8(u8 *q1, u8 mode)
+{
+ int i;
+ u8 rval;
+ u16 r5 = 0;
+ switch (mode)
+ {
+ case 0:
+ for (i = 0; i < 200; i++)
+ {
+ q1[i] = i + 1;
+ r5 += i + 1;
+ }
+ *((u16 *)(q1 + i)) = r5;
+ break;
+ case 1:
+ for (i = 0; i < 100; i++)
+ {
+ q1[i] = i + 1;
+ r5 += i + 1;
+ }
+ *((u16 *)(q1 + 200)) = r5;
+ break;
+ case 2:
+ for (i = 0; i < 200; i++)
+ {
+ rval = Random();
+ q1[i] = rval;
+ r5 += rval;
+ }
+ *((u16 *)(q1 + i)) = r5;
+ break;
+ case 3:
+ for (i = 0; i < 200; i++)
+ {
+ q1[i] = i + 1 + gUnknown_03000D74;
+ r5 += (i + 1 + gUnknown_03000D74) & 0xFF;
+ }
+ *((u16 *)(q1 + i)) = r5;
+ gUnknown_03000D74++;
+ break;
+ }
+}
+
+void PkmnStrToASCII(u8 *q1, const u8 *q2)
+{
+ int i;
+
+ for (i = 0; q2[i] != EOS; i++)
+ {
+ q1[i] = sWireless_RSEtoASCIITable[q2[i]];
+ }
+ q1[i] = 0;
+}
+
+void ASCIIToPkmnStr(u8 *q1, const u8 *q2)
+{
+ int i;
+
+ for (i = 0; q2[i] != 0; i++)
+ {
+ q1[i] = sWireless_ASCIItoRSETable[q2[i]];
+ }
+ q1[i] = EOS;
+}
+
+#ifdef NONMATCHING
+u8 sub_800DD1C(u8 maxFlags)
+{
+ u8 flagCount = 0;
+ u8 flags = gUnknown_03007890->unk_02;
+ u8 i;
+
+ if (gUnknown_03007890->unk_00 == 1)
+ {
+ i = 0;
+ for (i = 0; i < 4; flags >>= 1, i++)
+ {
+ if (flags & 1)
+ {
+ if (maxFlags == flagCount + 1)
+ {
+ return gUnknown_03007890->unk_0a[i];
+ }
+ flagCount++;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < 4; flags >>= 1, i++)
+ {
+ if (flags & 1)
+ {
+ return gUnknown_03007890->unk_0a[i];
+ }
+ }
+ }
+ return 0;
+}
+#else
+ASM_DIRECT u8 sub_800DD1C(u8 maxFlags)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r5, r0, 24\n"
+ "\tmovs r6, 0\n"
+ "\tldr r0, =gUnknown_03007890\n"
+ "\tldr r4, [r0]\n"
+ "\tldrb r2, [r4, 0x2]\n"
+ "\tldrb r1, [r4]\n"
+ "\tadds r7, r0, 0\n"
+ "\tcmp r1, 0x1\n"
+ "\tbne _0800DD72\n"
+ "\tmovs r3, 0\n"
+ "\tands r1, r2\n"
+ "\tcmp r1, 0\n"
+ "\tbeq _0800DD4E\n"
+ "\tcmp r5, 0x1\n"
+ "\tbne _0800DD48\n"
+ "\tldrb r0, [r4, 0xA]\n"
+ "\tb _0800DD8C\n"
+ "\t.pool\n"
+ "_0800DD48:\n"
+ "\tadds r0, r6, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r6, r0, 24\n"
+ "_0800DD4E:\n"
+ "\tlsrs r2, 1\n"
+ "\tadds r0, r3, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r3, r0, 24\n"
+ "\tcmp r3, 0x3\n"
+ "\tbhi _0800DD8A\n"
+ "\tmovs r0, 0x1\n"
+ "\tands r0, r2\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0800DD4E\n"
+ "\tadds r0, r6, 0x1\n"
+ "\tcmp r5, r0\n"
+ "\tbne _0800DD48\n"
+ "_0800DD68:\n"
+ "\tldr r0, [r7]\n"
+ "\tadds r0, 0xA\n"
+ "\tadds r0, r3\n"
+ "\tldrb r0, [r0]\n"
+ "\tb _0800DD8C\n"
+ "_0800DD72:\n"
+ "\tmovs r3, 0\n"
+ "\tmovs r1, 0x1\n"
+ "_0800DD76:\n"
+ "\tadds r0, r2, 0\n"
+ "\tands r0, r1\n"
+ "\tcmp r0, 0\n"
+ "\tbne _0800DD68\n"
+ "\tlsrs r2, 1\n"
+ "\tadds r0, r3, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r3, r0, 24\n"
+ "\tcmp r3, 0x3\n"
+ "\tbls _0800DD76\n"
+ "_0800DD8A:\n"
+ "\tmovs r0, 0\n"
+ "_0800DD8C:\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1");
+}
+#endif
+
+void sub_800DD94(struct UnkLinkRfuStruct_02022B14 *data, u8 r9, bool32 r2, int r3)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ data->playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
+ }
+ for (i = 0; i < 4; i++)
+ {
+ data->unk_04[i] = r3;
+ r3 >>= 8;
+ }
+ data->playerGender = gSaveBlock2Ptr->playerGender;
+ data->unk_0a_0 = r9;
+ data->unk_0a_7 = r2;
+ data->unk_00_0 = 2;
+ data->unk_01_2 = 3;
+ data->unk_00_4 = 0;
+ data->unk_00_5 = 0;
+ data->unk_00_6 = 0;
+ data->unk_00_7 = FlagGet(FLAG_0x87F);
+ data->unk_01_0 = IsNationalPokedexEnabled();
+ data->unk_01_1 = FlagGet(FLAG_SYS_GAME_CLEAR);
+}
+
+bool8 sub_800DE7C(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2, u8 idx)
+{
+ bool8 retVal;
+
+ if (gUnknown_03004140.unk_06 == 1)
+ {
+ retVal = TRUE;
+ if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04) && ((gUnknown_03007890->unk_07 >> idx) & 1))
+ {
+ memcpy(buff1, &gUnknown_03007890->unk_14[idx].unk_06, sizeof(gUnknown_03007890->unk_14[idx].unk_06));
+ memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, sizeof(gUnknown_03007890->unk_14[idx].unk_15));
+ }
+ else
+ {
+ memset(buff1, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_06));
+ memset(buff2, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_15));
+ }
+ }
+ else
+ {
+ retVal = FALSE;
+ if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04))
+ {
+ memcpy(buff1, &gUnknown_03007890->unk_14[idx].unk_06, sizeof(gUnknown_03007890->unk_14[idx].unk_06));
+ memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, sizeof(gUnknown_03007890->unk_14[idx].unk_15));
+ }
+ else
+ {
+ memset(buff1, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_06));
+ memset(buff2, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_15));
+ }
+ }
+ return retVal;
+}
+
+bool8 sub_800DF34(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2, u8 idx)
+{
+ bool8 retVal = FALSE;
+ if (gUnknown_03007890->unk_14[idx].unk_04 == 0x7F7D)
+ {
+ *buff1 = gUnknown_03007890->unk_14[idx].unk_06;
+ memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, 8);
+ retVal = TRUE;
+ }
+ else
+ {
+ *buff1 = (struct UnkLinkRfuStruct_02022B14){};
+ memset(buff2, 0, 8);
+ }
+ return retVal;
+}
+
+void sub_800DF90(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2)
+{
+ *buff1 = gUnknown_02022B14;
+ memcpy(buff2, gUnknown_02022B22, 8);
+}
+
+void CreateWirelessStatusIndicatorSprite(u8 x, u8 y)
+{
+ u8 sprId;
+
+ if (x == 0 && y == 0)
+ {
+ x = 0xE7;
+ y = 0x08;
+ }
+ if (gUnknown_03007890->unk_00 == 1)
+ {
+ sprId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0);
+ gSprites[sprId].data[7] = 0x1234;
+ gSprites[sprId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag);
+ gSprites[sprId].invisible = TRUE;
+ gWirelessStatusIndicatorSpriteId = sprId;
+ }
+ else
+ {
+ gWirelessStatusIndicatorSpriteId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0);
+ gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0x1234;
+ gSprites[gWirelessStatusIndicatorSpriteId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag);
+ gSprites[gWirelessStatusIndicatorSpriteId].invisible = TRUE;
+ }
+}
+
+void sub_800E084(void)
+{
+ if (gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234)
+ {
+ gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0;
+ DestroySprite(&gSprites[gWirelessStatusIndicatorSpriteId]);
+ gMain.oamBuffer[125] = gDummyOamData;
+ CpuCopy16(&gDummyOamData, (struct OamData *)OAM + 125, sizeof(struct OamData));
+ }
+}
+
+void sub_800E0E8(void)
+{
+ if (GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag) == 0xFFFF)
+ {
+ LoadCompressedObjectPic(&sWirelessStatusIndicatorSpriteSheet);
+ }
+ LoadSpritePalette(&sWirelessStatusIndicatorSpritePalette);
+ gWirelessStatusIndicatorSpriteId = 0xFF;
+}
+
+u8 sub_800E124(void)
+{
+ u8 i;
+ u8 flags = gUnknown_03007890->unk_02;
+ for (i = 0; i < 4; i++)
+ {
+ if (flags & 1)
+ {
+ return gUnknown_03007890->unk_0a[i];
+ }
+ flags >>= 1;
+ }
+ return 0;
+}
+
+void sub_800E15C(struct Sprite *sprite, int signalStrengthAnimNum)
+{
+ if (sprite->data[2] != signalStrengthAnimNum)
+ {
+ sprite->data[2] = signalStrengthAnimNum;
+ sprite->data[3] = 0;
+ sprite->data[4] = 0;
+ }
+}
+
+void sub_800E174(void)
+{
+ if (gWirelessStatusIndicatorSpriteId != 0xFF && gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234)
+ {
+ struct Sprite *sprite = &gSprites[gWirelessStatusIndicatorSpriteId];
+ u8 signalStrength = 255;
+ u8 i = 0;
+ if (gUnknown_03007890->unk_00 == 1)
+ {
+ for (i = 0; i < GetLinkPlayerCount() - 1; i++)
+ {
+ if (signalStrength >= sub_800DD1C(i + 1))
+ {
+ signalStrength = sub_800DD1C(i + 1);
+ }
+ }
+ }
+ else
+ {
+ signalStrength = sub_800E124();
+ }
+ if (sub_8012224() == TRUE)
+ {
+ sprite->data[0] = 4;
+ }
+ else if (signalStrength < 25)
+ {
+ sprite->data[0] = 3;
+ }
+ else if (signalStrength >= 25 && signalStrength < 127)
+ {
+ sprite->data[0] = 2;
+ }
+ else if (signalStrength >= 127 && signalStrength < 229)
+ {
+ sprite->data[0] = 1;
+ }
+ else if (signalStrength >= 229)
+ {
+ sprite->data[0] = 0;
+ }
+ if (sprite->data[0] != sprite->data[1])
+ {
+ sub_800E15C(sprite, sprite->data[0]);
+ sprite->data[1] = sprite->data[0];
+ }
+ if (sprite->anims[sprite->data[2]][sprite->data[4]].frame.duration < sprite->data[3])
+ {
+ sprite->data[4]++;
+ sprite->data[3] = 0;
+ if (sprite->anims[sprite->data[2]][sprite->data[4]].type == -2)
+ {
+ sprite->data[4] = 0;
+ }
+ }
+ else
+ {
+ sprite->data[3]++;
+ }
+ gMain.oamBuffer[125] = sWirelessStatusIndicatorOamData;
+ gMain.oamBuffer[125].x = sprite->pos1.x + sprite->centerToCornerVecX;
+ gMain.oamBuffer[125].y = sprite->pos1.y + sprite->centerToCornerVecY;
+ gMain.oamBuffer[125].paletteNum = sprite->oam.paletteNum;
+ gMain.oamBuffer[125].tileNum = sprite->data[6] + sprite->anims[sprite->data[2]][sprite->data[4]].frame.imageValue;
+ CpuCopy16(gMain.oamBuffer + 125, (struct OamData *)OAM + 125, sizeof(struct OamData));
+ if (sub_8011A74() == 1)
+ {
+ sub_800E084();
+ }
+ }
+}
+
+void sub_800E378(struct UnkSaveSubstruct_3b98 *dest, u32 trainerId, const u8 *name)
+{
+ dest->trainerId = trainerId;
+ StringCopy(dest->trainerName, name);
+}
+
+bool32 sub_800E388(const u8 *name)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (name[i] != 0)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_800E3A8(void)
+{
+ if (gWirelessCommType != 0)
+ {
+ int i;
+ int j;
+ int cnt;
+ int sp0[5];
+ struct UnkSaveSubstruct_3b98 *sp14 = calloc(20, sizeof(struct UnkSaveSubstruct_3b98));
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ sp0[i] = -1;
+ for (j = 0; j < 20; j++)
+ {
+ if ((u16)gLinkPlayers[i].trainerId == gSaveBlock1Ptr->unk_3B98[j].trainerId && StringCompare(gLinkPlayers[i].name, gSaveBlock1Ptr->unk_3B98[j].trainerName) == 0)
+ {
+ sp0[i] = j;
+ }
+ }
+ }
+ cnt = 0;
+ for (i = 0; i < GetLinkPlayerCount(); i++)
+ {
+ if (i != GetMultiplayerId() && gLinkPlayers[i].language != LANGUAGE_JAPANESE)
+ {
+ sub_800E378(&sp14[cnt], (u16)gLinkPlayers[i].trainerId, gLinkPlayers[i].name);
+ if (sp0[i] >= 0)
+ {
+ memset(gSaveBlock1Ptr->unk_3B98[sp0[i]].trainerName, 0, 8);
+ }
+ cnt++;
+ }
+ }
+ for (i = 0; i < 20; i++)
+ {
+ if (sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName))
+ {
+ sub_800E378(&sp14[cnt], gSaveBlock1Ptr->unk_3B98[i].trainerId, gSaveBlock1Ptr->unk_3B98[i].trainerName);
+ if (++cnt >= 20)
+ {
+ break;
+ }
+ }
+ }
+ memcpy(gSaveBlock1Ptr->unk_3B98, sp14, 20 * sizeof(struct UnkSaveSubstruct_3b98));
+ free(sp14);
+ }
+}
+
+bool32 sub_800E540(u16 id, u8 *name)
+{
+ int i;
+
+ for (i = 0; i < 20; i++)
+ {
+ if (StringCompare(gSaveBlock1Ptr->unk_3B98[i].trainerName, name) == 0 && gSaveBlock1Ptr->unk_3B98[i].trainerId == id)
+ {
+ return TRUE;
+ }
+ if (!sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName))
+ {
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_800E5AC(void)
+{
+ int i;
+
+ for (i = 0; i < 20; i++)
+ {
+ gSaveBlock1Ptr->unk_3B98[i].trainerId = 0;
+ CpuFill16(0, gSaveBlock1Ptr->unk_3B98[i].trainerName, 8);
+ }
+}
+
+void nullsub_5(void *unused_0, u8 unused_1, u8 unused_2)
+{
+ // debug?
+}
+
+void nullsub_13(u8 unused_0, u8 unused_1, u8 unused_2, u8 unused_3)
+{
+
+}
+
+void sub_800E604(void)
+{
+ int i;
+ u8 unk_ee_bak = gUnknown_03005000.unk_ee;
+ CpuFill16(0, &gUnknown_03005000, sizeof gUnknown_03005000);
+ gUnknown_03005000.unk_ee = unk_ee_bak;
+ gUnknown_03005000.unk_0c = 0xFF;
+ if (gUnknown_03005000.unk_ee != 4)
+ {
+ gUnknown_03005000.unk_ee = 0;
+ }
+ for (i = 0; i < 5; i++)
+ {
+ sub_800FCC4(gUnknown_03005000.unk_80 + i);
+ }
+ sub_800FCC4(&gUnknown_03005000.unk_6c);
+ sub_800D6C8(&gUnknown_03005000.unk_124);
+ sub_800D724(&gUnknown_03005000.unk_9e8);
+ CpuFill16(0, gSendCmd, sizeof gSendCmd);
+ CpuFill16(0, gRecvCmds, sizeof gRecvCmds);
+ CpuFill16(0, gLinkPlayers, sizeof gLinkPlayers)
+}
+
+void sub_800E6D0(void)
+{
+ IntrFunc serialIntr = gIntrTable[1];
+ IntrFunc timerIntr = gIntrTable[2];
+ sub_800E700();
+ rfu_REQ_stopMode();
+ rfu_waitREQComplete();
+ REG_IME = 0;
+ gIntrTable[1] = serialIntr;
+ gIntrTable[2] = timerIntr;
+ REG_IME = INTR_FLAG_VBLANK;
+}
+
+void sub_800E700(void)
+{
+ if (!rfu_initializeAPI(gUnknown_03004140.unk_50, sizeof gUnknown_03004140.unk_50, gIntrTable + 1, TRUE))
+ {
+ gLinkType = 0;
+ sub_800AAF4();
+ sub_80111B0(0);
+ sub_800E604();
+ rfu_setTimerInterrupt(3, gIntrTable + 2);
+ }
+}
+
+void sub_800E748(u8 taskId)
+{
+ sub_8010750();
+ switch (gUnknown_03005000.unk_04)
+ {
+ case 0:
+ sub_800BFCC(&gUnknown_02022B2C);
+ gUnknown_03005000.unk_04 = 1;
+ gTasks[taskId].data[1] = 1;
+ break;
+ case 1:
+ break;
+ case 2:
+ sub_800C054(gUnknown_03005000.unk_0c, 0, 240, gUnknown_082ED6E0);
+ gUnknown_03005000.unk_04 = 3;
+ gTasks[taskId].data[1] = 6;
+ break;
+ case 3:
+ break;
+ case 4:
+ sub_800C27C(FALSE);
+ gUnknown_03005000.unk_04 = 5;
+ break;
+ case 5:
+ break;
+ case 18:
+ gUnknown_03005000.unk_cdb = 0;
+ sub_800D52C(sub_800EDBC);
+ sub_800EAB4();
+ sub_800EAFC();
+ gUnknown_03005000.unk_04 = 20;
+ gTasks[taskId].data[1] = 8;
+ CreateTask(sub_801084C, 5);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+u8 sub_800E87C(u8 idx)
+{
+ return gUnknown_082ED6A5[idx];
+}
+
+void sub_800E88C(int r2, int r5)
+{
+ u8 i;
+ u8 r4 = 1;
+ int r1 = r2;
+ int r6 = 0;
+ if (r5 == -1)
+ {
+ for (i = 0; i < 4; r2 >>= 1, i++)
+ {
+ if (r2 & 1)
+ {
+ gUnknown_03005000.unk_cde[i] = r4;
+ r4++;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < 4; r1 >>= 1, i++)
+ {
+ if (!(r1 & 1))
+ {
+ gUnknown_03005000.unk_cde[i] = 0;
+ }
+ }
+ for (r4 = 4; r4 != 0; r4--)
+ {
+ for (i = 0; i < 4 && gUnknown_03005000.unk_cde[i] != r4; i++);
+ if (i == 4)
+ {
+ r6 = r4;
+ }
+ }
+ for (r5 &= ~r2, i = 0; i < 4; r5 >>= 1, i++)
+ {
+ if (r5 & 1)
+ {
+ gUnknown_03005000.unk_cde[i] = r6++;
+ }
+ }
+ }
+}
+
+void sub_800E94C(u8 taskId)
+{
+ switch (gUnknown_03005000.unk_04)
+ {
+ case 0:
+ sub_800BFCC(&gUnknown_082ED608);
+ gUnknown_03005000.unk_04 = 1;
+ gTasks[taskId].data[1] = 1;
+ break;
+ case 1:
+ break;
+ case 6:
+ sub_800C054(gUnknown_03005000.unk_0c, 0, 0xf0, gUnknown_082ED6E0);
+ gUnknown_03005000.unk_04 = 7;
+ gTasks[taskId].data[1] = 7;
+ break;
+ case 7:
+ break;
+ case 9:
+ gTasks[taskId].data[1] = 10;
+ break;
+ case 11:
+ switch (sub_80107A0())
+ {
+ case 5:
+ gUnknown_03005000.unk_04 = 12;
+ break;
+ case 6:
+ case 9:
+ sub_800D630();
+ gUnknown_03005000.unk_ce4 = 2;
+ DestroyTask(taskId);
+ break;
+ }
+ break;
+ case 12:
+ {
+ u8 r5 = 1 << gUnknown_03005000.unk_c3e;
+ rfu_clearSlot(12, gUnknown_03005000.unk_c3e);
+ rfu_setRecvBuffer(16, gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_c3f, 70);
+ rfu_UNI_setSendData(r5, gUnknown_03005000.unk_4c, 14);
+ gTasks[taskId].data[1] = 8;
+ DestroyTask(taskId);
+ if (gUnknown_02022B44.unk_0f == 0)
+ {
+ sub_801227C();
+ gUnknown_02022B44.unk_0f++;
+ }
+ CreateTask(sub_801084C, 5);
+ break;
+ }
+ }
+}
+
+static void sub_800EAB4(void)
+{
+ u8 i;
+ u8 r5 = gUnknown_03004140.unk_00;
+ for (i = 0; i < 4; i++)
+ {
+ if (r5 & 1)
+ {
+ rfu_setRecvBuffer(16, i, gUnknown_03005000.unk_14[i], 14);
+ rfu_clearSlot(3, i);
+ }
+ r5 >>= 1;
+ }
+}
+
+static void sub_800EAFC(void)
+{
+ u8 r5 = gUnknown_03004140.unk_00;
+ rfu_UNI_setSendData(r5, gUnknown_03005000.unk_c87, 70);
+ gUnknown_03005000.unk_cda = sub_800E87C(r5);
+ gUnknown_03005000.unk_ce2 = r5;
+ sub_800E88C(r5, -1);
+ gUnknown_03005000.unk_0c = 1;
+}
+
+void sub_800EB44(u8 taskId)
+{
+ if (sub_800F7DC()->unk_0a_0 == 0x54 && sub_8011A74() == 4)
+ {
+ rfu_REQ_disconnect(gUnknown_03004140.unk_00);
+ rfu_waitREQComplete();
+ sub_8011A64(0, 0);
+ }
+ switch (gUnknown_03005000.unk_04)
+ {
+ case 0:
+ sub_800BFCC(&gUnknown_02022B2C);
+ gUnknown_03005000.unk_04 = 1;
+ gTasks[taskId].data[1] = 1;
+ break;
+ case 1:
+ break;
+ case 17:
+ sub_800C054(2, 0, 240, gUnknown_082ED6E0);
+ sub_800D52C(sub_800ED34);
+ gUnknown_03005000.unk_04 = 18;
+ break;
+ case 18:
+ break;
+ case 13:
+ if (rfu_UNI_setSendData(1 << gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_4c, 14) == 0)
+ {
+ gUnknown_03005000.unk_0c = 0;
+ DestroyTask(taskId);
+ if (gTasks[taskId].data[7])
+ {
+ CreateTask(sub_8010D0C, 1);
+ }
+ else
+ {
+ CreateTask(sub_801084C, 5);
+ }
+ }
+ break;
+ case 14:
+ sub_800C27C(0);
+ gUnknown_03005000.unk_04 = 15;
+ break;
+ case 15:
+ break;
+ case 16:
+ gUnknown_03005000.unk_cdb = 0;
+ sub_800D52C(sub_800EDBC);
+ sub_8011068(1);
+ sub_800EAB4();
+ sub_800EAFC();
+ gUnknown_03005000.unk_04 = 20;
+ gTasks[taskId].data[1] = 8;
+ gUnknown_03005000.unk_0c = 1;
+ CreateTask(sub_801084C, 5);
+ gUnknown_03005000.unk_ce8 = 1;
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_800ED10(void)
+{
+ sub_800C054(1, 0, 240, gUnknown_082ED6E0);
+}
+
+void sub_800ED28(void)
+{
+ sub_800C27C(FALSE);
+}
+
+void sub_800ED34(u16 unused)
+{
+ int i;
+
+ for (i = 0; i < 14; i++)
+ {
+ gUnknown_03005000.unk_4c[i] = 0;
+ }
+ rfu_REQ_recvData();
+ rfu_waitREQComplete();
+ if (gUnknown_03007870[gUnknown_03005000.unk_c3e]->unk_12)
+ {
+ gUnknown_03005000.unk_cd0++;
+ sub_800D7D8(&gUnknown_03005000.unk_124, gUnknown_03005000.unk_c3f);
+ gUnknown_02022B44.unk_06++;
+ sub_800F048();
+ rfu_UNI_readySendData(gUnknown_03005000.unk_c3e);
+ rfu_UNI_clearRecvNewDataFlag(gUnknown_03005000.unk_c3e);
+ }
+ rfu_REQ_sendData_wrapper(1);
+}
+
+static void sub_800EDBC(u16 unused)
+{
+ gUnknown_03005000.unk_cdb = 1;
+}
+
+void sub_800EDD4(void)
+{
+ u8 i;
+
+ sub_800C048();
+ if (gUnknown_03005000.unk_0c == 1)
+ {
+ if (FuncIsActiveTask(sub_800E748) == TRUE)
+ {
+ DestroyTask(gUnknown_03005000.unk_67);
+ sub_800E604();
+ }
+ }
+ else if (gUnknown_03005000.unk_0c == 0)
+ {
+ if (FuncIsActiveTask(sub_800E94C) == TRUE)
+ {
+ DestroyTask(gUnknown_03005000.unk_67);
+ sub_800E604();
+ }
+ }
+ else if (gUnknown_03005000.unk_0c == 2)
+ {
+ if (FuncIsActiveTask(sub_800EB44) == TRUE)
+ {
+ DestroyTask(gUnknown_03005000.unk_67);
+ sub_800E604();
+ }
+ }
+ for (i = 0; i < 3; i++)
+ {
+ if (FuncIsActiveTask(gUnknown_082ED7E0[i]) == TRUE)
+ {
+ DestroyTask(FindTaskIdByFunc(gUnknown_082ED7E0[i]));
+ }
+ }
+}
+
+void sub_800EE78(void)
+{
+ gUnknown_03005000.unk_67 = CreateTask(sub_800E748, 1);
+}
+
+bool8 sub_800EE94(void)
+{
+ if (gUnknown_03005000.unk_04 == 7 && gUnknown_03005000.unk_ccd)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_800EEBC(void)
+{
+ if (gUnknown_03005000.unk_04 == 7 && !sub_800C12C(gUnknown_03007890->unk_14[gUnknown_03005000.unk_c3d].unk_00, 240))
+ {
+ gUnknown_03005000.unk_04 = 9;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_800EF00(void)
+{
+ gUnknown_03005000.unk_67 = CreateTask(sub_800E94C, 1);
+}
+
+bool8 sub_800EF1C(void)
+{
+ if (gUnknown_03004140.unk_00)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_800EF38(void)
+{
+ gUnknown_03005000.unk_04 = 4;
+ gUnknown_03005000.unk_ce7 = gUnknown_03004140.unk_00;
+}
+
+bool8 sub_800EF58(bool32 a0)
+{
+ if (gUnknown_03005000.unk_04 == 17 || a0)
+ {
+ gUnknown_03005000.unk_04 = 18;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_800EF7C(void)
+{
+ gUnknown_03005000.unk_04 = 14;
+}
+
+void sub_800EF88(u8 a0)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (a0 & 1)
+ {
+ rfu_UNI_readySendData(i);
+ break;
+ }
+ a0 >>= 1;
+ }
+}
+
+#ifdef NONMATCHING
+// FIXME: gUnknown_03005000.unk_c87 should be in r5
+// FIXME: gRecvCmds should be in r6 and r7
+void sub_800EFB0(void)
+{
+ int i, j;
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 7; j++)
+ {
+ gUnknown_03005000.unk_c87[i][j][1] = gRecvCmds[i][j] >> 8;
+ gUnknown_03005000.unk_c87[i][j][0] = gRecvCmds[i][j];
+ }
+ }
+ CpuFill16(0, gRecvCmds, sizeof gRecvCmds);
+}
+#else
+ASM_DIRECT void sub_800EFB0(void)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tsub sp, 0x4\n"
+ "\tmovs r2, 0\n"
+ "\tldr r7, =gRecvCmds\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r6, r7, 0\n"
+ "\tldr r1, =0x00000c87\n"
+ "\tadds r5, r0, r1\n"
+ "_0800EFC0:\n"
+ "\tmovs r3, 0\n"
+ "\tlsls r0, r2, 3\n"
+ "\tlsls r1, r2, 4\n"
+ "\tadds r4, r2, 0x1\n"
+ "\tsubs r0, r2\n"
+ "\tlsls r0, 1\n"
+ "\tadds r2, r0, r5\n"
+ "\tadds r1, r6\n"
+ "_0800EFD0:\n"
+ "\tldrh r0, [r1]\n"
+ "\tlsrs r0, 8\n"
+ "\tstrb r0, [r2, 0x1]\n"
+ "\tldrh r0, [r1]\n"
+ "\tstrb r0, [r2]\n"
+ "\tadds r2, 0x2\n"
+ "\tadds r1, 0x2\n"
+ "\tadds r3, 0x1\n"
+ "\tcmp r3, 0x6\n"
+ "\tble _0800EFD0\n"
+ "\tadds r2, r4, 0\n"
+ "\tcmp r2, 0x4\n"
+ "\tble _0800EFC0\n"
+ "\tmovs r0, 0\n"
+ "\tmov r1, sp\n"
+ "\tstrh r0, [r1]\n"
+ "\tldr r2, =0x01000028\n"
+ "\tmov r0, sp\n"
+ "\tadds r1, r7, 0\n"
+ "\tbl CpuSet\n"
+ "\tadd sp, 0x4\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.pool");
+}
+#endif
+
+void sub_800F014(void)
+{
+ int i;
+ for (i = 0; i < 7; i++)
+ {
+ gRecvCmds[0][i] = gSendCmd[i];
+ }
+ for (i = 0; i < 7; i++)
+ {
+ gSendCmd[i] = 0;
+ }
+}
+
+static void sub_800F048(void)
+{
+ if (gUnknown_03005000.unk_c3c)
+ {
+ u8 r2 = sub_800DAC8(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c);
+ if (gUnknown_03005000.unk_c1c.unk_1e == 0)
+ {
+ gUnknown_03005000.unk_c3c = 0;
+ }
+ if (r2)
+ {
+ return;
+ }
+ }
+ if (gUnknown_03005000.unk_c3c == 0)
+ {
+ sub_800D9DC(&gUnknown_03005000.unk_9e8, gUnknown_03005000.unk_4c);
+ sub_800DA68(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c);
+ }
+}
+
+bool32 sub_800F0B8(void)
+{
+ int i;
+ int j;
+
+ if (gUnknown_03007890->unk_06 == 0)
+ {
+ return FALSE;
+ }
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 7; j++)
+ {
+ if (gRecvCmds[i][j] != 0)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+bool32 sub_800F0F8(void)
+{
+ if (gUnknown_03005000.unk_04 < 20)
+ {
+ rfu_REQ_recvData();
+ rfu_waitREQComplete();
+ rfu_REQ_sendData_wrapper(0);
+ }
+ else
+ {
+ gUnknown_03005000.unk_cdb = 0;
+ if ((gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02) == gUnknown_03005000.unk_ce2 && (gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02))
+ {
+ if (!gUnknown_03005000.unk_cdc)
+ {
+ if (gUnknown_03005000.unk_ce3)
+ {
+ sub_8011D6C(gUnknown_03005000.unk_ce3);
+ gUnknown_03005000.unk_ce3 = 0;
+ if (gUnknown_03005000.unk_ce4 == 1)
+ {
+ sub_8011A64(2, 0x8000);
+ sub_8011170(0x8000);
+ return FALSE;
+ }
+ if (!gUnknown_03004140.unk_00)
+ {
+ sub_800EDD4();
+ gReceivedRemoteLinkPlayers = 0;
+ return FALSE;
+ }
+ }
+ sub_800EFB0();
+ rfu_UNI_readySendData(gUnknown_03005000.unk_cda);
+ rfu_REQ_sendData_wrapper(1);
+ }
+ else
+ {
+ rfu_REQ_PARENT_resumeRetransmitAndChange();
+ }
+ gUnknown_03005000.unk_0e = 1;
+ }
+ }
+ return FALSE;
+}
+
+bool32 sub_800F1E0(void)
+{
+ u16 i;
+ u16 flags;
+ u8 r0;
+ u16 j;
+ u8 retval;
+
+ if (gUnknown_03005000.unk_04 >= 20 && gUnknown_03005000.unk_0e == 1)
+ {
+ rfu_waitREQComplete();
+ while (gUnknown_03005000.unk_cdb == 0)
+ {
+ if (gUnknown_03005000.unk_ee != 0)
+ {
+ return FALSE;
+ }
+ }
+ rfu_REQ_recvData();
+ rfu_waitREQComplete();
+ if ((gUnknown_03004140.unk_03 & gUnknown_03005000.unk_ce2) == gUnknown_03005000.unk_ce2)
+ {
+ gUnknown_03005000.unk_cdc = 0;
+ gUnknown_02022B44.unk_06++;
+ flags = gUnknown_03004140.unk_00;
+ for (i = 0; i < 4; i++)
+ {
+ if (flags & 1)
+ {
+ if (gUnknown_03005000.unk_14[i][1])
+ {
+ if (gUnknown_03005000.unk_cee[i] != 0xff && (gUnknown_03005000.unk_14[i][0] >> 5) != ((gUnknown_03005000.unk_cee[i] + 1) & 7))
+ {
+ if (++gUnknown_03005000.unk_cea[i] > 4)
+ sub_8011170(0x8100);
+ }
+ else
+ {
+ gUnknown_03005000.unk_cee[i] = gUnknown_03005000.unk_14[i][0] / 32;
+ gUnknown_03005000.unk_cea[i] = 0;
+ gUnknown_03005000.unk_14[i][0] &= 0x1f;
+ r0 = gUnknown_03005000.unk_cde[i];
+ for (j = 0; j < 7; j++)
+ {
+ gRecvCmds[r0][j] = (gUnknown_03005000.unk_14[i][(j << 1) + 1] << 8) | gUnknown_03005000.unk_14[i][(j << 1) + 0];
+ gUnknown_03005000.unk_14[i][(j << 1) + 1] = 0;
+ gUnknown_03005000.unk_14[i][(j << 1) + 0] = 0;
+ }
+ }
+ }
+ rfu_UNI_clearRecvNewDataFlag(i);
+ }
+ flags >>= 1;
+ }
+ sub_800F014();
+ sub_800F86C(0);
+ sub_8010528();
+ if (gUnknown_03005000.unk_ce5 && !gUnknown_03005000.unk_cd9)
+ {
+ gUnknown_02022B44.unk_0e = 0;
+ rfu_clearSlot(3, gUnknown_03005000.unk_cda);
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03005000.unk_ce5 >> i) & 1)
+ {
+ rfu_setRecvBuffer(0x10, i, gUnknown_03005000.unk_14[i], 14);
+ }
+ }
+ sub_800E88C(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_ce2 | gUnknown_03005000.unk_ce5);
+ gUnknown_03005000.unk_ce9 = gUnknown_03005000.unk_ce5;
+ gUnknown_03005000.unk_ce2 |= gUnknown_03005000.unk_ce5;
+ gUnknown_03005000.unk_ce5 = 0;
+ rfu_UNI_setSendData(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_c87, 70);
+ gUnknown_03005000.unk_cda = sub_800E87C(gUnknown_03005000.unk_ce2);
+ CreateTask(sub_8010AAC, 0);
+ }
+ }
+ else
+ {
+ gUnknown_03005000.unk_cdc = 1;
+ gUnknown_03005000.unk_0e = 0;
+ }
+ gUnknown_03005000.unk_0e = 0;
+ }
+ retval = gUnknown_03005000.unk_cdc;
+ return gUnknown_03007890->unk_06 ? retval & 1 : FALSE;
+}
+
+void sub_800F498(u16 *a0, u8 *a1)
+{
+ int i;
+
+ if (a0[0])
+ {
+ a0[0] |= (gUnknown_03005000.unk_102 << 5);
+ gUnknown_03005000.unk_102 = (gUnknown_03005000.unk_102 + 1) & 7;
+ for (i = 0; i < 7; i++)
+ {
+ a1[2 * i + 1] = a0[i] >> 8;
+ a1[2 * i + 0] = a0[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < 14; i++)
+ a1[i] = 0;
+ }
+}
+
+bool32 sub_800F4F0(void)
+{
+ u8 i;
+ u8 j;
+ u8 sp00[MAX_RFU_PLAYERS * (2 * (CMD_LENGTH - 1))];
+ u8 sp48[2 * (CMD_LENGTH - 1)];
+ u8 switchval;
+
+ sub_800D934(&gUnknown_03005000.unk_124, sp00);
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ for (j = 0; j < CMD_LENGTH - 1; j++)
+ {
+ gRecvCmds[i][j] = (sp00[i * 14 + (j << 1) + 1] << 8) | sp00[i * 14 + (j << 1) + 0];
+ }
+ }
+ sub_800F86C(0);
+ if (gUnknown_03004140.unk_02 == 0 && gUnknown_03005000.unk_ce4)
+ {
+ rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03);
+ rfu_waitREQComplete();
+ switchval = sub_8011A74();
+ if (switchval != 1 && switchval != 6 && switchval != 9)
+ sub_8011A64(2, 0x9000);
+ rfu_clearAllSlot();
+ gReceivedRemoteLinkPlayers = FALSE;
+ gUnknown_03005000.unk_00 = 0;
+ if (gUnknown_03005000.unk_ce4 == 1)
+ {
+ sub_8011A64(2, 0x9000);
+ sub_8011170(0x9000);
+ }
+ gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0;
+ gUnknown_03005000.unk_ce4 = 0;
+ }
+ if (gUnknown_03005000.unk_cd0)
+ {
+ gUnknown_03005000.unk_cd0--;
+ sub_8010528();
+ sub_800F498(gSendCmd, sp48);
+ sub_800D888(&gUnknown_03005000.unk_9e8, sp48);
+ for (i = 0; i < CMD_LENGTH - 1; i++)
+ gSendCmd[i] = 0;
+ }
+ return sub_800F0B8();
+}
+
+#ifdef NONMATCHING
+void sub_800F638(u8 unused, u32 flags)
+{
+ int i;
+ int j;
+
+ u8 *r10 = gUnknown_03005000.unk_6c.unk_04;
+ for (i = 0; i < gUnknown_03005000.unk_6c.unk_02; i++)
+ {
+ if (!(flags & 1))
+ {
+ gUnknown_03000D90[0] = (~0x76ff) | i;
+ for (j = 0; j < 7; j++)
+ {
+ gUnknown_03000D90[j + 1] = (r10[12 * i + (j << 1) + 1] << 8) | r10[12 * i + (j << 1) + 0];
+ }
+ for (j = 0; j < 7; j++)
+ // This should be an ascending loop.
+ // GCC compiles this as descending.
+ {
+ gUnknown_03000D80[2 * j + 1] = gUnknown_03000D90[j] >> 8;
+ gUnknown_03000D80[2 * j + 0] = gUnknown_03000D90[j];
+ }
+ sub_800D888(&gUnknown_03005000.unk_9e8, gUnknown_03000D80);
+ gUnknown_03005000.unk_6c.unk_0c |= (1 << i);
+ }
+ flags >>= 1;
+ }
+}
+#else
+ASM_DIRECT void sub_800F638(u8 unused, u32 flags)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tldr r2, [r0, 0x70]\n"
+ "\tmov r10, r2\n"
+ "\tmovs r5, 0\n"
+ "\tadds r2, r0, 0\n"
+ "\tadds r2, 0x6E\n"
+ "\tldrh r3, [r2]\n"
+ "\tcmp r5, r3\n"
+ "\tbge _0800F6D4\n"
+ "\tmov r9, r0\n"
+ "\tldr r0, =gUnknown_03000D90\n"
+ "\tmov r8, r0\n"
+ "_0800F65A:\n"
+ "\tmovs r0, 0x1\n"
+ "\tands r0, r1\n"
+ "\tlsrs r7, r1, 1\n"
+ "\tadds r6, r5, 0x1\n"
+ "\tcmp r0, 0\n"
+ "\tbne _0800F6C8\n"
+ "\tldr r1, =0xffff8900\n"
+ "\tadds r0, r1, 0\n"
+ "\tadds r1, r5, 0\n"
+ "\torrs r1, r0\n"
+ "\tmov r2, r8\n"
+ "\tstrh r1, [r2]\n"
+ "\tmovs r4, 0\n"
+ "\tlsls r0, r5, 1\n"
+ "\tldr r3, =gUnknown_03000D80\n"
+ "\tmov r12, r3\n"
+ "\tadds r0, r5\n"
+ "\tlsls r0, 2\n"
+ "\tmov r1, r10\n"
+ "\tadds r2, r0, r1\n"
+ "\tmov r3, r8\n"
+ "\tadds r3, 0x2\n"
+ "_0800F686:\n"
+ "\tldrb r1, [r2, 0x1]\n"
+ "\tlsls r1, 8\n"
+ "\tldrb r0, [r2]\n"
+ "\torrs r0, r1\n"
+ "\tstrh r0, [r3]\n"
+ "\tadds r2, 0x2\n"
+ "\tadds r3, 0x2\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x6\n"
+ "\tble _0800F686\n"
+ "\tmovs r4, 0\n"
+ "\tldr r2, =gUnknown_03000D90\n"
+ "\tldr r1, =gUnknown_03000D80\n"
+ "_0800F6A0:\n"
+ "\tldrh r0, [r2]\n"
+ "\tlsrs r0, 8\n"
+ "\tstrb r0, [r1, 0x1]\n"
+ "\tldrh r0, [r2]\n"
+ "\tstrb r0, [r1]\n"
+ "\tadds r2, 0x2\n"
+ "\tadds r1, 0x2\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x6\n"
+ "\tble _0800F6A0\n"
+ "\tldr r0, =gUnknown_03005000+0x9E8\n"
+ "\tmov r1, r12\n"
+ "\tbl sub_800D888\n"
+ "\tmovs r1, 0x1\n"
+ "\tlsls r1, r5\n"
+ "\tmov r2, r9\n"
+ "\tldr r0, [r2, 0x78]\n"
+ "\torrs r0, r1\n"
+ "\tstr r0, [r2, 0x78]\n"
+ "_0800F6C8:\n"
+ "\tadds r1, r7, 0\n"
+ "\tadds r5, r6, 0\n"
+ "\tldr r3, =gUnknown_03005000+0x6E\n"
+ "\tldrh r3, [r3]\n"
+ "\tcmp r5, r3\n"
+ "\tblt _0800F65A\n"
+ "_0800F6D4:\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.pool");
+}
+#endif
+
+void sub_800F6FC(u8 a0)
+{
+ if (gUnknown_03005000.unk_0c == 1 && a0)
+ gUnknown_03005000.unk_61[a0] = 1;
+ else
+ gUnknown_03005000.unk_5c[a0] = 1;
+}
+
+void sub_800F728(u8 a0)
+{
+ gUnknown_03005000.unk_5c[a0] = 0;
+ gUnknown_03005000.unk_80[a0].unk_12 = 0;
+}
+
+u8 sub_800F74C(const u8 *a0)
+{
+ u8 i;
+
+ if (gUnknown_03005000.unk_0c == 1)
+ return FALSE;
+ for (i = 0; i < 4; i++)
+ {
+ gUnknown_03005000.unk_cde[i] = a0[i];
+ }
+ return a0[gUnknown_03005000.unk_c3e];
+}
+
+void rfu_func_080F97B8(void)
+{
+ if (gReceivedRemoteLinkPlayers && gUnknown_03005DA8 && gLinkTransferringData != 1)
+ {
+ gUnknown_03000D78[0]++;
+ gUnknown_03005DA8 |= (gUnknown_03000D78[0] << 8);
+ sub_800FD14(0xbe00);
+ }
+}
+
+struct UnkLinkRfuStruct_02022B14 *sub_800F7DC(void)
+{
+ return &gUnknown_02022B14;
+}
+
+bool32 sub_800F7E4(void)
+{
+ return gUnknown_03005000.unk_00 == rfu_func_080F97B8;
+}
+
+void sub_800F804(void)
+{
+ gUnknown_03005000.unk_00 = rfu_func_080F97B8;
+}
+
+void Rfu_set_zero(void)
+{
+ gUnknown_03005000.unk_00 = NULL;
+}
+
+void sub_800F820(void)
+{
+ sub_800FD14(0x4400);
+ if (GetMultiplayerId() == 0)
+ gSendCmd[6] = GetBlenderArrowPosition();
+ gUnknown_020223C0++;
+}
+
+void sub_800F850(void)
+{
+ if (gUnknown_03005000.unk_00 == NULL)
+ gUnknown_03005000.unk_00 = sub_800F820;
+}
+
+static void sub_800F86C(u8 unused)
+{
+ u16 i;
+ u16 j;
+
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ switch (gRecvCmds[i][0] & 0xff00)
+ {
+ case 0x7800:
+ if (gUnknown_03005000.unk_0c == 0 && gReceivedRemoteLinkPlayers != 0)
+ return;
+ // fallthrough
+ case 0x7700:
+ if (gUnknown_03007890->unk_00 == 0)
+ {
+ gUnknown_03005000.playerCount = gRecvCmds[i][1];
+ gUnknown_03005000.unk_cce = sub_800F74C((u8 *)(gRecvCmds[i] + 2));
+ }
+ break;
+ case 0x8800:
+ if (gUnknown_03005000.unk_80[i].unk_12 == 0)
+ {
+ gUnknown_03005000.unk_80[i].unk_00 = 0;
+ gUnknown_03005000.unk_80[i].unk_02 = gRecvCmds[i][1];
+ gUnknown_03005000.unk_80[i].unk_11 = gRecvCmds[i][2];
+ gUnknown_03005000.unk_80[i].unk_08 = 0;
+ gUnknown_03005000.unk_80[i].unk_12 = 1;
+ gUnknown_03005000.unk_5c[i] = 0;
+ }
+ break;
+ case 0x8900:
+ if (gUnknown_03005000.unk_80[i].unk_12 == 1)
+ {
+ gUnknown_03005000.unk_80[i].unk_00 = gRecvCmds[i][0] & 0xff;
+ gUnknown_03005000.unk_80[i].unk_08 |= (1 << gUnknown_03005000.unk_80[i].unk_00);
+ for (j = 0; j < 6; j++)
+ gBlockRecvBuffer[i][gUnknown_03005000.unk_80[i].unk_00 * 6 + j] = gRecvCmds[i][j + 1];
+ if (gUnknown_03005000.unk_80[i].unk_08 == gUnknown_082ED628[gUnknown_03005000.unk_80[i].unk_02])
+ {
+ gUnknown_03005000.unk_80[i].unk_12 = 2;
+ sub_800F6FC(i);
+ if (sub_800F7DC()->unk_0a_0 == 0x45 && gReceivedRemoteLinkPlayers != 0 && gUnknown_03005000.unk_0c == 0)
+ sub_8010A70(gBlockRecvBuffer);
+ }
+ }
+ break;
+ case 0xa100:
+ sub_800FE84(gUnknown_082ED6B8[gRecvCmds[i][1]].buffer, (u16)gUnknown_082ED6B8[gRecvCmds[i][1]].size);
+ break;
+ case 0x5f00:
+ gUnknown_03005000.unk_e4[i] = 1;
+ break;
+ case 0x6600:
+ if (gUnknown_03005000.unk_100 == gRecvCmds[i][1])
+ gUnknown_03005000.unk_e9[i] = 1;
+ break;
+ case 0xed00:
+ if (gUnknown_03005000.unk_0c == 0)
+ {
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ if (gRecvCmds[i][1] & gUnknown_03007890->unk_02)
+ {
+ gReceivedRemoteLinkPlayers = 0;
+ sub_800D630();
+ gUnknown_03005000.unk_ce4 = gRecvCmds[i][2];
+ }
+ gUnknown_03005000.playerCount = gRecvCmds[i][3];
+ sub_80109E8(gRecvCmds[i][1]);
+ }
+ }
+ else
+ {
+ sub_800FD14(0xee00);
+ gSendCmd[1] = gRecvCmds[i][1];
+ gSendCmd[2] = gRecvCmds[i][2];
+ gSendCmd[3] = gRecvCmds[i][3];
+ }
+ break;
+ case 0xee00:
+ if (gUnknown_03005000.unk_0c == 1)
+ {
+ gUnknown_03005000.unk_ce3 |= gRecvCmds[i][1];
+ gUnknown_03005000.unk_ce4 = gRecvCmds[i][2];
+ sub_80109E8(gRecvCmds[i][1]);
+ }
+ break;
+ case 0x4400:
+ case 0xbe00:
+ gLinkPartnersHeldKeys[i] = gRecvCmds[i][1];
+ break;
+ }
+ if (gUnknown_03005000.unk_0c == 1 && gUnknown_03005000.unk_61[i])
+ {
+ if (gUnknown_03005000.unk_61[i] == 4)
+ {
+ gUnknown_03005000.unk_5c[i] = 1;
+ gUnknown_03005000.unk_61[i] = 0;
+ }
+ else
+ gUnknown_03005000.unk_61[i]++;
+ }
+ }
+}
+
+bool8 sub_800FC60(void)
+{
+ int i;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_03005000.unk_80[i].unk_12)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool8 sub_800FC88(void)
+{
+ int i;
+
+ for (i = 0; i < gUnknown_03005000.playerCount; i++)
+ {
+ if (gUnknown_03005000.unk_80[i].unk_12 != 2 || gUnknown_03005000.unk_5c[i] != 1)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data)
+{
+ data->unk_00 = 0;
+ data->unk_02 = 0;
+ data->unk_04 = NULL;
+ data->unk_08 = 0;
+ data->unk_10 = 0;
+ data->unk_11 = 0;
+ data->unk_12 = 0;
+}
+
+u8 sub_800FCD8(void)
+{
+ u8 flags = 0;
+ int i;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_03005000.unk_80[i].unk_12 == 2 && gUnknown_03005000.unk_5c[i] == 1)
+ {
+ flags |= (1 << i);
+ }
+ }
+ return flags;
+}
+
+#ifdef NONMATCHING
+// The switch tree is incorrect
+void sub_800FD14(u16 command)
+{
+ u8 i;
+ u8 *buff;
+ u8 tmp;
+
+ gSendCmd[0] = command;
+ switch (command)
+ {
+ case 0x8800:
+ gSendCmd[1] = gUnknown_03005000.unk_6c.unk_02;
+ gSendCmd[2] = gUnknown_03005000.unk_6c.unk_11 + 0x80;
+ break;
+ case 0xa100:
+ if (sub_800FC60())
+ gSendCmd[1] = gUnknown_03005000.unk_5a;
+ break;
+ case 0x7800:
+ case 0x7700:
+ tmp = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3;
+ gUnknown_03005000.playerCount = gUnknown_082ED695[tmp] + 1;
+ gSendCmd[1] = gUnknown_03005000.playerCount;
+ buff = (u8 *)(gSendCmd + 2);
+ for (i = 0; i < 4; i++)
+ buff[i] = gUnknown_03005000.unk_cde[i];
+ break;
+ case 0x6600:
+ case 0x5f00:
+ gSendCmd[1] = gUnknown_03005000.unk_100;
+ break;
+ case 0x4400:
+ gSendCmd[0] = 0x4400;
+ gSendCmd[1] = gMain.heldKeys;
+ break;
+ case 0x2f00:
+ for (i = 0; i < 6; i++)
+ gSendCmd[1 + i] = gUnknown_03005000.unk_f2[i];
+ break;
+ case 0xbe00:
+ gSendCmd[1] = gUnknown_03005DA8;
+ break;
+ }
+}
+#else
+ASM_DIRECT void sub_800FD14(u16 command)
+{
+ asm_unified("\tpush {r4,r5,lr}\n"
+ "\tlsls r0, 16\n"
+ "\tlsrs r1, r0, 16\n"
+ "\tldr r5, =gSendCmd\n"
+ "\tstrh r1, [r5]\n"
+ "\tmovs r0, 0xF0\n"
+ "\tlsls r0, 7\n"
+ "\tadds r4, r5, 0\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FDB0_case_7700_case_7800\n"
+ "\tcmp r1, r0\n"
+ "\tbgt _0800FD62\n"
+ "\tmovs r0, 0xBE\n"
+ "\tlsls r0, 7\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FE00_case_5f00_case_6600\n"
+ "\tcmp r1, r0\n"
+ "\tbgt _0800FD50\n"
+ "\tmovs r0, 0xBC\n"
+ "\tlsls r0, 6\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FE20_case_2f00\n"
+ "\tmovs r0, 0x88\n"
+ "\tlsls r0, 7\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FE14_case_4400\n"
+ "\tb _0800FE46_break\n"
+ "\t.pool\n"
+ "_0800FD50:\n"
+ "\tmovs r0, 0xCC\n"
+ "\tlsls r0, 7\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FE00_case_5f00_case_6600\n"
+ "\tmovs r0, 0xEE\n"
+ "\tlsls r0, 7\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FDB0_case_7700_case_7800\n"
+ "\tb _0800FE46_break\n"
+ "_0800FD62:\n"
+ "\tmovs r0, 0xBE\n"
+ "\tlsls r0, 8\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FE40_case_be00\n"
+ "\tcmp r1, r0\n"
+ "\tbgt _0800FE46_break\n"
+ "\tmovs r0, 0x88\n"
+ "\tlsls r0, 8\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FD80_case_8800\n"
+ "\tmovs r0, 0xA1\n"
+ "\tlsls r0, 8\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0800FD98_case_a100\n"
+ "\tb _0800FE46_break\n"
+ "_0800FD80_case_8800:\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r1, r0, 0\n"
+ "\tadds r1, 0x6E\n"
+ "\tldrh r1, [r1]\n"
+ "\tstrh r1, [r5, 0x2]\n"
+ "\tadds r0, 0x7D\n"
+ "\tldrb r0, [r0]\n"
+ "\tadds r0, 0x80\n"
+ "\tstrh r0, [r5, 0x4]\n"
+ "\tb _0800FE46_break\n"
+ "\t.pool\n"
+ "_0800FD98_case_a100:\n"
+ "\tbl sub_800FC60\n"
+ "\tlsls r0, 24\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0800FE46_break\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r0, 0x5A\n"
+ "\tldrb r0, [r0]\n"
+ "\tb _0800FE44_str_break\n"
+ "\t.pool\n"
+ "_0800FDB0_case_7700_case_7800:\n"
+ "\tldr r3, =gUnknown_03005000\n"
+ "\tldr r1, =0x00000ce2\n"
+ "\tadds r0, r3, r1\n"
+ "\tldr r2, =0x00000ce3\n"
+ "\tadds r1, r3, r2\n"
+ "\tldrb r2, [r0]\n"
+ "\tldrb r0, [r1]\n"
+ "\teors r0, r2\n"
+ "\tldr r1, =gUnknown_082ED695\n"
+ "\tadds r0, r1\n"
+ "\tldrb r0, [r0]\n"
+ "\tadds r0, 0x1\n"
+ "\tstrb r0, [r3, 0xD]\n"
+ "\tldrb r0, [r3, 0xD]\n"
+ "\tstrh r0, [r4, 0x2]\n"
+ "\tadds r2, r4, 0x4\n"
+ "\tmovs r4, 0\n"
+ "\tldr r0, =0x00000cde\n"
+ "\tadds r3, r0\n"
+ "_0800FDD6:\n"
+ "\tadds r1, r2, r4\n"
+ "\tadds r0, r4, r3\n"
+ "\tldrb r0, [r0]\n"
+ "\tstrb r0, [r1]\n"
+ "\tadds r0, r4, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r4, r0, 24\n"
+ "\tcmp r4, 0x3\n"
+ "\tbls _0800FDD6\n"
+ "\tb _0800FE46_break\n"
+ "\t.pool\n"
+ "_0800FE00_case_5f00_case_6600:\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tmovs r1, 0x80\n"
+ "\tlsls r1, 1\n"
+ "\tadds r0, r1\n"
+ "\tldrh r0, [r0]\n"
+ "\tstrh r0, [r4, 0x2]\n"
+ "\tb _0800FE46_break\n"
+ "\t.pool\n"
+ "_0800FE14_case_4400:\n"
+ "\tstrh r1, [r5]\n"
+ "\tldr r0, =gMain\n"
+ "\tldrh r0, [r0, 0x2C]\n"
+ "\tb _0800FE44_str_break\n"
+ "\t.pool\n"
+ "_0800FE20_case_2f00:\n"
+ "\tmovs r4, 0\n"
+ "\tldr r3, =gUnknown_03005000+0xF2\n"
+ "_0800FE24:\n"
+ "\tadds r2, r4, 0x1\n"
+ "\tlsls r1, r2, 1\n"
+ "\tadds r1, r5\n"
+ "\tlsls r0, r4, 1\n"
+ "\tadds r0, r3\n"
+ "\tldrh r0, [r0]\n"
+ "\tstrh r0, [r1]\n"
+ "\tlsls r2, 24\n"
+ "\tlsrs r4, r2, 24\n"
+ "\tcmp r4, 0x5\n"
+ "\tbls _0800FE24\n"
+ "\tb _0800FE46_break\n"
+ "\t.pool\n"
+ "_0800FE40_case_be00:\n"
+ "\tldr r0, =gUnknown_03005DA8\n"
+ "\tldrh r0, [r0]\n"
+ "_0800FE44_str_break:\n"
+ "\tstrh r0, [r5, 0x2]\n"
+ "_0800FE46_break:\n"
+ "\tpop {r4,r5}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.pool");
+}
+#endif
+
+void sub_800FE50(u16 *a0)
+{
+ if (gSendCmd[0] == 0 && sub_8011A80() == 0)
+ {
+ memcpy(gUnknown_03005000.unk_f2, a0, sizeof(gUnknown_03005000.unk_f2));
+ sub_800FD14(0x2f00);
+ }
+}
+
+bool32 sub_800FE84(const u8 *src, size_t size)
+{
+ bool8 r4;
+ if (gUnknown_03005000.unk_00 != NULL)
+ return FALSE;
+ if (gSendCmd[0] != 0)
+ return FALSE;
+ if (gUnknown_03005000.unk_6c.unk_10 != 0)
+ {
+ gUnknown_02022B44.unk_83++;
+ return FALSE;
+ }
+ r4 = (size % 12) != 0;
+ gUnknown_03005000.unk_6c.unk_11 = GetMultiplayerId();
+ gUnknown_03005000.unk_6c.unk_10 = 1;
+ gUnknown_03005000.unk_6c.unk_02 = (size / 12) + r4;
+ gUnknown_03005000.unk_6c.unk_00 = 0;
+ if (size > 0x100)
+ gUnknown_03005000.unk_6c.unk_04 = src;
+ else
+ {
+ if (src != gBlockSendBuffer)
+ memcpy(gBlockSendBuffer, src, size);
+ gUnknown_03005000.unk_6c.unk_04 = gBlockSendBuffer;
+ }
+ sub_800FD14(0x8800);
+ gUnknown_03005000.unk_00 = rfufunc_80F9F44;
+ gUnknown_03005000.unk_5b = 0;
+ return TRUE;
+}
+
+static void rfufunc_80F9F44(void)
+{
+ if (gSendCmd[0] == 0)
+ {
+ sub_800FD14(0x8800);
+ if (gUnknown_03005000.unk_0c == 1)
+ {
+ if (++gUnknown_03005000.unk_5b > 2)
+ gUnknown_03005000.unk_00 = sub_800FFB0;
+ }
+ else
+ {
+ if ((gRecvCmds[GetMultiplayerId()][0] & 0xff00) == 0x8800)
+ gUnknown_03005000.unk_00 = sub_800FFB0;
+ }
+ }
+}
+
+static void sub_800FFB0(void)
+{
+ int i;
+ const u8 *src = gUnknown_03005000.unk_6c.unk_04;
+ gSendCmd[0] = 0x8900 | gUnknown_03005000.unk_6c.unk_00;
+ for (i = 0; i < 7; i++)
+ gSendCmd[i + 1] = (src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 1] << 8) | src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 0];
+ gUnknown_03005000.unk_6c.unk_00++;
+ if (gUnknown_03005000.unk_6c.unk_02 <= gUnknown_03005000.unk_6c.unk_00)
+ {
+ gUnknown_03005000.unk_6c.unk_10 = 0;
+ gUnknown_03005000.unk_00 = rfufunc_80FA020;
+ }
+}
+
+static void rfufunc_80FA020(void)
+{
+ const u8 *src = gUnknown_03005000.unk_6c.unk_04;
+ u8 mpId = GetMultiplayerId();
+ int i;
+ if (gUnknown_03005000.unk_0c == 0)
+ {
+ gSendCmd[0] = (~0x76ff) | (gUnknown_03005000.unk_6c.unk_02 - 1);
+ for (i = 0; i < 7; i++)
+ gSendCmd[i + 1] = (src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 1] << 8) | src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 0];
+ if ((u8)gRecvCmds[mpId][0] == gUnknown_03005000.unk_6c.unk_02 - 1)
+ {
+ if (gUnknown_03005000.unk_80[mpId].unk_08 != gUnknown_082ED628[gUnknown_03005000.unk_80[mpId].unk_02])
+ {
+ sub_800F638(mpId, gUnknown_03005000.unk_80[mpId].unk_08);
+ gUnknown_02022B44.unk_64++;
+ }
+ else
+ gUnknown_03005000.unk_00 = NULL;
+ }
+ }
+ else
+ gUnknown_03005000.unk_00 = NULL;
+}
+
+bool8 sub_8010100(u8 a0)
+{
+ gUnknown_03005000.unk_5a = a0;
+ sub_800FD14(0xa100);
+ return TRUE;
+}
+
+void sub_801011C(void)
+{
+ rfu_clearAllSlot();
+ sub_800C048();
+ gReceivedRemoteLinkPlayers = 0;
+ gUnknown_03005000.unk_ef = 1;
+ gUnknown_03005000.unk_00 = NULL;
+}
+
+void sub_8010148(void)
+{
+ rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03);
+ rfu_waitREQComplete();
+ sub_801011C();
+}
+
+void sub_8010168(void)
+{
+ if (gUnknown_03005000.unk_0c == 0)
+ {
+ sub_800D630();
+ gUnknown_03005000.unk_ce4 = 2;
+ }
+ else
+ gUnknown_03005000.unk_00 = sub_8010148;
+}
+
+void sub_8010198(void)
+{
+ sub_800D630();
+ gUnknown_03005000.unk_ce4 = 1;
+ gUnknown_03005000.unk_ce3 = gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03;
+}
+
+void sub_80101CC(void)
+{
+ int i;
+ u8 playerCount = gUnknown_03005000.playerCount;
+ int count = 0;
+
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ if (gUnknown_03005000.unk_e4[i])
+ count++;
+ }
+ if (count == playerCount)
+ {
+ gBattleTypeFlags &= ~BATTLE_TYPE_20;
+ if (gUnknown_03005000.unk_0c == 0)
+ {
+ gUnknown_03005000.unk_ee = 3;
+ sub_8010168();
+ }
+ else
+ gUnknown_03005000.unk_00 = sub_8010168;
+ }
+}
+
+void sub_801022C(void)
+{
+ if (gSendCmd[0] == 0 && gUnknown_03005000.unk_ce8 == 0)
+ {
+ sub_800FD14(0x5f00);
+ gUnknown_03005000.unk_00 = sub_80101CC;
+ }
+}
+
+void sub_8010264(u8 taskId)
+{
+ if (gUnknown_03005000.unk_00 == NULL)
+ {
+ gUnknown_03005000.unk_cd9 = 1;
+ gUnknown_03005000.unk_00 = sub_801022C;
+ DestroyTask(taskId);
+ }
+}
+
+void task_add_05_task_del_08FA224_when_no_RfuFunc(void)
+{
+ if (!FuncIsActiveTask(sub_8010264))
+ CreateTask(sub_8010264, 5);
+}
+
+void sub_80102B8(void)
+{
+ u8 playerCount;
+ u8 i;
+
+ if (GetMultiplayerId() != 0)
+ {
+ u8 r4 = gUnknown_03005000.unk_124.unk_8c2;
+ if (r4 == 0 && gUnknown_03005000.unk_fe > 0x3c)
+ {
+ sub_800FD14(0x6600);
+ gUnknown_03005000.unk_fe = r4;
+ }
+ }
+ playerCount = GetLinkPlayerCount();
+ for (i = 0; i < playerCount; i++)
+ {
+ if (gUnknown_03005000.unk_e9[i] == 0)
+ break;
+ }
+ if (i == playerCount)
+ {
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ gUnknown_03005000.unk_e9[i] = 0;
+ gUnknown_03005000.unk_100++;
+ gUnknown_03005000.unk_00 = NULL;
+ }
+ gUnknown_03005000.unk_fe++;
+}
+
+void sub_8010358(void)
+{
+ if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0)
+ {
+ sub_800FD14(0x6600);
+ gUnknown_03005000.unk_00 = sub_80102B8;
+ }
+}
+
+void sub_8010390(void)
+{
+ u8 i;
+ u8 playerCount;
+
+ if (GetMultiplayerId() != 0)
+ {
+ if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0)
+ {
+ sub_800FD14(0x6600);
+ gUnknown_03005000.unk_00 = sub_80102B8;
+ }
+ }
+ else
+ {
+ playerCount = GetLinkPlayerCount();
+ for (i = 1; i < playerCount; i++)
+ {
+ if (gUnknown_03005000.unk_e9[i] == 0)
+ break;
+ }
+ if (i == playerCount)
+ {
+ if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0)
+ {
+ sub_800FD14(0x6600);
+ gUnknown_03005000.unk_00 = sub_8010358;
+ }
+ }
+ }
+}
+
+void sub_8010434(void)
+{
+ if (gUnknown_03005000.unk_00 == NULL)
+ {
+ gUnknown_03005000.unk_00 = sub_8010390;
+ gUnknown_03005000.unk_fe = 0;
+ }
+}
+
+bool32 sub_8010454(u32 a0)
+{
+ int i;
+ for (i = 0; gUnknown_082ED6E0[i] != a0; i++)
+ {
+ if (gUnknown_082ED6E0[i] == 0xffff)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+u8 sub_801048C(bool32 a0)
+{
+ if (a0 == 0)
+ return sub_800D550(0, 0);
+ sub_800D550(1, 0x258);
+ return FALSE;
+}
+
+void sub_80104B0(void)
+{
+ gUnknown_03005000.unk_cd9 = 1;
+ sub_800C27C(FALSE);
+}
+
+u8 rfu_get_multiplayer_id(void)
+{
+ if (gUnknown_03005000.unk_0c == 1)
+ return 0;
+ return gUnknown_03005000.unk_cce;
+}
+
+u8 sub_80104F4(void)
+{
+ return gUnknown_03005000.playerCount;
+}
+
+bool8 sub_8010500(void)
+{
+ if (gUnknown_03005000.unk_f1 == 2)
+ return FALSE;
+ return gUnknown_03005000.unk_00 ? FALSE : TRUE;
+}
+
+static void sub_8010528(void)
+{
+ if (gUnknown_03005000.unk_00)
+ gUnknown_03005000.unk_00();
+}
+
+bool8 sub_8010540(void)
+{
+ int i;
+ bool8 retval = FALSE;
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03005000.unk_cd1[i] < 5 || gUnknown_03005000.unk_cd1[i] > 6)
+ {
+ if (gUnknown_03007880[i]->unk_34 == 0x46 || gUnknown_03007880[i]->unk_34 == 0x48)
+ {
+ if (gUnknown_03005000.unk_cd5[i] == 8)
+ {
+ gUnknown_03005000.unk_cd1[i] = 9;
+ gUnknown_03005000.unk_cd5[i] = 10;
+ rfu_clearSlot(8, i);
+ rfu_NI_setSendData(1 << i, 8, gUnknown_03005000.unk_cd1 + i, 1);
+ retval = TRUE;
+ }
+
+ }
+ else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47)
+ rfu_clearSlot(8, i);
+ {
+
+ }
+ }
+ }
+ return retval;
+}
+
+bool8 sub_80105EC(void)
+{
+ u8 flags = 0;
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03005000.unk_cd5[i] == 11)
+ {
+ flags |= (1 << i);
+ gUnknown_03005000.unk_cd5[i] = 0;
+ }
+ }
+ if (flags)
+ {
+ rfu_REQ_disconnect(flags);
+ rfu_waitREQComplete();
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03005000.unk_cd5[i] == 10 || gUnknown_03005000.unk_cd5[i] == 11)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_801064C(u16 a0, const u8 *a1)
+{
+ u8 r1 = sub_8011CE4(a1, a0);
+ if (r1 == 0xFF)
+ return TRUE;
+ if (gUnknown_03005000.unk_cd1[r1] == 9)
+ return TRUE;
+ return FALSE;
+}
+
+void sub_8010688(u8 a0, u16 a1, const u8 *a2)
+{
+ u8 r4 = sub_8011CE4(a2, a1);
+ gUnknown_03005000.unk_cd1[r4] = a0;
+ rfu_clearSlot(4, r4);
+ rfu_NI_setSendData(1 << r4, 8, gUnknown_03005000.unk_cd1 + r4, 1);
+}
+
+void sub_80106D4(void)
+{
+ gUnknown_03005000.unk_c85 = 8;
+ rfu_clearSlot(4, gUnknown_03005000.unk_c3e);
+ rfu_NI_setSendData(1 << gUnknown_03005000.unk_c3e, 8, &gUnknown_03005000.unk_c85, 1);
+}
+
+u8 sub_8010714(u16 a0, const u8 *a1)
+{
+ u8 r0 = sub_8011CE4(a1, a0);
+ if (r0 == 0xff)
+ return 2;
+ if (gUnknown_03007880[r0]->unk_0 == 0)
+ return TRUE;
+ return FALSE;
+}
+
+void sub_8010750(void)
+{
+ int i;
+
+ sub_8010540();
+ for (i = 0; i < 4; i++)
+ {
+ if (gUnknown_03007880[i]->unk_0 == 0x26 || gUnknown_03007880[i]->unk_0 == 0x27)
+ {
+ if (gUnknown_03005000.unk_cd5[i] == 10)
+ gUnknown_03005000.unk_cd5[i] = 11;
+ rfu_clearSlot(4, i);
+ }
+ }
+}
+
+int sub_80107A0(void)
+{
+ int retval = 0;
+ if (gUnknown_03005000.unk_c85 == 8)
+ {
+ if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x26 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x27)
+ rfu_clearSlot(4, gUnknown_03005000.unk_c3e);
+ }
+ if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x46 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x48)
+ {
+ rfu_clearSlot(8, gUnknown_03005000.unk_c3e);
+ sub_8011A64(gUnknown_03005000.unk_c86, 0);
+ retval = gUnknown_03005000.unk_c86;
+ }
+ else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47)
+ {
+ rfu_clearSlot(8, gUnknown_03005000.unk_c3e);
+ retval = 6;
+ }
+ return retval;
+}
+
+void sub_801084C(u8 taskId)
+{
+ int i;
+
+ if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2)
+ {
+ gUnknown_03005000.unk_ce8 = 0;
+ DestroyTask(taskId);
+ }
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ if (sub_800FC60())
+ {
+ ResetBlockReceivedFlags();
+ sub_800B348();
+ gTasks[taskId].data[0]++;
+ }
+ break;
+ case 1:
+ if (gUnknown_03005000.unk_0c == 1)
+ {
+ if (gReceivedRemoteLinkPlayers)
+ sub_800FD14(0x7800);
+ else
+ sub_800FD14(0x7700);
+ gTasks[taskId].data[0] = 101;
+ }
+ else
+ gTasks[taskId].data[0] = 2;
+ break;
+ case 101:
+ if (gSendCmd[0] == 0)
+ gTasks[taskId].data[0] = 2;
+ break;
+ case 2:
+ if (gUnknown_03005000.playerCount)
+ gTasks[taskId].data[0]++;
+ break;
+ case 3:
+ if (gUnknown_03005000.unk_0c == 1)
+ {
+ if (sub_800FC60())
+ {
+ gUnknown_03005000.unk_5a = 0;
+ sub_800FD14(0xa100);
+ gTasks[taskId].data[0]++;
+ }
+ }
+ else
+ gTasks[taskId].data[0]++;
+ break;
+ case 4:
+ if (sub_800FC88())
+ gTasks[taskId].data[0]++;
+ break;
+ case 5:
+ for (i = 0; i < gUnknown_03005000.playerCount; i++)
+ {
+ sub_800B3A4(i);
+ sub_800F728(i);
+ }
+ gTasks[taskId].data[0]++;
+ break;
+ case 6:
+ DestroyTask(taskId);
+ gReceivedRemoteLinkPlayers = 1;
+ gUnknown_03005000.unk_ce8 = 0;
+ sub_800D550(1, 0x258);
+ if (gUnknown_03005000.unk_ce6)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03005000.unk_ce6 >> i) & 1)
+ {
+ gUnknown_03005000.unk_ce5 = 1 << i;
+ gUnknown_03005000.unk_ce6 ^= (1 << i);
+ }
+ }
+ }
+ break;
+ }
+}
+
+void sub_80109E8(u16 a0)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if ((a0 >> i) & 1)
+ gUnknown_03005000.unk_cde[i] = 0;
+ }
+}
+
+void sub_8010A14(const struct UnkRfuStruct_8010A14 *a0)
+{
+ int i;
+ gUnknown_03005000.playerCount = a0->unk_0f;
+ for (i = 0; i < 4; i++)
+ gUnknown_03005000.unk_cde[i] = a0->unk_10[i];
+ for (i = 0; i < MAX_RFU_PLAYERS; i++)
+ {
+ gLinkPlayers[i] = a0->unk_14[i];
+ sub_800B524(gLinkPlayers + i);
+ }
+}
+
+void sub_8010A70(void *a0)
+{
+ if (strcmp(gUnknown_082ED7EC, a0) == 0)
+ {
+ sub_8010A14(a0);
+ CpuFill16(0, a0, sizeof(struct UnkRfuStruct_8010A14));
+ ResetBlockReceivedFlag(0);
+ }
+}
+
+void sub_8010AAC(u8 taskId)
+{
+ int i;
+ struct LinkPlayerBlock *r2;
+ struct UnkRfuStruct_8010A14 *r5;
+ u8 r4 = gUnknown_03005000.unk_cde[gUnknown_082ED68C[gUnknown_03005000.unk_ce9]];
+ if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2)
+ {
+ gUnknown_03005000.unk_ce8 = 0;
+ DestroyTask(taskId);
+ }
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ if (gSendCmd[0] == 0)
+ {
+ ResetBlockReceivedFlag(r4);
+ sub_800FD14(0x7800);
+ gTasks[taskId].data[0]++;
+ }
+ break;
+ case 1:
+ if (gSendCmd[0] == 0)
+ gTasks[taskId].data[0]++;
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() >> r4) & 1)
+ {
+ ResetBlockReceivedFlag(r4);
+ r2 = (struct LinkPlayerBlock *)gBlockRecvBuffer[r4];
+ gLinkPlayers[r4] = r2->linkPlayer;
+ sub_800B524(gLinkPlayers + r4);
+ gTasks[taskId].data[0]++;
+ }
+ break;
+ case 3:
+ r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer;
+ memcpy(r5->unk_00, gUnknown_082ED7EC, sizeof gUnknown_082ED7EC);
+ r5->unk_0f = gUnknown_03005000.playerCount;
+ for (i = 0; i < 4; i++)
+ r5->unk_10[i] = gUnknown_03005000.unk_cde[i];
+ memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers);
+ gTasks[taskId].data[0]++;
+ // fallthrough
+ case 4:
+ r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer;
+ r5->unk_0f = gUnknown_03005000.playerCount;
+ for (i = 0; i < 4; i++)
+ r5->unk_10[i] = gUnknown_03005000.unk_cde[i];
+ memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers);
+ if (SendBlock(0, gBlockSendBuffer, 0xa0))
+ gTasks[taskId].data[0]++;
+ break;
+ case 5:
+ if (sub_800A520() && GetBlockReceivedStatus() & 1)
+ {
+ CpuFill16(0, gBlockRecvBuffer, sizeof(struct UnkRfuStruct_8010A14));
+ ResetBlockReceivedFlag(0);
+ gUnknown_03005000.unk_ce8 = 0;
+ if (gUnknown_03005000.unk_ce6)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03005000.unk_ce6 >> i) & 1)
+ {
+ gUnknown_03005000.unk_ce5 = 1 << i;
+ gUnknown_03005000.unk_ce6 ^= (1 << i);
+ gUnknown_03005000.unk_ce8 = 1;
+ break;
+ }
+ }
+ }
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_8010D0C(u8 taskId)
+{
+ if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2)
+ DestroyTask(taskId);
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ if (gUnknown_03005000.playerCount)
+ {
+ sub_800B348();
+ SendBlock(0, gBlockSendBuffer, sizeof(struct LinkPlayerBlock));
+ gTasks[taskId].data[0]++;
+ }
+ break;
+ case 1:
+ if (sub_800A520())
+ gTasks[taskId].data[0]++;
+ break;
+ case 2:
+ if (GetBlockReceivedStatus() & 1)
+ {
+ sub_8010A14((const struct UnkRfuStruct_8010A14 *)gBlockRecvBuffer);
+ ResetBlockReceivedFlag(0);
+ gReceivedRemoteLinkPlayers = 1;
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_8010DB4(void)
+{
+ if (gUnknown_03005000.unk_ee == 1 && gUnknown_03004140.unk_02 == 0)
+ {
+ if (gMain.callback2 == sub_8018438 || gUnknown_03004140.unk_3c->unk_04)
+ gWirelessCommType = 2;
+ SetMainCallback2(CB2_LinkError);
+ gMain.savedCallback = CB2_LinkError;
+ sub_800AF18((gUnknown_03005000.unk_0a << 16) | (gUnknown_03005000.unk_10 << 8) | gUnknown_03005000.unk_12, gUnknown_03005000.unk_124.unk_8c2, gUnknown_03005000.unk_9e8.unk_232, sub_8011A74() == 2);
+ gUnknown_03005000.unk_ee = 2;
+ CloseLink();
+ }
+ else if (gUnknown_03005000.unk_9e8.unk_233 == 1 || gUnknown_03005000.unk_124.unk_8c3 == 1)
+ {
+ if (gUnknown_03004140.unk_02)
+ sub_800D630();
+ sub_8011A64(1, 0x7000);
+ sub_8011170(0x7000);
+ }
+}
+
+void rfu_REQ_recvData_then_sendData(void)
+{
+ if (gUnknown_03004140.unk_06 == 1)
+ {
+ rfu_REQ_recvData();
+ rfu_waitREQComplete();
+ rfu_REQ_sendData_wrapper(0);
+ }
+}
+
+bool32 sub_8010EC0(void)
+{
+ bool32 retval = FALSE;
+ gUnknown_03005000.unk_ccd = 0;
+ sub_800C54C(Random2());
+ if (gUnknown_03005000.unk_ef == 0)
+ {
+ switch (gUnknown_03005000.unk_0c)
+ {
+ case 1:
+ sub_800F0F8();
+ break;
+ case 0:
+ retval = sub_800F4F0();
+ break;
+ case 2:
+ rfu_REQ_recvData_then_sendData();
+ break;
+ }
+ }
+ return retval;
+}
+
+bool32 sub_8010F1C(void)
+{
+ bool32 retval = FALSE;
+ if (gUnknown_03005000.unk_ef == 0)
+ {
+ if (gUnknown_03005000.unk_0c == 1)
+ retval = sub_800F1E0();
+ sub_8010DB4();
+ }
+ return retval;
+}
+
+void sub_8010F48(void)
+{
+ StringCopy(gUnknown_02022B22, gSaveBlock2Ptr->playerName);
+}
+
+void sub_8010F60(void)
+{
+ gUnknown_02022B14 = (struct UnkLinkRfuStruct_02022B14){};
+ sub_800DD94(&gUnknown_02022B14, 0, 0, 0);
+}
+
+void sub_8010F84(u8 a0, u32 a1, u32 a2)
+{
+ sub_800DD94(&gUnknown_02022B14, a0, a2, a1);
+}
+
+void sub_8010FA0(bool32 a0, bool32 a1)
+{
+ gUnknown_02022B14.unk_00_4 = a0;
+ gUnknown_02022B14.unk_00_5 = a1;
+}
+
+void sub_8010FCC(u32 a0, u32 a1, u32 a2)
+{
+ gUnknown_02022B14.unk_09_2 = a0;
+ gUnknown_02022B14.unk_08_0 = a1;
+ gUnknown_02022B14.unk_0b_1 = a2;
+}
+
+u8 sub_801100C(int a0)
+{
+ u8 retval = 0x80;
+ retval |= (gLinkPlayers[a0].gender << 3);
+ retval |= (gLinkPlayers[a0].trainerId & 7);
+ return retval;
+}
+
+void sub_801103C(void)
+{
+ struct UnkLinkRfuStruct_02022B14 *r5 = &gUnknown_02022B14;
+ int i;
+
+ for (i = 1; i < GetLinkPlayerCount(); i++)
+ r5->unk_04[i - 1] = sub_801100C(i);
+}
+
+void sub_8011068(u8 a0)
+{
+ gUnknown_02022B14.unk_0a_7 = a0;
+ rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22);
+}
+
+void sub_8011090(u8 a0, u32 a1, u32 a2)
+{
+ if (a0)
+ sub_8010F84(a0, a1, a2);
+ rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22);
+}
+
+void sub_80110B8(u32 a0)
+{
+ int i;
+ u32 r5;
+ u32 r7;
+ int r8;
+
+ if (sub_800F7DC()->unk_0a_0 == 0x45)
+ {
+ r5 = 0;
+ r7 = 0;
+ r8 = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3;
+ for (i = 0; i < 4; i++)
+ {
+ if ((r8 >> i) & 1)
+ {
+ r7 |= ((0x80 | ((gLinkPlayers[gUnknown_03005000.unk_cde[i]].gender & 1) << 3) | (gLinkPlayers[gUnknown_03005000.unk_cde[i]].trainerId & 7)) << (r5 << 3));
+ r5++;
+ if (r5 == a0 - 1)
+ break;
+ }
+ }
+ sub_8011090(0x45, r7, 0);
+ }
+}
+
+void sub_8011170(u32 a0)
+{
+ if (gUnknown_03005000.unk_ee == 0)
+ {
+ gUnknown_03005000.unk_10 = gUnknown_03004140.unk_14;
+ gUnknown_03005000.unk_12 = gUnknown_03004140.unk_16;
+ gUnknown_03005000.unk_0a = a0;
+ gUnknown_03005000.unk_ee = 1;
+ }
+}
+
+void sub_80111A0(void)
+{
+ gUnknown_03005000.unk_ee = 0;
+}
+
+void sub_80111B0(bool32 a0)
+{
+ if (!a0)
+ gUnknown_03005000.unk_ee = 0;
+ else
+ gUnknown_03005000.unk_ee = 4;
+}
+
+void sub_80111DC(void)
+{
+ sub_8011E94(gUnknown_03004140.unk_00, 1);
+ gUnknown_03005000.unk_00 = NULL;
+}
+
+void sub_80111FC(void)
+{
+ gUnknown_03005000.unk_00 = sub_80111DC;
+}
+
+#ifdef NONMATCHING
+void sub_801120C(u8 a0)
+{
+ u8 i;
+ u8 r6 = 0;
+ struct RfuUnk5Sub *unk5Sub;
+ switch (a0)
+ {
+ case 0x00:
+ gUnknown_03005000.unk_04 = 2;
+ break;
+ case 0x10:
+ break;
+ case 0x11:
+ sub_80115EC(gUnknown_03004140.unk_14);
+ for (i = 0; i < 4; i++)
+ {
+ if ((gUnknown_03004140.unk_14 >> i) & 1)
+ {
+ unk5Sub = &gUnknown_03007890->unk_14[i];
+ if (unk5Sub->unk_06.unk_0a_0 == sub_800F7DC()->unk_0a_0)
+ {
+ gUnknown_03005000.unk_cd1[i] = 0;
+ gUnknown_03005000.unk_cd5[i] = 0;
+ rfu_setRecvBuffer(0x20, i, gUnknown_03005000.unk_cd5 + i, 1);
+ }
+ else
+ {
+ r6 |= (1 << i);
+ }
+ }
+ }
+ if (r6)
+ {
+ rfu_REQ_disconnect(r6);
+ rfu_waitREQComplete();
+ }
+ break;
+ case 0x12:
+ break;
+ case 0x13:
+ break;
+ case 0x14:
+ if (gUnknown_03005000.unk_ce7 != gUnknown_03004140.unk_00)
+ {
+ rfu_REQ_disconnect(gUnknown_03005000.unk_ce7 ^ gUnknown_03004140.unk_00);
+ rfu_waitREQComplete();
+ }
+ gUnknown_03005000.unk_04 = 0x11;
+ break;
+ case 0x31:
+ gUnknown_03005000.unk_f0 = 1;
+ break;
+ case 0x32:
+ gUnknown_03005000.unk_f0 = 3;
+ break;
+ case 0x30:
+ case 0x33:
+ gUnknown_03005000.unk_f0 = 4;
+ gUnknown_03005000.unk_ce2 &= ~gUnknown_03004140.unk_14;
+ if (gReceivedRemoteLinkPlayers == 1)
+ {
+ if (gUnknown_03005000.unk_ce2 == 0)
+ sub_8011170(a0);
+ else
+ sub_80111FC();
+ }
+ sub_8011A64(2, a0);
+ break;
+ case 0x42 ... 0x44:
+ break;
+ case 0xf3:
+ sub_8011A64(1, a0);
+ sub_8011170(a0);
+ gUnknown_03005000.unk_ef = 1;
+ break;
+ case 0xf0 ... 0xf2:
+ case 0xff:
+ sub_8011170(a0);
+ sub_8011A64(1, a0);
+ gUnknown_03005000.unk_cdb = 1;
+ break;
+ }
+}
+#else
+ASM_DIRECT void sub_801120C(u8 a0)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r4, r0, 24\n"
+ "\tmovs r6, 0\n"
+ "\tcmp r4, 0x32\n"
+ "\tbne _08011222\n"
+ "\tb _08011360_case_32\n"
+ "_08011222:\n"
+ "\tcmp r4, 0x32\n"
+ "\tbgt _08011252\n"
+ "\tcmp r4, 0x13\n"
+ "\tbgt _08011240\n"
+ "\tcmp r4, 0x12\n"
+ "\tblt _08011230\n"
+ "\tb _080113EE_break\n"
+ "_08011230:\n"
+ "\tcmp r4, 0x10\n"
+ "\tbne _08011236\n"
+ "\tb _080113EE_break\n"
+ "_08011236:\n"
+ "\tcmp r4, 0x10\n"
+ "\tbgt _0801128C_case_11\n"
+ "\tcmp r4, 0\n"
+ "\tbeq _0801127E_case_00\n"
+ "\tb _080113EE_break\n"
+ "_08011240:\n"
+ "\tcmp r4, 0x30\n"
+ "\tbne _08011246\n"
+ "\tb _0801136C_case_30_case_33\n"
+ "_08011246:\n"
+ "\tcmp r4, 0x30\n"
+ "\tble _0801124C\n"
+ "\tb _08011354_case_31\n"
+ "_0801124C:\n"
+ "\tcmp r4, 0x14\n"
+ "\tbeq _08011328_case_14\n"
+ "\tb _080113EE_break\n"
+ "_08011252:\n"
+ "\tcmp r4, 0x44\n"
+ "\tbgt _08011264\n"
+ "\tcmp r4, 0x42\n"
+ "\tblt _0801125C\n"
+ "\tb _080113EE_break\n"
+ "_0801125C:\n"
+ "\tcmp r4, 0x33\n"
+ "\tbne _08011262\n"
+ "\tb _0801136C_case_30_case_33\n"
+ "_08011262:\n"
+ "\tb _080113EE_break\n"
+ "_08011264:\n"
+ "\tcmp r4, 0xF3\n"
+ "\tbne _0801126A\n"
+ "\tb _080113BA_case_f3\n"
+ "_0801126A:\n"
+ "\tcmp r4, 0xF3\n"
+ "\tbgt _08011276\n"
+ "\tcmp r4, 0xF0\n"
+ "\tbge _08011274\n"
+ "\tb _080113EE_break\n"
+ "_08011274:\n"
+ "\tb _080113D4_case_f0_f1_f2_ff\n"
+ "_08011276:\n"
+ "\tcmp r4, 0xFF\n"
+ "\tbne _0801127C\n"
+ "\tb _080113D4_case_f0_f1_f2_ff\n"
+ "_0801127C:\n"
+ "\tb _080113EE_break\n"
+ "_0801127E_case_00:\n"
+ "\tldr r1, =gUnknown_03005000\n"
+ "\tmovs r0, 0x2\n"
+ "\tstrh r0, [r1, 0x4]\n"
+ "\tb _080113EE_break\n"
+ "\t.pool\n"
+ "_0801128C_case_11:\n"
+ "\tldr r0, =gUnknown_03004140\n"
+ "\tldrh r0, [r0, 0x14]\n"
+ "\tbl sub_80115EC\n"
+ "\tmovs r5, 0\n"
+ "\tmovs r0, 0x1\n"
+ "\tmov r8, r0\n"
+ "\tldr r1, =gUnknown_03005000\n"
+ "\tmov r9, r1\n"
+ "\tldr r3, =0x00000cd5\n"
+ "\tadd r3, r9\n"
+ "\tmov r10, r3\n"
+ "\tmovs r7, 0x7F\n"
+ "_080112A6:\n"
+ "\tldr r0, =gUnknown_03004140\n"
+ "\tldrh r0, [r0, 0x14]\n"
+ "\tasrs r0, r5\n"
+ "\tmov r1, r8\n"
+ "\tands r0, r1\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0801130E\n"
+ "\tldr r0, =gUnknown_03007890\n"
+ "\tlsls r1, r5, 5\n"
+ "\tadds r1, 0x14\n"
+ "\tldr r0, [r0]\n"
+ "\tadds r0, r1\n"
+ "\tldrb r0, [r0, 0x10]\n"
+ "\tadds r4, r7, 0\n"
+ "\tands r4, r0\n"
+ "\tbl sub_800F7DC\n"
+ "\tldrb r1, [r0, 0xA]\n"
+ "\tadds r0, r7, 0\n"
+ "\tands r0, r1\n"
+ "\tcmp r4, r0\n"
+ "\tbne _08011304\n"
+ "\tldr r0, =0x00000cd1\n"
+ "\tadd r0, r9\n"
+ "\tadds r0, r5, r0\n"
+ "\tmovs r1, 0\n"
+ "\tstrb r1, [r0]\n"
+ "\tmov r3, r10\n"
+ "\tadds r2, r5, r3\n"
+ "\tstrb r1, [r2]\n"
+ "\tmovs r0, 0x20\n"
+ "\tadds r1, r5, 0\n"
+ "\tmovs r3, 0x1\n"
+ "\tbl rfu_setRecvBuffer\n"
+ "\tb _0801130E\n"
+ "\t.pool\n"
+ "_08011304:\n"
+ "\tmov r0, r8\n"
+ "\tlsls r0, r5\n"
+ "\torrs r6, r0\n"
+ "\tlsls r0, r6, 24\n"
+ "\tlsrs r6, r0, 24\n"
+ "_0801130E:\n"
+ "\tadds r0, r5, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r5, r0, 24\n"
+ "\tcmp r5, 0x3\n"
+ "\tbls _080112A6\n"
+ "\tcmp r6, 0\n"
+ "\tbeq _080113EE_break\n"
+ "\tadds r0, r6, 0\n"
+ "\tbl rfu_REQ_disconnect\n"
+ "\tbl rfu_waitREQComplete\n"
+ "\tb _080113EE_break\n"
+ "_08011328_case_14:\n"
+ "\tldr r4, =gUnknown_03005000\n"
+ "\tldr r1, =0x00000ce7\n"
+ "\tadds r0, r4, r1\n"
+ "\tldr r1, =gUnknown_03004140\n"
+ "\tldrb r2, [r0]\n"
+ "\tldrb r0, [r1]\n"
+ "\tcmp r2, r0\n"
+ "\tbeq _08011342\n"
+ "\teors r0, r2\n"
+ "\tbl rfu_REQ_disconnect\n"
+ "\tbl rfu_waitREQComplete\n"
+ "_08011342:\n"
+ "\tmovs r0, 0x11\n"
+ "\tstrh r0, [r4, 0x4]\n"
+ "\tb _080113EE_break\n"
+ "\t.pool\n"
+ "_08011354_case_31:\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r0, 0xF0\n"
+ "\tb _080113EA\n"
+ "\t.pool\n"
+ "_08011360_case_32:\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r0, 0xF0\n"
+ "\tmovs r1, 0x3\n"
+ "\tb _080113EC\n"
+ "\t.pool\n"
+ "_0801136C_case_30_case_33:\n"
+ "\tldr r1, =gUnknown_03005000\n"
+ "\tadds r2, r1, 0\n"
+ "\tadds r2, 0xF0\n"
+ "\tmovs r0, 0x4\n"
+ "\tstrb r0, [r2]\n"
+ "\tldr r3, =0x00000ce2\n"
+ "\tadds r1, r3\n"
+ "\tldr r0, =gUnknown_03004140\n"
+ "\tldrb r2, [r0, 0x14]\n"
+ "\tldrb r0, [r1]\n"
+ "\tadds r3, r0, 0\n"
+ "\tbics r3, r2\n"
+ "\tadds r2, r3, 0\n"
+ "\tstrb r2, [r1]\n"
+ "\tldr r0, =gReceivedRemoteLinkPlayers\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r0, 0x1\n"
+ "\tbne _080113B0\n"
+ "\tcmp r2, 0\n"
+ "\tbne _080113AC\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl sub_8011170\n"
+ "\tb _080113B0\n"
+ "\t.pool\n"
+ "_080113AC:\n"
+ "\tbl sub_80111FC\n"
+ "_080113B0:\n"
+ "\tmovs r0, 0x2\n"
+ "\tadds r1, r4, 0\n"
+ "\tbl sub_8011A64\n"
+ "\tb _080113EE_break\n"
+ "_080113BA_case_f3:\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r1, 0xF3\n"
+ "\tbl sub_8011A64\n"
+ "\tmovs r0, 0xF3\n"
+ "\tbl sub_8011170\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tadds r0, 0xEF\n"
+ "\tb _080113EA\n"
+ "\t.pool\n"
+ "_080113D4_case_f0_f1_f2_ff:\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl sub_8011170\n"
+ "\tmovs r0, 0x1\n"
+ "\tadds r1, r4, 0\n"
+ "\tbl sub_8011A64\n"
+ "\tldr r0, =gUnknown_03005000\n"
+ "\tldr r1, =0x00000cdb\n"
+ "\tadds r0, r1\n"
+ "\tldrb r1, [r0]\n"
+ "_080113EA:\n"
+ "\tmovs r1, 0x1\n"
+ "_080113EC:\n"
+ "\tstrb r1, [r0]\n"
+ "_080113EE_break:\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.pool");
+}
+#endif
diff --git a/src/main.c b/src/main.c
index d4601293b..3be6b91c7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,50 +1,32 @@
#include "global.h"
-#include "main.h"
+#include "crt0.h"
+#include "malloc.h"
+#include "link.h"
+#include "link_rfu.h"
+#include "librfu.h"
#include "m4a.h"
+#include "bg.h"
#include "rtc.h"
+#include "scanline_effect.h"
+#include "overworld.h"
+#include "play_time.h"
#include "random.h"
#include "dma3.h"
#include "gba/flash_internal.h"
+#include "load_save.h"
+#include "gpu_regs.h"
+#include "agb_flash.h"
+#include "sound.h"
#include "battle.h"
+#include "battle_controllers.h"
+#include "text.h"
+#include "intro.h"
+#include "main.h"
-extern u16 GetGpuReg(u8);
-extern void SetGpuReg(u8, u16);
-extern void LinkVSync(void);
-extern void sub_800E174(void);
extern void sub_800B9B8(void);
-extern void InitGpuRegManager(void);
-extern void sub_800E6D0(void);
-extern void CheckForFlashMemory(void);
-extern void InitMapMusic(void);
-extern void ResetBgs(void);
-extern void SetDefaultFontsPointer(void);
-extern void InitHeap(void *heapStart, u32 heapSize); // malloc.h
-extern void rfu_REQ_stopMode(void);
-extern void rfu_waitREQComplete(void);
-extern bool32 sub_8087634(void);
-extern bool32 sub_80875C8(void);
-extern void ClearSpriteCopyRequests(void);
-extern void PlayTimeCounter_Update(void);
-extern void MapMusicMain(void);
-extern void EnableInterrupts(u16);
-extern void sub_8033648(void);
-extern u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void));
-extern void ScanlineEffect_Stop(void);
-
-extern struct SoundInfo gSoundInfo;
-extern u32 gFlashMemoryPresent;
-extern u32 IntrMain[];
-extern u8 gHeap[];
-extern struct SaveBlock2 gSaveblock2;
-extern struct PokemonStorage gPokemonStorage;
-extern u32 gBattleTypeFlags;
extern u8 gUnknown_03002748;
extern u32 *gUnknown_0203CF5C;
-void Timer3Intr(void);
-bool8 HandleLinkConnection(void);
-void c2_copyright_1(void);
-
static void VBlankIntr(void);
static void HBlankIntr(void);
static void VCountIntr(void);
@@ -79,19 +61,19 @@ const IntrFunc gIntrTableTemplate[] =
static u16 gUnknown_03000000;
-extern u16 gKeyRepeatStartDelay;
-extern u8 gUnknown_030022B4;
-extern struct Main gMain;
-extern u16 gKeyRepeatContinueDelay;
-extern u8 gSoftResetDisabled;
-extern IntrFunc gIntrTable[INTR_COUNT];
-extern bool8 gLinkVSyncDisabled;
-extern u32 IntrMain_Buffer[0x200];
-extern u8 gPcmDmaCounter;
+u16 gKeyRepeatStartDelay;
+bool8 gLinkTransferringData;
+struct Main gMain;
+u16 gKeyRepeatContinueDelay;
+bool8 gSoftResetDisabled;
+IntrFunc gIntrTable[INTR_COUNT];
+u8 gLinkVSyncDisabled;
+u32 IntrMain_Buffer[0x200];
+u8 gPcmDmaCounter;
-extern u16 gTrainerId;
+static EWRAM_DATA u16 gTrainerId = 0;
-EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL;
+//EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL;
static void UpdateLinkAndCallCallbacks(void);
static void InitMainCallbacks(void);
@@ -129,7 +111,7 @@ void AgbMain()
if (gFlashMemoryPresent != TRUE)
SetMainCallback2(NULL);
- gUnknown_030022B4 = 0;
+ gLinkTransferringData = FALSE;
gUnknown_03000000 = 0xFC0;
for (;;)
@@ -147,22 +129,22 @@ void AgbMain()
if (sub_8087634() == 1)
{
- gUnknown_030022B4 = 1;
+ gLinkTransferringData = TRUE;
UpdateLinkAndCallCallbacks();
- gUnknown_030022B4 = 0;
+ gLinkTransferringData = FALSE;
}
else
{
- gUnknown_030022B4 = 0;
+ gLinkTransferringData = FALSE;
UpdateLinkAndCallCallbacks();
if (sub_80875C8() == 1)
{
gMain.newKeys = 0;
ClearSpriteCopyRequests();
- gUnknown_030022B4 = 1;
+ gLinkTransferringData = TRUE;
UpdateLinkAndCallCallbacks();
- gUnknown_030022B4 = 0;
+ gLinkTransferringData = FALSE;
}
}
@@ -335,10 +317,10 @@ extern void CopyBufferedValuesToGpuRegs(void);
static void VBlankIntr(void)
{
- if (gLinkVSyncDisabled != FALSE)
+ if (gWirelessCommType != 0)
+ RfuVSync();
+ else if (gLinkVSyncDisabled == FALSE)
LinkVSync();
- else if (gUnknown_03002748 == FALSE)
- sub_800B9B8();
gMain.vblankCounter1++;
diff --git a/src/mystery_event_menu.c b/src/mystery_event_menu.c
index 31b366ae9..22e50f4e7 100644
--- a/src/mystery_event_menu.c
+++ b/src/mystery_event_menu.c
@@ -189,7 +189,7 @@ static void CB2_MysteryEventMenu(void)
{
if (gReceivedRemoteLinkPlayers != 0)
{
- if (sub_800A0C8(2, 2) == 3)
+ if (GetLinkPlayerDataExchangeStatusTimed(2, 2) == 3)
{
sub_800AC34();
GetEventLoadMessage(gStringVar4, 1);
diff --git a/src/pokeblock_feed.c b/src/pokeblock_feed.c
index 2039808cb..db92d56a8 100644
--- a/src/pokeblock_feed.c
+++ b/src/pokeblock_feed.c
@@ -50,7 +50,6 @@ struct PokeblockFeedStruct
extern u16 gSpecialVar_ItemId;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
-extern struct SpriteTemplate gUnknown_0202499C;
extern const u8 gBattleTerrainPalette_Frontier[];
extern const u8 gBattleTerrainTiles_Building[];
@@ -837,7 +836,7 @@ static u8 CreateMonSprite(struct Pokemon* mon)
gSprites[spriteId].callback = SpriteCallbackDummy;
sPokeblockFeed->noMonFlip = TRUE;
- if (!IsPokeSpriteNotFlipped(species))
+ if (!IsMonSpriteNotFlipped(species))
{
gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_MonNoFlip;
gSprites[spriteId].oam.affineMode = 3;
diff --git a/src/pokemon.c b/src/pokemon.c
new file mode 100644
index 000000000..25d532204
--- /dev/null
+++ b/src/pokemon.c
@@ -0,0 +1,6094 @@
+#include "global.h"
+#include "pokemon.h"
+#include "battle.h"
+#include "battle_setup.h"
+#include "battle_message.h"
+#include "random.h"
+#include "main.h"
+#include "constants/species.h"
+#include "constants/abilities.h"
+#include "constants/items.h"
+#include "constants/trainers.h"
+#include "constants/moves.h"
+#include "constants/hold_effects.h"
+#include "constants/battle_move_effects.h"
+#include "constants/songs.h"
+#include "string_util.h"
+#include "text.h"
+#include "link.h"
+#include "event_data.h"
+#include "item.h"
+#include "battle_controllers.h"
+#include "battle_message.h"
+#include "evolution_scene.h"
+#include "pokemon_animation.h"
+#include "pokedex.h"
+#include "pokeblock.h"
+#include "sound.h"
+#include "task.h"
+#include "rtc.h"
+#include "m4a.h"
+#include "malloc.h"
+#include "util.h"
+#include "strings.h"
+#include "pokenav.h"
+#include "pokemon_storage_system.h"
+#include "recorded_battle.h"
+
+struct SpeciesItem
+{
+ u16 species;
+ u16 item;
+};
+
+// Extracts the upper 16 bits of a 32-bit number
+#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
+
+// Extracts the lower 16 bits of a 32-bit number
+#define LOHALF(n) ((n) & 0xFFFF)
+
+extern const struct OamData gUnknown_0831ACB0;
+extern const struct OamData gUnknown_0831ACA8;
+extern const struct SpriteFrameImage gUnknown_082FF3A8[];
+extern const struct SpriteFrameImage gUnknown_082FF3C8[];
+extern const struct SpriteFrameImage gUnknown_082FF3E8[];
+extern const struct SpriteFrameImage gUnknown_082FF408[];
+extern const struct SpriteFrameImage gUnknown_082FF428[];
+extern const struct SpriteFrameImage gUnknown_082FF448[];
+extern const struct SpriteFrameImage gUnknown_082FF468[];
+extern const struct SpriteFrameImage gUnknown_082FF490[];
+extern const struct SpriteFrameImage gUnknown_082FF4B8[];
+extern const struct SpriteFrameImage gUnknown_082FF4D8[];
+extern const struct SpriteFrameImage gUnknown_082FF4F8[];
+extern const struct SpriteFrameImage gUnknown_082FF518[];
+extern const union AffineAnimCmd *const gUnknown_082FF618[];
+extern const union AffineAnimCmd *const gUnknown_082FF694[];
+extern const union AnimCmd *gUnknown_082FF70C[];
+extern const union AnimCmd *const *const gMonAnimationsSpriteAnimsPtrTable[];
+extern const union AnimCmd *const *const gUnknown_08305D0C[];
+extern const union AnimCmd *const *const gUnknown_0830536C[];
+extern const struct BattleMove gBattleMoves[];
+extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
+extern const struct UnknownPokemonStruct3 gUnknown_08610970[];
+extern const struct CompressedSpritePalette gMonPaletteTable[];
+extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
+extern const u8 gTrainerClassNames[][13];
+
+extern u8 pokemon_order_func(u8);
+extern u16 get_unknown_box_id(void);
+extern u8 StorageGetCurrentBox(void);
+extern void set_unknown_box_id(u8);
+extern void sub_803FA70(u8 battlerId);
+extern u8 sav1_map_get_name(void);
+extern const u8 *sub_81A1650(u8, u8 language);
+extern u8 BattleFrontierGetOpponentLvl(u8);
+extern u16 FacilityClassToPicIndex(u16);
+extern bool8 InBattlePyramid(void);
+extern bool8 InBattlePike(void);
+extern bool8 sub_806F104(void);
+extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId);
+extern u8 sub_81D63C8(u16 trainerOpponentId);
+extern u8 GetFrontierOpponentClass(u16 trainerId);
+extern void GetFrontierTrainerName(u8* dest, u16 trainerId);
+extern void sub_81C488C(u8);
+
+// this file's functions
+static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon);
+static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType);
+static void EncryptBoxMon(struct BoxPokemon *boxMon);
+static void DecryptBoxMon(struct BoxPokemon *boxMon);
+static void sub_806E6CC(u8 taskId);
+static bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId);
+
+// EWRAM vars
+EWRAM_DATA static u8 sLearningMoveTableID = 0;
+EWRAM_DATA u8 gPlayerPartyCount = 0;
+EWRAM_DATA u8 gEnemyPartyCount = 0;
+EWRAM_DATA struct Pokemon gPlayerParty[PARTY_SIZE] = {0};
+EWRAM_DATA struct Pokemon gEnemyParty[PARTY_SIZE] = {0};
+EWRAM_DATA struct SpriteTemplate gUnknown_0202499C = {0};
+EWRAM_DATA struct Unknown_806F160_Struct *gUnknown_020249B4[2] = {NULL};
+
+// const rom data
+const u16 gSpeciesToHoennPokedexNum[] = {203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 156, 157, 112, 113, 227, 228, 229, 230, 231, 232, 233, 234, 153, 154, 138, 139, 63, 64, 88, 89, 90, 235, 236, 237, 238, 239, 240, 241, 242, 158, 159, 243, 244, 245, 246, 247, 248, 249, 39, 40, 41, 73, 74, 75, 250, 251, 252, 66, 67, 57, 58, 59, 253, 254, 255, 256, 82, 83, 257, 92, 93, 258, 259, 106, 107, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 84, 85, 270, 271, 272, 273, 274, 275, 276, 108, 109, 169, 170, 277, 278, 279, 184, 185, 50, 51, 143, 144, 280, 281, 282, 283, 284, 167, 285, 52, 53, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 65, 181, 182, 155, 324, 137, 325, 326, 162, 163, 327, 328, 329, 91, 55, 56, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 161, 164, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 168, 357, 358, 359, 103, 104, 360, 361, 180, 362, 363, 364, 365, 115, 366, 367, 186, 165, 166, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43, 44, 25, 26, 34, 35, 114, 27, 28, 32, 33, 99, 100, 61, 62, 145, 131, 132, 60, 105, 68, 127, 128, 183, 129, 130, 140, 141, 97, 98, 116, 117, 118, 48, 49, 78, 79, 101, 102, 173, 174, 175, 119, 120, 171, 172, 125, 126, 54, 110, 111, 80, 81, 69, 76, 77, 121, 122, 160, 148, 149, 94, 36, 37, 38, 95, 96, 150, 45, 46, 47, 176, 177, 178, 152, 146, 147, 124, 123, 179, 70, 71, 72, 142, 86, 87, 133, 134, 135, 136, 29, 30, 31, 187, 188, 189, 190, 191, 192, 193, 194, 195, 198, 199, 200, 196, 197, 201, 202, 151};
+const u16 gSpeciesToNationalPokedexNum[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 290, 291, 292, 276, 277, 285, 286, 327, 278, 279, 283, 284, 320, 321, 300, 301, 352, 343, 344, 299, 324, 302, 339, 340, 370, 341, 342, 349, 350, 318, 319, 328, 329, 330, 296, 297, 309, 310, 322, 323, 363, 364, 365, 331, 332, 361, 362, 337, 338, 298, 325, 326, 311, 312, 303, 307, 308, 333, 334, 360, 355, 356, 315, 287, 288, 289, 316, 317, 357, 293, 294, 295, 366, 367, 368, 359, 353, 354, 336, 335, 369, 304, 305, 306, 351, 313, 314, 345, 346, 347, 348, 280, 281, 282, 371, 372, 373, 374, 375, 376, 377, 378, 379, 382, 383, 384, 380, 381, 385, 386, 358};
+const u16 gHoennToNationalOrder[] = {252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 63, 64, 65, 290, 291, 292, 293, 294, 295, 296, 297, 118, 119, 129, 130, 298, 183, 184, 74, 75, 76, 299, 300, 301, 41, 42, 169, 72, 73, 302, 303, 304, 305, 306, 66, 67, 68, 307, 308, 309, 310, 311, 312, 81, 82, 100, 101, 313, 314, 43, 44, 45, 182, 84, 85, 315, 316, 317, 318, 319, 320, 321, 322, 323, 218, 219, 324, 88, 89, 109, 110, 325, 326, 27, 28, 327, 227, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 174, 39, 40, 349, 350, 351, 120, 121, 352, 353, 354, 355, 356, 357, 358, 359, 37, 38, 172, 25, 26, 54, 55, 360, 202, 177, 178, 203, 231, 232, 127, 214, 111, 112, 361, 362, 363, 364, 365, 366, 367, 368, 369, 222, 170, 171, 370, 116, 117, 230, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 36, 46, 47, 48, 49, 50, 51, 52, 53, 56, 57, 58, 59, 60, 61, 62, 69, 70, 71, 77, 78, 79, 80, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 102, 103, 104, 105, 106, 107, 108, 113, 114, 115, 122, 123, 124, 125, 126, 128, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 173, 175, 176, 179, 180, 181, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 220, 221, 223, 224, 225, 226, 228, 229, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411};
+
+const struct SpindaSpot gSpindaSpotGraphics[] =
+{
+ {16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
+ {40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
+ {22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
+ {34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
+};
+
+#include "data/pokemon/item_effects.h"
+
+const s8 gNatureStatTable[][5] =
+{
+ // Atk Def Spd Sp.Atk Sp.Def
+ { 0, 0, 0, 0, 0}, // Hardy
+ { +1, -1, 0, 0, 0}, // Lonely
+ { +1, 0, -1, 0, 0}, // Brave
+ { +1, 0, 0, -1, 0}, // Adamant
+ { +1, 0, 0, 0, -1}, // Naughty
+ { -1, +1, 0, 0, 0}, // Bold
+ { 0, 0, 0, 0, 0}, // Docile
+ { 0, +1, -1, 0, 0}, // Relaxed
+ { 0, +1, 0, -1, 0}, // Impish
+ { 0, +1, 0, 0, -1}, // Lax
+ { -1, 0, +1, 0, 0}, // Timid
+ { 0, -1, +1, 0, 0}, // Hasty
+ { 0, 0, 0, 0, 0}, // Serious
+ { 0, 0, +1, -1, 0}, // Jolly
+ { 0, 0, +1, 0, -1}, // Naive
+ { -1, 0, 0, +1, 0}, // Modest
+ { 0, -1, 0, +1, 0}, // Mild
+ { 0, 0, -1, +1, 0}, // Quiet
+ { 0, 0, 0, 0, 0}, // Bashful
+ { 0, 0, 0, +1, -1}, // Rash
+ { -1, 0, 0, 0, +1}, // Calm
+ { 0, -1, 0, 0, +1}, // Gentle
+ { 0, 0, -1, 0, +1}, // Sassy
+ { 0, 0, 0, -1, +1}, // Careful
+ { 0, 0, 0, 0, 0}, // Quirky
+};
+
+#include "data/pokemon/tmhm_learnsets.h"
+#include "data/pokemon/trainer_class_lookups.h"
+#include "data/pokemon/cry_ids.h"
+#include "data/pokemon/experience_tables.h"
+#include "data/pokemon/base_stats.h"
+#include "data/pokemon/level_up_learnsets.h"
+#include "data/pokemon/evolution.h"
+#include "data/pokemon/level_up_learnset_pointers.h"
+
+static const u8 sMonFrontAnimIdsTable[] =
+{
+ 0x06, // SPECIES_BULBASAUR
+ 0x17, // SPECIES_IVYSAUR
+ 0x2f, // SPECIES_VENUSAUR
+ 0x52, // SPECIES_CHARMANDER
+ 0x25, // SPECIES_CHARMELEON
+ 0x10, // SPECIES_CHARIZARD
+ 0x0b, // SPECIES_SQUIRTLE
+ 0x13, // SPECIES_WARTORTLE
+ 0x19, // SPECIES_BLASTOISE
+ 0x0b, // SPECIES_CATERPIE
+ 0x0b, // SPECIES_METAPOD
+ 0x1d, // SPECIES_BUTTERFREE
+ 0x46, // SPECIES_WEEDLE
+ 0x20, // SPECIES_KAKUNA
+ 0x02, // SPECIES_BEEDRILL
+ 0x47, // SPECIES_PIDGEY
+ 0x17, // SPECIES_PIDGEOTTO
+ 0x29, // SPECIES_PIDGEOT
+ 0x43, // SPECIES_RATTATA
+ 0x2b, // SPECIES_RATICATE
+ 0x18, // SPECIES_SPEAROW
+ 0x2b, // SPECIES_FEAROW
+ 0x16, // SPECIES_EKANS
+ 0x17, // SPECIES_ARBOK
+ 0x2c, // SPECIES_PIKACHU
+ 0x17, // SPECIES_RAICHU
+ 0x2d, // SPECIES_SANDSHREW
+ 0x17, // SPECIES_SANDSLASH
+ 0x00, // SPECIES_NIDORAN_F
+ 0x17, // SPECIES_NIDORINA
+ 0x0f, // SPECIES_NIDOQUEEN
+ 0x09, // SPECIES_NIDORAN_M
+ 0x13, // SPECIES_NIDORINO
+ 0x0f, // SPECIES_NIDOKING
+ 0x00, // SPECIES_CLEFAIRY
+ 0x4a, // SPECIES_CLEFABLE
+ 0x17, // SPECIES_VULPIX
+ 0x10, // SPECIES_NINETALES
+ 0x48, // SPECIES_JIGGLYPUFF
+ 0x31, // SPECIES_WIGGLYTUFF
+ 0x00, // SPECIES_ZUBAT
+ 0x1d, // SPECIES_GOLBAT
+ 0x00, // SPECIES_ODDISH
+ 0x45, // SPECIES_GLOOM
+ 0x49, // SPECIES_VILEPLUME
+ 0x46, // SPECIES_PARAS
+ 0x0f, // SPECIES_PARASECT
+ 0x06, // SPECIES_VENONAT
+ 0x4b, // SPECIES_VENOMOTH
+ 0x10, // SPECIES_DIGLETT
+ 0x4c, // SPECIES_DUGTRIO
+ 0x52, // SPECIES_MEOWTH
+ 0x17, // SPECIES_PERSIAN
+ 0x06, // SPECIES_PSYDUCK
+ 0x4c, // SPECIES_GOLDUCK
+ 0x32, // SPECIES_MANKEY
+ 0x48, // SPECIES_PRIMEAPE
+ 0x25, // SPECIES_GROWLITHE
+ 0x02, // SPECIES_ARCANINE
+ 0x00, // SPECIES_POLIWAG
+ 0x32, // SPECIES_POLIWHIRL
+ 0x19, // SPECIES_POLIWRATH
+ 0x31, // SPECIES_ABRA
+ 0x09, // SPECIES_KADABRA
+ 0x17, // SPECIES_ALAKAZAM
+ 0x00, // SPECIES_MACHOP
+ 0x10, // SPECIES_MACHOKE
+ 0x31, // SPECIES_MACHAMP
+ 0x17, // SPECIES_BELLSPROUT
+ 0x0d, // SPECIES_WEEPINBELL
+ 0x32, // SPECIES_VICTREEBEL
+ 0x00, // SPECIES_TENTACOOL
+ 0x00, // SPECIES_TENTACRUEL
+ 0x48, // SPECIES_GEODUDE
+ 0x48, // SPECIES_GRAVELER
+ 0x2f, // SPECIES_GOLEM
+ 0x20, // SPECIES_PONYTA
+ 0x11, // SPECIES_RAPIDASH
+ 0x45, // SPECIES_SLOWPOKE
+ 0x0b, // SPECIES_SLOWBRO
+ 0x54, // SPECIES_MAGNEMITE
+ 0x2c, // SPECIES_MAGNETON
+ 0x48, // SPECIES_FARFETCHD
+ 0x4c, // SPECIES_DODUO
+ 0x41, // SPECIES_DODRIO
+ 0x0b, // SPECIES_SEEL
+ 0x45, // SPECIES_DEWGONG
+ 0x46, // SPECIES_GRIMER
+ 0x30, // SPECIES_MUK
+ 0x12, // SPECIES_SHELLDER
+ 0x1d, // SPECIES_CLOYSTER
+ 0x15, // SPECIES_GASTLY
+ 0x35, // SPECIES_HAUNTER
+ 0x3a, // SPECIES_GENGAR
+ 0x43, // SPECIES_ONIX
+ 0x4f, // SPECIES_DROWZEE
+ 0x09, // SPECIES_HYPNO
+ 0x03, // SPECIES_KRABBY
+ 0x4b, // SPECIES_KINGLER
+ 0x00, // SPECIES_VOLTORB
+ 0x00, // SPECIES_ELECTRODE
+ 0x46, // SPECIES_EXEGGCUTE
+ 0x32, // SPECIES_EXEGGUTOR
+ 0x48, // SPECIES_CUBONE
+ 0x05, // SPECIES_MAROWAK
+ 0x16, // SPECIES_HITMONLEE
+ 0x09, // SPECIES_HITMONCHAN
+ 0x45, // SPECIES_LICKITUNG
+ 0x13, // SPECIES_KOFFING
+ 0x04, // SPECIES_WEEZING
+ 0x10, // SPECIES_RHYHORN
+ 0x13, // SPECIES_RHYDON
+ 0x45, // SPECIES_CHANSEY
+ 0x48, // SPECIES_TANGELA
+ 0x17, // SPECIES_KANGASKHAN
+ 0x12, // SPECIES_HORSEA
+ 0x04, // SPECIES_SEADRA
+ 0x0d, // SPECIES_GOLDEEN
+ 0x1c, // SPECIES_SEAKING
+ 0x4e, // SPECIES_STARYU
+ 0x12, // SPECIES_STARMIE
+ 0x46, // SPECIES_MR_MIME
+ 0x02, // SPECIES_SCYTHER
+ 0x17, // SPECIES_JYNX
+ 0x2c, // SPECIES_ELECTABUZZ
+ 0x0f, // SPECIES_MAGMAR
+ 0x09, // SPECIES_PINSIR
+ 0x19, // SPECIES_TAUROS
+ 0x05, // SPECIES_MAGIKARP
+ 0x48, // SPECIES_GYARADOS
+ 0x17, // SPECIES_LAPRAS
+ 0x01, // SPECIES_DITTO
+ 0x17, // SPECIES_EEVEE
+ 0x17, // SPECIES_VAPOREON
+ 0x00, // SPECIES_JOLTEON
+ 0x17, // SPECIES_FLAREON
+ 0x52, // SPECIES_PORYGON
+ 0x51, // SPECIES_OMANYTE
+ 0x09, // SPECIES_OMASTAR
+ 0x1d, // SPECIES_KABUTO
+ 0x0f, // SPECIES_KABUTOPS
+ 0x47, // SPECIES_AERODACTYL
+ 0x0b, // SPECIES_SNORLAX
+ 0x09, // SPECIES_ARTICUNO
+ 0x2c, // SPECIES_ZAPDOS
+ 0x45, // SPECIES_MOLTRES
+ 0x00, // SPECIES_DRATINI
+ 0x10, // SPECIES_DRAGONAIR
+ 0x47, // SPECIES_DRAGONITE
+ 0x09, // SPECIES_MEWTWO
+ 0x0d, // SPECIES_MEW
+ 0x00, // SPECIES_CHIKORITA
+ 0x00, // SPECIES_BAYLEEF
+ 0x17, // SPECIES_MEGANIUM
+ 0x52, // SPECIES_CYNDAQUIL
+ 0x17, // SPECIES_QUILAVA
+ 0x10, // SPECIES_TYPHLOSION
+ 0x31, // SPECIES_TOTODILE
+ 0x0f, // SPECIES_CROCONAW
+ 0x0f, // SPECIES_FERALIGATR
+ 0x00, // SPECIES_SENTRET
+ 0x32, // SPECIES_FURRET
+ 0x47, // SPECIES_HOOTHOOT
+ 0x17, // SPECIES_NOCTOWL
+ 0x52, // SPECIES_LEDYBA
+ 0x47, // SPECIES_LEDIAN
+ 0x4f, // SPECIES_SPINARAK
+ 0x0f, // SPECIES_ARIADOS
+ 0x00, // SPECIES_CROBAT
+ 0x45, // SPECIES_CHINCHOU
+ 0x51, // SPECIES_LANTURN
+ 0x1e, // SPECIES_PICHU
+ 0x52, // SPECIES_CLEFFA
+ 0x0c, // SPECIES_IGGLYBUFF
+ 0x0b, // SPECIES_TOGEPI
+ 0x00, // SPECIES_TOGETIC
+ 0x31, // SPECIES_NATU
+ 0x09, // SPECIES_XATU
+ 0x00, // SPECIES_MAREEP
+ 0x1e, // SPECIES_FLAAFFY
+ 0x2c, // SPECIES_AMPHAROS
+ 0x0b, // SPECIES_BELLOSSOM
+ 0x00, // SPECIES_MARILL
+ 0x4a, // SPECIES_AZUMARILL
+ 0x46, // SPECIES_SUDOWOODO
+ 0x32, // SPECIES_POLITOED
+ 0x1c, // SPECIES_HOPPIP
+ 0x18, // SPECIES_SKIPLOOM
+ 0x51, // SPECIES_JUMPLUFF
+ 0x32, // SPECIES_AIPOM
+ 0x52, // SPECIES_SUNKERN
+ 0x00, // SPECIES_SUNFLORA
+ 0x2b, // SPECIES_YANMA
+ 0x00, // SPECIES_WOOPER
+ 0x16, // SPECIES_QUAGSIRE
+ 0x09, // SPECIES_ESPEON
+ 0x10, // SPECIES_UMBREON
+ 0x00, // SPECIES_MURKROW
+ 0x13, // SPECIES_SLOWKING
+ 0x1c, // SPECIES_MISDREAVUS
+ 0x0a, // SPECIES_UNOWN
+ 0x30, // SPECIES_WOBBUFFET
+ 0x1e, // SPECIES_GIRAFARIG
+ 0x0b, // SPECIES_PINECO
+ 0x10, // SPECIES_FORRETRESS
+ 0x00, // SPECIES_DUNSPARCE
+ 0x13, // SPECIES_GLIGAR
+ 0x0f, // SPECIES_STEELIX
+ 0x17, // SPECIES_SNUBBULL
+ 0x10, // SPECIES_GRANBULL
+ 0x3a, // SPECIES_QWILFISH
+ 0x02, // SPECIES_SCIZOR
+ 0x0b, // SPECIES_SHUCKLE
+ 0x41, // SPECIES_HERACROSS
+ 0x16, // SPECIES_SNEASEL
+ 0x17, // SPECIES_TEDDIURSA
+ 0x10, // SPECIES_URSARING
+ 0x17, // SPECIES_SLUGMA
+ 0x17, // SPECIES_MAGCARGO
+ 0x00, // SPECIES_SWINUB
+ 0x0f, // SPECIES_PILOSWINE
+ 0x03, // SPECIES_CORSOLA
+ 0x52, // SPECIES_REMORAID
+ 0x17, // SPECIES_OCTILLERY
+ 0x52, // SPECIES_DELIBIRD
+ 0x0d, // SPECIES_MANTINE
+ 0x17, // SPECIES_SKARMORY
+ 0x17, // SPECIES_HOUNDOUR
+ 0x10, // SPECIES_HOUNDOOM
+ 0x42, // SPECIES_KINGDRA
+ 0x32, // SPECIES_PHANPY
+ 0x19, // SPECIES_DONPHAN
+ 0x00, // SPECIES_PORYGON2
+ 0x00, // SPECIES_STANTLER
+ 0x31, // SPECIES_SMEARGLE
+ 0x16, // SPECIES_TYROGUE
+ 0x02, // SPECIES_HITMONTOP
+ 0x09, // SPECIES_SMOOCHUM
+ 0x2c, // SPECIES_ELEKID
+ 0x00, // SPECIES_MAGBY
+ 0x45, // SPECIES_MILTANK
+ 0x00, // SPECIES_BLISSEY
+ 0x2c, // SPECIES_RAIKOU
+ 0x09, // SPECIES_ENTEI
+ 0x10, // SPECIES_SUICUNE
+ 0x52, // SPECIES_LARVITAR
+ 0x10, // SPECIES_PUPITAR
+ 0x0f, // SPECIES_TYRANITAR
+ 0x3a, // SPECIES_LUGIA
+ 0x09, // SPECIES_HO_OH
+ 0x18, // SPECIES_CELEBI
+ 0x00, // 252
+ 0x00, // 253
+ 0x00, // 254
+ 0x00, // 255
+ 0x00, // 256
+ 0x00, // 257
+ 0x00, // 258
+ 0x00, // 259
+ 0x00, // 260
+ 0x00, // 261
+ 0x00, // 262
+ 0x00, // 263
+ 0x00, // 264
+ 0x00, // 265
+ 0x00, // 266
+ 0x00, // 267
+ 0x00, // 268
+ 0x00, // 269
+ 0x00, // 270
+ 0x00, // 271
+ 0x00, // 272
+ 0x00, // 273
+ 0x00, // 274
+ 0x00, // 275
+ 0x00, // 276
+ 0x00, // SPECIES_TREECKO
+ 0x17, // SPECIES_GROVYLE
+ 0x10, // SPECIES_SCEPTILE
+ 0x16, // SPECIES_TORCHIC
+ 0x06, // SPECIES_COMBUSKEN
+ 0x0f, // SPECIES_BLAZIKEN
+ 0x01, // SPECIES_MUDKIP
+ 0x04, // SPECIES_MARSHTOMP
+ 0x1e, // SPECIES_SWAMPERT
+ 0x10, // SPECIES_POOCHYENA
+ 0x10, // SPECIES_MIGHTYENA
+ 0x03, // SPECIES_ZIGZAGOON
+ 0x09, // SPECIES_LINOONE
+ 0x00, // SPECIES_WURMPLE
+ 0x00, // SPECIES_SILCOON
+ 0x04, // SPECIES_BEAUTIFLY
+ 0x04, // SPECIES_CASCOON
+ 0x06, // SPECIES_DUSTOX
+ 0x00, // SPECIES_LOTAD
+ 0x00, // SPECIES_LOMBRE
+ 0x49, // SPECIES_LUDICOLO
+ 0x05, // SPECIES_SEEDOT
+ 0x00, // SPECIES_NUZLEAF
+ 0x02, // SPECIES_SHIFTRY
+ 0x00, // SPECIES_NINCADA
+ 0x46, // SPECIES_NINJASK
+ 0x1c, // SPECIES_SHEDINJA
+ 0x1e, // SPECIES_TAILLOW
+ 0x01, // SPECIES_SWELLOW
+ 0x00, // SPECIES_SHROOMISH
+ 0x00, // SPECIES_BRELOOM
+ 0x31, // SPECIES_SPINDA
+ 0x1b, // SPECIES_WINGULL
+ 0x1c, // SPECIES_PELIPPER
+ 0x00, // SPECIES_SURSKIT
+ 0x00, // SPECIES_MASQUERAIN
+ 0x01, // SPECIES_WAILMER
+ 0x1c, // SPECIES_WAILORD
+ 0x00, // SPECIES_SKITTY
+ 0x17, // SPECIES_DELCATTY
+ 0x35, // SPECIES_KECLEON
+ 0x1d, // SPECIES_BALTOY
+ 0x51, // SPECIES_CLAYDOL
+ 0x49, // SPECIES_NOSEPASS
+ 0x17, // SPECIES_TORKOAL
+ 0x15, // SPECIES_SABLEYE
+ 0x49, // SPECIES_BARBOACH
+ 0x49, // SPECIES_WHISCASH
+ 0x1d, // SPECIES_LUVDISC
+ 0x10, // SPECIES_CORPHISH
+ 0x09, // SPECIES_CRAWDAUNT
+ 0x49, // SPECIES_FEEBAS
+ 0x22, // SPECIES_MILOTIC
+ 0x49, // SPECIES_CARVANHA
+ 0x56, // SPECIES_SHARPEDO
+ 0x10, // SPECIES_TRAPINCH
+ 0x0f, // SPECIES_VIBRAVA
+ 0x4b, // SPECIES_FLYGON
+ 0x0b, // SPECIES_MAKUHITA
+ 0x34, // SPECIES_HARIYAMA
+ 0x00, // SPECIES_ELECTRIKE
+ 0x00, // SPECIES_MANECTRIC
+ 0x04, // SPECIES_NUMEL
+ 0x10, // SPECIES_CAMERUPT
+ 0x53, // SPECIES_SPHEAL
+ 0x17, // SPECIES_SEALEO
+ 0x0f, // SPECIES_WALREIN
+ 0x49, // SPECIES_CACNEA
+ 0x04, // SPECIES_CACTURNE
+ 0x45, // SPECIES_SNORUNT
+ 0x0a, // SPECIES_GLALIE
+ 0x0e, // SPECIES_LUNATONE
+ 0x08, // SPECIES_SOLROCK
+ 0x00, // SPECIES_AZURILL
+ 0x56, // SPECIES_SPOINK
+ 0x32, // SPECIES_GRUMPIG
+ 0x00, // SPECIES_PLUSLE
+ 0x01, // SPECIES_MINUN
+ 0x00, // SPECIES_MAWILE
+ 0x05, // SPECIES_MEDITITE
+ 0x45, // SPECIES_MEDICHAM
+ 0x04, // SPECIES_SWABLU
+ 0x16, // SPECIES_ALTARIA
+ 0x32, // SPECIES_WYNAUT
+ 0x0a, // SPECIES_DUSKULL
+ 0x02, // SPECIES_DUSCLOPS
+ 0x45, // SPECIES_ROSELIA
+ 0x45, // SPECIES_SLAKOTH
+ 0x31, // SPECIES_VIGOROTH
+ 0x45, // SPECIES_SLAKING
+ 0x00, // SPECIES_GULPIN
+ 0x45, // SPECIES_SWALOT
+ 0x10, // SPECIES_TROPIUS
+ 0x03, // SPECIES_WHISMUR
+ 0x49, // SPECIES_LOUDRED
+ 0x19, // SPECIES_EXPLOUD
+ 0x12, // SPECIES_CLAMPERL
+ 0x09, // SPECIES_HUNTAIL
+ 0x1c, // SPECIES_GOREBYSS
+ 0x11, // SPECIES_ABSOL
+ 0x1c, // SPECIES_SHUPPET
+ 0x0d, // SPECIES_BANETTE
+ 0x17, // SPECIES_SEVIPER
+ 0x09, // SPECIES_ZANGOOSE
+ 0x1a, // SPECIES_RELICANTH
+ 0x45, // SPECIES_ARON
+ 0x00, // SPECIES_LAIRON
+ 0x19, // SPECIES_AGGRON
+ 0x1d, // SPECIES_CASTFORM
+ 0x00, // SPECIES_VOLBEAT
+ 0x05, // SPECIES_ILLUMISE
+ 0x17, // SPECIES_LILEEP
+ 0x19, // SPECIES_CRADILY
+ 0x12, // SPECIES_ANORITH
+ 0x10, // SPECIES_ARMALDO
+ 0x45, // SPECIES_RALTS
+ 0x00, // SPECIES_KIRLIA
+ 0x00, // SPECIES_GARDEVOIR
+ 0x19, // SPECIES_BAGON
+ 0x04, // SPECIES_SHELGON
+ 0x0f, // SPECIES_SALAMENCE
+ 0x0f, // SPECIES_BELDUM
+ 0x04, // SPECIES_METANG
+ 0x10, // SPECIES_METAGROSS
+ 0x01, // SPECIES_REGIROCK
+ 0x44, // SPECIES_REGICE
+ 0x09, // SPECIES_REGISTEEL
+ 0x2d, // SPECIES_KYOGRE
+ 0x10, // SPECIES_GROUDON
+ 0x0f, // SPECIES_RAYQUAZA
+ 0x2d, // SPECIES_LATIAS
+ 0x10, // SPECIES_LATIOS
+ 0x0d, // SPECIES_JIRACHI
+ 0x1b, // SPECIES_DEOXYS
+ 0x1d, // SPECIES_CHIMECHO
+};
+
+static const u8 sMonAnimationDelayTable[] =
+{
+ 0x00, // SPECIES_BULBASAUR
+ 0x00, // SPECIES_IVYSAUR
+ 0x00, // SPECIES_VENUSAUR
+ 0x00, // SPECIES_CHARMANDER
+ 0x00, // SPECIES_CHARMELEON
+ 0x00, // SPECIES_CHARIZARD
+ 0x00, // SPECIES_SQUIRTLE
+ 0x00, // SPECIES_WARTORTLE
+ 0x32, // SPECIES_BLASTOISE
+ 0x00, // SPECIES_CATERPIE
+ 0x00, // SPECIES_METAPOD
+ 0x00, // SPECIES_BUTTERFREE
+ 0x0a, // SPECIES_WEEDLE
+ 0x14, // SPECIES_KAKUNA
+ 0x23, // SPECIES_BEEDRILL
+ 0x00, // SPECIES_PIDGEY
+ 0x19, // SPECIES_PIDGEOTTO
+ 0x00, // SPECIES_PIDGEOT
+ 0x00, // SPECIES_RATTATA
+ 0x00, // SPECIES_RATICATE
+ 0x00, // SPECIES_SPEAROW
+ 0x02, // SPECIES_FEAROW
+ 0x1e, // SPECIES_EKANS
+ 0x00, // SPECIES_ARBOK
+ 0x00, // SPECIES_PIKACHU
+ 0x00, // SPECIES_RAICHU
+ 0x00, // SPECIES_SANDSHREW
+ 0x00, // SPECIES_SANDSLASH
+ 0x1c, // SPECIES_NIDORAN_F
+ 0x00, // SPECIES_NIDORINA
+ 0x00, // SPECIES_NIDOQUEEN
+ 0x00, // SPECIES_NIDORAN_M
+ 0x00, // SPECIES_NIDORINO
+ 0x19, // SPECIES_NIDOKING
+ 0x00, // SPECIES_CLEFAIRY
+ 0x00, // SPECIES_CLEFABLE
+ 0x00, // SPECIES_VULPIX
+ 0x00, // SPECIES_NINETALES
+ 0x00, // SPECIES_JIGGLYPUFF
+ 0x00, // SPECIES_WIGGLYTUFF
+ 0x00, // SPECIES_ZUBAT
+ 0x00, // SPECIES_GOLBAT
+ 0x00, // SPECIES_ODDISH
+ 0x00, // SPECIES_GLOOM
+ 0x00, // SPECIES_VILEPLUME
+ 0x0a, // SPECIES_PARAS
+ 0x2d, // SPECIES_PARASECT
+ 0x14, // SPECIES_VENONAT
+ 0x00, // SPECIES_VENOMOTH
+ 0x19, // SPECIES_DIGLETT
+ 0x23, // SPECIES_DUGTRIO
+ 0x28, // SPECIES_MEOWTH
+ 0x14, // SPECIES_PERSIAN
+ 0x00, // SPECIES_PSYDUCK
+ 0x00, // SPECIES_GOLDUCK
+ 0x14, // SPECIES_MANKEY
+ 0x00, // SPECIES_PRIMEAPE
+ 0x1e, // SPECIES_GROWLITHE
+ 0x28, // SPECIES_ARCANINE
+ 0x00, // SPECIES_POLIWAG
+ 0x05, // SPECIES_POLIWHIRL
+ 0x00, // SPECIES_POLIWRATH
+ 0x00, // SPECIES_ABRA
+ 0x00, // SPECIES_KADABRA
+ 0x00, // SPECIES_ALAKAZAM
+ 0x00, // SPECIES_MACHOP
+ 0x00, // SPECIES_MACHOKE
+ 0x00, // SPECIES_MACHAMP
+ 0x00, // SPECIES_BELLSPROUT
+ 0x03, // SPECIES_WEEPINBELL
+ 0x00, // SPECIES_VICTREEBEL
+ 0x00, // SPECIES_TENTACOOL
+ 0x00, // SPECIES_TENTACRUEL
+ 0x00, // SPECIES_GEODUDE
+ 0x00, // SPECIES_GRAVELER
+ 0x00, // SPECIES_GOLEM
+ 0x00, // SPECIES_PONYTA
+ 0x00, // SPECIES_RAPIDASH
+ 0x00, // SPECIES_SLOWPOKE
+ 0x00, // SPECIES_SLOWBRO
+ 0x00, // SPECIES_MAGNEMITE
+ 0x00, // SPECIES_MAGNETON
+ 0x00, // SPECIES_FARFETCHD
+ 0x00, // SPECIES_DODUO
+ 0x00, // SPECIES_DODRIO
+ 0x00, // SPECIES_SEEL
+ 0x00, // SPECIES_DEWGONG
+ 0x00, // SPECIES_GRIMER
+ 0x2d, // SPECIES_MUK
+ 0x14, // SPECIES_SHELLDER
+ 0x00, // SPECIES_CLOYSTER
+ 0x00, // SPECIES_GASTLY
+ 0x17, // SPECIES_HAUNTER
+ 0x00, // SPECIES_GENGAR
+ 0x00, // SPECIES_ONIX
+ 0x30, // SPECIES_DROWZEE
+ 0x28, // SPECIES_HYPNO
+ 0x00, // SPECIES_KRABBY
+ 0x00, // SPECIES_KINGLER
+ 0x00, // SPECIES_VOLTORB
+ 0x00, // SPECIES_ELECTRODE
+ 0x00, // SPECIES_EXEGGCUTE
+ 0x00, // SPECIES_EXEGGUTOR
+ 0x00, // SPECIES_CUBONE
+ 0x00, // SPECIES_MAROWAK
+ 0x00, // SPECIES_HITMONLEE
+ 0x19, // SPECIES_HITMONCHAN
+ 0x00, // SPECIES_LICKITUNG
+ 0x00, // SPECIES_KOFFING
+ 0x00, // SPECIES_WEEZING
+ 0x00, // SPECIES_RHYHORN
+ 0x00, // SPECIES_RHYDON
+ 0x00, // SPECIES_CHANSEY
+ 0x00, // SPECIES_TANGELA
+ 0x00, // SPECIES_KANGASKHAN
+ 0x00, // SPECIES_HORSEA
+ 0x00, // SPECIES_SEADRA
+ 0x00, // SPECIES_GOLDEEN
+ 0x00, // SPECIES_SEAKING
+ 0x00, // SPECIES_STARYU
+ 0x00, // SPECIES_STARMIE
+ 0x00, // SPECIES_MR_MIME
+ 0x0a, // SPECIES_SCYTHER
+ 0x00, // SPECIES_JYNX
+ 0x00, // SPECIES_ELECTABUZZ
+ 0x00, // SPECIES_MAGMAR
+ 0x00, // SPECIES_PINSIR
+ 0x0a, // SPECIES_TAUROS
+ 0x00, // SPECIES_MAGIKARP
+ 0x00, // SPECIES_GYARADOS
+ 0x00, // SPECIES_LAPRAS
+ 0x00, // SPECIES_DITTO
+ 0x00, // SPECIES_EEVEE
+ 0x00, // SPECIES_VAPOREON
+ 0x00, // SPECIES_JOLTEON
+ 0x00, // SPECIES_FLAREON
+ 0x00, // SPECIES_PORYGON
+ 0x00, // SPECIES_OMANYTE
+ 0x00, // SPECIES_OMASTAR
+ 0x00, // SPECIES_KABUTO
+ 0x00, // SPECIES_KABUTOPS
+ 0x00, // SPECIES_AERODACTYL
+ 0x00, // SPECIES_SNORLAX
+ 0x00, // SPECIES_ARTICUNO
+ 0x00, // SPECIES_ZAPDOS
+ 0x00, // SPECIES_MOLTRES
+ 0x00, // SPECIES_DRATINI
+ 0x00, // SPECIES_DRAGONAIR
+ 0x00, // SPECIES_DRAGONITE
+ 0x00, // SPECIES_MEWTWO
+ 0x00, // SPECIES_MEW
+ 0x00, // SPECIES_CHIKORITA
+ 0x00, // SPECIES_BAYLEEF
+ 0x00, // SPECIES_MEGANIUM
+ 0x00, // SPECIES_CYNDAQUIL
+ 0x00, // SPECIES_QUILAVA
+ 0x14, // SPECIES_TYPHLOSION
+ 0x00, // SPECIES_TOTODILE
+ 0x00, // SPECIES_CROCONAW
+ 0x05, // SPECIES_FERALIGATR
+ 0x00, // SPECIES_SENTRET
+ 0x00, // SPECIES_FURRET
+ 0x00, // SPECIES_HOOTHOOT
+ 0x00, // SPECIES_NOCTOWL
+ 0x00, // SPECIES_LEDYBA
+ 0x00, // SPECIES_LEDIAN
+ 0x00, // SPECIES_SPINARAK
+ 0x00, // SPECIES_ARIADOS
+ 0x00, // SPECIES_CROBAT
+ 0x00, // SPECIES_CHINCHOU
+ 0x00, // SPECIES_LANTURN
+ 0x00, // SPECIES_PICHU
+ 0x00, // SPECIES_CLEFFA
+ 0x00, // SPECIES_IGGLYBUFF
+ 0x00, // SPECIES_TOGEPI
+ 0x00, // SPECIES_TOGETIC
+ 0x1e, // SPECIES_NATU
+ 0x00, // SPECIES_XATU
+ 0x32, // SPECIES_MAREEP
+ 0x00, // SPECIES_FLAAFFY
+ 0x0a, // SPECIES_AMPHAROS
+ 0x00, // SPECIES_BELLOSSOM
+ 0x00, // SPECIES_MARILL
+ 0x00, // SPECIES_AZUMARILL
+ 0x00, // SPECIES_SUDOWOODO
+ 0x28, // SPECIES_POLITOED
+ 0x00, // SPECIES_HOPPIP
+ 0x00, // SPECIES_SKIPLOOM
+ 0x00, // SPECIES_JUMPLUFF
+ 0x00, // SPECIES_AIPOM
+ 0x00, // SPECIES_SUNKERN
+ 0x00, // SPECIES_SUNFLORA
+ 0x00, // SPECIES_YANMA
+ 0x00, // SPECIES_WOOPER
+ 0x00, // SPECIES_QUAGSIRE
+ 0x00, // SPECIES_ESPEON
+ 0x00, // SPECIES_UMBREON
+ 0x00, // SPECIES_MURKROW
+ 0x00, // SPECIES_SLOWKING
+ 0x00, // SPECIES_MISDREAVUS
+ 0x00, // SPECIES_UNOWN
+ 0x00, // SPECIES_WOBBUFFET
+ 0x00, // SPECIES_GIRAFARIG
+ 0x00, // SPECIES_PINECO
+ 0x00, // SPECIES_FORRETRESS
+ 0x0a, // SPECIES_DUNSPARCE
+ 0x00, // SPECIES_GLIGAR
+ 0x2d, // SPECIES_STEELIX
+ 0x00, // SPECIES_SNUBBULL
+ 0x00, // SPECIES_GRANBULL
+ 0x27, // SPECIES_QWILFISH
+ 0x13, // SPECIES_SCIZOR
+ 0x00, // SPECIES_SHUCKLE
+ 0x00, // SPECIES_HERACROSS
+ 0x00, // SPECIES_SNEASEL
+ 0x00, // SPECIES_TEDDIURSA
+ 0x00, // SPECIES_URSARING
+ 0x00, // SPECIES_SLUGMA
+ 0x00, // SPECIES_MAGCARGO
+ 0x00, // SPECIES_SWINUB
+ 0x00, // SPECIES_PILOSWINE
+ 0x00, // SPECIES_CORSOLA
+ 0x00, // SPECIES_REMORAID
+ 0x14, // SPECIES_OCTILLERY
+ 0x00, // SPECIES_DELIBIRD
+ 0x00, // SPECIES_MANTINE
+ 0x00, // SPECIES_SKARMORY
+ 0x00, // SPECIES_HOUNDOUR
+ 0x00, // SPECIES_HOUNDOOM
+ 0x00, // SPECIES_KINGDRA
+ 0x00, // SPECIES_PHANPY
+ 0x00, // SPECIES_DONPHAN
+ 0x00, // SPECIES_PORYGON2
+ 0x00, // SPECIES_STANTLER
+ 0x00, // SPECIES_SMEARGLE
+ 0x00, // SPECIES_TYROGUE
+ 0x00, // SPECIES_HITMONTOP
+ 0x28, // SPECIES_SMOOCHUM
+ 0x00, // SPECIES_ELEKID
+ 0x00, // SPECIES_MAGBY
+ 0x00, // SPECIES_MILTANK
+ 0x00, // SPECIES_BLISSEY
+ 0x00, // SPECIES_RAIKOU
+ 0x00, // SPECIES_ENTEI
+ 0x00, // SPECIES_SUICUNE
+ 0x00, // SPECIES_LARVITAR
+ 0x00, // SPECIES_PUPITAR
+ 0x0a, // SPECIES_TYRANITAR
+ 0x14, // SPECIES_LUGIA
+ 0x00, // SPECIES_HO_OH
+ 0x00, // SPECIES_CELEBI
+ 0x00, // 252
+ 0x00, // 253
+ 0x00, // 254
+ 0x00, // 255
+ 0x00, // 256
+ 0x00, // 257
+ 0x00, // 258
+ 0x00, // 259
+ 0x00, // 260
+ 0x00, // 261
+ 0x00, // 262
+ 0x00, // 263
+ 0x00, // 264
+ 0x00, // 265
+ 0x00, // 266
+ 0x00, // 267
+ 0x00, // 268
+ 0x00, // 269
+ 0x00, // 270
+ 0x00, // 271
+ 0x00, // 272
+ 0x00, // 273
+ 0x00, // 274
+ 0x00, // 275
+ 0x00, // 276
+ 0x00, // SPECIES_TREECKO
+ 0x00, // SPECIES_GROVYLE
+ 0x00, // SPECIES_SCEPTILE
+ 0x00, // SPECIES_TORCHIC
+ 0x00, // SPECIES_COMBUSKEN
+ 0x00, // SPECIES_BLAZIKEN
+ 0x00, // SPECIES_MUDKIP
+ 0x00, // SPECIES_MARSHTOMP
+ 0x00, // SPECIES_SWAMPERT
+ 0x00, // SPECIES_POOCHYENA
+ 0x00, // SPECIES_MIGHTYENA
+ 0x00, // SPECIES_ZIGZAGOON
+ 0x00, // SPECIES_LINOONE
+ 0x00, // SPECIES_WURMPLE
+ 0x00, // SPECIES_SILCOON
+ 0x00, // SPECIES_BEAUTIFLY
+ 0x00, // SPECIES_CASCOON
+ 0x00, // SPECIES_DUSTOX
+ 0x00, // SPECIES_LOTAD
+ 0x00, // SPECIES_LOMBRE
+ 0x00, // SPECIES_LUDICOLO
+ 0x00, // SPECIES_SEEDOT
+ 0x00, // SPECIES_NUZLEAF
+ 0x00, // SPECIES_SHIFTRY
+ 0x00, // SPECIES_NINCADA
+ 0x00, // SPECIES_NINJASK
+ 0x00, // SPECIES_SHEDINJA
+ 0x00, // SPECIES_TAILLOW
+ 0x00, // SPECIES_SWELLOW
+ 0x00, // SPECIES_SHROOMISH
+ 0x00, // SPECIES_BRELOOM
+ 0x00, // SPECIES_SPINDA
+ 0x00, // SPECIES_WINGULL
+ 0x00, // SPECIES_PELIPPER
+ 0x00, // SPECIES_SURSKIT
+ 0x00, // SPECIES_MASQUERAIN
+ 0x00, // SPECIES_WAILMER
+ 0x0a, // SPECIES_WAILORD
+ 0x00, // SPECIES_SKITTY
+ 0x00, // SPECIES_DELCATTY
+ 0x1e, // SPECIES_KECLEON
+ 0x00, // SPECIES_BALTOY
+ 0x00, // SPECIES_CLAYDOL
+ 0x00, // SPECIES_NOSEPASS
+ 0x00, // SPECIES_TORKOAL
+ 0x00, // SPECIES_SABLEYE
+ 0x00, // SPECIES_BARBOACH
+ 0x00, // SPECIES_WHISCASH
+ 0x00, // SPECIES_LUVDISC
+ 0x00, // SPECIES_CORPHISH
+ 0x00, // SPECIES_CRAWDAUNT
+ 0x00, // SPECIES_FEEBAS
+ 0x2d, // SPECIES_MILOTIC
+ 0x00, // SPECIES_CARVANHA
+ 0x00, // SPECIES_SHARPEDO
+ 0x00, // SPECIES_TRAPINCH
+ 0x00, // SPECIES_VIBRAVA
+ 0x00, // SPECIES_FLYGON
+ 0x00, // SPECIES_MAKUHITA
+ 0x00, // SPECIES_HARIYAMA
+ 0x00, // SPECIES_ELECTRIKE
+ 0x00, // SPECIES_MANECTRIC
+ 0x00, // SPECIES_NUMEL
+ 0x00, // SPECIES_CAMERUPT
+ 0x0f, // SPECIES_SPHEAL
+ 0x00, // SPECIES_SEALEO
+ 0x00, // SPECIES_WALREIN
+ 0x00, // SPECIES_CACNEA
+ 0x00, // SPECIES_CACTURNE
+ 0x14, // SPECIES_SNORUNT
+ 0x00, // SPECIES_GLALIE
+ 0x00, // SPECIES_LUNATONE
+ 0x00, // SPECIES_SOLROCK
+ 0x00, // SPECIES_AZURILL
+ 0x00, // SPECIES_SPOINK
+ 0x0f, // SPECIES_GRUMPIG
+ 0x00, // SPECIES_PLUSLE
+ 0x00, // SPECIES_MINUN
+ 0x00, // SPECIES_MAWILE
+ 0x00, // SPECIES_MEDITITE
+ 0x00, // SPECIES_MEDICHAM
+ 0x00, // SPECIES_SWABLU
+ 0x00, // SPECIES_ALTARIA
+ 0x0f, // SPECIES_WYNAUT
+ 0x00, // SPECIES_DUSKULL
+ 0x1e, // SPECIES_DUSCLOPS
+ 0x00, // SPECIES_ROSELIA
+ 0x00, // SPECIES_SLAKOTH
+ 0x00, // SPECIES_VIGOROTH
+ 0x00, // SPECIES_SLAKING
+ 0x00, // SPECIES_GULPIN
+ 0x00, // SPECIES_SWALOT
+ 0x00, // SPECIES_TROPIUS
+ 0x00, // SPECIES_WHISMUR
+ 0x00, // SPECIES_LOUDRED
+ 0x00, // SPECIES_EXPLOUD
+ 0x00, // SPECIES_CLAMPERL
+ 0x00, // SPECIES_HUNTAIL
+ 0x00, // SPECIES_GOREBYSS
+ 0x2d, // SPECIES_ABSOL
+ 0x00, // SPECIES_SHUPPET
+ 0x00, // SPECIES_BANETTE
+ 0x00, // SPECIES_SEVIPER
+ 0x00, // SPECIES_ZANGOOSE
+ 0x00, // SPECIES_RELICANTH
+ 0x00, // SPECIES_ARON
+ 0x00, // SPECIES_LAIRON
+ 0x00, // SPECIES_AGGRON
+ 0x00, // SPECIES_CASTFORM
+ 0x00, // SPECIES_VOLBEAT
+ 0x00, // SPECIES_ILLUMISE
+ 0x00, // SPECIES_LILEEP
+ 0x00, // SPECIES_CRADILY
+ 0x00, // SPECIES_ANORITH
+ 0x00, // SPECIES_ARMALDO
+ 0x00, // SPECIES_RALTS
+ 0x00, // SPECIES_KIRLIA
+ 0x00, // SPECIES_GARDEVOIR
+ 0x00, // SPECIES_BAGON
+ 0x00, // SPECIES_SHELGON
+ 0x46, // SPECIES_SALAMENCE
+ 0x00, // SPECIES_BELDUM
+ 0x00, // SPECIES_METANG
+ 0x00, // SPECIES_METAGROSS
+ 0x00, // SPECIES_REGIROCK
+ 0x00, // SPECIES_REGICE
+ 0x00, // SPECIES_REGISTEEL
+ 0x3c, // SPECIES_KYOGRE
+ 0x00, // SPECIES_GROUDON
+ 0x3c, // SPECIES_RAYQUAZA
+ 0x00, // SPECIES_LATIAS
+ 0x00, // SPECIES_LATIOS
+ 0x00, // SPECIES_JIRACHI
+ 0x00, // SPECIES_DEOXYS
+ 0x00, // SPECIES_CHIMECHO
+};
+
+const u8 gUnknown_08329D22[] = {0x03, 0x0c, 0x30, 0xc0}; // Masks for getting PP Up count, also PP Max values
+const u8 gUnknown_08329D26[] = {0xfc, 0xf3, 0xcf, 0x3f}; // Masks for setting PP Up count
+const u8 gUnknown_08329D2A[] = {0x01, 0x04, 0x10, 0x40}; // Values added to PP Up count
+
+const u8 gStatStageRatios[][2] =
+{
+ {10, 40}, // -6
+ {10, 35}, // -5
+ {10, 30}, // -4
+ {10, 25}, // -3
+ {10, 20}, // -2
+ {10, 15}, // -1
+ {10, 10}, // 0
+ {15, 10}, // +1
+ {20, 10}, // +2
+ {25, 10}, // +3
+ {30, 10}, // +4
+ {35, 10}, // +5
+ {40, 10}, // +6
+};
+
+static const u16 sDeoxysBaseStats[] =
+{
+ 50, // Hp
+ 95, // Attack
+ 90, // Defense
+ 180, // Speed
+ 95, // Sp.Attack
+ 90, // Sp.Defense
+};
+
+const u16 gUnknown_08329D54[] =
+{
+ FACILITY_CLASS_COOLTRAINER_M, FACILITY_CLASS_BLACK_BELT, FACILITY_CLASS_CAMPER,
+ FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_PSYCHIC_M, FACILITY_CLASS_BUG_CATCHER,
+ FACILITY_CLASS_PKMN_BREEDER_2, FACILITY_CLASS_GUITARIST, FACILITY_CLASS_COOLTRAINER_F,
+ FACILITY_CLASS_HEX_MANIAC, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_LASS,
+ FACILITY_CLASS_PSYCHIC_F, FACILITY_CLASS_BATTLE_GIRL, FACILITY_CLASS_PKMN_BREEDER_1,
+ FACILITY_CLASS_BEAUTY
+};
+
+static const u8 sHoldEffectToType[][2] =
+{
+ {HOLD_EFFECT_BUG_POWER, TYPE_BUG},
+ {HOLD_EFFECT_STEEL_POWER, TYPE_STEEL},
+ {HOLD_EFFECT_GROUND_POWER, TYPE_GROUND},
+ {HOLD_EFFECT_ROCK_POWER, TYPE_ROCK},
+ {HOLD_EFFECT_GRASS_POWER, TYPE_GRASS},
+ {HOLD_EFFECT_DARK_POWER, TYPE_DARK},
+ {HOLD_EFFECT_FIGHTING_POWER, TYPE_FIGHTING},
+ {HOLD_EFFECT_ELECTRIC_POWER, TYPE_ELECTRIC},
+ {HOLD_EFFECT_WATER_POWER, TYPE_WATER},
+ {HOLD_EFFECT_FLYING_POWER, TYPE_FLYING},
+ {HOLD_EFFECT_POISON_POWER, TYPE_POISON},
+ {HOLD_EFFECT_ICE_POWER, TYPE_ICE},
+ {HOLD_EFFECT_GHOST_POWER, TYPE_GHOST},
+ {HOLD_EFFECT_PSYCHIC_POWER, TYPE_PSYCHIC},
+ {HOLD_EFFECT_FIRE_POWER, TYPE_FIRE},
+ {HOLD_EFFECT_DRAGON_POWER, TYPE_DRAGON},
+ {HOLD_EFFECT_NORMAL_POWER, TYPE_NORMAL},
+};
+
+const struct SpriteTemplate gUnknown_08329D98[MAX_BATTLERS_COUNT] =
+{
+ { // B_POSITION_PLAYER_LEFT
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF3A8,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ { // B_POSITION_OPPONENT_LEFT
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACA8,
+ .anims = NULL,
+ .images = gUnknown_082FF3C8,
+ .affineAnims = gUnknown_082FF694,
+ .callback = oac_poke_opponent,
+ },
+ { // B_POSITION_PLAYER_RIGHT
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF3E8,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ { // B_POSITION_OPPONENT_RIGHT
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACA8,
+ .anims = NULL,
+ .images = gUnknown_082FF408,
+ .affineAnims = gUnknown_082FF694,
+ .callback = oac_poke_opponent
+ },
+};
+
+static const struct SpriteTemplate gUnknown_08329DF8[] =
+{
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF428,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF448,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF468,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF490,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF4B8,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF4D8,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF4F8,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+ {
+ .tileTag = 0xFFFF,
+ .paletteTag = 0,
+ .oam = &gUnknown_0831ACB0,
+ .anims = NULL,
+ .images = gUnknown_082FF518,
+ .affineAnims = gUnknown_082FF618,
+ .callback = sub_8039BB4,
+ },
+};
+
+static const u8 sSecretBaseFacilityClasses[2][5] =
+{
+ {FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_BUG_CATCHER, FACILITY_CLASS_RICH_BOY, FACILITY_CLASS_CAMPER, FACILITY_CLASS_COOLTRAINER_M},
+ {FACILITY_CLASS_LASS, FACILITY_CLASS_SCHOOL_KID_F, FACILITY_CLASS_LADY, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_COOLTRAINER_F}
+};
+
+static const u8 sGetMonDataEVConstants[] =
+{
+ MON_DATA_HP_EV,
+ MON_DATA_ATK_EV,
+ MON_DATA_DEF_EV,
+ MON_DATA_SPEED_EV,
+ MON_DATA_SPDEF_EV,
+ MON_DATA_SPATK_EV
+};
+
+static const u8 gUnknown_08329EC8[] =
+{
+ STAT_ATK, STAT_ATK, STAT_SPEED, STAT_DEF, STAT_SPATK, STAT_ACC
+};
+
+static const s8 gUnknown_08329ECE[][3] =
+{
+ { 5, 3, 2},
+ { 5, 3, 2},
+ { 1, 1, 0},
+ { 3, 2, 1},
+ { 1, 1, 0},
+ { 1, 1, 1},
+ {-1, -1, -1},
+ {-5, -5, -10},
+ {-5, -5, -10},
+};
+
+static const u16 sHMMoves[] =
+{
+ MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH,
+ MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, 0xFFFF
+};
+
+static const struct SpeciesItem sAlteringCaveWildMonHeldItems[] =
+{
+ {SPECIES_NONE, ITEM_NONE},
+ {SPECIES_MAREEP, ITEM_GANLON_BERRY},
+ {SPECIES_PINECO, ITEM_APICOT_BERRY},
+ {SPECIES_HOUNDOUR, ITEM_BIG_MUSHROOM},
+ {SPECIES_TEDDIURSA, ITEM_PETAYA_BERRY},
+ {SPECIES_AIPOM, ITEM_BERRY_JUICE},
+ {SPECIES_SHUCKLE, ITEM_BERRY_JUICE},
+ {SPECIES_STANTLER, ITEM_PETAYA_BERRY},
+ {SPECIES_SMEARGLE, ITEM_SALAC_BERRY},
+};
+
+static const struct OamData sOamData_8329F20 =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0
+};
+
+static const struct SpriteTemplate gUnknown_08329F28 =
+{
+ .tileTag = 0xFFFF,
+ .paletteTag = 0xFFFF,
+ .oam = &sOamData_8329F20,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+// code
+void ZeroBoxMonData(struct BoxPokemon *boxMon)
+{
+ u8 *raw = (u8 *)boxMon;
+ u32 i;
+ for (i = 0; i < sizeof(struct BoxPokemon); i++)
+ raw[i] = 0;
+}
+
+void ZeroMonData(struct Pokemon *mon)
+{
+ u32 arg;
+ ZeroBoxMonData(&mon->box);
+ arg = 0;
+ SetMonData(mon, MON_DATA_STATUS, &arg);
+ SetMonData(mon, MON_DATA_LEVEL, &arg);
+ SetMonData(mon, MON_DATA_HP, &arg);
+ SetMonData(mon, MON_DATA_MAX_HP, &arg);
+ SetMonData(mon, MON_DATA_ATK, &arg);
+ SetMonData(mon, MON_DATA_DEF, &arg);
+ SetMonData(mon, MON_DATA_SPEED, &arg);
+ SetMonData(mon, MON_DATA_SPATK, &arg);
+ SetMonData(mon, MON_DATA_SPDEF, &arg);
+ arg = 255;
+ SetMonData(mon, MON_DATA_MAIL, &arg);
+}
+
+void ZeroPlayerPartyMons(void)
+{
+ s32 i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ ZeroMonData(&gPlayerParty[i]);
+}
+
+void ZeroEnemyPartyMons(void)
+{
+ s32 i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ ZeroMonData(&gEnemyParty[i]);
+}
+
+void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
+{
+ u32 arg;
+ ZeroMonData(mon);
+ CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId);
+ SetMonData(mon, MON_DATA_LEVEL, &level);
+ arg = 255;
+ SetMonData(mon, MON_DATA_MAIL, &arg);
+ CalculateMonStats(mon);
+}
+
+void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
+{
+ u8 speciesName[POKEMON_NAME_LENGTH + 1];
+ u32 personality;
+ u32 value;
+ u16 checksum;
+
+ ZeroBoxMonData(boxMon);
+
+ if (hasFixedPersonality)
+ personality = fixedPersonality;
+ else
+ personality = Random32();
+
+ SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality);
+
+ //Determine original trainer ID
+ if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny
+ {
+ u32 shinyValue;
+ do
+ {
+ value = Random32();
+ shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
+ } while (shinyValue < 8);
+ }
+ else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID
+ {
+ value = fixedOtId;
+ }
+ else //Player is the OT
+ {
+ value = gSaveBlock2Ptr->playerTrainerId[0]
+ | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
+ | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
+ | (gSaveBlock2Ptr->playerTrainerId[3] << 24);
+ }
+
+ SetBoxMonData(boxMon, MON_DATA_OT_ID, &value);
+
+ checksum = CalculateBoxMonChecksum(boxMon);
+ SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum);
+ EncryptBoxMon(boxMon);
+ GetSpeciesName(speciesName, species);
+ SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName);
+ SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage);
+ SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName);
+ SetBoxMonData(boxMon, MON_DATA_SPECIES, &species);
+ SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]);
+ SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship);
+ value = sav1_map_get_name();
+ SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value);
+ SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
+ SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
+ value = ITEM_POKE_BALL;
+ SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value);
+ SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
+
+ if (fixedIV < 32)
+ {
+ SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV);
+ SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV);
+ }
+ else
+ {
+ u32 iv;
+ value = Random();
+
+ iv = value & 0x1F;
+ SetBoxMonData(boxMon, MON_DATA_HP_IV, &iv);
+ iv = (value & 0x3E0) >> 5;
+ SetBoxMonData(boxMon, MON_DATA_ATK_IV, &iv);
+ iv = (value & 0x7C00) >> 10;
+ SetBoxMonData(boxMon, MON_DATA_DEF_IV, &iv);
+
+ value = Random();
+
+ iv = value & 0x1F;
+ SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &iv);
+ iv = (value & 0x3E0) >> 5;
+ SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv);
+ iv = (value & 0x7C00) >> 10;
+ SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv);
+ }
+
+ if (gBaseStats[species].ability2)
+ {
+ value = personality & 1;
+ SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value);
+ }
+
+ GiveBoxMonInitialMoveset(boxMon);
+}
+
+void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature)
+{
+ u32 personality;
+
+ do
+ {
+ personality = Random32();
+ }
+ while (nature != GetNatureFromPersonality(personality));
+
+ CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
+}
+
+void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter)
+{
+ u32 personality;
+
+ if ((u8)(unownLetter - 1) < 28)
+ {
+ u16 actualLetter;
+
+ do
+ {
+ personality = Random32();
+ actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28);
+ }
+ while (nature != GetNatureFromPersonality(personality)
+ || gender != GetGenderFromSpeciesAndPersonality(species, personality)
+ || actualLetter != unownLetter - 1);
+ }
+ else
+ {
+ do
+ {
+ personality = Random32();
+ }
+ while (nature != GetNatureFromPersonality(personality)
+ || gender != GetGenderFromSpeciesAndPersonality(species, personality));
+ }
+
+ CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
+}
+
+// This is only used to create Wally's Ralts.
+void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level)
+{
+ u32 personality;
+ u32 otId;
+
+ do
+ {
+ otId = Random32();
+ personality = Random32();
+ }
+ while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE);
+ CreateMon(mon, species, level, 32, 1, personality, OT_ID_PRESET, otId);
+}
+
+void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality)
+{
+ CreateMon(mon, species, level, 0, 1, personality, OT_ID_PLAYER_ID, 0);
+ SetMonData(mon, MON_DATA_IVS, &ivs);
+ CalculateMonStats(mon);
+}
+
+void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId)
+{
+ CreateMon(mon, species, level, 0, 0, 0, OT_ID_PRESET, otId);
+ SetMonData(mon, MON_DATA_HP_IV, &ivs[0]);
+ SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]);
+ SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]);
+ SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]);
+ SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]);
+ SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]);
+ CalculateMonStats(mon);
+}
+
+void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread)
+{
+ s32 i;
+ s32 statCount = 0;
+ u16 evAmount;
+ u8 evsBits;
+
+ CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0);
+
+ evsBits = evSpread;
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ if (evsBits & 1)
+ statCount++;
+ evsBits >>= 1;
+ }
+
+ evAmount = MAX_TOTAL_EVS / statCount;
+
+ evsBits = 1;
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ if (evSpread & evsBits)
+ SetMonData(mon, MON_DATA_HP_EV + i, &evAmount);
+ evsBits <<= 1;
+ }
+
+ CalculateMonStats(mon);
+}
+
+void sub_806819C(struct Pokemon *mon, struct UnknownPokemonStruct *src)
+{
+ s32 i;
+ u8 nickname[30];
+ u8 language;
+ u8 value;
+
+ CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId);
+
+ for (i = 0; i < 4; i++)
+ SetMonMoveSlot(mon, src->moves[i], i);
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
+
+ StringCopy(nickname, src->nickname);
+
+ if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
+ {
+ language = LANGUAGE_JAPANESE;
+ StripExtCtrlCodes(nickname);
+ }
+ else
+ {
+ language = GAME_LANGUAGE;
+ }
+
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ SetMonData(mon, MON_DATA_NICKNAME, nickname);
+ SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
+ SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
+ SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
+ SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
+ SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
+ SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
+ value = src->altAbility;
+ SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
+ value = src->hpIV;
+ SetMonData(mon, MON_DATA_HP_IV, &value);
+ value = src->attackIV;
+ SetMonData(mon, MON_DATA_ATK_IV, &value);
+ value = src->defenseIV;
+ SetMonData(mon, MON_DATA_DEF_IV, &value);
+ value = src->speedIV;
+ SetMonData(mon, MON_DATA_SPEED_IV, &value);
+ value = src->spAttackIV;
+ SetMonData(mon, MON_DATA_SPATK_IV, &value);
+ value = src->spDefenseIV;
+ SetMonData(mon, MON_DATA_SPDEF_IV, &value);
+ MonRestorePP(mon);
+ CalculateMonStats(mon);
+}
+
+void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lvl50)
+{
+ s32 i;
+ u8 nickname[30];
+ u8 level;
+ u8 language;
+ u8 value;
+
+ if (gSaveBlock2Ptr->frontierChosenLvl != 0)
+ level = BattleFrontierGetOpponentLvl(gSaveBlock2Ptr->frontierChosenLvl);
+ else if (lvl50)
+ level = 50;
+ else
+ level = src->level;
+
+ CreateMon(mon, src->species, level, 0, 1, src->personality, 1, src->otId);
+
+ for (i = 0; i < 4; i++)
+ SetMonMoveSlot(mon, src->moves[i], i);
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
+
+ StringCopy(nickname, src->nickname);
+
+ if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
+ {
+ language = LANGUAGE_JAPANESE;
+ StripExtCtrlCodes(nickname);
+ }
+ else
+ {
+ language = GAME_LANGUAGE;
+ }
+
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ SetMonData(mon, MON_DATA_NICKNAME, nickname);
+ SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
+ SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
+ SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
+ SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
+ SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
+ SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
+ value = src->altAbility;
+ SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
+ value = src->hpIV;
+ SetMonData(mon, MON_DATA_HP_IV, &value);
+ value = src->attackIV;
+ SetMonData(mon, MON_DATA_ATK_IV, &value);
+ value = src->defenseIV;
+ SetMonData(mon, MON_DATA_DEF_IV, &value);
+ value = src->speedIV;
+ SetMonData(mon, MON_DATA_SPEED_IV, &value);
+ value = src->spAttackIV;
+ SetMonData(mon, MON_DATA_SPATK_IV, &value);
+ value = src->spDefenseIV;
+ SetMonData(mon, MON_DATA_SPDEF_IV, &value);
+ MonRestorePP(mon);
+ CalculateMonStats(mon);
+}
+
+void sub_8068528(struct Pokemon *mon, const struct UnknownPokemonStruct2 *src, u8 monId)
+{
+ s32 i;
+ u16 evAmount;
+ u8 language;
+ u32 otId = gUnknown_08610970[src->field_0_0].field_30;
+ u32 personality = ((gUnknown_08610970[src->field_0_0].field_30 >> 8) | ((gUnknown_08610970[src->field_0_0].field_30 & 0xFF) << 8))
+ + src->mons[monId].species + src->field_2;
+
+ CreateMon(mon,
+ src->mons[monId].species,
+ BattleFrontierGetOpponentLvl(src->field_0_1 - 1),
+ 0x1F,
+ TRUE,
+ personality,
+ TRUE,
+ otId);
+
+ SetMonData(mon, MON_DATA_HELD_ITEM, &src->mons[monId].item);
+ for (i = 0; i < 4; i++)
+ SetMonMoveSlot(mon, src->mons[monId].moves[i], i);
+
+ evAmount = MAX_TOTAL_EVS / NUM_STATS;
+ for (i = 0; i < NUM_STATS; i++)
+ SetMonData(mon, MON_DATA_HP_EV + i, &evAmount);
+
+ language = src->language;
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ SetMonData(mon, MON_DATA_OT_NAME, sub_81A1650(src->field_0_0, language));
+ CalculateMonStats(mon);
+}
+
+void CreateMonWithEVSpreadPersonalityOTID(struct Pokemon *mon, u16 species, u8 level, u8 nature, u8 fixedIV, u8 evSpread, u32 otId)
+{
+ s32 i;
+ s32 statCount = 0;
+ u8 evsBits;
+ u16 evAmount;
+
+ // i is reused as personality value
+ do
+ {
+ i = Random32();
+ } while (nature != GetNatureFromPersonality(i));
+
+ CreateMon(mon, species, level, fixedIV, TRUE, i, TRUE, otId);
+ evsBits = evSpread;
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ if (evsBits & 1)
+ statCount++;
+ evsBits >>= 1;
+ }
+
+ evAmount = MAX_TOTAL_EVS / statCount;
+ evsBits = 1;
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ if (evSpread & evsBits)
+ SetMonData(mon, MON_DATA_HP_EV + i, &evAmount);
+ evsBits <<= 1;
+ }
+
+ CalculateMonStats(mon);
+}
+
+void sub_80686FC(struct Pokemon *mon, struct UnknownPokemonStruct *dest)
+{
+ s32 i;
+ u16 heldItem;
+
+ dest->species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ heldItem = 0;
+
+ dest->heldItem = heldItem;
+
+ for (i = 0; i < 4; i++)
+ dest->moves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, NULL);
+
+ dest->level = GetMonData(mon, MON_DATA_LEVEL, NULL);
+ dest->ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ dest->otId = GetMonData(mon, MON_DATA_OT_ID, NULL);
+ dest->hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL);
+ dest->attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL);
+ dest->defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL);
+ dest->speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL);
+ dest->spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL);
+ dest->spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL);
+ dest->friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
+ dest->hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL);
+ dest->attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL);
+ dest->defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL);
+ dest->speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL);
+ dest->spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL);
+ dest->spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
+ dest->altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
+ dest->personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL);
+ GetMonData(mon, MON_DATA_NICKNAME, dest->nickname);
+}
+
+void CreateObedientMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
+{
+ bool32 obedient = TRUE;
+
+ CreateMon(mon, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId);
+ SetMonData(mon, MON_DATA_OBEDIENCE, &obedient);
+}
+
+bool8 sub_80688F8(u8 caseId, u8 battlerId)
+{
+ switch (caseId)
+ {
+ case 0:
+ default:
+ return FALSE;
+ case 1:
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ return FALSE;
+ if (!gMain.inBattle)
+ return FALSE;
+ if (gLinkPlayers[GetMultiplayerId()].lp_field_18 == battlerId)
+ return FALSE;
+ break;
+ case 2:
+ break;
+ case 3:
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ return FALSE;
+ if (!gMain.inBattle)
+ return FALSE;
+ if (battlerId == 1 || battlerId == 4 || battlerId == 5)
+ return TRUE;
+ return FALSE;
+ case 4:
+ break;
+ case 5:
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (!gMain.inBattle)
+ return FALSE;
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (gLinkPlayers[GetMultiplayerId()].lp_field_18 == battlerId)
+ return FALSE;
+ }
+ else
+ {
+ if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!gMain.inBattle)
+ return FALSE;
+ if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static s32 GetDeoxysStat(struct Pokemon *mon, s32 statId)
+{
+ s32 ivVal, evVal;
+ s32 statValue;
+ u8 nature, statId_;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_20)
+ return 0;
+ if (GetMonData(mon, MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS)
+ return 0;
+
+ ivVal = GetMonData(mon, MON_DATA_HP_IV + statId, NULL);
+ evVal = GetMonData(mon, MON_DATA_HP_EV + statId, NULL);
+ statValue = (u16)(((sDeoxysBaseStats[statId] * 2 + ivVal + evVal / 4) * mon->level) / 100 + 5);
+
+ nature = GetNature(mon);
+ statId_ = statId; // needed to match
+ statValue = ModifyStatByNature(nature, statValue, statId_);
+
+ return statValue;
+}
+
+void SetDeoxysStats(void)
+{
+ s32 i, value;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ struct Pokemon *mon = &gPlayerParty[i];
+
+ if (GetMonData(mon, MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS)
+ continue;
+
+ value = GetMonData(mon, MON_DATA_ATK, NULL);
+ SetMonData(mon, MON_DATA_ATK, &value);
+
+ value = GetMonData(mon, MON_DATA_DEF, NULL);
+ SetMonData(mon, MON_DATA_DEF, &value);
+
+ value = GetMonData(mon, MON_DATA_SPEED, NULL);
+ SetMonData(mon, MON_DATA_SPEED, &value);
+
+ value = GetMonData(mon, MON_DATA_SPATK, NULL);
+ SetMonData(mon, MON_DATA_SPATK, &value);
+
+ value = GetMonData(mon, MON_DATA_SPDEF, NULL);
+ SetMonData(mon, MON_DATA_SPDEF, &value);
+ }
+}
+
+u16 sub_8068B48(void)
+{
+ u8 linkId;
+ u32 arrId;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ linkId = gUnknown_0203C7B4 ^ 1;
+ else
+ linkId = GetMultiplayerId() ^ 1;
+
+ arrId = gLinkPlayers[linkId].trainerId & 7;
+ arrId |= gLinkPlayers[linkId].gender << 3;
+ return FacilityClassToPicIndex(gUnknown_08329D54[arrId]);
+}
+
+u16 sub_8068BB0(void)
+{
+ u8 linkId;
+ u32 arrId;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ linkId = gUnknown_0203C7B4 ^ 1;
+ else
+ linkId = GetMultiplayerId() ^ 1;
+
+ arrId = gLinkPlayers[linkId].trainerId & 7;
+ arrId |= gLinkPlayers[linkId].gender << 3;
+ return gFacilityClassToTrainerClass[gUnknown_08329D54[arrId]];
+}
+
+void CreateObedientEnemyMon(void)
+{
+ s32 species = gSpecialVar_0x8004;
+ s32 level = gSpecialVar_0x8005;
+ s32 itemId = gSpecialVar_0x8006;
+
+ ZeroEnemyPartyMons();
+ CreateObedientMon(&gEnemyParty[0], species, level, 32, 0, 0, 0, 0);
+ if (itemId)
+ {
+ u8 heldItem[2];
+ heldItem[0] = itemId;
+ heldItem[1] = itemId >> 8;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem);
+ }
+}
+
+static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon)
+{
+ u16 checksum = 0;
+ union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0);
+ union PokemonSubstruct *substruct1 = GetSubstruct(boxMon, boxMon->personality, 1);
+ union PokemonSubstruct *substruct2 = GetSubstruct(boxMon, boxMon->personality, 2);
+ union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3);
+ s32 i;
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct0->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct1->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct2->raw[i];
+
+ for (i = 0; i < 6; i++)
+ checksum += substruct3->raw[i];
+
+ return checksum;
+}
+
+#define CALC_STAT(base, iv, ev, statIndex, field) \
+{ \
+ u8 baseStat = gBaseStats[species].base; \
+ s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \
+ u8 nature = GetNature(mon); \
+ n = ModifyStatByNature(nature, n, statIndex); \
+ SetMonData(mon, field, &n); \
+}
+
+void CalculateMonStats(struct Pokemon *mon)
+{
+ s32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL);
+ s32 currentHP = GetMonData(mon, MON_DATA_HP, NULL);
+ s32 hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL);
+ s32 hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL);
+ s32 attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL);
+ s32 attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL);
+ s32 defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL);
+ s32 defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL);
+ s32 speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL);
+ s32 speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL);
+ s32 spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL);
+ s32 spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL);
+ s32 spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
+ s32 spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL);
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ s32 level = GetLevelFromMonExp(mon);
+ s32 newMaxHP;
+
+ SetMonData(mon, MON_DATA_LEVEL, &level);
+
+ if (species == SPECIES_SHEDINJA)
+ {
+ newMaxHP = 1;
+ }
+ else
+ {
+ s32 n = 2 * gBaseStats[species].baseHP + hpIV;
+ newMaxHP = (((n + hpEV / 4) * level) / 100) + level + 10;
+ }
+
+ gBattleScripting.field_23 = newMaxHP - oldMaxHP;
+ if (gBattleScripting.field_23 == 0)
+ gBattleScripting.field_23 = 1;
+
+ SetMonData(mon, MON_DATA_MAX_HP, &newMaxHP);
+
+ CALC_STAT(baseAttack, attackIV, attackEV, 1, MON_DATA_ATK)
+ CALC_STAT(baseDefense, defenseIV, defenseEV, 2, MON_DATA_DEF)
+ CALC_STAT(baseSpeed, speedIV, speedEV, 3, MON_DATA_SPEED)
+ CALC_STAT(baseSpAttack, spAttackIV, spAttackEV, 4, MON_DATA_SPATK)
+ CALC_STAT(baseSpDefense, spDefenseIV, spDefenseEV, 5, MON_DATA_SPDEF)
+
+ if (species == SPECIES_SHEDINJA)
+ {
+ if (currentHP != 0 || oldMaxHP == 0)
+ currentHP = 1;
+ else
+ return;
+ }
+ else
+ {
+ if (currentHP == 0 && oldMaxHP == 0)
+ currentHP = newMaxHP;
+ else if (currentHP != 0)
+ currentHP += newMaxHP - oldMaxHP;
+ else
+ return;
+ }
+
+ SetMonData(mon, MON_DATA_HP, &currentHP);
+}
+
+void BoxMonToMon(const struct BoxPokemon *src, struct Pokemon *dest)
+{
+ u32 value = 0;
+ dest->box = *src;
+ SetMonData(dest, MON_DATA_STATUS, &value);
+ SetMonData(dest, MON_DATA_HP, &value);
+ SetMonData(dest, MON_DATA_MAX_HP, &value);
+ value = 255;
+ SetMonData(dest, MON_DATA_MAIL, &value);
+ CalculateMonStats(dest);
+}
+
+u8 GetLevelFromMonExp(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u32 exp = GetMonData(mon, MON_DATA_EXP, NULL);
+ s32 level = 1;
+
+ while (level <= MAX_MON_LEVEL && gExperienceTables[gBaseStats[species].growthRate][level] <= exp)
+ level++;
+
+ return level - 1;
+}
+
+u8 GetLevelFromBoxMonExp(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ u32 exp = GetBoxMonData(boxMon, MON_DATA_EXP, NULL);
+ s32 level = 1;
+
+ while (level <= MAX_MON_LEVEL && gExperienceTables[gBaseStats[species].growthRate][level] <= exp)
+ level++;
+
+ return level - 1;
+}
+
+u16 GiveMoveToMon(struct Pokemon *mon, u16 move)
+{
+ return GiveMoveToBoxMon(&mon->box, move);
+}
+
+u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move)
+{
+ s32 i;
+ for (i = 0; i < 4; i++)
+ {
+ u16 existingMove = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, NULL);
+ if (!existingMove)
+ {
+ SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &move);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &gBattleMoves[move].pp);
+ return move;
+ }
+ if (existingMove == move)
+ return -2;
+ }
+ return -1;
+}
+
+u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!mon->moves[i])
+ {
+ mon->moves[i] = move;
+ mon->pp[i] = gBattleMoves[move].pp;
+ return move;
+ }
+ }
+
+ return -1;
+}
+
+void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot)
+{
+ SetMonData(mon, MON_DATA_MOVE1 + slot, &move);
+ SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp);
+}
+
+void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot)
+{
+ mon->moves[slot] = move;
+ mon->pp[slot] = gBattleMoves[move].pp;
+}
+
+void GiveMonInitialMoveset(struct Pokemon *mon)
+{
+ GiveBoxMonInitialMoveset(&mon->box);
+}
+
+void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ s32 level = GetLevelFromBoxMonExp(boxMon);
+ s32 i;
+
+ for (i = 0; gLevelUpLearnsets[species][i] != (u16)-1; i++)
+ {
+ u16 moveLevel;
+ u16 move;
+
+ moveLevel = (gLevelUpLearnsets[species][i] & 0xFE00);
+
+ if (moveLevel > (level << 9))
+ break;
+
+ move = (gLevelUpLearnsets[species][i] & 0x1FF);
+
+ if (GiveMoveToBoxMon(boxMon, move) == (u16)-1)
+ DeleteFirstMoveAndGiveMoveToBoxMon(boxMon, move);
+ }
+}
+
+u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove)
+{
+ u32 retVal = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, NULL);
+
+ // since you can learn more than one move per level
+ // the game needs to know whether you decided to
+ // learn it or keep the old set to avoid asking
+ // you to learn the same move over and over again
+ if (firstMove)
+ {
+ sLearningMoveTableID = 0;
+
+ while ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) != (level << 9))
+ {
+ sLearningMoveTableID++;
+ if (gLevelUpLearnsets[species][sLearningMoveTableID] == 0xFFFF)
+ return 0;
+ }
+ }
+
+ if ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) == (level << 9))
+ {
+ gMoveToLearn = (gLevelUpLearnsets[species][sLearningMoveTableID] & 0x1FF);
+ sLearningMoveTableID++;
+ retVal = GiveMoveToMon(mon, gMoveToLearn);
+ }
+
+ return retVal;
+}
+
+void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move)
+{
+ s32 i;
+ u16 moves[4];
+ u8 pp[4];
+ u8 ppBonuses;
+
+ for (i = 0; i < 3; i++)
+ {
+ moves[i] = GetMonData(mon, MON_DATA_MOVE2 + i, NULL);
+ pp[i] = GetMonData(mon, MON_DATA_PP2 + i, NULL);
+ }
+
+ ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses >>= 2;
+ moves[3] = move;
+ pp[3] = gBattleMoves[move].pp;
+
+ for (i = 0; i < 4; i++)
+ {
+ SetMonData(mon, MON_DATA_MOVE1 + i, &moves[i]);
+ SetMonData(mon, MON_DATA_PP1 + i, &pp[i]);
+ }
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
+
+void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move)
+{
+ s32 i;
+ u16 moves[4];
+ u8 pp[4];
+ u8 ppBonuses;
+
+ for (i = 0; i < 3; i++)
+ {
+ moves[i] = GetBoxMonData(boxMon, MON_DATA_MOVE2 + i, NULL);
+ pp[i] = GetBoxMonData(boxMon, MON_DATA_PP2 + i, NULL);
+ }
+
+ ppBonuses = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses >>= 2;
+ moves[3] = move;
+ pp[3] = gBattleMoves[move].pp;
+
+ for (i = 0; i < 4; i++)
+ {
+ SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &moves[i]);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp[i]);
+ }
+
+ SetBoxMonData(boxMon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
+
+#define APPLY_STAT_MOD(var, mon, stat, statIndex) \
+{ \
+ (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \
+ (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \
+}
+
+s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef)
+{
+ u32 i;
+ s32 damage = 0;
+ s32 damageHelper;
+ u8 type;
+ u16 attack, defense;
+ u16 spAttack, spDefense;
+ u8 defenderHoldEffect;
+ u8 defenderHoldEffectParam;
+ u8 attackerHoldEffect;
+ u8 attackerHoldEffectParam;
+
+ if (!powerOverride)
+ gBattleMovePower = gBattleMoves[move].power;
+ else
+ gBattleMovePower = powerOverride;
+
+ if (!typeOverride)
+ type = gBattleMoves[move].type;
+ else
+ type = typeOverride & 0x3F;
+
+ attack = attacker->attack;
+ defense = defender->defense;
+ spAttack = attacker->spAttack;
+ spDefense = defender->spDefense;
+
+ if (attacker->item == ITEM_ENIGMA_BERRY)
+ {
+ attackerHoldEffect = gEnigmaBerries[bankAtk].holdEffect;
+ attackerHoldEffectParam = gEnigmaBerries[bankAtk].holdEffectParam;
+ }
+ else
+ {
+ attackerHoldEffect = ItemId_GetHoldEffect(attacker->item);
+ attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item);
+ }
+
+ if (defender->item == ITEM_ENIGMA_BERRY)
+ {
+ defenderHoldEffect = gEnigmaBerries[bankDef].holdEffect;
+ defenderHoldEffectParam = gEnigmaBerries[bankDef].holdEffectParam;
+ }
+ else
+ {
+ defenderHoldEffect = ItemId_GetHoldEffect(defender->item);
+ defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item);
+ }
+
+ if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER)
+ attack *= 2;
+
+ if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, bankAtk))
+ attack = (110 * attack) / 100;
+ if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, bankDef))
+ defense = (110 * defense) / 100;
+ if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankAtk))
+ spAttack = (110 * spAttack) / 100;
+ if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankDef))
+ spDefense = (110 * spDefense) / 100;
+
+ for (i = 0; i < ARRAY_COUNT(sHoldEffectToType); i++)
+ {
+ if (attackerHoldEffect == sHoldEffectToType[i][0]
+ && type == sHoldEffectToType[i][1])
+ {
+ if (type <= 8)
+ attack = (attack * (attackerHoldEffectParam + 100)) / 100;
+ else
+ spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100;
+ break;
+ }
+ }
+
+ if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND)
+ attack = (150 * attack) / 100;
+ if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS))
+ spAttack = (150 * spAttack) / 100;
+ if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS))
+ spDefense = (150 * spDefense) / 100;
+ if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL)
+ spAttack *= 2;
+ if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL)
+ spDefense *= 2;
+ if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU)
+ spAttack *= 2;
+ if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO)
+ defense *= 2;
+ if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK))
+ attack *= 2;
+ if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE))
+ spAttack /= 2;
+ if (attacker->ability == ABILITY_HUSTLE)
+ attack = (150 * attack) / 100;
+ if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0))
+ spAttack = (150 * spAttack) / 100;
+ if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0))
+ spAttack = (150 * spAttack) / 100;
+ if (attacker->ability == ABILITY_GUTS && attacker->status1)
+ attack = (150 * attack) / 100;
+ if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1)
+ defense = (150 * defense) / 100;
+ if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0))
+ gBattleMovePower /= 2;
+ if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0))
+ gBattleMovePower /= 2;
+ if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3))
+ gBattleMovePower = (150 * gBattleMovePower) / 100;
+ if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3))
+ gBattleMovePower = (150 * gBattleMovePower) / 100;
+ if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3))
+ gBattleMovePower = (150 * gBattleMovePower) / 100;
+ if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3))
+ gBattleMovePower = (150 * gBattleMovePower) / 100;
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION)
+ defense /= 2;
+
+ if (type < TYPE_MYSTERY) // is physical
+ {
+ if (gCritMultiplier == 2)
+ {
+ if (attacker->statStages[STAT_ATK] > 6)
+ APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
+ else
+ damage = attack;
+ }
+ else
+ APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
+
+ damage = damage * gBattleMovePower;
+ damage *= (2 * attacker->level / 5 + 2);
+
+ if (gCritMultiplier == 2)
+ {
+ if (defender->statStages[STAT_DEF] < 6)
+ APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
+ else
+ damageHelper = defense;
+ }
+ else
+ APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
+
+ damage = damage / damageHelper;
+ damage /= 50;
+
+ if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS)
+ damage /= 2;
+
+ if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1)
+ {
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2)
+ damage = 2 * (damage / 3);
+ else
+ damage /= 2;
+ }
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2)
+ damage /= 2;
+
+ // moves always do at least 1 damage.
+ if (damage == 0)
+ damage = 1;
+ }
+
+ if (type == TYPE_MYSTERY)
+ damage = 0; // is ??? type. does 0 damage.
+
+ if (type > TYPE_MYSTERY) // is special?
+ {
+ if (gCritMultiplier == 2)
+ {
+ if (attacker->statStages[STAT_SPATK] > 6)
+ APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
+ else
+ damage = spAttack;
+ }
+ else
+ APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
+
+ damage = damage * gBattleMovePower;
+ damage *= (2 * attacker->level / 5 + 2);
+
+ if (gCritMultiplier == 2)
+ {
+ if (defender->statStages[STAT_SPDEF] < 6)
+ APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
+ else
+ damageHelper = spDefense;
+ }
+ else
+ APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
+
+ damage = (damage / damageHelper);
+ damage /= 50;
+
+ if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1)
+ {
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2)
+ damage = 2 * (damage / 3);
+ else
+ damage /= 2;
+ }
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2)
+ damage /= 2;
+
+ // are effects of weather negated with cloud nine or air lock
+ if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0)
+ && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0))
+ {
+ if (gBattleWeather & WEATHER_RAIN_TEMPORARY)
+ {
+ switch (type)
+ {
+ case TYPE_FIRE:
+ damage /= 2;
+ break;
+ case TYPE_WATER:
+ damage = (15 * damage) / 10;
+ break;
+ }
+ }
+
+ // any weather except sun weakens solar beam
+ if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM)
+ damage /= 2;
+
+ // sunny
+ if (gBattleWeather & WEATHER_SUN_ANY)
+ {
+ switch (type)
+ {
+ case TYPE_FIRE:
+ damage = (15 * damage) / 10;
+ break;
+ case TYPE_WATER:
+ damage /= 2;
+ break;
+ }
+ }
+ }
+
+ // flash fire triggered
+ if ((gBattleResources->flags->flags[bankAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE)
+ damage = (15 * damage) / 10;
+ }
+
+ return damage + 2;
+}
+
+u8 CountAliveMonsInBattle(u8 caseId)
+{
+ s32 i;
+ u8 retVal = 0;
+
+ switch (caseId)
+ {
+ case BATTLE_ALIVE_EXCEPT_ACTIVE:
+ for (i = 0; i < 4; i++)
+ {
+ if (i != gActiveBattler && !(gAbsentBattlerFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ case BATTLE_ALIVE_ATK_SIDE:
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBattlerSide(i) == GetBattlerSide(gBattlerAttacker) && !(gAbsentBattlerFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ case BATTLE_ALIVE_DEF_SIDE:
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBattlerSide(i) == GetBattlerSide(gBattlerTarget) && !(gAbsentBattlerFlags & gBitTable[i]))
+ retVal++;
+ }
+ break;
+ }
+
+ return retVal;
+}
+
+static bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId)
+{
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER))
+ return FALSE;
+ if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
+ return FALSE;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
+ return FALSE;
+ if (FlagGet(badgeFlag))
+ return TRUE;
+ return FALSE;
+}
+
+u8 GetDefaultMoveTarget(u8 battlerId)
+{
+ u8 opposing = BATTLE_OPPOSITE(GetBattlerPosition(battlerId) & BIT_SIDE);
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ return GetBattlerAtPosition(opposing);
+ if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1)
+ {
+ u8 position;
+
+ if ((Random() & 1) == 0)
+ position = BATTLE_PARTNER(opposing);
+ else
+ position = opposing;
+
+ return GetBattlerAtPosition(position);
+ }
+ else
+ {
+ if ((gAbsentBattlerFlags & gBitTable[opposing]))
+ return GetBattlerAtPosition(BATTLE_PARTNER(opposing));
+ else
+ return GetBattlerAtPosition(opposing);
+ }
+}
+
+u8 GetMonGender(struct Pokemon *mon)
+{
+ return GetBoxMonGender(&mon->box);
+}
+
+u8 GetBoxMonGender(struct BoxPokemon *boxMon)
+{
+ u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
+ u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL);
+
+ switch (gBaseStats[species].genderRatio)
+ {
+ case MON_MALE:
+ case MON_FEMALE:
+ case MON_GENDERLESS:
+ return gBaseStats[species].genderRatio;
+ }
+
+ if (gBaseStats[species].genderRatio > (personality & 0xFF))
+ return MON_FEMALE;
+ else
+ return MON_MALE;
+}
+
+u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
+{
+ switch (gBaseStats[species].genderRatio)
+ {
+ case MON_MALE:
+ case MON_FEMALE:
+ case MON_GENDERLESS:
+ return gBaseStats[species].genderRatio;
+ }
+
+ if (gBaseStats[species].genderRatio > (personality & 0xFF))
+ return MON_FEMALE;
+ else
+ return MON_MALE;
+}
+
+void sub_806A068(u16 species, u8 battlerPosition)
+{
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition];
+ else if (gUnknown_020249B4[0])
+ gUnknown_0202499C = gUnknown_020249B4[0]->templates[battlerPosition];
+ else if (gUnknown_020249B4[1])
+ gUnknown_0202499C = gUnknown_020249B4[1]->templates[battlerPosition];
+ else
+ gUnknown_0202499C = gUnknown_08329D98[battlerPosition];
+
+ gUnknown_0202499C.paletteTag = species;
+ if (battlerPosition == 0 || battlerPosition == 2)
+ gUnknown_0202499C.anims = gUnknown_082FF70C;
+ else if (species > 500)
+ gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species - 500];
+ else
+ gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species];
+}
+
+void sub_806A12C(u16 trainerSpriteId, u8 battlerPosition)
+{
+ gUnknown_0202499C.paletteTag = trainerSpriteId;
+ if (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_PLAYER_RIGHT)
+ {
+ gUnknown_0202499C = gUnknown_08329DF8[trainerSpriteId];
+ gUnknown_0202499C.anims = gUnknown_08305D0C[trainerSpriteId];
+ }
+ else
+ {
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition];
+ else
+ gUnknown_0202499C = gUnknown_08329D98[battlerPosition];
+ gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId];
+ }
+}
+
+void sub_806A1C0(u16 arg0, u8 battlerPosition)
+{
+ if (gMonSpritesGfxPtr != NULL)
+ gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition];
+ else
+ gUnknown_0202499C = gUnknown_08329D98[battlerPosition];
+
+ gUnknown_0202499C.paletteTag = arg0;
+ gUnknown_0202499C.anims = gUnknown_0830536C[arg0];
+}
+
+static void EncryptBoxMon(struct BoxPokemon *boxMon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ boxMon->secure.raw[i] ^= boxMon->personality;
+ boxMon->secure.raw[i] ^= boxMon->otId;
+ }
+}
+
+static void DecryptBoxMon(struct BoxPokemon *boxMon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ boxMon->secure.raw[i] ^= boxMon->otId;
+ boxMon->secure.raw[i] ^= boxMon->personality;
+ }
+}
+
+#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
+case n: \
+ { \
+ union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \
+ union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \
+ \
+ switch (substructType) \
+ { \
+ case 0: \
+ substruct = &substructs ## n [v1]; \
+ break; \
+ case 1: \
+ substruct = &substructs ## n [v2]; \
+ break; \
+ case 2: \
+ substruct = &substructs ## n [v3]; \
+ break; \
+ case 3: \
+ substruct = &substructs ## n [v4]; \
+ break; \
+ } \
+ break; \
+ } \
+
+
+static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType)
+{
+ union PokemonSubstruct *substruct = NULL;
+
+ switch (personality % 24)
+ {
+ SUBSTRUCT_CASE( 0,0,1,2,3)
+ SUBSTRUCT_CASE( 1,0,1,3,2)
+ SUBSTRUCT_CASE( 2,0,2,1,3)
+ SUBSTRUCT_CASE( 3,0,3,1,2)
+ SUBSTRUCT_CASE( 4,0,2,3,1)
+ SUBSTRUCT_CASE( 5,0,3,2,1)
+ SUBSTRUCT_CASE( 6,1,0,2,3)
+ SUBSTRUCT_CASE( 7,1,0,3,2)
+ SUBSTRUCT_CASE( 8,2,0,1,3)
+ SUBSTRUCT_CASE( 9,3,0,1,2)
+ SUBSTRUCT_CASE(10,2,0,3,1)
+ SUBSTRUCT_CASE(11,3,0,2,1)
+ SUBSTRUCT_CASE(12,1,2,0,3)
+ SUBSTRUCT_CASE(13,1,3,0,2)
+ SUBSTRUCT_CASE(14,2,1,0,3)
+ SUBSTRUCT_CASE(15,3,1,0,2)
+ SUBSTRUCT_CASE(16,2,3,0,1)
+ SUBSTRUCT_CASE(17,3,2,0,1)
+ SUBSTRUCT_CASE(18,1,2,3,0)
+ SUBSTRUCT_CASE(19,1,3,2,0)
+ SUBSTRUCT_CASE(20,2,1,3,0)
+ SUBSTRUCT_CASE(21,3,1,2,0)
+ SUBSTRUCT_CASE(22,2,3,1,0)
+ SUBSTRUCT_CASE(23,3,2,1,0)
+ }
+
+ return substruct;
+}
+
+u32 GetMonData(struct Pokemon *mon, s32 field, u8* data)
+{
+ u32 ret;
+
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ ret = mon->status;
+ break;
+ case MON_DATA_LEVEL:
+ ret = mon->level;
+ break;
+ case MON_DATA_HP:
+ ret = mon->hp;
+ break;
+ case MON_DATA_MAX_HP:
+ ret = mon->maxHP;
+ break;
+ case MON_DATA_ATK:
+ ret = (u16)GetDeoxysStat(mon, STAT_ATK);
+ if (!ret)
+ ret = mon->attack;
+ break;
+ case MON_DATA_DEF:
+ ret = (u16)GetDeoxysStat(mon, STAT_DEF);
+ if (!ret)
+ ret = mon->defense;
+ break;
+ case MON_DATA_SPEED:
+ ret = (u16)GetDeoxysStat(mon, STAT_SPEED);
+ if (!ret)
+ ret = mon->speed;
+ break;
+ case MON_DATA_SPATK:
+ ret = (u16)GetDeoxysStat(mon, STAT_SPATK);
+ if (!ret)
+ ret = mon->spAttack;
+ break;
+ case MON_DATA_SPDEF:
+ ret = (u16)GetDeoxysStat(mon, STAT_SPDEF);
+ if (!ret)
+ ret = mon->spDefense;
+ break;
+ case MON_DATA_ATK2:
+ ret = mon->attack;
+ break;
+ case MON_DATA_DEF2:
+ ret = mon->defense;
+ break;
+ case MON_DATA_SPEED2:
+ ret = mon->speed;
+ break;
+ case MON_DATA_SPATK2:
+ ret = mon->spAttack;
+ break;
+ case MON_DATA_SPDEF2:
+ ret = mon->spDefense;
+ break;
+ case MON_DATA_MAIL:
+ ret = mon->mail;
+ break;
+ default:
+ ret = GetBoxMonData(&mon->box, field, data);
+ break;
+ }
+ return ret;
+}
+
+u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
+{
+ s32 i;
+ u32 retVal = 0;
+ struct PokemonSubstruct0 *substruct0 = NULL;
+ struct PokemonSubstruct1 *substruct1 = NULL;
+ struct PokemonSubstruct2 *substruct2 = NULL;
+ struct PokemonSubstruct3 *substruct3 = NULL;
+
+ if (field > MON_DATA_10)
+ {
+ substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
+ substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
+ substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
+ substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
+
+ DecryptBoxMon(boxMon);
+
+ if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
+ {
+ boxMon->isBadEgg = 1;
+ boxMon->isEgg = 1;
+ substruct3->isEgg = 1;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ retVal = boxMon->personality;
+ break;
+ case MON_DATA_OT_ID:
+ retVal = boxMon->otId;
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ if (boxMon->isBadEgg)
+ {
+ for (retVal = 0;
+ retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS;
+ data[retVal] = gText_BadEgg[retVal], retVal++) {}
+
+ data[retVal] = EOS;
+ }
+ else if (boxMon->isEgg)
+ {
+ StringCopy(data, gText_EggNickname);
+ retVal = StringLength(data);
+ }
+ else if (boxMon->language == LANGUAGE_JAPANESE)
+ {
+ data[0] = EXT_CTRL_CODE_BEGIN;
+ data[1] = EXT_CTRL_CODE_JPN;
+
+ for (retVal = 2, i = 0;
+ i < 5 && boxMon->nickname[i] != EOS;
+ data[retVal] = boxMon->nickname[i], retVal++, i++) {}
+
+ data[retVal++] = EXT_CTRL_CODE_BEGIN;
+ data[retVal++] = EXT_CTRL_CODE_ENG;
+ data[retVal] = EOS;
+ }
+ else
+ {
+ for (retVal = 0;
+ retVal < POKEMON_NAME_LENGTH;
+ data[retVal] = boxMon->nickname[retVal], retVal++){}
+
+ data[retVal] = EOS;
+ }
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ retVal = boxMon->language;
+ break;
+ case MON_DATA_SANITY_BIT1:
+ retVal = boxMon->isBadEgg;
+ break;
+ case MON_DATA_SANITY_BIT2:
+ retVal = boxMon->hasSpecies;
+ break;
+ case MON_DATA_SANITY_BIT3:
+ retVal = boxMon->isEgg;
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ retVal = 0;
+
+ while (retVal < OT_NAME_LENGTH)
+ {
+ data[retVal] = boxMon->otName[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ retVal = boxMon->markings;
+ break;
+ case MON_DATA_CHECKSUM:
+ retVal = boxMon->checksum;
+ break;
+ case MON_DATA_10:
+ retVal = boxMon->unknown;
+ break;
+ case MON_DATA_SPECIES:
+ retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species;
+ break;
+ case MON_DATA_HELD_ITEM:
+ retVal = substruct0->heldItem;
+ break;
+ case MON_DATA_EXP:
+ retVal = substruct0->experience;
+ break;
+ case MON_DATA_PP_BONUSES:
+ retVal = substruct0->ppBonuses;
+ break;
+ case MON_DATA_FRIENDSHIP:
+ retVal = substruct0->friendship;
+ break;
+ case MON_DATA_MOVE1:
+ case MON_DATA_MOVE2:
+ case MON_DATA_MOVE3:
+ case MON_DATA_MOVE4:
+ retVal = substruct1->moves[field - MON_DATA_MOVE1];
+ break;
+ case MON_DATA_PP1:
+ case MON_DATA_PP2:
+ case MON_DATA_PP3:
+ case MON_DATA_PP4:
+ retVal = substruct1->pp[field - MON_DATA_PP1];
+ break;
+ case MON_DATA_HP_EV:
+ retVal = substruct2->hpEV;
+ break;
+ case MON_DATA_ATK_EV:
+ retVal = substruct2->attackEV;
+ break;
+ case MON_DATA_DEF_EV:
+ retVal = substruct2->defenseEV;
+ break;
+ case MON_DATA_SPEED_EV:
+ retVal = substruct2->speedEV;
+ break;
+ case MON_DATA_SPATK_EV:
+ retVal = substruct2->spAttackEV;
+ break;
+ case MON_DATA_SPDEF_EV:
+ retVal = substruct2->spDefenseEV;
+ break;
+ case MON_DATA_COOL:
+ retVal = substruct2->cool;
+ break;
+ case MON_DATA_BEAUTY:
+ retVal = substruct2->beauty;
+ break;
+ case MON_DATA_CUTE:
+ retVal = substruct2->cute;
+ break;
+ case MON_DATA_SMART:
+ retVal = substruct2->smart;
+ break;
+ case MON_DATA_TOUGH:
+ retVal = substruct2->tough;
+ break;
+ case MON_DATA_SHEEN:
+ retVal = substruct2->sheen;
+ break;
+ case MON_DATA_POKERUS:
+ retVal = substruct3->pokerus;
+ break;
+ case MON_DATA_MET_LOCATION:
+ retVal = substruct3->metLocation;
+ break;
+ case MON_DATA_MET_LEVEL:
+ retVal = substruct3->metLevel;
+ break;
+ case MON_DATA_MET_GAME:
+ retVal = substruct3->metGame;
+ break;
+ case MON_DATA_POKEBALL:
+ retVal = substruct3->pokeball;
+ break;
+ case MON_DATA_OT_GENDER:
+ retVal = substruct3->otGender;
+ break;
+ case MON_DATA_HP_IV:
+ retVal = substruct3->hpIV;
+ break;
+ case MON_DATA_ATK_IV:
+ retVal = substruct3->attackIV;
+ break;
+ case MON_DATA_DEF_IV:
+ retVal = substruct3->defenseIV;
+ break;
+ case MON_DATA_SPEED_IV:
+ retVal = substruct3->speedIV;
+ break;
+ case MON_DATA_SPATK_IV:
+ retVal = substruct3->spAttackIV;
+ break;
+ case MON_DATA_SPDEF_IV:
+ retVal = substruct3->spDefenseIV;
+ break;
+ case MON_DATA_IS_EGG:
+ retVal = substruct3->isEgg;
+ break;
+ case MON_DATA_ALT_ABILITY:
+ retVal = substruct3->altAbility;
+ break;
+ case MON_DATA_COOL_RIBBON:
+ retVal = substruct3->coolRibbon;
+ break;
+ case MON_DATA_BEAUTY_RIBBON:
+ retVal = substruct3->beautyRibbon;
+ break;
+ case MON_DATA_CUTE_RIBBON:
+ retVal = substruct3->cuteRibbon;
+ break;
+ case MON_DATA_SMART_RIBBON:
+ retVal = substruct3->smartRibbon;
+ break;
+ case MON_DATA_TOUGH_RIBBON:
+ retVal = substruct3->toughRibbon;
+ break;
+ case MON_DATA_CHAMPION_RIBBON:
+ retVal = substruct3->championRibbon;
+ break;
+ case MON_DATA_WINNING_RIBBON:
+ retVal = substruct3->winningRibbon;
+ break;
+ case MON_DATA_VICTORY_RIBBON:
+ retVal = substruct3->victoryRibbon;
+ break;
+ case MON_DATA_ARTIST_RIBBON:
+ retVal = substruct3->artistRibbon;
+ break;
+ case MON_DATA_EFFORT_RIBBON:
+ retVal = substruct3->effortRibbon;
+ break;
+ case MON_DATA_GIFT_RIBBON_1:
+ retVal = substruct3->giftRibbon1;
+ break;
+ case MON_DATA_GIFT_RIBBON_2:
+ retVal = substruct3->giftRibbon2;
+ break;
+ case MON_DATA_GIFT_RIBBON_3:
+ retVal = substruct3->giftRibbon3;
+ break;
+ case MON_DATA_GIFT_RIBBON_4:
+ retVal = substruct3->giftRibbon4;
+ break;
+ case MON_DATA_GIFT_RIBBON_5:
+ retVal = substruct3->giftRibbon5;
+ break;
+ case MON_DATA_GIFT_RIBBON_6:
+ retVal = substruct3->giftRibbon6;
+ break;
+ case MON_DATA_GIFT_RIBBON_7:
+ retVal = substruct3->giftRibbon7;
+ break;
+ case MON_DATA_FATEFUL_ENCOUNTER:
+ retVal = substruct3->fatefulEncounter;
+ break;
+ case MON_DATA_OBEDIENCE:
+ retVal = substruct3->obedient;
+ break;
+ case MON_DATA_SPECIES2:
+ retVal = substruct0->species;
+ if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg))
+ retVal = SPECIES_EGG;
+ break;
+ case MON_DATA_IVS:
+ retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25);
+ break;
+ case MON_DATA_KNOWN_MOVES:
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ u16 *moves = (u16 *)data;
+ s32 i = 0;
+
+ while (moves[i] != 355)
+ {
+ u16 move = moves[i];
+ if (substruct1->moves[0] == move
+ || substruct1->moves[1] == move
+ || substruct1->moves[2] == move
+ || substruct1->moves[3] == move)
+ retVal |= gBitTable[i];
+ i++;
+ }
+ }
+ break;
+ case MON_DATA_RIBBON_COUNT:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal += substruct3->coolRibbon;
+ retVal += substruct3->beautyRibbon;
+ retVal += substruct3->cuteRibbon;
+ retVal += substruct3->smartRibbon;
+ retVal += substruct3->toughRibbon;
+ retVal += substruct3->championRibbon;
+ retVal += substruct3->winningRibbon;
+ retVal += substruct3->victoryRibbon;
+ retVal += substruct3->artistRibbon;
+ retVal += substruct3->effortRibbon;
+ retVal += substruct3->giftRibbon1;
+ retVal += substruct3->giftRibbon2;
+ retVal += substruct3->giftRibbon3;
+ retVal += substruct3->giftRibbon4;
+ retVal += substruct3->giftRibbon5;
+ retVal += substruct3->giftRibbon6;
+ retVal += substruct3->giftRibbon7;
+ }
+ break;
+ case MON_DATA_RIBBONS:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal = substruct3->championRibbon
+ | (substruct3->coolRibbon << 1)
+ | (substruct3->beautyRibbon << 4)
+ | (substruct3->cuteRibbon << 7)
+ | (substruct3->smartRibbon << 10)
+ | (substruct3->toughRibbon << 13)
+ | (substruct3->winningRibbon << 16)
+ | (substruct3->victoryRibbon << 17)
+ | (substruct3->artistRibbon << 18)
+ | (substruct3->effortRibbon << 19)
+ | (substruct3->giftRibbon1 << 20)
+ | (substruct3->giftRibbon2 << 21)
+ | (substruct3->giftRibbon3 << 22)
+ | (substruct3->giftRibbon4 << 23)
+ | (substruct3->giftRibbon5 << 24)
+ | (substruct3->giftRibbon6 << 25)
+ | (substruct3->giftRibbon7 << 26);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (field > MON_DATA_10)
+ EncryptBoxMon(boxMon);
+
+ return retVal;
+}
+
+#define SET8(lhs) (lhs) = *data
+#define SET16(lhs) (lhs) = data[0] + (data[1] << 8)
+#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)
+
+void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg)
+{
+ const u8* data = dataArg;
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ SET32(mon->status);
+ break;
+ case MON_DATA_LEVEL:
+ SET8(mon->level);
+ break;
+ case MON_DATA_HP:
+ SET16(mon->hp);
+ break;
+ case MON_DATA_MAX_HP:
+ SET16(mon->maxHP);
+ break;
+ case MON_DATA_ATK:
+ SET16(mon->attack);
+ break;
+ case MON_DATA_DEF:
+ SET16(mon->defense);
+ break;
+ case MON_DATA_SPEED:
+ SET16(mon->speed);
+ break;
+ case MON_DATA_SPATK:
+ SET16(mon->spAttack);
+ break;
+ case MON_DATA_SPDEF:
+ SET16(mon->spDefense);
+ break;
+ case MON_DATA_MAIL:
+ SET8(mon->mail);
+ break;
+ case MON_DATA_SPECIES2:
+ break;
+ default:
+ SetBoxMonData(&mon->box, field, data);
+ break;
+ }
+}
+
+void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
+{
+ const u8* data = dataArg;
+
+ struct PokemonSubstruct0 *substruct0 = NULL;
+ struct PokemonSubstruct1 *substruct1 = NULL;
+ struct PokemonSubstruct2 *substruct2 = NULL;
+ struct PokemonSubstruct3 *substruct3 = NULL;
+
+ if (field > MON_DATA_10)
+ {
+ substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
+ substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
+ substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
+ substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
+
+ DecryptBoxMon(boxMon);
+
+ if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
+ {
+ boxMon->isBadEgg = 1;
+ boxMon->isEgg = 1;
+ substruct3->isEgg = 1;
+ EncryptBoxMon(boxMon);
+ return;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ SET32(boxMon->personality);
+ break;
+ case MON_DATA_OT_ID:
+ SET32(boxMon->otId);
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ s32 i;
+ for (i = 0; i < POKEMON_NAME_LENGTH; i++)
+ boxMon->nickname[i] = data[i];
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ SET8(boxMon->language);
+ break;
+ case MON_DATA_SANITY_BIT1:
+ SET8(boxMon->isBadEgg);
+ break;
+ case MON_DATA_SANITY_BIT2:
+ SET8(boxMon->hasSpecies);
+ break;
+ case MON_DATA_SANITY_BIT3:
+ SET8(boxMon->isEgg);
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ s32 i;
+ for (i = 0; i < OT_NAME_LENGTH; i++)
+ boxMon->otName[i] = data[i];
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ SET8(boxMon->markings);
+ break;
+ case MON_DATA_CHECKSUM:
+ SET16(boxMon->checksum);
+ break;
+ case MON_DATA_10:
+ SET16(boxMon->unknown);
+ break;
+ case MON_DATA_SPECIES:
+ {
+ SET16(substruct0->species);
+ if (substruct0->species)
+ boxMon->hasSpecies = 1;
+ else
+ boxMon->hasSpecies = 0;
+ break;
+ }
+ case MON_DATA_HELD_ITEM:
+ SET16(substruct0->heldItem);
+ break;
+ case MON_DATA_EXP:
+ SET32(substruct0->experience);
+ break;
+ case MON_DATA_PP_BONUSES:
+ SET8(substruct0->ppBonuses);
+ break;
+ case MON_DATA_FRIENDSHIP:
+ SET8(substruct0->friendship);
+ break;
+ case MON_DATA_MOVE1:
+ case MON_DATA_MOVE2:
+ case MON_DATA_MOVE3:
+ case MON_DATA_MOVE4:
+ SET16(substruct1->moves[field - MON_DATA_MOVE1]);
+ break;
+ case MON_DATA_PP1:
+ case MON_DATA_PP2:
+ case MON_DATA_PP3:
+ case MON_DATA_PP4:
+ SET8(substruct1->pp[field - MON_DATA_PP1]);
+ break;
+ case MON_DATA_HP_EV:
+ SET8(substruct2->hpEV);
+ break;
+ case MON_DATA_ATK_EV:
+ SET8(substruct2->attackEV);
+ break;
+ case MON_DATA_DEF_EV:
+ SET8(substruct2->defenseEV);
+ break;
+ case MON_DATA_SPEED_EV:
+ SET8(substruct2->speedEV);
+ break;
+ case MON_DATA_SPATK_EV:
+ SET8(substruct2->spAttackEV);
+ break;
+ case MON_DATA_SPDEF_EV:
+ SET8(substruct2->spDefenseEV);
+ break;
+ case MON_DATA_COOL:
+ SET8(substruct2->cool);
+ break;
+ case MON_DATA_BEAUTY:
+ SET8(substruct2->beauty);
+ break;
+ case MON_DATA_CUTE:
+ SET8(substruct2->cute);
+ break;
+ case MON_DATA_SMART:
+ SET8(substruct2->smart);
+ break;
+ case MON_DATA_TOUGH:
+ SET8(substruct2->tough);
+ break;
+ case MON_DATA_SHEEN:
+ SET8(substruct2->sheen);
+ break;
+ case MON_DATA_POKERUS:
+ SET8(substruct3->pokerus);
+ break;
+ case MON_DATA_MET_LOCATION:
+ SET8(substruct3->metLocation);
+ break;
+ case MON_DATA_MET_LEVEL:
+ {
+ u8 metLevel = *data;
+ substruct3->metLevel = metLevel;
+ break;
+ }
+ case MON_DATA_MET_GAME:
+ SET8(substruct3->metGame);
+ break;
+ case MON_DATA_POKEBALL:
+ {
+ u8 pokeball = *data;
+ substruct3->pokeball = pokeball;
+ break;
+ }
+ case MON_DATA_OT_GENDER:
+ SET8(substruct3->otGender);
+ break;
+ case MON_DATA_HP_IV:
+ SET8(substruct3->hpIV);
+ break;
+ case MON_DATA_ATK_IV:
+ SET8(substruct3->attackIV);
+ break;
+ case MON_DATA_DEF_IV:
+ SET8(substruct3->defenseIV);
+ break;
+ case MON_DATA_SPEED_IV:
+ SET8(substruct3->speedIV);
+ break;
+ case MON_DATA_SPATK_IV:
+ SET8(substruct3->spAttackIV);
+ break;
+ case MON_DATA_SPDEF_IV:
+ SET8(substruct3->spDefenseIV);
+ break;
+ case MON_DATA_IS_EGG:
+ SET8(substruct3->isEgg);
+ if (substruct3->isEgg)
+ boxMon->isEgg = 1;
+ else
+ boxMon->isEgg = 0;
+ break;
+ case MON_DATA_ALT_ABILITY:
+ SET8(substruct3->altAbility);
+ break;
+ case MON_DATA_COOL_RIBBON:
+ SET8(substruct3->coolRibbon);
+ break;
+ case MON_DATA_BEAUTY_RIBBON:
+ SET8(substruct3->beautyRibbon);
+ break;
+ case MON_DATA_CUTE_RIBBON:
+ SET8(substruct3->cuteRibbon);
+ break;
+ case MON_DATA_SMART_RIBBON:
+ SET8(substruct3->smartRibbon);
+ break;
+ case MON_DATA_TOUGH_RIBBON:
+ SET8(substruct3->toughRibbon);
+ break;
+ case MON_DATA_CHAMPION_RIBBON:
+ SET8(substruct3->championRibbon);
+ break;
+ case MON_DATA_WINNING_RIBBON:
+ SET8(substruct3->winningRibbon);
+ break;
+ case MON_DATA_VICTORY_RIBBON:
+ SET8(substruct3->victoryRibbon);
+ break;
+ case MON_DATA_ARTIST_RIBBON:
+ SET8(substruct3->artistRibbon);
+ break;
+ case MON_DATA_EFFORT_RIBBON:
+ SET8(substruct3->effortRibbon);
+ break;
+ case MON_DATA_GIFT_RIBBON_1:
+ SET8(substruct3->giftRibbon1);
+ break;
+ case MON_DATA_GIFT_RIBBON_2:
+ SET8(substruct3->giftRibbon2);
+ break;
+ case MON_DATA_GIFT_RIBBON_3:
+ SET8(substruct3->giftRibbon3);
+ break;
+ case MON_DATA_GIFT_RIBBON_4:
+ SET8(substruct3->giftRibbon4);
+ break;
+ case MON_DATA_GIFT_RIBBON_5:
+ SET8(substruct3->giftRibbon5);
+ break;
+ case MON_DATA_GIFT_RIBBON_6:
+ SET8(substruct3->giftRibbon6);
+ break;
+ case MON_DATA_GIFT_RIBBON_7:
+ SET8(substruct3->giftRibbon7);
+ break;
+ case MON_DATA_FATEFUL_ENCOUNTER:
+ SET8(substruct3->fatefulEncounter);
+ break;
+ case MON_DATA_OBEDIENCE:
+ SET8(substruct3->obedient);
+ break;
+ case MON_DATA_IVS:
+ {
+ u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ substruct3->hpIV = ivs & 0x1F;
+ substruct3->attackIV = (ivs >> 5) & 0x1F;
+ substruct3->defenseIV = (ivs >> 10) & 0x1F;
+ substruct3->speedIV = (ivs >> 15) & 0x1F;
+ substruct3->spAttackIV = (ivs >> 20) & 0x1F;
+ substruct3->spDefenseIV = (ivs >> 25) & 0x1F;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (field > MON_DATA_10)
+ {
+ boxMon->checksum = CalculateBoxMonChecksum(boxMon);
+ EncryptBoxMon(boxMon);
+ }
+}
+
+void CopyMon(void *dest, void *src, size_t size)
+{
+ memcpy(dest, src, size);
+}
+
+u8 GiveMonToPlayer(struct Pokemon *mon)
+{
+ s32 i;
+
+ SetMonData(mon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName);
+ SetMonData(mon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
+ SetMonData(mon, MON_DATA_OT_ID, gSaveBlock2Ptr->playerTrainerId);
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ break;
+ }
+
+ if (i >= PARTY_SIZE)
+ return SendMonToPC(mon);
+
+ CopyMon(&gPlayerParty[i], mon, sizeof(*mon));
+ gPlayerPartyCount = i + 1;
+ return MON_GIVEN_TO_PARTY;
+}
+
+u8 SendMonToPC(struct Pokemon* mon)
+{
+ s32 boxNo, boxPos;
+
+ set_unknown_box_id(VarGet(VAR_STORAGE_UNKNOWN));
+
+ boxNo = StorageGetCurrentBox();
+
+ do
+ {
+ for (boxPos = 0; boxPos < 30; boxPos++)
+ {
+ struct BoxPokemon* checkingMon = GetBoxedMonPtr(boxNo, boxPos);
+ if (GetBoxMonData(checkingMon, MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ {
+ MonRestorePP(mon);
+ CopyMon(checkingMon, &mon->box, sizeof(mon->box));
+ gSpecialVar_MonBoxId = boxNo;
+ gSpecialVar_MonBoxPos = boxPos;
+ if (get_unknown_box_id() != boxNo)
+ FlagClear(FLAG_SYS_STORAGE_UNKNOWN_FLAG);
+ VarSet(VAR_STORAGE_UNKNOWN, boxNo);
+ return MON_GIVEN_TO_PC;
+ }
+ }
+
+ boxNo++;
+ if (boxNo == 14)
+ boxNo = 0;
+ } while (boxNo != StorageGetCurrentBox());
+
+ return MON_CANT_GIVE;
+}
+
+u8 CalculatePlayerPartyCount(void)
+{
+ gPlayerPartyCount = 0;
+
+ while (gPlayerPartyCount < 6
+ && GetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
+ {
+ gPlayerPartyCount++;
+ }
+
+ return gPlayerPartyCount;
+}
+
+u8 CalculateEnemyPartyCount(void)
+{
+ gEnemyPartyCount = 0;
+
+ while (gEnemyPartyCount < 6
+ && GetMonData(&gEnemyParty[gEnemyPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
+ {
+ gEnemyPartyCount++;
+ }
+
+ return gEnemyPartyCount;
+}
+
+u8 GetMonsStateToDoubles(void)
+{
+ s32 aliveCount = 0;
+ s32 i;
+ CalculatePlayerPartyCount();
+
+ if (gPlayerPartyCount == 1)
+ return gPlayerPartyCount; // PLAYER_HAS_ONE_MON
+
+ for (i = 0; i < gPlayerPartyCount; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG
+ && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0
+ && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_NONE)
+ aliveCount++;
+ }
+
+ return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
+}
+
+u8 GetMonsStateToDoubles_2(void)
+{
+ s32 aliveCount = 0;
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL);
+ if (species != SPECIES_EGG && species != SPECIES_NONE
+ && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0)
+ aliveCount++;
+ }
+
+ if (aliveCount == 1)
+ return PLAYER_HAS_ONE_MON; // may have more than one, but only one is alive
+
+ return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
+}
+
+u8 GetAbilityBySpecies(u16 species, bool8 altAbility)
+{
+ if (altAbility)
+ gLastUsedAbility = gBaseStats[species].ability2;
+ else
+ gLastUsedAbility = gBaseStats[species].ability1;
+
+ return gLastUsedAbility;
+}
+
+u8 GetMonAbility(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
+ u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
+ return GetAbilityBySpecies(species, altAbility);
+}
+
+void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord)
+{
+ s32 i, j;
+
+ ZeroEnemyPartyMons();
+ *gBattleResources->secretBase = *secretBaseRecord;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (gBattleResources->secretBase->party.species[i])
+ {
+ CreateMon(&gEnemyParty[i],
+ gBattleResources->secretBase->party.species[i],
+ gBattleResources->secretBase->party.levels[i],
+ 15,
+ 1,
+ gBattleResources->secretBase->party.personality[i],
+ 2,
+ 0);
+
+ SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gBattleResources->secretBase->party.heldItems[i]);
+
+ for (j = 0; j < 6; j++)
+ SetMonData(&gEnemyParty[i], MON_DATA_HP_EV + j, &gBattleResources->secretBase->party.EVs[i]);
+
+ for (j = 0; j < 4; j++)
+ {
+ SetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j, &gBattleResources->secretBase->party.moves[i * 4 + j]);
+ SetMonData(&gEnemyParty[i], MON_DATA_PP1 + j, &gBattleMoves[gBattleResources->secretBase->party.moves[i * 4 + j]].pp);
+ }
+ }
+ }
+}
+
+u8 GetSecretBaseTrainerPicIndex(void)
+{
+ u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5];
+ return gFacilityClassToPicIndex[facilityClass];
+}
+
+u8 GetSecretBaseTrainerClass(void)
+{
+ u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5];
+ return gFacilityClassToTrainerClass[facilityClass];
+}
+
+bool8 IsPlayerPartyAndPokemonStorageFull(void)
+{
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
+ return FALSE;
+
+ return IsPokemonStorageFull();
+}
+
+bool8 IsPokemonStorageFull(void)
+{
+ s32 i, j;
+
+ for (i = 0; i < 14; i++)
+ for (j = 0; j < 30; j++)
+ if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
+ return FALSE;
+
+ return TRUE;
+}
+
+void GetSpeciesName(u8 *name, u16 species)
+{
+ s32 i;
+
+ for (i = 0; i <= POKEMON_NAME_LENGTH; i++)
+ {
+ if (species > NUM_SPECIES)
+ name[i] = gSpeciesNames[0][i];
+ else
+ name[i] = gSpeciesNames[species][i];
+
+ if (name[i] == EOS)
+ break;
+ }
+
+ name[i] = EOS;
+}
+
+u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex)
+{
+ u8 basePP = gBattleMoves[move].pp;
+ return basePP + ((basePP * 20 * ((gUnknown_08329D22[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100);
+}
+
+void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex)
+{
+ u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ ppBonuses &= gUnknown_08329D26[moveIndex];
+ SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
+}
+
+void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex)
+{
+ mon->ppBonuses &= gUnknown_08329D26[moveIndex];
+}
+
+void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex)
+{
+ u16* hpSwitchout;
+ s32 i;
+ u8 nickname[POKEMON_NAME_LENGTH * 2];
+
+ gBattleMons[battlerId].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
+ gBattleMons[battlerId].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL);
+
+ for (i = 0; i < 4; i++)
+ {
+ gBattleMons[battlerId].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL);
+ gBattleMons[battlerId].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL);
+ }
+
+ gBattleMons[battlerId].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL);
+ gBattleMons[battlerId].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL);
+ gBattleMons[battlerId].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL);
+ gBattleMons[battlerId].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL);
+ gBattleMons[battlerId].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL);
+ gBattleMons[battlerId].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL);
+ gBattleMons[battlerId].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED_IV, NULL);
+ gBattleMons[battlerId].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL);
+ gBattleMons[battlerId].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL);
+ gBattleMons[battlerId].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL);
+ gBattleMons[battlerId].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL);
+ gBattleMons[battlerId].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL);
+ gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL);
+ gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL);
+ gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL);
+ gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL);
+ gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED, NULL);
+ gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL);
+ gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL);
+ gBattleMons[battlerId].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL);
+ gBattleMons[battlerId].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL);
+ gBattleMons[battlerId].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL);
+ gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1;
+ gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2;
+ gBattleMons[battlerId].ability = GetAbilityBySpecies(gBattleMons[battlerId].species, gBattleMons[battlerId].altAbility);
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
+ StringCopy10(gBattleMons[battlerId].nickname, nickname);
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[battlerId].otName);
+
+ hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(battlerId)];
+ *hpSwitchout = gBattleMons[battlerId].hp;
+
+ for (i = 0; i < 8; i++)
+ gBattleMons[battlerId].statStages[i] = 6;
+
+ gBattleMons[battlerId].status2 = 0;
+ sub_803FA70(battlerId);
+ ClearTemporarySpeciesSpriteData(battlerId, FALSE);
+}
+
+bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex)
+{
+ return PokemonUseItemEffects(mon, item, partyIndex, moveIndex, 0);
+}
+
+bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e)
+{
+ u32 dataUnsigned;
+ s32 dataSigned;
+ s32 friendship;
+ s32 cmdIndex;
+ bool8 retVal = TRUE;
+ const u8 *itemEffect;
+ u8 var_3C = 6;
+ u32 var_38;
+ s8 var_34 = 0;
+ u8 holdEffect;
+ u8 battlerId = 4;
+ u32 var_28 = 0;
+ u16 heldItem;
+ u8 r10;
+ u32 r4;
+ u32 r5;
+ s8 r2;
+ u16 evCount;
+
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ holdEffect = gEnigmaBerries[gBattlerInMenuId].holdEffect;
+ else
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ gPotentialItemEffectBattler = gBattlerInMenuId;
+ if (gMain.inBattle)
+ {
+ gActiveBattler = gBattlerInMenuId;
+ cmdIndex = (GetBattlerSide(gActiveBattler) != B_SIDE_PLAYER);
+ while (cmdIndex < gBattlersCount)
+ {
+ if (gBattlerPartyIndexes[cmdIndex] == partyIndex)
+ {
+ battlerId = cmdIndex;
+ break;
+ }
+ cmdIndex += 2;
+ }
+ }
+ else
+ {
+ gActiveBattler = 0;
+ battlerId = MAX_BATTLERS_COUNT;
+ }
+
+ if (!IS_POKEMON_ITEM(item))
+ return TRUE;
+ if (gItemEffectTable[item - 13] == NULL && item != ITEM_ENIGMA_BERRY)
+ return TRUE;
+
+ if (item == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ itemEffect = gEnigmaBerries[gActiveBattler].itemEffect;
+ else
+ itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ }
+ else
+ {
+ itemEffect = gItemEffectTable[item - 13];
+ }
+
+ for (cmdIndex = 0; cmdIndex < 6; cmdIndex++)
+ {
+ switch (cmdIndex)
+ {
+ // status healing effects
+ case 0:
+ if ((itemEffect[cmdIndex] & 0x80)
+ && gMain.inBattle && battlerId != 4 && (gBattleMons[battlerId].status2 & STATUS2_INFATUATION))
+ {
+ gBattleMons[battlerId].status2 &= ~STATUS2_INFATUATION;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0x30)
+ && !(gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY))
+ {
+ gBattleMons[gActiveBattler].status2 |= STATUS2_FOCUS_ENERGY;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0xF)
+ && gBattleMons[gActiveBattler].statStages[STAT_ATK] < 12)
+ {
+ gBattleMons[gActiveBattler].statStages[STAT_ATK] += itemEffect[cmdIndex] & 0xF;
+ if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > 12)
+ gBattleMons[gActiveBattler].statStages[STAT_ATK] = 12;
+ retVal = FALSE;
+ }
+ break;
+ // in-battle stat boosting effects?
+ case 1:
+ if ((itemEffect[cmdIndex] & 0xF0)
+ && gBattleMons[gActiveBattler].statStages[STAT_DEF] < 12)
+ {
+ gBattleMons[gActiveBattler].statStages[STAT_DEF] += (itemEffect[cmdIndex] & 0xF0) >> 4;
+ if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > 12)
+ gBattleMons[gActiveBattler].statStages[STAT_DEF] = 12;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0xF)
+ && gBattleMons[gActiveBattler].statStages[STAT_SPEED] < 12)
+ {
+ gBattleMons[gActiveBattler].statStages[STAT_SPEED] += itemEffect[cmdIndex] & 0xF;
+ if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > 12)
+ gBattleMons[gActiveBattler].statStages[STAT_SPEED] = 12;
+ retVal = FALSE;
+ }
+ break;
+ // more stat boosting effects?
+ case 2:
+ if ((itemEffect[cmdIndex] & 0xF0)
+ && gBattleMons[gActiveBattler].statStages[STAT_ACC] < 12)
+ {
+ gBattleMons[gActiveBattler].statStages[STAT_ACC] += (itemEffect[cmdIndex] & 0xF0) >> 4;
+ if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > 12)
+ gBattleMons[gActiveBattler].statStages[STAT_ACC] = 12;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0xF)
+ && gBattleMons[gActiveBattler].statStages[STAT_SPATK] < 12)
+ {
+ gBattleMons[gActiveBattler].statStages[STAT_SPATK] += itemEffect[cmdIndex] & 0xF;
+ if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > 12)
+ gBattleMons[gActiveBattler].statStages[STAT_SPATK] = 12;
+ retVal = FALSE;
+ }
+ break;
+ case 3:
+ if ((itemEffect[cmdIndex] & 0x80)
+ && gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer == 0)
+ {
+ gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer = 5;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0x40) // raise level
+ && GetMonData(mon, MON_DATA_LEVEL, NULL) != MAX_MON_LEVEL)
+ {
+ dataUnsigned = gExperienceTables[gBaseStats[GetMonData(mon, MON_DATA_SPECIES, NULL)].growthRate][GetMonData(mon, MON_DATA_LEVEL, NULL) + 1];
+ SetMonData(mon, MON_DATA_EXP, &dataUnsigned);
+ CalculateMonStats(mon);
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0x20)
+ && HealStatusConditions(mon, partyIndex, 7, battlerId) == 0)
+ {
+ if (battlerId != 4)
+ gBattleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE;
+ retVal = FALSE;
+ }
+ if ((itemEffect[cmdIndex] & 0x10) && HealStatusConditions(mon, partyIndex, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0)
+ retVal = FALSE;
+ if ((itemEffect[cmdIndex] & 8) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0)
+ retVal = FALSE;
+ if ((itemEffect[cmdIndex] & 4) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE, battlerId) == 0)
+ retVal = FALSE;
+ if ((itemEffect[cmdIndex] & 2) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0)
+ retVal = FALSE;
+ if ((itemEffect[cmdIndex] & 1) // heal confusion
+ && gMain.inBattle && battlerId != 4 && (gBattleMons[battlerId].status2 & STATUS2_CONFUSION))
+ {
+ gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
+ retVal = FALSE;
+ }
+ break;
+ // EV, HP, and PP raising effects
+ case 4:
+ r10 = itemEffect[cmdIndex];
+ if (r10 & 0x20)
+ {
+ r10 &= ~0x20;
+ dataUnsigned = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & gUnknown_08329D22[moveIndex]) >> (moveIndex * 2);
+ var_38 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex);
+ if (dataUnsigned <= 2 && var_38 > 4)
+ {
+ dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL) + gUnknown_08329D2A[moveIndex];
+ SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned);
+
+ dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - var_38;
+ dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL) + dataUnsigned;
+ SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned);
+ retVal = FALSE;
+ }
+ }
+ var_38 = 0;
+ while (r10 != 0)
+ {
+ if (r10 & 1)
+ {
+ switch (var_38)
+ {
+ case 0:
+ case 1:
+ evCount = GetMonEVCount(mon);
+ r5 = itemEffect[var_3C];
+ dataSigned = GetMonData(mon, sGetMonDataEVConstants[var_38], NULL);
+ r2 = r5;
+ if (r2 > 0)
+ {
+ if (evCount >= MAX_TOTAL_EVS)
+ return TRUE;
+ if (dataSigned >= 100)
+ break;
+
+ if (dataSigned + r2 > 100)
+ r5 = 100 - (dataSigned + r2) + r2;
+ else
+ r5 = r2;
+
+ if (evCount + r5 > MAX_TOTAL_EVS)
+ r5 += MAX_TOTAL_EVS - (evCount + r5);
+ dataSigned += r5;
+ }
+ else
+ {
+ if (dataSigned == 0)
+ {
+ var_28 = 1;
+ var_3C++;
+ break;
+ }
+ dataSigned += r2;
+ if (dataSigned < 0)
+ dataSigned = 0;
+ }
+ SetMonData(mon, sGetMonDataEVConstants[var_38], &dataSigned);
+ CalculateMonStats(mon);
+ var_3C++;
+ retVal = FALSE;
+ break;
+ case 2:
+ // revive?
+ if (r10 & 0x10)
+ {
+ if (GetMonData(mon, MON_DATA_HP, NULL) != 0)
+ {
+ var_3C++;
+ break;
+ }
+ if (gMain.inBattle)
+ {
+ if (battlerId != 4)
+ {
+ gAbsentBattlerFlags &= ~gBitTable[battlerId];
+ CopyPlayerPartyMonToBattleData(battlerId, pokemon_order_func(gBattlerPartyIndexes[battlerId]));
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.unk4 < 255)
+ gBattleResults.unk4++;
+ }
+ else
+ {
+ gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2];
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.unk4 < 255)
+ gBattleResults.unk4++;
+ }
+ }
+ }
+ else
+ {
+ if (GetMonData(mon, MON_DATA_HP, NULL) == 0)
+ {
+ var_3C++;
+ break;
+ }
+ }
+ dataUnsigned = itemEffect[var_3C++];
+ switch (dataUnsigned)
+ {
+ case 0xFF:
+ dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL) - GetMonData(mon, MON_DATA_HP, NULL);
+ break;
+ case 0xFE:
+ dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL) / 2;
+ if (dataUnsigned == 0)
+ dataUnsigned = 1;
+ break;
+ case 0xFD:
+ dataUnsigned = gBattleScripting.field_23;
+ break;
+ }
+ if (GetMonData(mon, MON_DATA_MAX_HP, NULL) != GetMonData(mon, MON_DATA_HP, NULL))
+ {
+ if (e == 0)
+ {
+ dataUnsigned = GetMonData(mon, MON_DATA_HP, NULL) + dataUnsigned;
+ if (dataUnsigned > GetMonData(mon, MON_DATA_MAX_HP, NULL))
+ dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL);
+ SetMonData(mon, MON_DATA_HP, &dataUnsigned);
+ if (gMain.inBattle && battlerId != 4)
+ {
+ gBattleMons[battlerId].hp = dataUnsigned;
+ if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ {
+ if (gBattleResults.unk3 < 255)
+ gBattleResults.unk3++;
+ // I have to re-use this variable to match.
+ r5 = gActiveBattler;
+ gActiveBattler = battlerId;
+ BtlController_EmitGetMonData(0, 0, 0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ gActiveBattler = r5;
+ }
+ }
+ }
+ else
+ {
+ gBattleMoveDamage = -dataUnsigned;
+ }
+ retVal = FALSE;
+ }
+ r10 &= 0xEF;
+ break;
+ case 3:
+ if (!(r10 & 2))
+ {
+ for (r5 = 0; (signed)(r5) < (signed)(4); r5++)
+ {
+ u16 moveId;
+
+ dataUnsigned = GetMonData(mon, MON_DATA_PP1 + r5, NULL);
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL);
+ if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5))
+ {
+ dataUnsigned += itemEffect[var_3C];
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL);
+ if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5))
+ {
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL);
+ dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5);
+ }
+ SetMonData(mon, MON_DATA_PP1 + r5, &dataUnsigned);
+ if (gMain.inBattle
+ && battlerId != 4 && !(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[battlerId].unk18_b & gBitTable[r5]))
+ gBattleMons[battlerId].pp[r5] = dataUnsigned;
+ retVal = FALSE;
+ }
+ }
+ var_3C++;
+ }
+ else
+ {
+ u16 moveId;
+
+ dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL);
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL);
+ if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex))
+ {
+ dataUnsigned += itemEffect[var_3C++];
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL);
+ if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex))
+ {
+ moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL);
+ dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex);
+ }
+ SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned);
+ if (gMain.inBattle
+ && battlerId != 4 && !(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[battlerId].unk18_b & gBitTable[moveIndex]))
+ gBattleMons[battlerId].pp[moveIndex] = dataUnsigned;
+ retVal = FALSE;
+ }
+ }
+ break;
+ case 7:
+ {
+ u16 targetSpecies = GetEvolutionTargetSpecies(mon, 2, item);
+
+ if (targetSpecies != SPECIES_NONE)
+ {
+ BeginEvolutionScene(mon, targetSpecies, 0, partyIndex);
+ return FALSE;
+ }
+ }
+ break;
+ }
+ }
+ var_38++;
+ r10 >>= 1;
+ }
+ break;
+ case 5:
+ r10 = itemEffect[cmdIndex];
+ var_38 = 0;
+ while (r10 != 0)
+ {
+ if (r10 & 1)
+ {
+ switch (var_38)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ evCount = GetMonEVCount(mon);
+ r5 = itemEffect[var_3C];
+ dataSigned = GetMonData(mon, sGetMonDataEVConstants[var_38 + 2], NULL);
+ r2 = r5;
+ if (r2 > 0)
+ {
+ if (evCount >= MAX_TOTAL_EVS)
+ return TRUE;
+ if (dataSigned >= 100)
+ break;
+
+ if (dataSigned + r2 > 100)
+ r5 = 100 - (dataSigned + r2) + r2;
+ else
+ r5 = r2;
+
+ if (evCount + r5 > MAX_TOTAL_EVS)
+ r5 += MAX_TOTAL_EVS - (evCount + r5);
+ dataSigned += r5;
+ }
+ else
+ {
+ if (dataSigned == 0)
+ {
+ var_28 = 1;
+ var_3C++;
+ break;
+ }
+ dataSigned += r2;
+ if (dataSigned < 0)
+ dataSigned = 0;
+ }
+ SetMonData(mon, sGetMonDataEVConstants[var_38 + 2], &dataSigned);
+ CalculateMonStats(mon);
+ retVal = FALSE;
+ var_3C++;
+ break;
+ case 4:
+ dataUnsigned = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & gUnknown_08329D22[moveIndex]) >> (moveIndex * 2);
+ r5 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex);
+ if (dataUnsigned < 3 && r5 > 4)
+ {
+ dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
+ dataUnsigned &= gUnknown_08329D26[moveIndex];
+ dataUnsigned += gUnknown_08329D2A[moveIndex] * 3;
+
+ SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned);
+ dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - r5;
+ dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL) + dataUnsigned;
+ SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned);
+ retVal = FALSE;
+ }
+ break;
+ case 5:
+ if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 100 && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0)
+ {
+ var_34 = itemEffect[var_3C];
+ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
+ if (var_34 > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ friendship += 150 * var_34 / 100;
+ else
+ friendship += var_34;
+ if (var_34 > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
+ retVal = FALSE;
+ }
+ var_3C++;
+ break;
+ case 6:
+ if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 100 && GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 200
+ && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0)
+ {
+ var_34 = itemEffect[var_3C];
+ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
+ if ((s8)(var_34) > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ friendship += 150 * var_34 / 100;
+ else
+ friendship += var_34;
+ if (var_34 > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
+ retVal = FALSE;
+ }
+ var_3C++;
+ break;
+ case 7:
+ if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 200 && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0)
+ {
+ var_34 = itemEffect[var_3C];
+ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
+ if ((s8)(var_34) > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ friendship += 150 * var_34 / 100;
+ else
+ friendship += var_34;
+ if (var_34 > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
+ retVal = FALSE;
+ }
+ var_3C++;
+ break;
+ }
+ }
+ var_38++;
+ r10 >>= 1;
+ }
+ break;
+ }
+ }
+ return retVal;
+}
+
+bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battlerId)
+{
+ u32 status = GetMonData(mon, MON_DATA_STATUS, 0);
+
+ if (status & healMask)
+ {
+ status &= ~healMask;
+ SetMonData(mon, MON_DATA_STATUS, &status);
+ if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT)
+ gBattleMons[battlerId].status1 &= ~healMask;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
+{
+ const u8 *temp;
+ const u8 *itemEffect;
+ u8 offset;
+ int i;
+ u8 j;
+ u8 val;
+
+ offset = 6;
+
+ temp = gItemEffectTable[itemId - 13];
+
+ if (!temp && itemId != ITEM_ENIGMA_BERRY)
+ return 0;
+
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ temp = gEnigmaBerries[gActiveBattler].itemEffect;
+ }
+
+ itemEffect = temp;
+
+ for (i = 0; i < 6; i++)
+ {
+ switch (i)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (i == effectByte)
+ return 0;
+ break;
+ case 4:
+ val = itemEffect[4];
+ if (val & 0x20)
+ val &= 0xDF;
+ j = 0;
+ while (val)
+ {
+ if (val & 1)
+ {
+ switch (j)
+ {
+ case 2:
+ if (val & 0x10)
+ val &= 0xEF;
+ case 0:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 1:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 3:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 7:
+ if (i == effectByte)
+ return 0;
+ break;
+ }
+ }
+ j++;
+ val >>= 1;
+ if (i == effectByte)
+ effectBit >>= 1;
+ }
+ break;
+ case 5:
+ val = itemEffect[5];
+ j = 0;
+ while (val)
+ {
+ if (val & 1)
+ {
+ switch (j)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ if (i == effectByte && (val & effectBit))
+ return offset;
+ offset++;
+ break;
+ case 7:
+ if (i == effectByte)
+ return 0;
+ break;
+ }
+ }
+ j++;
+ val >>= 1;
+ if (i == effectByte)
+ effectBit >>= 1;
+ }
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static void sub_806CF24(s32 arg0)
+{
+ gBattlerTarget = gBattlerInMenuId;
+ StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[arg0]]);
+ StringCopy(gBattleTextBuff2, gText_StatRose);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
+}
+
+u8 *sub_806CF78(u16 itemId)
+{
+ int i;
+ const u8 *itemEffect;
+
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ itemEffect = gEnigmaBerries[gBattlerInMenuId].itemEffect;
+ else
+ itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ }
+ else
+ {
+ itemEffect = gItemEffectTable[itemId - 13];
+ }
+
+ gPotentialItemEffectBattler = gBattlerInMenuId;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (itemEffect[i] & 0xF)
+ sub_806CF24(i * 2);
+ if (itemEffect[i] & 0xF0)
+ {
+ if (i)
+ {
+ sub_806CF24(i * 2 + 1);
+ }
+ else
+ {
+ gBattlerAttacker = gBattlerInMenuId;
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
+ }
+ }
+ }
+
+ if (itemEffect[3] & 0x80)
+ {
+ gBattlerAttacker = gBattlerInMenuId;
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
+ }
+
+ return gDisplayedStringBattle;
+}
+
+u8 GetNature(struct Pokemon *mon)
+{
+ return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25;
+}
+
+u8 GetNatureFromPersonality(u32 personality)
+{
+ return personality % 25;
+}
+
+u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem)
+{
+ int i;
+ u16 targetSpecies = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ u8 level;
+ u16 friendship;
+ u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0);
+ u16 upperPersonality = personality >> 16;
+ u8 holdEffect;
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+
+ if (holdEffect == 38 && type != 3)
+ return 0;
+
+ switch (type)
+ {
+ case 0:
+ level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
+
+ for (i = 0; i < 5; i++)
+ {
+ switch (gEvolutionTable[species][i].method)
+ {
+ case EVO_FRIENDSHIP:
+ if (friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_DAY:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_NIGHT:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL:
+ if (gEvolutionTable[species][i].param <= level)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_GT_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_EQ_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_LT_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_SILCOON:
+ if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_CASCOON:
+ if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_NINJASK:
+ if (gEvolutionTable[species][i].param <= level)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_BEAUTY:
+ if (gEvolutionTable[species][i].param <= beauty)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < 5; i++)
+ {
+ switch (gEvolutionTable[species][i].method)
+ {
+ case EVO_TRADE:
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_TRADE_ITEM:
+ if (gEvolutionTable[species][i].param == heldItem)
+ {
+ heldItem = 0;
+ SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem);
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ }
+ break;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ for (i = 0; i < 5; i++)
+ {
+ if (gEvolutionTable[species][i].method == EVO_ITEM
+ && gEvolutionTable[species][i].param == evolutionItem)
+ {
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ }
+ }
+ break;
+ }
+
+ return targetSpecies;
+}
+
+u16 HoennPokedexNumToSpecies(u16 hoennNum)
+{
+ u16 species;
+
+ if (!hoennNum)
+ return 0;
+
+ species = 0;
+
+ while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum)
+ species++;
+
+ if (species == 411)
+ return 0;
+
+ return species + 1;
+}
+
+u16 NationalPokedexNumToSpecies(u16 nationalNum)
+{
+ u16 species;
+
+ if (!nationalNum)
+ return 0;
+
+ species = 0;
+
+ while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum)
+ species++;
+
+ if (species == 411)
+ return 0;
+
+ return species + 1;
+}
+
+u16 NationalToHoennOrder(u16 nationalNum)
+{
+ u16 hoennNum;
+
+ if (!nationalNum)
+ return 0;
+
+ hoennNum = 0;
+
+ while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum)
+ hoennNum++;
+
+ if (hoennNum == 411)
+ return 0;
+
+ return hoennNum + 1;
+}
+
+u16 SpeciesToNationalPokedexNum(u16 species)
+{
+ if (!species)
+ return 0;
+
+ return gSpeciesToNationalPokedexNum[species - 1];
+}
+
+u16 SpeciesToHoennPokedexNum(u16 species)
+{
+ if (!species)
+ return 0;
+
+ return gSpeciesToHoennPokedexNum[species - 1];
+}
+
+u16 HoennToNationalOrder(u16 hoennNum)
+{
+ if (!hoennNum)
+ return 0;
+
+ return gHoennToNationalOrder[hoennNum - 1];
+}
+
+u16 SpeciesToCryId(u16 species)
+{
+ if (species <= 250)
+ return species;
+
+ if (species < 276)
+ return 200;
+
+ return gSpeciesIdToCryId[species - 276];
+}
+
+void sub_806D544(u16 species, u32 personality, u8 *dest)
+{
+ if (species == SPECIES_SPINDA
+ && dest != gMonSpritesGfxPtr->sprites[0]
+ && dest != gMonSpritesGfxPtr->sprites[2])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4)
+{
+ if (species == SPECIES_SPINDA && a4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
+{
+ u8 language;
+ GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
+ language = GetMonData(mon, MON_DATA_LANGUAGE, &language);
+ if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1))
+ SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
+}
+
+bool8 sub_806D7EC(void)
+{
+ bool8 retVal = FALSE;
+ switch (gLinkPlayers[GetMultiplayerId()].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+bool16 sub_806D82C(u8 id)
+{
+ bool16 retVal = FALSE;
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+s32 GetBattlerMultiplayerId(u16 a1)
+{
+ s32 id;
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ if (gLinkPlayers[id].lp_field_18 == a1)
+ break;
+ return id;
+}
+
+u8 GetTrainerEncounterMusicId(u16 trainerOpponentId)
+{
+ if (InBattlePyramid())
+ return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId);
+ if (sub_81D5C18())
+ return sub_81D63C8(trainerOpponentId);
+ return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId);
+}
+
+u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex)
+{
+ if (statIndex < 1 || statIndex > 5)
+ {
+ // should just be "return n", but it wouldn't match without this
+ u16 retVal = n;
+ retVal++;
+ retVal--;
+ return retVal;
+ }
+
+ switch (gNatureStatTable[nature][statIndex - 1])
+ {
+ case 1:
+ return (u16)(n * 110) / 100;
+ case -1:
+ return (u16)(n * 90) / 100;
+ }
+
+ return n;
+}
+
+void AdjustFriendship(struct Pokemon *mon, u8 event)
+{
+ u16 species, heldItem;
+ u8 holdEffect;
+
+ if (sub_806F104())
+ return;
+
+ species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ else
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (species && species != SPECIES_EGG)
+ {
+ u8 friendshipLevel = 0;
+ s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
+ if (friendship > 99)
+ friendshipLevel++;
+ if (friendship > 199)
+ friendshipLevel++;
+ if ((event != 5 || !(Random() & 1))
+ && (event != 3
+ || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION))))
+ {
+ s8 mod = gUnknown_08329ECE[event][friendshipLevel];
+ if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ mod = (150 * mod) / 100;
+ friendship += mod;
+ if (mod > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
+ }
+ }
+}
+
+void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
+{
+ u8 evs[NUM_STATS];
+ u16 evIncrease = 0;
+ u16 totalEVs = 0;
+ u16 heldItem;
+ u8 holdEffect;
+ int i;
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0);
+ totalEVs += evs[i];
+ }
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ u8 hasHadPokerus;
+ int multiplier;
+
+ if (totalEVs >= MAX_TOTAL_EVS)
+ break;
+
+ hasHadPokerus = CheckPartyHasHadPokerus(mon, 0);
+
+ if (hasHadPokerus)
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ switch (i)
+ {
+ case 0:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier;
+ break;
+ case 1:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier;
+ break;
+ case 2:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier;
+ break;
+ case 3:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier;
+ break;
+ case 4:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier;
+ break;
+ case 5:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier;
+ break;
+ }
+
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ else
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ evIncrease *= 2;
+
+ if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
+ evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
+
+ if (evs[i] + (s16)evIncrease > 255)
+ {
+ int val1 = (s16)evIncrease + 255;
+ int val2 = evs[i] + evIncrease;
+ evIncrease = val1 - val2;
+ }
+
+ evs[i] += evIncrease;
+ totalEVs += evIncrease;
+ SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]);
+ }
+}
+
+u16 GetMonEVCount(struct Pokemon *mon)
+{
+ int i;
+ u16 count = 0;
+
+ for (i = 0; i < NUM_STATS; i++)
+ count += GetMonData(mon, MON_DATA_HP_EV + i, 0);
+
+ return count;
+}
+
+void RandomlyGivePartyPokerus(struct Pokemon *party)
+{
+ u16 rnd = Random();
+ if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
+ {
+ struct Pokemon *mon;
+
+ do
+ {
+ do
+ {
+ rnd = Random() % PARTY_SIZE;
+ mon = &party[rnd];
+ }
+ while (!GetMonData(mon, MON_DATA_SPECIES, 0));
+ }
+ while (GetMonData(mon, MON_DATA_IS_EGG, 0));
+
+ if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
+ {
+ u8 rnd2;
+
+ do
+ {
+ rnd2 = Random();
+ }
+ while ((rnd2 & 0x7) == 0);
+
+ if (rnd2 & 0xF0)
+ rnd2 &= 0x7;
+
+ rnd2 |= (rnd2 << 4);
+ rnd2 &= 0xF3;
+ rnd2++;
+
+ SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
+ }
+ }
+}
+
+u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF)
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0))
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+void UpdatePartyPokerusTime(u16 days)
+{
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
+ if (pokerus & 0xF)
+ {
+ if ((pokerus & 0xF) < days || days > 4)
+ pokerus &= 0xF0;
+ else
+ pokerus -= days;
+
+ if (pokerus == 0)
+ pokerus = 0x10;
+
+ SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
+ }
+ }
+ }
+}
+
+void PartySpreadPokerus(struct Pokemon *party)
+{
+ if ((Random() % 3) == 0)
+ {
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
+ u8 curPokerus = pokerus;
+ if (pokerus)
+ {
+ if (pokerus & 0xF)
+ {
+ // spread to adjacent party members
+ if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
+ SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
+ if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
+ {
+ SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
+ i++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool8 TryIncrementMonLevel(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1;
+ u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0);
+ if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL])
+ {
+ expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL];
+ SetMonData(mon, MON_DATA_EXP, &expPoints);
+ }
+ if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel])
+ {
+ return FALSE;
+ }
+ else
+ {
+ SetMonData(mon, MON_DATA_LEVEL, &nextLevel);
+ return TRUE;
+ }
+}
+
+u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ if (species == SPECIES_EGG)
+ {
+ return 0;
+ }
+ else if (tm < 32)
+ {
+ u32 mask = 1 << tm;
+ return gTMHMLearnsets[species][0] & mask;
+ }
+ else
+ {
+ u32 mask = 1 << (tm - 32);
+ return gTMHMLearnsets[species][1] & mask;
+ }
+}
+
+u32 CanSpeciesLearnTMHM(u16 species, u8 tm)
+{
+ if (species == SPECIES_EGG)
+ {
+ return 0;
+ }
+ else if (tm < 32)
+ {
+ u32 mask = 1 << tm;
+ return gTMHMLearnsets[species][0] & mask;
+ }
+ else
+ {
+ u32 mask = 1 << (tm - 32);
+ return gTMHMLearnsets[species][1] & mask;
+ }
+}
+
+u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves)
+{
+ u16 learnedMoves[4];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)
+{
+ u8 numMoves = 0;
+ int i;
+
+ for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+
+ return numMoves;
+}
+
+u8 GetNumberOfRelearnableMoves(struct Pokemon *mon)
+{
+ u16 learnedMoves[4];
+ u16 moves[20];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ if (species == SPECIES_EGG)
+ return 0;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u16 SpeciesToPokedexNum(u16 species)
+{
+ if (IsNationalPokedexEnabled())
+ {
+ return SpeciesToNationalPokedexNum(species);
+ }
+ else
+ {
+ species = SpeciesToHoennPokedexNum(species);
+ if (species <= 202)
+ return species;
+ return 0xFFFF;
+ }
+}
+
+bool32 sub_806E3F8(u16 species)
+{
+ if (SpeciesToHoennPokedexNum(species) > 202)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void ClearBattleMonForms(void)
+{
+ int i;
+ for (i = 0; i < MAX_BATTLERS_COUNT; i++)
+ gBattleMonForms[i] = 0;
+}
+
+u16 GetBattleBGM(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
+ return MUS_BATTLE34;
+ if (gBattleTypeFlags & BATTLE_TYPE_REGI)
+ return MUS_BATTLE36;
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ return MUS_BATTLE20;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ u8 trainerClass;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
+ else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
+ trainerClass = TRAINER_CLASS_EXPERT;
+ else
+ trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
+
+ switch (trainerClass)
+ {
+ case TRAINER_CLASS_AQUA_LEADER:
+ case TRAINER_CLASS_MAGMA_LEADER:
+ return MUS_BATTLE30;
+ case TRAINER_CLASS_TEAM_AQUA:
+ case TRAINER_CLASS_TEAM_MAGMA:
+ case TRAINER_CLASS_AQUA_ADMIN:
+ case TRAINER_CLASS_MAGMA_ADMIN:
+ return MUS_BATTLE31;
+ case TRAINER_CLASS_LEADER:
+ return MUS_BATTLE32;
+ case TRAINER_CLASS_CHAMPION:
+ return MUS_BATTLE33;
+ case TRAINER_CLASS_PKMN_TRAINER_3:
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ return MUS_BATTLE35;
+ if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
+ return MUS_BATTLE20;
+ return MUS_BATTLE35;
+ case TRAINER_CLASS_ELITE_FOUR:
+ return MUS_BATTLE38;
+ case TRAINER_CLASS_SALON_MAIDEN:
+ case TRAINER_CLASS_DOME_ACE:
+ case TRAINER_CLASS_PALACE_MAVEN:
+ case TRAINER_CLASS_ARENA_TYCOON:
+ case TRAINER_CLASS_FACTORY_HEAD:
+ case TRAINER_CLASS_PIKE_QUEEN:
+ case TRAINER_CLASS_PYRAMID_KING:
+ return MUS_VS_FRONT;
+ default:
+ return MUS_BATTLE20;
+ }
+ }
+ return MUS_BATTLE27;
+}
+
+void PlayBattleBGM(void)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ PlayBGM(GetBattleBGM());
+}
+
+void PlayMapChosenOrBattleBGM(u16 songId)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ if (songId)
+ PlayNewMapMusic(songId);
+ else
+ PlayNewMapMusic(GetBattleBGM());
+}
+
+void sub_806E694(u16 songId)
+{
+ u8 taskId;
+
+ ResetMapMusic();
+ m4aMPlayAllStop();
+
+ taskId = CreateTask(sub_806E6CC, 0);
+ gTasks[taskId].data[0] = songId;
+}
+
+static void sub_806E6CC(u8 taskId)
+{
+ if (gTasks[taskId].data[0])
+ PlayNewMapMusic(gTasks[taskId].data[0]);
+ else
+ PlayNewMapMusic(GetBattleBGM());
+ DestroyTask(taskId);
+}
+
+const u8 *GetMonFrontSpritePal(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality);
+}
+
+// Extracts the upper 16 bits of a 32-bit number
+#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
+
+// Extracts the lower 16 bits of a 32-bit number
+#define LOHALF(n) ((n) & 0xFFFF)
+
+const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
+{
+ u32 shinyValue;
+
+ if (species > SPECIES_EGG)
+ return gMonPaletteTable[0].data;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return gMonShinyPaletteTable[species].data;
+ else
+ return gMonPaletteTable[species].data;
+}
+
+const struct CompressedSpritePalette *GetMonSpritePalStruct(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality);
+}
+
+const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality)
+{
+ u32 shinyValue;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return &gMonShinyPaletteTable[species];
+ else
+ return &gMonPaletteTable[species];
+}
+
+bool32 IsHMMove2(u16 move)
+{
+ int i = 0;
+ while (sHMMoves[i] != 0xFFFF)
+ {
+ if (sHMMoves[i++] == move)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 IsMonSpriteNotFlipped(u16 species)
+{
+ return gBaseStats[species].noFlip;
+}
+
+s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor)
+{
+ u8 nature = GetNature(mon);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
+}
+
+s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor)
+{
+ u8 nature = GetNatureFromPersonality(personality);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
+}
+
+bool8 IsTradedMon(struct Pokemon *mon)
+{
+ u8 otName[OT_NAME_LENGTH + 1];
+ u32 otId;
+ GetMonData(mon, MON_DATA_OT_NAME, otName);
+ otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ return IsOtherTrainer(otId, otName);
+}
+
+bool8 IsOtherTrainer(u32 otId, u8 *otName)
+{
+ if (otId ==
+ (gSaveBlock2Ptr->playerTrainerId[0]
+ | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
+ | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
+ | (gSaveBlock2Ptr->playerTrainerId[3] << 24)))
+ {
+ int i;
+
+ for (i = 0; otName[i] != EOS; i++)
+ if (otName[i] != gSaveBlock2Ptr->playerName[i])
+ return TRUE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void MonRestorePP(struct Pokemon *mon)
+{
+ BoxMonRestorePP(&mon->box);
+}
+
+void BoxMonRestorePP(struct BoxPokemon *boxMon)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0))
+ {
+ u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0);
+ u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0);
+ u8 pp = CalculatePPWithBonus(move, bonus, i);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp);
+ }
+ }
+}
+
+void sub_806E994(void)
+{
+ gLastUsedAbility = gBattleStruct->field_B0;
+
+ gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
+ gBattleTextBuff1[2] = gBattleStruct->field_49;
+ gBattleTextBuff1[4] = B_BUFF_EOS;
+
+ if (!GetBattlerSide(gBattleStruct->field_49))
+ gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]);
+ else
+ gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49];
+
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, pokemon_order_func(gBattlerPartyIndexes[gBattlerInMenuId]))
+
+ BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
+}
+
+static s32 GetWildMonTableIdInAlteringCave(u16 species)
+{
+ s32 i;
+ for (i = 0; i < (s32) ARRAY_COUNT(sAlteringCaveWildMonHeldItems); i++)
+ if (sAlteringCaveWildMonHeldItems[i].species == species)
+ return i;
+ return 0;
+}
+
+void SetWildMonHeldItem(void)
+{
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
+ {
+ u16 rnd = Random() % 100;
+ u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
+ u16 var1 = 45;
+ u16 var2 = 95;
+ if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0)
+ && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES)
+ {
+ var1 = 20;
+ var2 = 80;
+ }
+ if (gMapHeader.mapDataId == 0x1A4)
+ {
+ s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
+ if (alteringCaveId != 0)
+ {
+ if (rnd < var2)
+ return;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &sAlteringCaveWildMonHeldItems[alteringCaveId].item);
+ }
+ else
+ {
+ if (rnd < var1)
+ return;
+ if (rnd < var2)
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ else
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
+ }
+ }
+ else
+ {
+ if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0)
+ {
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ }
+ else
+ {
+ if (rnd < var1)
+ return;
+ if (rnd < var2)
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ else
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
+ }
+ }
+ }
+}
+
+bool8 IsMonShiny(struct Pokemon *mon)
+{
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return IsShinyOtIdPersonality(otId, personality);
+}
+
+bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
+{
+ bool8 retVal = FALSE;
+ u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ retVal = TRUE;
+ return retVal;
+}
+
+const u8 *GetTrainerPartnerName(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ if (gPartnerTrainerId == STEVEN_PARTNER_ID)
+ {
+ return gTrainers[TRAINER_STEVEN].trainerName;
+ }
+ else
+ {
+ GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
+ return gStringVar1;
+ }
+ }
+ else
+ {
+ u8 id = GetMultiplayerId();
+ return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name;
+ }
+}
+
+#define READ_PTR_FROM_TASK(taskId, dataId) \
+ (void*)( \
+ ((u16)(gTasks[taskId].data[dataId]) | \
+ ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10)))
+
+#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \
+{ \
+ gTasks[taskId].data[dataId] = (u32)(ptr); \
+ gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \
+}
+
+static void Task_AnimateAfterDelay(u8 taskId)
+{
+ if (--gTasks[taskId].data[3] == 0)
+ {
+ LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
+{
+ if (--gTasks[taskId].data[3] == 0)
+ {
+ StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
+ sub_81C488C(0xFF);
+ DestroyTask(taskId);
+ }
+}
+
+void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
+{
+ if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
+ DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80);
+ else
+ DoMonFrontSpriteAnimation(sprite, species, noCry, arg3);
+}
+
+void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
+{
+ s8 pan;
+ switch (arg3 & 0x7F)
+ {
+ case 0:
+ pan = -25;
+ break;
+ case 1:
+ pan = 25;
+ break;
+ default:
+ pan = 0;
+ break;
+ }
+ if (arg3 & 0x80)
+ {
+ if (!noCry)
+ PlayCry1(species, pan);
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ if (!noCry)
+ {
+ PlayCry1(species, pan);
+ if (HasTwoFramesAnimation(species))
+ StartSpriteAnim(sprite, 1);
+ }
+ if (sMonAnimationDelayTable[species - 1] != 0)
+ {
+ u8 taskId = CreateTask(Task_AnimateAfterDelay, 0);
+ STORE_PTR_IN_TASK(sprite, taskId, 0);
+ gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1];
+ gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1];
+ }
+ else
+ {
+ LaunchAnimationTaskForFrontSprite(sprite, sMonFrontAnimIdsTable[species - 1]);
+ }
+ sprite->callback = SpriteCallbackDummy_2;
+ }
+}
+
+void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame)
+{
+ if (!oneFrame && HasTwoFramesAnimation(species))
+ StartSpriteAnim(sprite, 1);
+ if (sMonAnimationDelayTable[species - 1] != 0)
+ {
+ u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0);
+ STORE_PTR_IN_TASK(sprite, taskId, 0);
+ gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1];
+ gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1];
+ sub_81C488C(taskId);
+ SetSpriteCB_MonAnimDummy(sprite);
+ }
+ else
+ {
+ StartMonSummaryAnimation(sprite, sMonFrontAnimIdsTable[species - 1]);
+ }
+}
+
+void sub_806EE98(void)
+{
+ u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay);
+ if (delayTaskId != 0xFF)
+ DestroyTask(delayTaskId);
+}
+
+void BattleAnimateBackSprite(struct Sprite* sprite, u16 species)
+{
+ if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
+ {
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species));
+ sprite->callback = SpriteCallbackDummy_2;
+ }
+}
+
+u8 sub_806EF08(u8 arg0)
+{
+ s32 i;
+ s32 var = 0;
+ u8 multiplayerId = GetMultiplayerId();
+ switch (gLinkPlayers[multiplayerId].lp_field_18)
+ {
+ case 0:
+ case 2:
+ var = (arg0 != 0) ? 1 : 3;
+ break;
+ case 1:
+ case 3:
+ var = (arg0 != 0) ? 2 : 0;
+ break;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (gLinkPlayers[i].lp_field_18 == (s16)(var))
+ break;
+ }
+ return i;
+}
+
+u8 sub_806EF84(u8 arg0, u8 arg1)
+{
+ s32 i;
+ s32 var = 0;
+ switch (gLinkPlayers[arg1].lp_field_18)
+ {
+ case 0:
+ case 2:
+ var = (arg0 != 0) ? 1 : 3;
+ break;
+ case 1:
+ case 3:
+ var = (arg0 != 0) ? 2 : 0;
+ break;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (gLinkPlayers[i].lp_field_18 == (s16)(var))
+ break;
+ }
+ return i;
+}
+
+u16 FacilityClassToPicIndex(u16 facilityClass)
+{
+ return gFacilityClassToPicIndex[facilityClass];
+}
+
+u16 PlayerGenderToFrontTrainerPicId(u8 playerGender)
+{
+ if (playerGender != MALE)
+ return FacilityClassToPicIndex(FACILITY_CLASS_PKMN_TRAINER_BRENDAN);
+ else
+ return FacilityClassToPicIndex(FACILITY_CLASS_PKMN_TRAINER_MAY);
+}
+
+void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
+{
+ u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT;
+ if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set
+ {
+ GetSetPokedexFlag(nationalNum, caseId);
+ if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN)
+ gSaveBlock2Ptr->pokedex.unownPersonality = personality;
+ if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA)
+ gSaveBlock2Ptr->pokedex.spindaPersonality = personality;
+ }
+}
+
+const u8 *GetTrainerClassNameFromId(u16 trainerId)
+{
+ if (trainerId > NO_OF_TRAINERS)
+ trainerId = 0;
+ return gTrainerClassNames[gTrainers[trainerId].trainerClass];
+}
+
+const u8 *GetTrainerNameFromId(u16 trainerId)
+{
+ if (trainerId > NO_OF_TRAINERS)
+ trainerId = 0;
+ return gTrainers[trainerId].trainerName;
+}
+
+bool8 HasTwoFramesAnimation(u16 species)
+{
+ return (species != SPECIES_CASTFORM
+ && species != SPECIES_DEOXYS
+ && species != SPECIES_SPINDA
+ && species != SPECIES_UNOWN);
+}
+
+bool8 sub_806F104(void)
+{
+ if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER))
+ return TRUE;
+ if (!gMain.inBattle && (InBattlePike() || InBattlePyramid()))
+ return TRUE;
+ return FALSE;
+}
+
+#define FORCE_SIGNED(x)(-(x * (-1)))
+
+static void sub_806F160(struct Unknown_806F160_Struct* structPtr)
+{
+ u16 i, j;
+ for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++)
+ {
+ structPtr->templates[i] = gUnknown_08329D98[i];
+ for (j = 0; j < structPtr->field_1; j++)
+ {
+ asm("");
+ structPtr->frameImages[i * structPtr->field_1 + j].data = &structPtr->byteArrays[i][j * 0x800];
+ }
+ structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_1];
+ }
+}
+
+static void sub_806F1FC(struct Unknown_806F160_Struct* structPtr)
+{
+ u16 i, j;
+ for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++)
+ {
+ structPtr->templates[i] = gUnknown_08329F28;
+ for (j = 0; j < structPtr->field_1; j++)
+ {
+ structPtr->frameImages[i * structPtr->field_0_0 + j].data = &structPtr->byteArrays[i][j * 0x800];
+ }
+ structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_0_0];
+ structPtr->templates[i].anims = gUnknown_082FF70C;
+ structPtr->templates[i].paletteTag = i;
+ }
+}
+
+struct Unknown_806F160_Struct *sub_806F2AC(u8 id, u8 arg1)
+{
+ u8 i;
+ u8 flags;
+ struct Unknown_806F160_Struct *structPtr;
+
+ flags = 0;
+ id %= 2;
+ structPtr = AllocZeroed(sizeof(*structPtr));
+ if (structPtr == NULL)
+ return NULL;
+
+ switch (arg1)
+ {
+ case 2:
+ structPtr->field_0_0 = 7;
+ structPtr->field_0_1 = 7;
+ structPtr->field_1 = 4;
+ structPtr->field_3_0 = 1;
+ structPtr->field_3_1 = 2;
+ break;
+ case 0:
+ default:
+ structPtr->field_0_0 = 4;
+ structPtr->field_0_1 = 4;
+ structPtr->field_1 = 4;
+ structPtr->field_3_0 = 1;
+ structPtr->field_3_1 = 0;
+ break;
+ }
+
+ structPtr->bytes = AllocZeroed(structPtr->field_3_0 * 0x800 * 4 * structPtr->field_0_0);
+ structPtr->byteArrays = AllocZeroed(structPtr->field_0_0 * 32);
+ if (structPtr->bytes == NULL || structPtr->byteArrays == NULL)
+ {
+ flags |= 1;
+ }
+ else
+ {
+ for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++)
+ structPtr->byteArrays[i] = structPtr->bytes + (structPtr->field_3_0 * (i << 0xD));
+ }
+
+ structPtr->templates = AllocZeroed(sizeof(struct SpriteTemplate) * structPtr->field_0_0);
+ structPtr->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * structPtr->field_0_0 * structPtr->field_1);
+ if (structPtr->templates == NULL || structPtr->frameImages == NULL)
+ {
+ flags |= 2;
+ }
+ else
+ {
+ for (i = 0; i < structPtr->field_1 * structPtr->field_0_0; i++)
+ structPtr->frameImages[i].size = 0x800;
+
+ switch (structPtr->field_3_1)
+ {
+ case 2:
+ sub_806F1FC(structPtr);
+ break;
+ case 0:
+ case 1:
+ default:
+ sub_806F160(structPtr);
+ break;
+ }
+ }
+
+ if (flags & 2)
+ {
+ if (structPtr->frameImages != NULL)
+ FREE_AND_SET_NULL(structPtr->frameImages);
+ if (structPtr->templates != NULL)
+ FREE_AND_SET_NULL(structPtr->templates);
+ }
+ if (flags & 1)
+ {
+ if (structPtr->byteArrays != NULL)
+ FREE_AND_SET_NULL(structPtr->byteArrays);
+ if (structPtr->bytes != NULL)
+ FREE_AND_SET_NULL(structPtr->bytes);
+ }
+
+ if (flags)
+ {
+ memset(structPtr, 0, sizeof(*structPtr));
+ Free(structPtr);
+ }
+ else
+ {
+ structPtr->magic = 0xA3;
+ gUnknown_020249B4[id] = structPtr;
+ }
+
+ return gUnknown_020249B4[id];
+}
+
+void sub_806F47C(u8 id)
+{
+ struct Unknown_806F160_Struct *structPtr;
+
+ id %= 2;
+ structPtr = gUnknown_020249B4[id];
+ if (structPtr == NULL)
+ return;
+
+ if (structPtr->magic != 0xA3)
+ {
+ memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct));
+ }
+ else
+ {
+
+ if (structPtr->frameImages != NULL)
+ FREE_AND_SET_NULL(structPtr->frameImages);
+ if (structPtr->templates != NULL)
+ FREE_AND_SET_NULL(structPtr->templates);
+ if (structPtr->byteArrays != NULL)
+ FREE_AND_SET_NULL(structPtr->byteArrays);
+ if (structPtr->bytes != NULL)
+ FREE_AND_SET_NULL(structPtr->bytes);
+
+ memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct));
+ Free(structPtr);
+ }
+}
+
+u8 *sub_806F4F8(u8 id, u8 arg1)
+{
+ struct Unknown_806F160_Struct *structPtr = gUnknown_020249B4[id % 2];
+ if (structPtr->magic != 0xA3)
+ {
+ return NULL;
+ }
+ else
+ {
+ if (arg1 >= FORCE_SIGNED(structPtr->field_0_0))
+ arg1 = 0;
+
+ return structPtr->byteArrays[arg1];
+ }
+}
diff --git a/src/pokemon_1.c b/src/pokemon_1.c
deleted file mode 100644
index cafd86c07..000000000
--- a/src/pokemon_1.c
+++ /dev/null
@@ -1,457 +0,0 @@
-#include "global.h"
-#include "pokemon.h"
-#include "random.h"
-#include "main.h"
-#include "constants/species.h"
-#include "constants/abilities.h"
-#include "constants/items.h"
-#include "constants/trainers.h"
-#include "constants/moves.h"
-#include "string_util.h"
-#include "text.h"
-
-//Extracts the upper 16 bits of a 32-bit number
-#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
-
-//Extracts the lower 16 bits of a 32-bit number
-#define LOHALF(n) ((n) & 0xFFFF)
-
-extern u8 sav1_map_get_name(void);
-
-// EWRAM vars
-EWRAM_DATA u8 sLearningMoveTableID = 0;
-EWRAM_DATA u8 gPlayerPartyCount = 0;
-EWRAM_DATA u8 gEnemyPartyCount = 0;
-EWRAM_DATA struct Pokemon gPlayerParty[PARTY_SIZE] = {0};
-EWRAM_DATA struct Pokemon gEnemyParty[PARTY_SIZE] = {0};
-
-// const rom data
-const u16 gSpeciesToHoennPokedexNum[] = {203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 156, 157, 112, 113, 227, 228, 229, 230, 231, 232, 233, 234, 153, 154, 138, 139, 63, 64, 88, 89, 90, 235, 236, 237, 238, 239, 240, 241, 242, 158, 159, 243, 244, 245, 246, 247, 248, 249, 39, 40, 41, 73, 74, 75, 250, 251, 252, 66, 67, 57, 58, 59, 253, 254, 255, 256, 82, 83, 257, 92, 93, 258, 259, 106, 107, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 84, 85, 270, 271, 272, 273, 274, 275, 276, 108, 109, 169, 170, 277, 278, 279, 184, 185, 50, 51, 143, 144, 280, 281, 282, 283, 284, 167, 285, 52, 53, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 65, 181, 182, 155, 324, 137, 325, 326, 162, 163, 327, 328, 329, 91, 55, 56, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 161, 164, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 168, 357, 358, 359, 103, 104, 360, 361, 180, 362, 363, 364, 365, 115, 366, 367, 186, 165, 166, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43, 44, 25, 26, 34, 35, 114, 27, 28, 32, 33, 99, 100, 61, 62, 145, 131, 132, 60, 105, 68, 127, 128, 183, 129, 130, 140, 141, 97, 98, 116, 117, 118, 48, 49, 78, 79, 101, 102, 173, 174, 175, 119, 120, 171, 172, 125, 126, 54, 110, 111, 80, 81, 69, 76, 77, 121, 122, 160, 148, 149, 94, 36, 37, 38, 95, 96, 150, 45, 46, 47, 176, 177, 178, 152, 146, 147, 124, 123, 179, 70, 71, 72, 142, 86, 87, 133, 134, 135, 136, 29, 30, 31, 187, 188, 189, 190, 191, 192, 193, 194, 195, 198, 199, 200, 196, 197, 201, 202, 151};
-const u16 gSpeciesToNationalPokedexNum[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 290, 291, 292, 276, 277, 285, 286, 327, 278, 279, 283, 284, 320, 321, 300, 301, 352, 343, 344, 299, 324, 302, 339, 340, 370, 341, 342, 349, 350, 318, 319, 328, 329, 330, 296, 297, 309, 310, 322, 323, 363, 364, 365, 331, 332, 361, 362, 337, 338, 298, 325, 326, 311, 312, 303, 307, 308, 333, 334, 360, 355, 356, 315, 287, 288, 289, 316, 317, 357, 293, 294, 295, 366, 367, 368, 359, 353, 354, 336, 335, 369, 304, 305, 306, 351, 313, 314, 345, 346, 347, 348, 280, 281, 282, 371, 372, 373, 374, 375, 376, 377, 378, 379, 382, 383, 384, 380, 381, 385, 386, 358};
-const u16 gHoennToNationalOrder[] = {252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 63, 64, 65, 290, 291, 292, 293, 294, 295, 296, 297, 118, 119, 129, 130, 298, 183, 184, 74, 75, 76, 299, 300, 301, 41, 42, 169, 72, 73, 302, 303, 304, 305, 306, 66, 67, 68, 307, 308, 309, 310, 311, 312, 81, 82, 100, 101, 313, 314, 43, 44, 45, 182, 84, 85, 315, 316, 317, 318, 319, 320, 321, 322, 323, 218, 219, 324, 88, 89, 109, 110, 325, 326, 27, 28, 327, 227, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 174, 39, 40, 349, 350, 351, 120, 121, 352, 353, 354, 355, 356, 357, 358, 359, 37, 38, 172, 25, 26, 54, 55, 360, 202, 177, 178, 203, 231, 232, 127, 214, 111, 112, 361, 362, 363, 364, 365, 366, 367, 368, 369, 222, 170, 171, 370, 116, 117, 230, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 36, 46, 47, 48, 49, 50, 51, 52, 53, 56, 57, 58, 59, 60, 61, 62, 69, 70, 71, 77, 78, 79, 80, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 102, 103, 104, 105, 106, 107, 108, 113, 114, 115, 122, 123, 124, 125, 126, 128, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 173, 175, 176, 179, 180, 181, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 220, 221, 223, 224, 225, 226, 228, 229, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411};
-
-const struct SpindaSpot gSpindaSpotGraphics[] =
-{
- {16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
- {40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
- {22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
- {34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
-};
-
-#include "data/pokemon/item_effects.h"
-
-const s8 gNatureStatTable[][5] =
-{
- // Atk Def Spd Sp.Atk Sp.Def
- { 0, 0, 0, 0, 0}, // Hardy
- { +1, -1, 0, 0, 0}, // Lonely
- { +1, 0, -1, 0, 0}, // Brave
- { +1, 0, 0, -1, 0}, // Adamant
- { +1, 0, 0, 0, -1}, // Naughty
- { -1, +1, 0, 0, 0}, // Bold
- { 0, 0, 0, 0, 0}, // Docile
- { 0, +1, -1, 0, 0}, // Relaxed
- { 0, +1, 0, -1, 0}, // Impish
- { 0, +1, 0, 0, -1}, // Lax
- { -1, 0, +1, 0, 0}, // Timid
- { 0, -1, +1, 0, 0}, // Hasty
- { 0, 0, 0, 0, 0}, // Serious
- { 0, 0, +1, -1, 0}, // Jolly
- { 0, 0, +1, 0, -1}, // Naive
- { -1, 0, 0, +1, 0}, // Modest
- { 0, -1, 0, +1, 0}, // Mild
- { 0, 0, -1, +1, 0}, // Quiet
- { 0, 0, 0, 0, 0}, // Bashful
- { 0, 0, 0, +1, -1}, // Rash
- { -1, 0, 0, 0, +1}, // Calm
- { 0, -1, 0, 0, +1}, // Gentle
- { 0, 0, -1, 0, +1}, // Sassy
- { 0, 0, 0, -1, +1}, // Careful
- { 0, 0, 0, 0, 0}, // Quirky
-};
-
-#include "data/pokemon/tmhm_learnsets.h"
-#include "data/pokemon/trainer_class_lookups.h"
-#include "data/pokemon/cry_ids.h"
-#include "data/pokemon/experience_tables.h"
-#include "data/pokemon/base_stats.h"
-#include "data/pokemon/level_up_learnsets.h"
-#include "data/pokemon/evolution.h"
-#include "data/pokemon/level_up_learnset_pointers.h"
-
-// code
-void ZeroBoxMonData(struct BoxPokemon *boxMon)
-{
- u8 *raw = (u8 *)boxMon;
- u32 i;
- for (i = 0; i < sizeof(struct BoxPokemon); i++)
- raw[i] = 0;
-}
-
-void ZeroMonData(struct Pokemon *mon)
-{
- u32 arg;
- ZeroBoxMonData(&mon->box);
- arg = 0;
- SetMonData(mon, MON_DATA_STATUS, &arg);
- SetMonData(mon, MON_DATA_LEVEL, &arg);
- SetMonData(mon, MON_DATA_HP, &arg);
- SetMonData(mon, MON_DATA_MAX_HP, &arg);
- SetMonData(mon, MON_DATA_ATK, &arg);
- SetMonData(mon, MON_DATA_DEF, &arg);
- SetMonData(mon, MON_DATA_SPEED, &arg);
- SetMonData(mon, MON_DATA_SPATK, &arg);
- SetMonData(mon, MON_DATA_SPDEF, &arg);
- arg = 255;
- SetMonData(mon, MON_DATA_MAIL, &arg);
-}
-
-void ZeroPlayerPartyMons(void)
-{
- s32 i;
- for (i = 0; i < PARTY_SIZE; i++)
- ZeroMonData(&gPlayerParty[i]);
-}
-
-void ZeroEnemyPartyMons(void)
-{
- s32 i;
- for (i = 0; i < PARTY_SIZE; i++)
- ZeroMonData(&gEnemyParty[i]);
-}
-
-void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
-{
- u32 arg;
- ZeroMonData(mon);
- CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId);
- SetMonData(mon, MON_DATA_LEVEL, &level);
- arg = 255;
- SetMonData(mon, MON_DATA_MAIL, &arg);
- CalculateMonStats(mon);
-}
-
-void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
-{
- u8 speciesName[POKEMON_NAME_LENGTH + 1];
- u32 personality;
- u32 value;
- u16 checksum;
-
- ZeroBoxMonData(boxMon);
-
- if (hasFixedPersonality)
- personality = fixedPersonality;
- else
- personality = Random32();
-
- SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality);
-
- //Determine original trainer ID
- if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny
- {
- u32 shinyValue;
- do
- {
- value = Random32();
- shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
- } while (shinyValue < 8);
- }
- else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID
- {
- value = fixedOtId;
- }
- else //Player is the OT
- {
- value = gSaveBlock2Ptr->playerTrainerId[0]
- | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
- | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
- | (gSaveBlock2Ptr->playerTrainerId[3] << 24);
- }
-
- SetBoxMonData(boxMon, MON_DATA_OT_ID, &value);
-
- checksum = CalculateBoxMonChecksum(boxMon);
- SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum);
- EncryptBoxMon(boxMon);
- GetSpeciesName(speciesName, species);
- SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName);
- SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage);
- SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName);
- SetBoxMonData(boxMon, MON_DATA_SPECIES, &species);
- SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]);
- SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship);
- value = sav1_map_get_name();
- SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value);
- SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
- SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
- value = ITEM_POKE_BALL;
- SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value);
- SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
-
- if (fixedIV < 32)
- {
- SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV);
- SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV);
- SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV);
- SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &fixedIV);
- SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV);
- SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV);
- }
- else
- {
- u32 iv;
- value = Random();
-
- iv = value & 0x1F;
- SetBoxMonData(boxMon, MON_DATA_HP_IV, &iv);
- iv = (value & 0x3E0) >> 5;
- SetBoxMonData(boxMon, MON_DATA_ATK_IV, &iv);
- iv = (value & 0x7C00) >> 10;
- SetBoxMonData(boxMon, MON_DATA_DEF_IV, &iv);
-
- value = Random();
-
- iv = value & 0x1F;
- SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &iv);
- iv = (value & 0x3E0) >> 5;
- SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv);
- iv = (value & 0x7C00) >> 10;
- SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv);
- }
-
- if (gBaseStats[species].ability2)
- {
- value = personality & 1;
- SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value);
- }
-
- GiveBoxMonInitialMoveset(boxMon);
-}
-
-void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature)
-{
- u32 personality;
-
- do
- {
- personality = Random32();
- }
- while (nature != GetNatureFromPersonality(personality));
-
- CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
-}
-
-void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter)
-{
- u32 personality;
-
- if ((u8)(unownLetter - 1) < 28)
- {
- u16 actualLetter;
-
- do
- {
- personality = Random32();
- actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28);
- }
- while (nature != GetNatureFromPersonality(personality)
- || gender != GetGenderFromSpeciesAndPersonality(species, personality)
- || actualLetter != unownLetter - 1);
- }
- else
- {
- do
- {
- personality = Random32();
- }
- while (nature != GetNatureFromPersonality(personality)
- || gender != GetGenderFromSpeciesAndPersonality(species, personality));
- }
-
- CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
-}
-
-// This is only used to create Wally's Ralts.
-void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level)
-{
- u32 personality;
- u32 otId;
-
- do
- {
- otId = Random32();
- personality = Random32();
- }
- while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE);
- CreateMon(mon, species, level, 32, 1, personality, OT_ID_PRESET, otId);
-}
-
-void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality)
-{
- CreateMon(mon, species, level, 0, 1, personality, OT_ID_PLAYER_ID, 0);
- SetMonData(mon, MON_DATA_IVS, &ivs);
- CalculateMonStats(mon);
-}
-
-void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId)
-{
- CreateMon(mon, species, level, 0, 0, 0, OT_ID_PRESET, otId);
- SetMonData(mon, MON_DATA_HP_IV, &ivs[0]);
- SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]);
- SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]);
- SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]);
- SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]);
- SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]);
- CalculateMonStats(mon);
-}
-
-void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread)
-{
- s32 i;
- s32 statCount = 0;
- u16 evAmount;
- u8 temp;
-
- CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0);
-
- temp = evSpread;
-
- for (i = 0; i < 6; i++)
- {
- if (temp & 1)
- statCount++;
- temp >>= 1;
- }
-
- evAmount = 510 / statCount;
-
- temp = 1;
-
- for (i = 0; i < 6; i++)
- {
- if (evSpread & temp)
- SetMonData(mon, MON_DATA_HP_EV + i, &evAmount);
- temp <<= 1;
- }
-
- CalculateMonStats(mon);
-}
-
-void sub_806819C(struct Pokemon *mon, struct UnknownPokemonStruct *src)
-{
- s32 i;
- u8 nickname[30];
- u8 language;
- u8 value;
-
- CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId);
-
- for (i = 0; i < 4; i++)
- SetMonMoveSlot(mon, src->moves[i], i);
-
- SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
- SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
- SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
-
- StringCopy(nickname, src->nickname);
-
- if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
- {
- language = LANGUAGE_JAPANESE;
- StripExtCtrlCodes(nickname);
- }
- else
- {
- language = GAME_LANGUAGE;
- }
-
- SetMonData(mon, MON_DATA_LANGUAGE, &language);
- SetMonData(mon, MON_DATA_NICKNAME, nickname);
- SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
- SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
- SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
- SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
- SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
- SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
- value = src->altAbility;
- SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
- value = src->hpIV;
- SetMonData(mon, MON_DATA_HP_IV, &value);
- value = src->attackIV;
- SetMonData(mon, MON_DATA_ATK_IV, &value);
- value = src->defenseIV;
- SetMonData(mon, MON_DATA_DEF_IV, &value);
- value = src->speedIV;
- SetMonData(mon, MON_DATA_SPEED_IV, &value);
- value = src->spAttackIV;
- SetMonData(mon, MON_DATA_SPATK_IV, &value);
- value = src->spDefenseIV;
- SetMonData(mon, MON_DATA_SPDEF_IV, &value);
- MonRestorePP(mon);
- CalculateMonStats(mon);
-}
-
-u8 BattleFrontierGetOpponentLvl(u8);
-
-void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lvl50)
-{
- s32 i;
- u8 nickname[30];
- u8 level;
- u8 language;
- u8 value;
-
- if (gSaveBlock2Ptr->frontierChosenLvl != 0)
- level = BattleFrontierGetOpponentLvl(gSaveBlock2Ptr->frontierChosenLvl);
- else if (lvl50)
- level = 50;
- else
- level = src->level;
-
- CreateMon(mon, src->species, level, 0, 1, src->personality, 1, src->otId);
-
- for (i = 0; i < 4; i++)
- SetMonMoveSlot(mon, src->moves[i], i);
-
- SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
- SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
- SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
-
- StringCopy(nickname, src->nickname);
-
- if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
- {
- language = LANGUAGE_JAPANESE;
- StripExtCtrlCodes(nickname);
- }
- else
- {
- language = GAME_LANGUAGE;
- }
-
- SetMonData(mon, MON_DATA_LANGUAGE, &language);
- SetMonData(mon, MON_DATA_NICKNAME, nickname);
- SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
- SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
- SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
- SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
- SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
- SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
- value = src->altAbility;
- SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
- value = src->hpIV;
- SetMonData(mon, MON_DATA_HP_IV, &value);
- value = src->attackIV;
- SetMonData(mon, MON_DATA_ATK_IV, &value);
- value = src->defenseIV;
- SetMonData(mon, MON_DATA_DEF_IV, &value);
- value = src->speedIV;
- SetMonData(mon, MON_DATA_SPEED_IV, &value);
- value = src->spAttackIV;
- SetMonData(mon, MON_DATA_SPATK_IV, &value);
- value = src->spDefenseIV;
- SetMonData(mon, MON_DATA_SPDEF_IV, &value);
- MonRestorePP(mon);
- CalculateMonStats(mon);
-}
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
deleted file mode 100644
index 3f37381c3..000000000
--- a/src/pokemon_2.c
+++ /dev/null
@@ -1,1365 +0,0 @@
-#include "global.h"
-#include "pokemon.h"
-#include "battle.h"
-#include "event_data.h"
-#include "random.h"
-#include "sprite.h"
-#include "constants/species.h"
-#include "text.h"
-#include "string_util.h"
-
-struct Unknown_020249B4
-{
- u8 unk0[0xC];
- struct SpriteTemplate* templates;
-};
-
-extern u8 gAbsentBattlerFlags;
-extern u8 gActiveBattler;
-extern u8 gBattlerAttacker;
-extern u8 gBattlerTarget;
-extern u8 gLastUsedAbility;
-extern u16 gTrainerBattleOpponent_A;
-extern u32 gBattleTypeFlags;
-extern struct SpriteTemplate gUnknown_0202499C;
-extern struct Unknown_020249B4* gUnknown_020249B4[2];
-
-extern const u32 gBitTable[];
-extern const struct SpriteTemplate gUnknown_08329D98[];
-extern const struct SpriteTemplate gUnknown_08329DF8[];
-extern const union AnimCmd* gUnknown_082FF70C[];
-extern const union AnimCmd* const * const gMonAnimationsSpriteAnimsPtrTable[];
-extern const union AnimCmd* const * const gUnknown_08305D0C[];
-extern const union AnimCmd* const * const gUnknown_0830536C[];
-extern const u8 gText_BadEgg[];
-extern const u8 gText_EggNickname[];
-
-extern u8 GetBattlerSide(u8 bank);
-extern u8 GetBattlerAtPosition(u8 bank);
-extern u8 GetBattlerPosition(u8 bank);
-
-u8 CountAliveMonsInBattle(u8 caseId)
-{
- s32 i;
- u8 retVal = 0;
-
- switch (caseId)
- {
- case BATTLE_ALIVE_EXCEPT_ACTIVE:
- for (i = 0; i < 4; i++)
- {
- if (i != gActiveBattler && !(gAbsentBattlerFlags & gBitTable[i]))
- retVal++;
- }
- break;
- case BATTLE_ALIVE_ATK_SIDE:
- for (i = 0; i < 4; i++)
- {
- if (GetBattlerSide(i) == GetBattlerSide(gBattlerAttacker) && !(gAbsentBattlerFlags & gBitTable[i]))
- retVal++;
- }
- break;
- case BATTLE_ALIVE_DEF_SIDE:
- for (i = 0; i < 4; i++)
- {
- if (GetBattlerSide(i) == GetBattlerSide(gBattlerTarget) && !(gAbsentBattlerFlags & gBitTable[i]))
- retVal++;
- }
- break;
- }
-
- return retVal;
-}
-
-bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 bank)
-{
- if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER))
- return FALSE;
- if (GetBattlerSide(bank) != B_SIDE_PLAYER)
- return FALSE;
- if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
- return FALSE;
- if (FlagGet(badgeFlag))
- return TRUE;
- return FALSE;
-}
-
-u8 GetDefaultMoveTarget(u8 bank)
-{
- u8 status = GetBattlerPosition(bank) & 1;
-
- status ^= 1;
- if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
- return GetBattlerAtPosition(status);
- if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1)
- {
- u8 val;
-
- if ((Random() & 1) == 0)
- val = status ^ 2;
- else
- val = status;
- return GetBattlerAtPosition(val);
- }
- else
- {
- if ((gAbsentBattlerFlags & gBitTable[status]))
- return GetBattlerAtPosition(status ^ 2);
- else
- return GetBattlerAtPosition(status);
- }
-}
-
-u8 GetMonGender(struct Pokemon *mon)
-{
- return GetBoxMonGender(&mon->box);
-}
-
-u8 GetBoxMonGender(struct BoxPokemon *boxMon)
-{
- u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
- u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL);
-
- switch (gBaseStats[species].genderRatio)
- {
- case MON_MALE:
- case MON_FEMALE:
- case MON_GENDERLESS:
- return gBaseStats[species].genderRatio;
- }
-
- if (gBaseStats[species].genderRatio > (personality & 0xFF))
- return MON_FEMALE;
- else
- return MON_MALE;
-}
-
-u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
-{
- switch (gBaseStats[species].genderRatio)
- {
- case MON_MALE:
- case MON_FEMALE:
- case MON_GENDERLESS:
- return gBaseStats[species].genderRatio;
- }
-
- if (gBaseStats[species].genderRatio > (personality & 0xFF))
- return MON_FEMALE;
- else
- return MON_MALE;
-}
-
-void sub_806A068(u16 species, u8 bankIdentity)
-{
- if (gMonSpritesGfxPtr != NULL)
- gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
- else if (gUnknown_020249B4[0])
- gUnknown_0202499C = gUnknown_020249B4[0]->templates[bankIdentity];
- else if (gUnknown_020249B4[1])
- gUnknown_0202499C = gUnknown_020249B4[1]->templates[bankIdentity];
- else
- gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
-
- gUnknown_0202499C.paletteTag = species;
- if (bankIdentity == 0 || bankIdentity == 2)
- gUnknown_0202499C.anims = gUnknown_082FF70C;
- else if (species > 500)
- gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species - 500];
- else
- gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species];
-}
-
-void sub_806A12C(u16 trainerSpriteId, u8 bankIdentity)
-{
- gUnknown_0202499C.paletteTag = trainerSpriteId;
- if (bankIdentity == 0 || bankIdentity == 2)
- {
- gUnknown_0202499C = gUnknown_08329DF8[trainerSpriteId];
- gUnknown_0202499C.anims = gUnknown_08305D0C[trainerSpriteId];
- }
- else
- {
- if (gMonSpritesGfxPtr != NULL)
- gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
- else
- gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
- gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId];
- }
-}
-
-void sub_806A1C0(u16 arg0, u8 bankIdentity)
-{
- if (gMonSpritesGfxPtr != NULL)
- gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity];
- else
- gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
-
- gUnknown_0202499C.paletteTag = arg0;
- gUnknown_0202499C.anims = gUnknown_0830536C[arg0];
-}
-
-void EncryptBoxMon(struct BoxPokemon *boxMon)
-{
- u32 i;
- for (i = 0; i < 12; i++)
- {
- boxMon->secure.raw[i] ^= boxMon->personality;
- boxMon->secure.raw[i] ^= boxMon->otId;
- }
-}
-
-void DecryptBoxMon(struct BoxPokemon *boxMon)
-{
- u32 i;
- for (i = 0; i < 12; i++)
- {
- boxMon->secure.raw[i] ^= boxMon->otId;
- boxMon->secure.raw[i] ^= boxMon->personality;
- }
-}
-
-#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
-case n: \
- { \
- union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \
- union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \
- \
- switch (substructType) \
- { \
- case 0: \
- substruct = &substructs ## n [v1]; \
- break; \
- case 1: \
- substruct = &substructs ## n [v2]; \
- break; \
- case 2: \
- substruct = &substructs ## n [v3]; \
- break; \
- case 3: \
- substruct = &substructs ## n [v4]; \
- break; \
- } \
- break; \
- } \
-
-
-union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType)
-{
- union PokemonSubstruct *substruct = NULL;
-
- switch (personality % 24)
- {
- SUBSTRUCT_CASE( 0,0,1,2,3)
- SUBSTRUCT_CASE( 1,0,1,3,2)
- SUBSTRUCT_CASE( 2,0,2,1,3)
- SUBSTRUCT_CASE( 3,0,3,1,2)
- SUBSTRUCT_CASE( 4,0,2,3,1)
- SUBSTRUCT_CASE( 5,0,3,2,1)
- SUBSTRUCT_CASE( 6,1,0,2,3)
- SUBSTRUCT_CASE( 7,1,0,3,2)
- SUBSTRUCT_CASE( 8,2,0,1,3)
- SUBSTRUCT_CASE( 9,3,0,1,2)
- SUBSTRUCT_CASE(10,2,0,3,1)
- SUBSTRUCT_CASE(11,3,0,2,1)
- SUBSTRUCT_CASE(12,1,2,0,3)
- SUBSTRUCT_CASE(13,1,3,0,2)
- SUBSTRUCT_CASE(14,2,1,0,3)
- SUBSTRUCT_CASE(15,3,1,0,2)
- SUBSTRUCT_CASE(16,2,3,0,1)
- SUBSTRUCT_CASE(17,3,2,0,1)
- SUBSTRUCT_CASE(18,1,2,3,0)
- SUBSTRUCT_CASE(19,1,3,2,0)
- SUBSTRUCT_CASE(20,2,1,3,0)
- SUBSTRUCT_CASE(21,3,1,2,0)
- SUBSTRUCT_CASE(22,2,3,1,0)
- SUBSTRUCT_CASE(23,3,2,1,0)
- }
-
- return substruct;
-}
-
-extern u16 GetDeoxysStat(struct Pokemon *mon, s32 statId);
-
-u32 GetMonData(struct Pokemon *mon, s32 field, u8* data)
-{
- u32 ret;
-
- switch (field)
- {
- case MON_DATA_STATUS:
- ret = mon->status;
- break;
- case MON_DATA_LEVEL:
- ret = mon->level;
- break;
- case MON_DATA_HP:
- ret = mon->hp;
- break;
- case MON_DATA_MAX_HP:
- ret = mon->maxHP;
- break;
- case MON_DATA_ATK:
- ret = GetDeoxysStat(mon, STAT_ATK);
- if (!ret)
- ret = mon->attack;
- break;
- case MON_DATA_DEF:
- ret = GetDeoxysStat(mon, STAT_DEF);
- if (!ret)
- ret = mon->defense;
- break;
- case MON_DATA_SPEED:
- ret = GetDeoxysStat(mon, STAT_SPEED);
- if (!ret)
- ret = mon->speed;
- break;
- case MON_DATA_SPATK:
- ret = GetDeoxysStat(mon, STAT_SPATK);
- if (!ret)
- ret = mon->spAttack;
- break;
- case MON_DATA_SPDEF:
- ret = GetDeoxysStat(mon, STAT_SPDEF);
- if (!ret)
- ret = mon->spDefense;
- break;
- case MON_DATA_ATK2:
- ret = mon->attack;
- break;
- case MON_DATA_DEF2:
- ret = mon->defense;
- break;
- case MON_DATA_SPEED2:
- ret = mon->speed;
- break;
- case MON_DATA_SPATK2:
- ret = mon->spAttack;
- break;
- case MON_DATA_SPDEF2:
- ret = mon->spDefense;
- break;
- case MON_DATA_MAIL:
- ret = mon->mail;
- break;
- default:
- ret = GetBoxMonData(&mon->box, field, data);
- break;
- }
- return ret;
-}
-
-u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
-{
- s32 i;
- u32 retVal = 0;
- struct PokemonSubstruct0 *substruct0 = NULL;
- struct PokemonSubstruct1 *substruct1 = NULL;
- struct PokemonSubstruct2 *substruct2 = NULL;
- struct PokemonSubstruct3 *substruct3 = NULL;
-
- if (field > MON_DATA_10)
- {
- substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
- substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
- substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
- substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
-
- DecryptBoxMon(boxMon);
-
- if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
- {
- boxMon->isBadEgg = 1;
- boxMon->isEgg = 1;
- substruct3->isEgg = 1;
- }
- }
-
- switch (field)
- {
- case MON_DATA_PERSONALITY:
- retVal = boxMon->personality;
- break;
- case MON_DATA_OT_ID:
- retVal = boxMon->otId;
- break;
- case MON_DATA_NICKNAME:
- {
- if (boxMon->isBadEgg)
- {
- for (retVal = 0;
- retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS;
- data[retVal] = gText_BadEgg[retVal], retVal++) {}
-
- data[retVal] = EOS;
- }
- else if (boxMon->isEgg)
- {
- StringCopy(data, gText_EggNickname);
- retVal = StringLength(data);
- }
- else if (boxMon->language == LANGUAGE_JAPANESE)
- {
- data[0] = EXT_CTRL_CODE_BEGIN;
- data[1] = EXT_CTRL_CODE_JPN;
-
- for (retVal = 2, i = 0;
- i < 5 && boxMon->nickname[i] != EOS;
- data[retVal] = boxMon->nickname[i], retVal++, i++) {}
-
- data[retVal++] = EXT_CTRL_CODE_BEGIN;
- data[retVal++] = EXT_CTRL_CODE_ENG;
- data[retVal] = EOS;
- }
- else
- {
- for (retVal = 0;
- retVal < POKEMON_NAME_LENGTH;
- data[retVal] = boxMon->nickname[retVal], retVal++){}
-
- data[retVal] = EOS;
- }
- break;
- }
- case MON_DATA_LANGUAGE:
- retVal = boxMon->language;
- break;
- case MON_DATA_SANITY_BIT1:
- retVal = boxMon->isBadEgg;
- break;
- case MON_DATA_SANITY_BIT2:
- retVal = boxMon->hasSpecies;
- break;
- case MON_DATA_SANITY_BIT3:
- retVal = boxMon->isEgg;
- break;
- case MON_DATA_OT_NAME:
- {
- retVal = 0;
-
- while (retVal < OT_NAME_LENGTH)
- {
- data[retVal] = boxMon->otName[retVal];
- retVal++;
- }
-
- data[retVal] = EOS;
- break;
- }
- case MON_DATA_MARKINGS:
- retVal = boxMon->markings;
- break;
- case MON_DATA_CHECKSUM:
- retVal = boxMon->checksum;
- break;
- case MON_DATA_10:
- retVal = boxMon->unknown;
- break;
- case MON_DATA_SPECIES:
- retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species;
- break;
- case MON_DATA_HELD_ITEM:
- retVal = substruct0->heldItem;
- break;
- case MON_DATA_EXP:
- retVal = substruct0->experience;
- break;
- case MON_DATA_PP_BONUSES:
- retVal = substruct0->ppBonuses;
- break;
- case MON_DATA_FRIENDSHIP:
- retVal = substruct0->friendship;
- break;
- case MON_DATA_MOVE1:
- case MON_DATA_MOVE2:
- case MON_DATA_MOVE3:
- case MON_DATA_MOVE4:
- retVal = substruct1->moves[field - MON_DATA_MOVE1];
- break;
- case MON_DATA_PP1:
- case MON_DATA_PP2:
- case MON_DATA_PP3:
- case MON_DATA_PP4:
- retVal = substruct1->pp[field - MON_DATA_PP1];
- break;
- case MON_DATA_HP_EV:
- retVal = substruct2->hpEV;
- break;
- case MON_DATA_ATK_EV:
- retVal = substruct2->attackEV;
- break;
- case MON_DATA_DEF_EV:
- retVal = substruct2->defenseEV;
- break;
- case MON_DATA_SPEED_EV:
- retVal = substruct2->speedEV;
- break;
- case MON_DATA_SPATK_EV:
- retVal = substruct2->spAttackEV;
- break;
- case MON_DATA_SPDEF_EV:
- retVal = substruct2->spDefenseEV;
- break;
- case MON_DATA_COOL:
- retVal = substruct2->cool;
- break;
- case MON_DATA_BEAUTY:
- retVal = substruct2->beauty;
- break;
- case MON_DATA_CUTE:
- retVal = substruct2->cute;
- break;
- case MON_DATA_SMART:
- retVal = substruct2->smart;
- break;
- case MON_DATA_TOUGH:
- retVal = substruct2->tough;
- break;
- case MON_DATA_SHEEN:
- retVal = substruct2->sheen;
- break;
- case MON_DATA_POKERUS:
- retVal = substruct3->pokerus;
- break;
- case MON_DATA_MET_LOCATION:
- retVal = substruct3->metLocation;
- break;
- case MON_DATA_MET_LEVEL:
- retVal = substruct3->metLevel;
- break;
- case MON_DATA_MET_GAME:
- retVal = substruct3->metGame;
- break;
- case MON_DATA_POKEBALL:
- retVal = substruct3->pokeball;
- break;
- case MON_DATA_OT_GENDER:
- retVal = substruct3->otGender;
- break;
- case MON_DATA_HP_IV:
- retVal = substruct3->hpIV;
- break;
- case MON_DATA_ATK_IV:
- retVal = substruct3->attackIV;
- break;
- case MON_DATA_DEF_IV:
- retVal = substruct3->defenseIV;
- break;
- case MON_DATA_SPEED_IV:
- retVal = substruct3->speedIV;
- break;
- case MON_DATA_SPATK_IV:
- retVal = substruct3->spAttackIV;
- break;
- case MON_DATA_SPDEF_IV:
- retVal = substruct3->spDefenseIV;
- break;
- case MON_DATA_IS_EGG:
- retVal = substruct3->isEgg;
- break;
- case MON_DATA_ALT_ABILITY:
- retVal = substruct3->altAbility;
- break;
- case MON_DATA_COOL_RIBBON:
- retVal = substruct3->coolRibbon;
- break;
- case MON_DATA_BEAUTY_RIBBON:
- retVal = substruct3->beautyRibbon;
- break;
- case MON_DATA_CUTE_RIBBON:
- retVal = substruct3->cuteRibbon;
- break;
- case MON_DATA_SMART_RIBBON:
- retVal = substruct3->smartRibbon;
- break;
- case MON_DATA_TOUGH_RIBBON:
- retVal = substruct3->toughRibbon;
- break;
- case MON_DATA_CHAMPION_RIBBON:
- retVal = substruct3->championRibbon;
- break;
- case MON_DATA_WINNING_RIBBON:
- retVal = substruct3->winningRibbon;
- break;
- case MON_DATA_VICTORY_RIBBON:
- retVal = substruct3->victoryRibbon;
- break;
- case MON_DATA_ARTIST_RIBBON:
- retVal = substruct3->artistRibbon;
- break;
- case MON_DATA_EFFORT_RIBBON:
- retVal = substruct3->effortRibbon;
- break;
- case MON_DATA_GIFT_RIBBON_1:
- retVal = substruct3->giftRibbon1;
- break;
- case MON_DATA_GIFT_RIBBON_2:
- retVal = substruct3->giftRibbon2;
- break;
- case MON_DATA_GIFT_RIBBON_3:
- retVal = substruct3->giftRibbon3;
- break;
- case MON_DATA_GIFT_RIBBON_4:
- retVal = substruct3->giftRibbon4;
- break;
- case MON_DATA_GIFT_RIBBON_5:
- retVal = substruct3->giftRibbon5;
- break;
- case MON_DATA_GIFT_RIBBON_6:
- retVal = substruct3->giftRibbon6;
- break;
- case MON_DATA_GIFT_RIBBON_7:
- retVal = substruct3->giftRibbon7;
- break;
- case MON_DATA_FATEFUL_ENCOUNTER:
- retVal = substruct3->fatefulEncounter;
- break;
- case MON_DATA_OBEDIENCE:
- retVal = substruct3->obedient;
- break;
- case MON_DATA_SPECIES2:
- retVal = substruct0->species;
- if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg))
- retVal = SPECIES_EGG;
- break;
- case MON_DATA_IVS:
- retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25);
- break;
- case MON_DATA_KNOWN_MOVES:
- if (substruct0->species && !substruct3->isEgg)
- {
- u16 *moves = (u16 *)data;
- s32 i = 0;
-
- while (moves[i] != 355)
- {
- u16 move = moves[i];
- if (substruct1->moves[0] == move
- || substruct1->moves[1] == move
- || substruct1->moves[2] == move
- || substruct1->moves[3] == move)
- retVal |= gBitTable[i];
- i++;
- }
- }
- break;
- case MON_DATA_RIBBON_COUNT:
- retVal = 0;
- if (substruct0->species && !substruct3->isEgg)
- {
- retVal += substruct3->coolRibbon;
- retVal += substruct3->beautyRibbon;
- retVal += substruct3->cuteRibbon;
- retVal += substruct3->smartRibbon;
- retVal += substruct3->toughRibbon;
- retVal += substruct3->championRibbon;
- retVal += substruct3->winningRibbon;
- retVal += substruct3->victoryRibbon;
- retVal += substruct3->artistRibbon;
- retVal += substruct3->effortRibbon;
- retVal += substruct3->giftRibbon1;
- retVal += substruct3->giftRibbon2;
- retVal += substruct3->giftRibbon3;
- retVal += substruct3->giftRibbon4;
- retVal += substruct3->giftRibbon5;
- retVal += substruct3->giftRibbon6;
- retVal += substruct3->giftRibbon7;
- }
- break;
- case MON_DATA_RIBBONS:
- retVal = 0;
- if (substruct0->species && !substruct3->isEgg)
- {
- retVal = substruct3->championRibbon
- | (substruct3->coolRibbon << 1)
- | (substruct3->beautyRibbon << 4)
- | (substruct3->cuteRibbon << 7)
- | (substruct3->smartRibbon << 10)
- | (substruct3->toughRibbon << 13)
- | (substruct3->winningRibbon << 16)
- | (substruct3->victoryRibbon << 17)
- | (substruct3->artistRibbon << 18)
- | (substruct3->effortRibbon << 19)
- | (substruct3->giftRibbon1 << 20)
- | (substruct3->giftRibbon2 << 21)
- | (substruct3->giftRibbon3 << 22)
- | (substruct3->giftRibbon4 << 23)
- | (substruct3->giftRibbon5 << 24)
- | (substruct3->giftRibbon6 << 25)
- | (substruct3->giftRibbon7 << 26);
- }
- break;
- default:
- break;
- }
-
- if (field > MON_DATA_10)
- EncryptBoxMon(boxMon);
-
- return retVal;
-}
-
-#define SET8(lhs) (lhs) = *data
-#define SET16(lhs) (lhs) = data[0] + (data[1] << 8)
-#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)
-
-void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg)
-{
- const u8* data = dataArg;
- switch (field)
- {
- case MON_DATA_STATUS:
- SET32(mon->status);
- break;
- case MON_DATA_LEVEL:
- SET8(mon->level);
- break;
- case MON_DATA_HP:
- SET16(mon->hp);
- break;
- case MON_DATA_MAX_HP:
- SET16(mon->maxHP);
- break;
- case MON_DATA_ATK:
- SET16(mon->attack);
- break;
- case MON_DATA_DEF:
- SET16(mon->defense);
- break;
- case MON_DATA_SPEED:
- SET16(mon->speed);
- break;
- case MON_DATA_SPATK:
- SET16(mon->spAttack);
- break;
- case MON_DATA_SPDEF:
- SET16(mon->spDefense);
- break;
- case MON_DATA_MAIL:
- SET8(mon->mail);
- break;
- case MON_DATA_SPECIES2:
- break;
- default:
- SetBoxMonData(&mon->box, field, data);
- break;
- }
-}
-
-void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
-{
- const u8* data = dataArg;
-
- struct PokemonSubstruct0 *substruct0 = NULL;
- struct PokemonSubstruct1 *substruct1 = NULL;
- struct PokemonSubstruct2 *substruct2 = NULL;
- struct PokemonSubstruct3 *substruct3 = NULL;
-
- if (field > MON_DATA_10)
- {
- substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0);
- substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1);
- substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2);
- substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3);
-
- DecryptBoxMon(boxMon);
-
- if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum)
- {
- boxMon->isBadEgg = 1;
- boxMon->isEgg = 1;
- substruct3->isEgg = 1;
- EncryptBoxMon(boxMon);
- return;
- }
- }
-
- switch (field)
- {
- case MON_DATA_PERSONALITY:
- SET32(boxMon->personality);
- break;
- case MON_DATA_OT_ID:
- SET32(boxMon->otId);
- break;
- case MON_DATA_NICKNAME:
- {
- s32 i;
- for (i = 0; i < POKEMON_NAME_LENGTH; i++)
- boxMon->nickname[i] = data[i];
- break;
- }
- case MON_DATA_LANGUAGE:
- SET8(boxMon->language);
- break;
- case MON_DATA_SANITY_BIT1:
- SET8(boxMon->isBadEgg);
- break;
- case MON_DATA_SANITY_BIT2:
- SET8(boxMon->hasSpecies);
- break;
- case MON_DATA_SANITY_BIT3:
- SET8(boxMon->isEgg);
- break;
- case MON_DATA_OT_NAME:
- {
- s32 i;
- for (i = 0; i < OT_NAME_LENGTH; i++)
- boxMon->otName[i] = data[i];
- break;
- }
- case MON_DATA_MARKINGS:
- SET8(boxMon->markings);
- break;
- case MON_DATA_CHECKSUM:
- SET16(boxMon->checksum);
- break;
- case MON_DATA_10:
- SET16(boxMon->unknown);
- break;
- case MON_DATA_SPECIES:
- {
- SET16(substruct0->species);
- if (substruct0->species)
- boxMon->hasSpecies = 1;
- else
- boxMon->hasSpecies = 0;
- break;
- }
- case MON_DATA_HELD_ITEM:
- SET16(substruct0->heldItem);
- break;
- case MON_DATA_EXP:
- SET32(substruct0->experience);
- break;
- case MON_DATA_PP_BONUSES:
- SET8(substruct0->ppBonuses);
- break;
- case MON_DATA_FRIENDSHIP:
- SET8(substruct0->friendship);
- break;
- case MON_DATA_MOVE1:
- case MON_DATA_MOVE2:
- case MON_DATA_MOVE3:
- case MON_DATA_MOVE4:
- SET16(substruct1->moves[field - MON_DATA_MOVE1]);
- break;
- case MON_DATA_PP1:
- case MON_DATA_PP2:
- case MON_DATA_PP3:
- case MON_DATA_PP4:
- SET8(substruct1->pp[field - MON_DATA_PP1]);
- break;
- case MON_DATA_HP_EV:
- SET8(substruct2->hpEV);
- break;
- case MON_DATA_ATK_EV:
- SET8(substruct2->attackEV);
- break;
- case MON_DATA_DEF_EV:
- SET8(substruct2->defenseEV);
- break;
- case MON_DATA_SPEED_EV:
- SET8(substruct2->speedEV);
- break;
- case MON_DATA_SPATK_EV:
- SET8(substruct2->spAttackEV);
- break;
- case MON_DATA_SPDEF_EV:
- SET8(substruct2->spDefenseEV);
- break;
- case MON_DATA_COOL:
- SET8(substruct2->cool);
- break;
- case MON_DATA_BEAUTY:
- SET8(substruct2->beauty);
- break;
- case MON_DATA_CUTE:
- SET8(substruct2->cute);
- break;
- case MON_DATA_SMART:
- SET8(substruct2->smart);
- break;
- case MON_DATA_TOUGH:
- SET8(substruct2->tough);
- break;
- case MON_DATA_SHEEN:
- SET8(substruct2->sheen);
- break;
- case MON_DATA_POKERUS:
- SET8(substruct3->pokerus);
- break;
- case MON_DATA_MET_LOCATION:
- SET8(substruct3->metLocation);
- break;
- case MON_DATA_MET_LEVEL:
- {
- u8 metLevel = *data;
- substruct3->metLevel = metLevel;
- break;
- }
- case MON_DATA_MET_GAME:
- SET8(substruct3->metGame);
- break;
- case MON_DATA_POKEBALL:
- {
- u8 pokeball = *data;
- substruct3->pokeball = pokeball;
- break;
- }
- case MON_DATA_OT_GENDER:
- SET8(substruct3->otGender);
- break;
- case MON_DATA_HP_IV:
- SET8(substruct3->hpIV);
- break;
- case MON_DATA_ATK_IV:
- SET8(substruct3->attackIV);
- break;
- case MON_DATA_DEF_IV:
- SET8(substruct3->defenseIV);
- break;
- case MON_DATA_SPEED_IV:
- SET8(substruct3->speedIV);
- break;
- case MON_DATA_SPATK_IV:
- SET8(substruct3->spAttackIV);
- break;
- case MON_DATA_SPDEF_IV:
- SET8(substruct3->spDefenseIV);
- break;
- case MON_DATA_IS_EGG:
- SET8(substruct3->isEgg);
- if (substruct3->isEgg)
- boxMon->isEgg = 1;
- else
- boxMon->isEgg = 0;
- break;
- case MON_DATA_ALT_ABILITY:
- SET8(substruct3->altAbility);
- break;
- case MON_DATA_COOL_RIBBON:
- SET8(substruct3->coolRibbon);
- break;
- case MON_DATA_BEAUTY_RIBBON:
- SET8(substruct3->beautyRibbon);
- break;
- case MON_DATA_CUTE_RIBBON:
- SET8(substruct3->cuteRibbon);
- break;
- case MON_DATA_SMART_RIBBON:
- SET8(substruct3->smartRibbon);
- break;
- case MON_DATA_TOUGH_RIBBON:
- SET8(substruct3->toughRibbon);
- break;
- case MON_DATA_CHAMPION_RIBBON:
- SET8(substruct3->championRibbon);
- break;
- case MON_DATA_WINNING_RIBBON:
- SET8(substruct3->winningRibbon);
- break;
- case MON_DATA_VICTORY_RIBBON:
- SET8(substruct3->victoryRibbon);
- break;
- case MON_DATA_ARTIST_RIBBON:
- SET8(substruct3->artistRibbon);
- break;
- case MON_DATA_EFFORT_RIBBON:
- SET8(substruct3->effortRibbon);
- break;
- case MON_DATA_GIFT_RIBBON_1:
- SET8(substruct3->giftRibbon1);
- break;
- case MON_DATA_GIFT_RIBBON_2:
- SET8(substruct3->giftRibbon2);
- break;
- case MON_DATA_GIFT_RIBBON_3:
- SET8(substruct3->giftRibbon3);
- break;
- case MON_DATA_GIFT_RIBBON_4:
- SET8(substruct3->giftRibbon4);
- break;
- case MON_DATA_GIFT_RIBBON_5:
- SET8(substruct3->giftRibbon5);
- break;
- case MON_DATA_GIFT_RIBBON_6:
- SET8(substruct3->giftRibbon6);
- break;
- case MON_DATA_GIFT_RIBBON_7:
- SET8(substruct3->giftRibbon7);
- break;
- case MON_DATA_FATEFUL_ENCOUNTER:
- SET8(substruct3->fatefulEncounter);
- break;
- case MON_DATA_OBEDIENCE:
- SET8(substruct3->obedient);
- break;
- case MON_DATA_IVS:
- {
- u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
- substruct3->hpIV = ivs & 0x1F;
- substruct3->attackIV = (ivs >> 5) & 0x1F;
- substruct3->defenseIV = (ivs >> 10) & 0x1F;
- substruct3->speedIV = (ivs >> 15) & 0x1F;
- substruct3->spAttackIV = (ivs >> 20) & 0x1F;
- substruct3->spDefenseIV = (ivs >> 25) & 0x1F;
- break;
- }
- default:
- break;
- }
-
- if (field > MON_DATA_10)
- {
- boxMon->checksum = CalculateBoxMonChecksum(boxMon);
- EncryptBoxMon(boxMon);
- }
-}
-
-void CopyMon(void *dest, void *src, size_t size)
-{
- memcpy(dest, src, size);
-}
-
-u8 GiveMonToPlayer(struct Pokemon *mon)
-{
- s32 i;
-
- SetMonData(mon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName);
- SetMonData(mon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
- SetMonData(mon, MON_DATA_OT_ID, gSaveBlock2Ptr->playerTrainerId);
-
- i = 0;
-
- while (i < 6 && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
- i++;
-
- if (i >= 6)
- return SendMonToPC(mon);
-
- CopyMon(&gPlayerParty[i], mon, sizeof(*mon));
- gPlayerPartyCount = i + 1;
- return MON_GIVEN_TO_PARTY;
-}
-
-extern u16 get_unknown_box_id(void);
-extern u8 StorageGetCurrentBox(void);
-extern void set_unknown_box_id(u8);
-extern struct BoxPokemon* GetBoxedMonPtr(u8 boxNumber, u8 boxPosition);
-
-u8 SendMonToPC(struct Pokemon* mon)
-{
- s32 boxNo, boxPos;
-
- set_unknown_box_id(VarGet(VAR_STORAGE_UNKNOWN));
-
- boxNo = StorageGetCurrentBox();
-
- do
- {
- for (boxPos = 0; boxPos < 30; boxPos++)
- {
- struct BoxPokemon* checkingMon = GetBoxedMonPtr(boxNo, boxPos);
- if (GetBoxMonData(checkingMon, MON_DATA_SPECIES, NULL) == SPECIES_NONE)
- {
- MonRestorePP(mon);
- CopyMon(checkingMon, &mon->box, sizeof(mon->box));
- gSpecialVar_MonBoxId = boxNo;
- gSpecialVar_MonBoxPos = boxPos;
- if (get_unknown_box_id() != boxNo)
- FlagClear(FLAG_SYS_STORAGE_UNKNOWN_FLAG);
- VarSet(VAR_STORAGE_UNKNOWN, boxNo);
- return MON_GIVEN_TO_PC;
- }
- }
-
- boxNo++;
- if (boxNo == 14)
- boxNo = 0;
- } while (boxNo != StorageGetCurrentBox());
-
- return MON_CANT_GIVE;
-}
-
-u8 CalculatePlayerPartyCount(void)
-{
- gPlayerPartyCount = 0;
-
- while (gPlayerPartyCount < 6
- && GetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
- {
- gPlayerPartyCount++;
- }
-
- return gPlayerPartyCount;
-}
-
-u8 CalculateEnemyPartyCount(void)
-{
- gEnemyPartyCount = 0;
-
- while (gEnemyPartyCount < 6
- && GetMonData(&gEnemyParty[gEnemyPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE)
- {
- gEnemyPartyCount++;
- }
-
- return gEnemyPartyCount;
-}
-
-u8 GetMonsStateToDoubles(void)
-{
- s32 aliveCount = 0;
- s32 i;
- CalculatePlayerPartyCount();
-
- if (gPlayerPartyCount == 1)
- return gPlayerPartyCount; // PLAYER_HAS_ONE_MON
-
- for (i = 0; i < gPlayerPartyCount; i++)
- {
- if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG
- && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0
- && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_NONE)
- aliveCount++;
- }
-
- return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
-}
-
-u8 GetMonsStateToDoubles_2(void)
-{
- s32 aliveCount = 0;
- s32 i;
-
- for (i = 0; i < PARTY_SIZE; i++)
- {
- u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL);
- if (species != SPECIES_EGG && species != SPECIES_NONE
- && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0)
- aliveCount++;
- }
-
- if (aliveCount == 1)
- return PLAYER_HAS_ONE_MON; // may have more than one, but only one is alive
-
- return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
-}
-
-u8 GetAbilityBySpecies(u16 species, bool8 altAbility)
-{
- if (altAbility)
- gLastUsedAbility = gBaseStats[species].ability2;
- else
- gLastUsedAbility = gBaseStats[species].ability1;
-
- return gLastUsedAbility;
-}
-
-u8 GetMonAbility(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
- u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
- return GetAbilityBySpecies(species, altAbility);
-}
-
-extern const struct BattleMove gBattleMoves[];
-
-void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord)
-{
- s32 i, j;
-
- ZeroEnemyPartyMons();
- *gBattleResources->secretBase = *secretBaseRecord;
-
- for (i = 0; i < PARTY_SIZE; i++)
- {
- if (gBattleResources->secretBase->party.species[i])
- {
- CreateMon(&gEnemyParty[i],
- gBattleResources->secretBase->party.species[i],
- gBattleResources->secretBase->party.levels[i],
- 15,
- 1,
- gBattleResources->secretBase->party.personality[i],
- 2,
- 0);
-
- SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gBattleResources->secretBase->party.heldItems[i]);
-
- for (j = 0; j < 6; j++)
- SetMonData(&gEnemyParty[i], MON_DATA_HP_EV + j, &gBattleResources->secretBase->party.EVs[i]);
-
- for (j = 0; j < 4; j++)
- {
- SetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j, &gBattleResources->secretBase->party.moves[i * 4 + j]);
- SetMonData(&gEnemyParty[i], MON_DATA_PP1 + j, &gBattleMoves[gBattleResources->secretBase->party.moves[i * 4 + j]].pp);
- }
- }
- }
-}
-
-extern const u8 gFacilityClassToPicIndex[];
-extern const u8 gFacilityClassToTrainerClass[];
-extern const u8 gSecretBaseTrainerClasses[][5];
-
-u8 GetSecretBaseTrainerPicIndex(void)
-{
- u8 trainerClass = gSecretBaseTrainerClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5];
- return gFacilityClassToPicIndex[trainerClass];
-}
-
-u8 GetSecretBaseTrainerNameIndex(void)
-{
- u8 trainerClass = gSecretBaseTrainerClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5];
- return gFacilityClassToTrainerClass[trainerClass];
-}
-
-bool8 IsPlayerPartyAndPokemonStorageFull(void)
-{
- s32 i;
-
- for (i = 0; i < 6; i++)
- if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE)
- return FALSE;
-
- return IsPokemonStorageFull();
-}
-
-extern u32 GetBoxMonDataFromAnyBox(u8 boxNo, u8 boxPos, s32 field);
-
-bool8 IsPokemonStorageFull(void)
-{
- s32 i, j;
-
- for (i = 0; i < 14; i++)
- for (j = 0; j < 30; j++)
- if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE)
- return FALSE;
-
- return TRUE;
-}
-
-extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
-
-void GetSpeciesName(u8 *name, u16 species)
-{
- s32 i;
-
- for (i = 0; i <= POKEMON_NAME_LENGTH; i++)
- {
- if (species > NUM_SPECIES)
- name[i] = gSpeciesNames[0][i];
- else
- name[i] = gSpeciesNames[species][i];
-
- if (name[i] == EOS)
- break;
- }
-
- name[i] = EOS;
-}
-
-extern const u8 gUnknown_08329D22[];
-extern const u8 gUnknown_08329D26[];
-
-u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex)
-{
- u8 basePP = gBattleMoves[move].pp;
- return basePP + ((basePP * 20 * ((gUnknown_08329D22[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100);
-}
-
-void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex)
-{
- u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL);
- ppBonuses &= gUnknown_08329D26[moveIndex];
- SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
-}
-
-void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex)
-{
- mon->ppBonuses &= gUnknown_08329D26[moveIndex];
-}
-
-void sub_803FA70(u8 bank);
-void ClearTemporarySpeciesSpriteData(u8 bank, bool8);
-
-extern struct BattlePokemon gBattleMons[4];
-
-void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
-{
- u16* hpSwitchout;
- s32 i;
- u8 nickname[POKEMON_NAME_LENGTH * 2];
-
- gBattleMons[bank].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
- gBattleMons[bank].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL);
-
- for (i = 0; i < 4; i++)
- {
- gBattleMons[bank].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL);
- gBattleMons[bank].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL);
- }
-
- gBattleMons[bank].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL);
- gBattleMons[bank].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL);
- gBattleMons[bank].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL);
- gBattleMons[bank].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL);
- gBattleMons[bank].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL);
- gBattleMons[bank].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL);
- gBattleMons[bank].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED_IV, NULL);
- gBattleMons[bank].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL);
- gBattleMons[bank].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL);
- gBattleMons[bank].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL);
- gBattleMons[bank].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL);
- gBattleMons[bank].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL);
- gBattleMons[bank].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL);
- gBattleMons[bank].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL);
- gBattleMons[bank].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL);
- gBattleMons[bank].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL);
- gBattleMons[bank].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED, NULL);
- gBattleMons[bank].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL);
- gBattleMons[bank].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL);
- gBattleMons[bank].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL);
- gBattleMons[bank].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL);
- gBattleMons[bank].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL);
- gBattleMons[bank].type1 = gBaseStats[gBattleMons[bank].species].type1;
- gBattleMons[bank].type2 = gBaseStats[gBattleMons[bank].species].type2;
- gBattleMons[bank].ability = GetAbilityBySpecies(gBattleMons[bank].species, gBattleMons[bank].altAbility);
- GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
- StringCopy10(gBattleMons[bank].nickname, nickname);
- GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[bank].otName);
-
- hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(bank)];
- *hpSwitchout = gBattleMons[bank].hp;
-
- for (i = 0; i < 8; i++)
- gBattleMons[bank].statStages[i] = 6;
-
- gBattleMons[bank].status2 = 0;
- sub_803FA70(bank);
- ClearTemporarySpeciesSpriteData(bank, FALSE);
-}
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
deleted file mode 100644
index 0dd1131de..000000000
--- a/src/pokemon_3.c
+++ /dev/null
@@ -1,1749 +0,0 @@
-#include "global.h"
-#include "pokemon.h"
-#include "main.h"
-#include "constants/items.h"
-#include "string_util.h"
-#include "battle_message.h"
-#include "rtc.h"
-#include "item.h"
-#include "battle.h"
-#include "constants/species.h"
-#include "link.h"
-#include "constants/hold_effects.h"
-#include "random.h"
-#include "constants/trainers.h"
-#include "constants/songs.h"
-#include "sound.h"
-#include "m4a.h"
-#include "task.h"
-#include "sprite.h"
-#include "text.h"
-#include "constants/abilities.h"
-#include "pokemon_animation.h"
-#include "pokedex.h"
-#include "pokeblock.h"
-
-extern struct BattlePokemon gBattleMons[4];
-extern struct BattleEnigmaBerry gEnigmaBerries[4];
-extern u8 gActiveBattler;
-extern u8 gBattlerInMenuId;
-extern u8 gBattlerTarget;
-extern u8 gBattlerAttacker;
-extern u8 gPotentialItemEffectBattler;
-extern u16 gTrainerBattleOpponent_A;
-extern u32 gBattleTypeFlags;
-extern u8 gBattleMonForms[4];
-extern u16 gBattlerPartyIndexes[4];
-extern u8 gLastUsedAbility;
-extern u16 gPartnerTrainerId;
-extern u32 gHitMarker;
-
-extern const u16 gSpeciesToHoennPokedexNum[];
-extern const u16 gSpeciesToNationalPokedexNum[];
-extern const u16 gHoennToNationalOrder[];
-extern const u16 gSpeciesIdToCryId[];
-extern const struct SpindaSpot gSpindaSpotGraphics[];
-extern const u8* const gStatNamesTable[];
-extern const u8 gSpeciesNames[][11];
-extern const u8 gUnknown_08329EC8[];
-extern const u8 gText_StatRose[];
-extern const u8 gText_PkmnsStatChanged2[];
-extern const u8 gText_PkmnGettingPumped[];
-extern const u8 gText_PkmnShroudedInMist[];
-extern const s8 gNatureStatTable[][5];
-extern const s8 gUnknown_08329ECE[][3];
-extern const u32 gBitTable[];
-extern const u32 gTMHMLearnsets[][2];
-extern const u8 gText_BattleWallyName[];
-extern const u8 gText_PkmnsXPreventsSwitching[];
-extern const struct CompressedSpritePalette gMonPaletteTable[];
-extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
-extern const u16 gHMMoves[];
-extern const u8 gMonAnimationDelayTable[];
-extern const u8 gMonFrontAnimIdsTable[];
-
-extern bool8 InBattlePyramid(void);
-extern bool8 InBattlePike(void);
-extern bool8 sub_81D5C18(void);
-extern bool8 sub_806F104(void);
-extern bool32 IsNationalPokedexEnabled(void);
-extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId);
-extern u8 sub_81D63C8(u16 trainerOpponentId);
-extern u8 sav1_map_get_name(void);
-extern u8 GetFrontierOpponentClass(u16 trainerId);
-extern u8 pokemon_order_func(u8 bankPartyId);
-extern void GetFrontierTrainerName(u8* dest, u16 trainerId);
-extern void sub_81C488C(u8);
-
-static void sub_806E6CC(u8 taskId);
-
-bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battleBank)
-{
- u32 status = GetMonData(mon, MON_DATA_STATUS, 0);
-
- if (status & healMask)
- {
- status &= ~healMask;
- SetMonData(mon, MON_DATA_STATUS, (u8 *)&status);
- if (gMain.inBattle && battleBank != 4)
- gBattleMons[battleBank].status1 &= ~healMask;
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
-{
- const u8 *temp;
- const u8 *itemEffect;
- u8 offset;
- int i;
- u8 j;
- u8 val;
-
- offset = 6;
-
- temp = gItemEffectTable[itemId - 13];
-
- if (!temp && itemId != ITEM_ENIGMA_BERRY)
- return 0;
-
- if (itemId == ITEM_ENIGMA_BERRY)
- {
- temp = gEnigmaBerries[gActiveBattler].itemEffect;
- }
-
- itemEffect = temp;
-
- for (i = 0; i < 6; i++)
- {
- switch (i)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- if (i == effectByte)
- return 0;
- break;
- case 4:
- val = itemEffect[4];
- if (val & 0x20)
- val &= 0xDF;
- j = 0;
- while (val)
- {
- if (val & 1)
- {
- switch (j)
- {
- case 2:
- if (val & 0x10)
- val &= 0xEF;
- case 0:
- if (i == effectByte && (val & effectBit))
- return offset;
- offset++;
- break;
- case 1:
- if (i == effectByte && (val & effectBit))
- return offset;
- offset++;
- break;
- case 3:
- if (i == effectByte && (val & effectBit))
- return offset;
- offset++;
- break;
- case 7:
- if (i == effectByte)
- return 0;
- break;
- }
- }
- j++;
- val >>= 1;
- if (i == effectByte)
- effectBit >>= 1;
- }
- break;
- case 5:
- val = itemEffect[5];
- j = 0;
- while (val)
- {
- if (val & 1)
- {
- switch (j)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- if (i == effectByte && (val & effectBit))
- return offset;
- offset++;
- break;
- case 7:
- if (i == effectByte)
- return 0;
- break;
- }
- }
- j++;
- val >>= 1;
- if (i == effectByte)
- effectBit >>= 1;
- }
- break;
- }
- }
-
- return offset;
-}
-
-void sub_806CF24(s32 stat)
-{
- gBattlerTarget = gBattlerInMenuId;
- StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]);
- StringCopy(gBattleTextBuff2, gText_StatRose);
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
-}
-
-u8 *sub_806CF78(u16 itemId)
-{
- int i;
- const u8 *itemEffect;
-
- if (itemId == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- itemEffect = gEnigmaBerries[gBattlerInMenuId].itemEffect;
- else
- itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
- }
- else
- {
- itemEffect = gItemEffectTable[itemId - 13];
- }
-
- gPotentialItemEffectBattler = gBattlerInMenuId;
-
- for (i = 0; i < 3; i++)
- {
- if (itemEffect[i] & 0xF)
- sub_806CF24(i * 2);
- if (itemEffect[i] & 0xF0)
- {
- if (i)
- {
- sub_806CF24(i * 2 + 1);
- }
- else
- {
- gBattlerAttacker = gBattlerInMenuId;
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
- }
- }
- }
-
- if (itemEffect[3] & 0x80)
- {
- gBattlerAttacker = gBattlerInMenuId;
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
- }
-
- return gDisplayedStringBattle;
-}
-
-u8 GetNature(struct Pokemon *mon)
-{
- return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25;
-}
-
-u8 GetNatureFromPersonality(u32 personality)
-{
- return personality % 25;
-}
-
-u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem)
-{
- int i;
- u16 targetSpecies = 0;
- u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
- u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- u8 level;
- u16 friendship;
- u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0);
- u16 upperPersonality = personality >> 16;
- u8 holdEffect;
-
- if (heldItem == ITEM_ENIGMA_BERRY)
- holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
- else
- holdEffect = ItemId_GetHoldEffect(heldItem);
-
- if (holdEffect == 38 && type != 3)
- return 0;
-
- switch (type)
- {
- case 0:
- level = GetMonData(mon, MON_DATA_LEVEL, 0);
- friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
-
- for (i = 0; i < 5; i++)
- {
- switch (gEvolutionTable[species][i].method)
- {
- case EVO_FRIENDSHIP:
- if (friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_FRIENDSHIP_DAY:
- RtcCalcLocalTime();
- if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_FRIENDSHIP_NIGHT:
- RtcCalcLocalTime();
- if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL:
- if (gEvolutionTable[species][i].param <= level)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_GT_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_EQ_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_LT_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_SILCOON:
- if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_CASCOON:
- if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_NINJASK:
- if (gEvolutionTable[species][i].param <= level)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_BEAUTY:
- if (gEvolutionTable[species][i].param <= beauty)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- }
- }
- break;
- case 1:
- for (i = 0; i < 5; i++)
- {
- switch (gEvolutionTable[species][i].method)
- {
- case EVO_TRADE:
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_TRADE_ITEM:
- if (gEvolutionTable[species][i].param == heldItem)
- {
- heldItem = 0;
- SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem);
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- }
- break;
- }
- }
- break;
- case 2:
- case 3:
- for (i = 0; i < 5; i++)
- {
- if (gEvolutionTable[species][i].method == EVO_ITEM
- && gEvolutionTable[species][i].param == evolutionItem)
- {
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- }
- }
- break;
- }
-
- return targetSpecies;
-}
-
-u16 HoennPokedexNumToSpecies(u16 hoennNum)
-{
- u16 species;
-
- if (!hoennNum)
- return 0;
-
- species = 0;
-
- while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum)
- species++;
-
- if (species == 411)
- return 0;
-
- return species + 1;
-}
-
-u16 NationalPokedexNumToSpecies(u16 nationalNum)
-{
- u16 species;
-
- if (!nationalNum)
- return 0;
-
- species = 0;
-
- while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum)
- species++;
-
- if (species == 411)
- return 0;
-
- return species + 1;
-}
-
-u16 NationalToHoennOrder(u16 nationalNum)
-{
- u16 hoennNum;
-
- if (!nationalNum)
- return 0;
-
- hoennNum = 0;
-
- while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum)
- hoennNum++;
-
- if (hoennNum == 411)
- return 0;
-
- return hoennNum + 1;
-}
-
-u16 SpeciesToNationalPokedexNum(u16 species)
-{
- if (!species)
- return 0;
-
- return gSpeciesToNationalPokedexNum[species - 1];
-}
-
-u16 SpeciesToHoennPokedexNum(u16 species)
-{
- if (!species)
- return 0;
-
- return gSpeciesToHoennPokedexNum[species - 1];
-}
-
-u16 HoennToNationalOrder(u16 hoennNum)
-{
- if (!hoennNum)
- return 0;
-
- return gHoennToNationalOrder[hoennNum - 1];
-}
-
-u16 SpeciesToCryId(u16 species)
-{
- if (species <= 250)
- return species;
-
- if (species < 276)
- return 200;
-
- return gSpeciesIdToCryId[species - 276];
-}
-
-void sub_806D544(u16 species, u32 personality, u8 *dest)
-{
- if (species == SPECIES_SPINDA
- && dest != gMonSpritesGfxPtr->sprites[0]
- && dest != gMonSpritesGfxPtr->sprites[2])
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int j;
- u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
- u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
-
- for (j = 0; j < 16; j++)
- {
- int k;
- s32 row = gSpindaSpotGraphics[i].image[j];
-
- for (k = x; k < x + 16; k++)
- {
- u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
-
- if (row & 1)
- {
- if (k & 1)
- {
- if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
- *val += 0x40;
- }
- else
- {
- if ((u8)((*val & 0xF) - 0x01) <= 0x02)
- *val += 0x04;
- }
- }
-
- row >>= 1;
- }
-
- y++;
- }
-
- personality >>= 8;
- }
- }
-}
-
-void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4)
-{
- if (species == SPECIES_SPINDA && a4)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int j;
- u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
- u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
-
- for (j = 0; j < 16; j++)
- {
- int k;
- s32 row = gSpindaSpotGraphics[i].image[j];
-
- for (k = x; k < x + 16; k++)
- {
- u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
-
- if (row & 1)
- {
- if (k & 1)
- {
- if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
- *val += 0x40;
- }
- else
- {
- if ((u8)((*val & 0xF) - 0x01) <= 0x02)
- *val += 0x04;
- }
- }
-
- row >>= 1;
- }
-
- y++;
- }
-
- personality >>= 8;
- }
- }
-}
-
-void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
-{
- u8 language;
- GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
- language = GetMonData(mon, MON_DATA_LANGUAGE, &language);
- if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1))
- SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
-}
-
-bool8 sub_806D7EC(void)
-{
- bool8 retVal = FALSE;
- switch (gLinkPlayers[GetMultiplayerId()].lp_field_18)
- {
- case 0:
- case 3:
- retVal = FALSE;
- break;
- case 1:
- case 2:
- retVal = TRUE;
- break;
- }
- return retVal;
-}
-
-bool16 sub_806D82C(u8 id)
-{
- bool16 retVal = FALSE;
- switch (gLinkPlayers[id].lp_field_18)
- {
- case 0:
- case 3:
- retVal = FALSE;
- break;
- case 1:
- case 2:
- retVal = TRUE;
- break;
- }
- return retVal;
-}
-
-s32 GetBattlerMultiplayerId(u16 a1)
-{
- s32 id;
- for (id = 0; id < MAX_LINK_PLAYERS; id++)
- if (gLinkPlayers[id].lp_field_18 == a1)
- break;
- return id;
-}
-
-u8 GetTrainerEncounterMusicId(u16 trainerOpponentId)
-{
- if (InBattlePyramid())
- return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId);
- if (sub_81D5C18())
- return sub_81D63C8(trainerOpponentId);
- return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId);
-}
-
-u16 nature_stat_mod(u8 nature, u16 n, u8 statIndex)
-{
- if (statIndex < 1 || statIndex > 5)
- {
- // should just be "return n", but it wouldn't match without this
- u16 retVal = n;
- retVal++;
- retVal--;
- return retVal;
- }
-
- switch (gNatureStatTable[nature][statIndex - 1])
- {
- case 1:
- return (u16)(n * 110) / 100;
- case -1:
- return (u16)(n * 90) / 100;
- }
-
- return n;
-}
-
-void AdjustFriendship(struct Pokemon *mon, u8 event)
-{
- u16 species, heldItem;
- u8 holdEffect;
-
- if (sub_806F104())
- return;
-
- species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
-
- if (heldItem == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- holdEffect = gEnigmaBerries[0].holdEffect;
- else
- holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
- }
- else
- {
- holdEffect = ItemId_GetHoldEffect(heldItem);
- }
-
- if (species && species != SPECIES_EGG)
- {
- u8 friendshipLevel = 0;
- s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
- if (friendship > 99)
- friendshipLevel++;
- if (friendship > 199)
- friendshipLevel++;
- if ((event != 5 || !(Random() & 1))
- && (event != 3
- || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
- && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION))))
- {
- s8 mod = gUnknown_08329ECE[event][friendshipLevel];
- if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
- mod = (150 * mod) / 100;
- friendship += mod;
- if (mod > 0)
- {
- if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
- friendship++;
- if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
- friendship++;
- }
- if (friendship < 0)
- friendship = 0;
- if (friendship > 255)
- friendship = 255;
- SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
- }
- }
-}
-
-void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
-{
- u8 evs[NUM_STATS];
- u16 evIncrease = 0;
- u16 totalEVs = 0;
- u16 heldItem;
- u8 holdEffect;
- int i;
-
- for (i = 0; i < NUM_STATS; i++)
- {
- evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0);
- totalEVs += evs[i];
- }
-
- for (i = 0; i < NUM_STATS; i++)
- {
- u8 hasHadPokerus;
- int multiplier;
-
- if (totalEVs >= MAX_TOTAL_EVS)
- break;
-
- hasHadPokerus = CheckPartyHasHadPokerus(mon, 0);
-
- if (hasHadPokerus)
- multiplier = 2;
- else
- multiplier = 1;
-
- switch (i)
- {
- case 0:
- evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier;
- break;
- case 1:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier;
- break;
- case 2:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier;
- break;
- case 3:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier;
- break;
- case 4:
- evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier;
- break;
- case 5:
- evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier;
- break;
- }
-
- heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
-
- if (heldItem == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- holdEffect = gEnigmaBerries[0].holdEffect;
- else
- holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
- }
- else
- {
- holdEffect = ItemId_GetHoldEffect(heldItem);
- }
-
- if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
- evIncrease *= 2;
-
- if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
- evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
-
- if (evs[i] + (s16)evIncrease > 255)
- {
- int val1 = (s16)evIncrease + 255;
- int val2 = evs[i] + evIncrease;
- evIncrease = val1 - val2;
- }
-
- evs[i] += evIncrease;
- totalEVs += evIncrease;
- SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]);
- }
-}
-
-u16 GetMonEVCount(struct Pokemon *mon)
-{
- int i;
- u16 count = 0;
-
- for (i = 0; i < NUM_STATS; i++)
- count += GetMonData(mon, MON_DATA_HP_EV + i, 0);
-
- return count;
-}
-
-void RandomlyGivePartyPokerus(struct Pokemon *party)
-{
- u16 rnd = Random();
- if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
- {
- struct Pokemon *mon;
-
- do
- {
- do
- {
- rnd = Random() % PARTY_SIZE;
- mon = &party[rnd];
- }
- while (!GetMonData(mon, MON_DATA_SPECIES, 0));
- }
- while (GetMonData(mon, MON_DATA_IS_EGG, 0));
-
- if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
- {
- u8 rnd2;
-
- do
- {
- rnd2 = Random();
- }
- while ((rnd2 & 0x7) == 0);
-
- if (rnd2 & 0xF0)
- rnd2 &= 0x7;
-
- rnd2 |= (rnd2 << 4);
- rnd2 &= 0xF3;
- rnd2++;
-
- SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
- }
- }
-}
-
-u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
-{
- u8 retVal;
-
- int partyIndex = 0;
- unsigned curBit = 1;
- retVal = 0;
-
- if (selection)
- {
- do
- {
- if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF))
- retVal |= curBit;
- partyIndex++;
- curBit <<= 1;
- selection >>= 1;
- }
- while (selection);
- }
- else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF)
- {
- retVal = 1;
- }
-
- return retVal;
-}
-
-u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
-{
- u8 retVal;
-
- int partyIndex = 0;
- unsigned curBit = 1;
- retVal = 0;
-
- if (selection)
- {
- do
- {
- if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0))
- retVal |= curBit;
- partyIndex++;
- curBit <<= 1;
- selection >>= 1;
- }
- while (selection);
- }
- else if (GetMonData(&party[0], MON_DATA_POKERUS, 0))
- {
- retVal = 1;
- }
-
- return retVal;
-}
-
-void UpdatePartyPokerusTime(u16 days)
-{
- int i;
- for (i = 0; i < PARTY_SIZE; i++)
- {
- if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
- {
- u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
- if (pokerus & 0xF)
- {
- if ((pokerus & 0xF) < days || days > 4)
- pokerus &= 0xF0;
- else
- pokerus -= days;
-
- if (pokerus == 0)
- pokerus = 0x10;
-
- SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
- }
- }
- }
-}
-
-void PartySpreadPokerus(struct Pokemon *party)
-{
- if ((Random() % 3) == 0)
- {
- int i;
- for (i = 0; i < PARTY_SIZE; i++)
- {
- if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
- {
- u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
- u8 curPokerus = pokerus;
- if (pokerus)
- {
- if (pokerus & 0xF)
- {
- // spread to adjacent party members
- if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
- SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
- if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
- {
- SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
- i++;
- }
- }
- }
- }
- }
- }
-}
-
-bool8 TryIncrementMonLevel(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
- u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1;
- u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0);
- if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL])
- {
- expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL];
- SetMonData(mon, MON_DATA_EXP, &expPoints);
- }
- if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel])
- {
- return FALSE;
- }
- else
- {
- SetMonData(mon, MON_DATA_LEVEL, &nextLevel);
- return TRUE;
- }
-}
-
-u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- if (species == SPECIES_EGG)
- {
- return 0;
- }
- else if (tm < 32)
- {
- u32 mask = 1 << tm;
- return gTMHMLearnsets[species][0] & mask;
- }
- else
- {
- u32 mask = 1 << (tm - 32);
- return gTMHMLearnsets[species][1] & mask;
- }
-}
-
-u32 CanSpeciesLearnTMHM(u16 species, u8 tm)
-{
- if (species == SPECIES_EGG)
- {
- return 0;
- }
- else if (tm < 32)
- {
- u32 mask = 1 << tm;
- return gTMHMLearnsets[species][0] & mask;
- }
- else
- {
- u32 mask = 1 << (tm - 32);
- return gTMHMLearnsets[species][1] & mask;
- }
-}
-
-u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves)
-{
- u16 learnedMoves[4];
- u8 numMoves = 0;
- u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
- u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
- int i, j, k;
-
- for (i = 0; i < 4; i++)
- learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
-
- for (i = 0; i < 20; i++)
- {
- u16 moveLevel;
-
- if (gLevelUpLearnsets[species][i] == 0xFFFF)
- break;
-
- moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
-
- if (moveLevel <= (level << 9))
- {
- for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
- ;
-
- if (j == 4)
- {
- for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
- ;
-
- if (k == numMoves)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
- }
- }
- }
-
- return numMoves;
-}
-
-u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)
-{
- u8 numMoves = 0;
- int i;
-
- for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
-
- return numMoves;
-}
-
-u8 GetNumberOfRelearnableMoves(struct Pokemon *mon)
-{
- u16 learnedMoves[4];
- u16 moves[20];
- u8 numMoves = 0;
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
- int i, j, k;
-
- if (species == SPECIES_EGG)
- return 0;
-
- for (i = 0; i < 4; i++)
- learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
-
- for (i = 0; i < 20; i++)
- {
- u16 moveLevel;
-
- if (gLevelUpLearnsets[species][i] == 0xFFFF)
- break;
-
- moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
-
- if (moveLevel <= (level << 9))
- {
- for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
- ;
-
- if (j == 4)
- {
- for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
- ;
-
- if (k == numMoves)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
- }
- }
- }
-
- return numMoves;
-}
-
-u16 SpeciesToPokedexNum(u16 species)
-{
- if (IsNationalPokedexEnabled())
- {
- return SpeciesToNationalPokedexNum(species);
- }
- else
- {
- species = SpeciesToHoennPokedexNum(species);
- if (species <= 202)
- return species;
- return 0xFFFF;
- }
-}
-
-bool32 sub_806E3F8(u16 species)
-{
- if (SpeciesToHoennPokedexNum(species) > 202)
- return FALSE;
- else
- return TRUE;
-}
-
-void ClearBattleMonForms(void)
-{
- int i;
- for (i = 0; i < 4; i++)
- gBattleMonForms[i] = 0;
-}
-
-u16 GetBattleBGM(void)
-{
- if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
- return MUS_BATTLE34;
- if (gBattleTypeFlags & BATTLE_TYPE_REGI)
- return MUS_BATTLE36;
- if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
- return MUS_BATTLE20;
- if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
- {
- u8 trainerClass;
-
- if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
- trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
- else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
- trainerClass = TRAINER_CLASS_EXPERT;
- else
- trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
-
- switch (trainerClass)
- {
- case TRAINER_CLASS_AQUA_LEADER:
- case TRAINER_CLASS_MAGMA_LEADER:
- return MUS_BATTLE30;
- case TRAINER_CLASS_TEAM_AQUA:
- case TRAINER_CLASS_TEAM_MAGMA:
- case TRAINER_CLASS_AQUA_ADMIN:
- case TRAINER_CLASS_MAGMA_ADMIN:
- return MUS_BATTLE31;
- case TRAINER_CLASS_LEADER:
- return MUS_BATTLE32;
- case TRAINER_CLASS_CHAMPION:
- return MUS_BATTLE33;
- case TRAINER_CLASS_PKMN_TRAINER_3:
- if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
- return MUS_BATTLE35;
- if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
- return MUS_BATTLE20;
- return MUS_BATTLE35;
- case TRAINER_CLASS_ELITE_FOUR:
- return MUS_BATTLE38;
- case TRAINER_CLASS_SALON_MAIDEN:
- case TRAINER_CLASS_DOME_ACE:
- case TRAINER_CLASS_PALACE_MAVEN:
- case TRAINER_CLASS_ARENA_TYCOON:
- case TRAINER_CLASS_FACTORY_HEAD:
- case TRAINER_CLASS_PIKE_QUEEN:
- case TRAINER_CLASS_PYRAMID_KING:
- return MUS_VS_FRONT;
- default:
- return MUS_BATTLE20;
- }
- }
- return MUS_BATTLE27;
-}
-
-void PlayBattleBGM(void)
-{
- ResetMapMusic();
- m4aMPlayAllStop();
- PlayBGM(GetBattleBGM());
-}
-
-void PlayMapChosenOrBattleBGM(u16 songId)
-{
- ResetMapMusic();
- m4aMPlayAllStop();
- if (songId)
- PlayNewMapMusic(songId);
- else
- PlayNewMapMusic(GetBattleBGM());
-}
-
-void sub_806E694(u16 songId)
-{
- u8 taskId;
-
- ResetMapMusic();
- m4aMPlayAllStop();
-
- taskId = CreateTask(sub_806E6CC, 0);
- gTasks[taskId].data[0] = songId;
-}
-
-static void sub_806E6CC(u8 taskId)
-{
- if (gTasks[taskId].data[0])
- PlayNewMapMusic(gTasks[taskId].data[0]);
- else
- PlayNewMapMusic(GetBattleBGM());
- DestroyTask(taskId);
-}
-
-const u8 *GetMonFrontSpritePal(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality);
-}
-
-// Extracts the upper 16 bits of a 32-bit number
-#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
-
-// Extracts the lower 16 bits of a 32-bit number
-#define LOHALF(n) ((n) & 0xFFFF)
-
-const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
-{
- u32 shinyValue;
-
- if (species > SPECIES_EGG)
- return gMonPaletteTable[0].data;
-
- shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- return gMonShinyPaletteTable[species].data;
- else
- return gMonPaletteTable[species].data;
-}
-
-const struct CompressedSpritePalette *sub_806E794(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality);
-}
-
-const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality)
-{
- u32 shinyValue;
-
- shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- return &gMonShinyPaletteTable[species];
- else
- return &gMonPaletteTable[species];
-}
-
-bool32 IsHMMove2(u16 move)
-{
- int i = 0;
- while (gHMMoves[i] != 0xFFFF)
- {
- if (gHMMoves[i++] == move)
- return TRUE;
- }
- return FALSE;
-}
-
-bool8 IsPokeSpriteNotFlipped(u16 species)
-{
- return gBaseStats[species].noFlip;
-}
-
-s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor)
-{
- u8 nature = GetNature(mon);
- return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
-}
-
-s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor)
-{
- u8 nature = GetNatureFromPersonality(personality);
- return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
-}
-
-bool8 IsTradedMon(struct Pokemon *mon)
-{
- u8 otName[OT_NAME_LENGTH + 1];
- u32 otId;
- GetMonData(mon, MON_DATA_OT_NAME, otName);
- otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- return IsOtherTrainer(otId, otName);
-}
-
-bool8 IsOtherTrainer(u32 otId, u8 *otName)
-{
- if (otId ==
- (gSaveBlock2Ptr->playerTrainerId[0]
- | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
- | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
- | (gSaveBlock2Ptr->playerTrainerId[3] << 24)))
- {
- int i;
-
- for (i = 0; otName[i] != EOS; i++)
- if (otName[i] != gSaveBlock2Ptr->playerName[i])
- return TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-void MonRestorePP(struct Pokemon *mon)
-{
- BoxMonRestorePP(&mon->box);
-}
-
-void BoxMonRestorePP(struct BoxPokemon *boxMon)
-{
- int i;
-
- for (i = 0; i < 4; i++)
- {
- if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0))
- {
- u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0);
- u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0);
- u8 pp = CalculatePPWithBonus(move, bonus, i);
- SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp);
- }
- }
-}
-
-void sub_806E994(void)
-{
- gLastUsedAbility = gBattleStruct->field_B0;
-
- gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
- gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
- gBattleTextBuff1[2] = gBattleStruct->field_49;
- gBattleTextBuff1[4] = B_BUFF_EOS;
-
- if (!GetBattlerSide(gBattleStruct->field_49))
- gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]);
- else
- gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49];
-
- PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, pokemon_order_func(gBattlerPartyIndexes[gBattlerInMenuId]))
-
- BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
-}
-
-struct PokeItem
-{
- u16 species;
- u16 item;
-};
-
-extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
-
-static s32 GetWildMonTableIdInAlteringCave(u16 species)
-{
- s32 i;
- for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++)
- if (gAlteringCaveWildMonHeldItems[i].species == species)
- return i;
- return 0;
-}
-
-void SetWildMonHeldItem(void)
-{
- if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
- {
- u16 rnd = Random() % 100;
- u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
- u16 var1 = 45;
- u16 var2 = 95;
- if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0)
- && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES)
- {
- var1 = 20;
- var2 = 80;
- }
- if (gMapHeader.mapDataId == 0x1A4)
- {
- s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
- if (alteringCaveId != 0)
- {
- if (rnd < var2)
- return;
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gAlteringCaveWildMonHeldItems[alteringCaveId].item);
- }
- else
- {
- if (rnd < var1)
- return;
- if (rnd < var2)
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- else
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
- }
- }
- else
- {
- if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0)
- {
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- }
- else
- {
- if (rnd < var1)
- return;
- if (rnd < var2)
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- else
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
- }
- }
- }
-}
-
-bool8 IsMonShiny(struct Pokemon *mon)
-{
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return IsShinyOtIdPersonality(otId, personality);
-}
-
-bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
-{
- bool8 retVal = FALSE;
- u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- retVal = TRUE;
- return retVal;
-}
-
-const u8 *GetTrainerPartnerName(void)
-{
- if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
- {
- if (gPartnerTrainerId == STEVEN_PARTNER_ID)
- {
- return gTrainers[TRAINER_STEVEN].trainerName;
- }
- else
- {
- GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
- return gStringVar1;
- }
- }
- else
- {
- u8 id = GetMultiplayerId();
- return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name;
- }
-}
-
-#define READ_PTR_FROM_TASK(taskId, dataId) \
- (void*)( \
- ((u16)(gTasks[taskId].data[dataId]) | \
- ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10)))
-
-#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \
-{ \
- gTasks[taskId].data[dataId] = (u32)(ptr); \
- gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \
-}
-
-static void Task_AnimateAfterDelay(u8 taskId)
-{
- if (--gTasks[taskId].data[3] == 0)
- {
- LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
- DestroyTask(taskId);
- }
-}
-
-static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
-{
- if (--gTasks[taskId].data[3] == 0)
- {
- StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
- sub_81C488C(0xFF);
- DestroyTask(taskId);
- }
-}
-
-void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
-{
- if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
- DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80);
- else
- DoMonFrontSpriteAnimation(sprite, species, noCry, arg3);
-}
-
-extern void SpriteCallbackDummy_2(struct Sprite*);
-
-void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
-{
- s8 pan;
- switch (arg3 & 0x7F)
- {
- case 0:
- pan = -25;
- break;
- case 1:
- pan = 25;
- break;
- default:
- pan = 0;
- break;
- }
- if (arg3 & 0x80)
- {
- if (!noCry)
- PlayCry1(species, pan);
- sprite->callback = SpriteCallbackDummy;
- }
- else
- {
- if (!noCry)
- {
- PlayCry1(species, pan);
- if (HasTwoFramesAnimation(species))
- StartSpriteAnim(sprite, 1);
- }
- if (gMonAnimationDelayTable[species - 1] != 0)
- {
- u8 taskId = CreateTask(Task_AnimateAfterDelay, 0);
- STORE_PTR_IN_TASK(sprite, taskId, 0);
- gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
- gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
- }
- else
- {
- LaunchAnimationTaskForFrontSprite(sprite, gMonFrontAnimIdsTable[species - 1]);
- }
- sprite->callback = SpriteCallbackDummy_2;
- }
-}
-
-void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame)
-{
- if (!oneFrame && HasTwoFramesAnimation(species))
- StartSpriteAnim(sprite, 1);
- if (gMonAnimationDelayTable[species - 1] != 0)
- {
- u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0);
- STORE_PTR_IN_TASK(sprite, taskId, 0);
- gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
- gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
- sub_81C488C(taskId);
- SetSpriteCB_MonAnimDummy(sprite);
- }
- else
- {
- StartMonSummaryAnimation(sprite, gMonFrontAnimIdsTable[species - 1]);
- }
-}
-
-void sub_806EE98(void)
-{
- u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay);
- if (delayTaskId != 0xFF)
- DestroyTask(delayTaskId);
-}
-
-void BattleAnimateBackSprite(struct Sprite* sprite, u16 species)
-{
- if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
- {
- sprite->callback = SpriteCallbackDummy;
- }
- else
- {
- LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species));
- sprite->callback = SpriteCallbackDummy_2;
- }
-}
-
-u8 sub_806EF08(u8 arg0)
-{
- s32 i;
- s32 var = 0;
- u8 multiplayerId = GetMultiplayerId();
- switch (gLinkPlayers[multiplayerId].lp_field_18)
- {
- case 0:
- case 2:
- var = (arg0 != 0) ? 1 : 3;
- break;
- case 1:
- case 3:
- var = (arg0 != 0) ? 2 : 0;
- break;
- }
- for (i = 0; i < 4; i++)
- {
- if (gLinkPlayers[i].lp_field_18 == (s16)(var))
- break;
- }
- return i;
-}
-
-u8 sub_806EF84(u8 arg0, u8 arg1)
-{
- s32 i;
- s32 var = 0;
- switch (gLinkPlayers[arg1].lp_field_18)
- {
- case 0:
- case 2:
- var = (arg0 != 0) ? 1 : 3;
- break;
- case 1:
- case 3:
- var = (arg0 != 0) ? 2 : 0;
- break;
- }
- for (i = 0; i < 4; i++)
- {
- if (gLinkPlayers[i].lp_field_18 == (s16)(var))
- break;
- }
- return i;
-}
-
-extern const u8 gFacilityClassToPicIndex[];
-
-u16 sub_806EFF0(u16 arg0)
-{
- return gFacilityClassToPicIndex[arg0];
-}
-
-u16 PlayerGenderToFrontTrainerPicId(u8 playerGender)
-{
- if (playerGender)
- return sub_806EFF0(0x3F);
- else
- return sub_806EFF0(0x3C);
-}
-
-extern const u8 gTrainerClassNames[][13];
-
-void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
-{
- u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT;
- if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set
- {
- GetSetPokedexFlag(nationalNum, caseId);
- if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN)
- gSaveBlock2Ptr->pokedex.unownPersonality = personality;
- if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA)
- gSaveBlock2Ptr->pokedex.spindaPersonality = personality;
- }
-}
-
-const u8 *GetTrainerClassNameFromId(u16 trainerId)
-{
- if (trainerId > NO_OF_TRAINERS)
- trainerId = 0;
- return gTrainerClassNames[gTrainers[trainerId].trainerClass];
-}
-
-const u8 *GetTrainerNameFromId(u16 trainerId)
-{
- if (trainerId > NO_OF_TRAINERS)
- trainerId = 0;
- return gTrainers[trainerId].trainerName;
-}
-
-bool8 HasTwoFramesAnimation(u16 species)
-{
- return (species != SPECIES_CASTFORM
- && species != SPECIES_DEOXYS
- && species != SPECIES_SPINDA
- && species != SPECIES_UNOWN);
-}
-
-bool8 sub_806F104(void)
-{
- if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER))
- return TRUE;
- if (!gMain.inBattle && (InBattlePike() || InBattlePyramid()))
- return TRUE;
- return FALSE;
-}
-
-/*
-
-extern const struct SpriteTemplate gUnknown_08329D98[];
-
-struct Unknown_806F160_Struct
-{
- u8 field_0;
- u8 field_1;
- u8 field_2;
- u8 field_3;
- u8 field_4;
- u8 field_5;
- u8 field_6;
- u8 field_7;
- u8 field_8;
- u8 field_9;
- u8 field_A;
- u8 field_B;
- struct SpriteTemplate* templates;
-};
-
-void sub_806F160(struct Unknown_806F160_Struct* structPtr)
-{
- u16 i, j;
- for (i = 0; i < structPtr->field_0; i++)
- {
- structPtr->templates[i] = gUnknown_08329D98[i];
- for (j = 0; j < structPtr->field_1)
- {
- // no clue what the pointer in the struct point to :/
- }
- }
-} */
-
diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c
index 8c9e7a8a0..1e5245d70 100644
--- a/src/pokemon_summary_screen.c
+++ b/src/pokemon_summary_screen.c
@@ -21,6 +21,11 @@
#include "text.h"
#include "window.h"
#include "event_data.h"
+#include "gpu_regs.h"
+#include "menu.h"
+#include "international_string_util.h"
+#include "scanline_effect.h"
+#include "menu_helpers.h"
struct ContestMove
{
@@ -42,7 +47,6 @@ extern struct BgTemplate gUnknown_0861CBB4;
extern u8 gUnknown_0203CF20;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
extern s8 gUnknown_0861CC1C[];
-extern u8 gUnknown_08329D22[];
extern u8 gUnknown_0203CF21;
extern struct UnkStruct_61CC04 gUnknown_0861CC04;
extern struct UnkStruct_61CC04 gUnknown_0861CC10;
@@ -65,20 +69,9 @@ extern u8 gUnknown_0861CE7B[];
extern struct WindowTemplate gUnknown_0861CCEC;
extern struct WindowTemplate gUnknown_0861CD14;
-extern void sub_806F2AC(u8 a, u8 b);
void sub_81C488C(u8 a);
-extern void do_scheduled_bg_tilemap_copies_to_vram(void);
extern u8 sub_81221EC();
extern u8 sub_81221AC();
-extern void SetVBlankHBlankCallbacksToNull();
-extern void ResetVramOamAndBgCntRegs();
-extern void clear_scheduled_bg_copies_to_vram();
-extern void ScanlineEffect_Stop();
-extern void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable);
-extern void ShowBg(u8 a);
-extern void SetGpuReg(u8 regOffset, u16 value);
-extern void schedule_bg_copy_tilemap_to_vram(u8 a);
-extern void SetBgTilemapBuffer(u8 bg, void *tilemap);
extern u8 gUnknown_08D9862C;
extern u8 gUnknown_08D98CC8;
extern u8 gUnknown_08D987FC;
@@ -93,9 +86,6 @@ extern struct CompressedSpritePalette gUnknown_0861D100;
extern struct CompressedSpritePalette gUnknown_0861D07C;
extern u8 gMoveTypes_Pal;
extern u8 gUnknown_08D97D0C;
-extern void reset_temp_tile_data_buffers();
-extern void decompress_and_copy_tile_data_to_vram(u8 a, void* tiledata, u8 b, u8 c, u8 d);
-extern u8 free_temp_tile_data_buffers_if_possible();
extern void sub_81C1E20(u8 taskId);
extern u8 *GetMonNickname(struct Pokemon *mon, u8 *dest);
extern u16 SpeciesToPokedexNum(u16 species);
@@ -158,11 +148,7 @@ extern u8 gText_ThreeDashes[];
extern u8 gUnknown_0861CE97[];
extern struct BattleMove gBattleMoves[];
-extern u32 ChangeBgX(u8 bg, u32 value, u8 op);
extern void sub_8199C30(u8 a, u8 b, u8 c, u8 d, u8 e, u8 f);
-extern void AddTextPrinterParameterized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, const u8* colors, s8 speed, u8 *str);
-extern s32 GetStringCenterAlignXOffset(u8 fontId, u8 *str, s32 totalWidth);
-extern s32 GetStringRightAlignXOffset(u8 fontId, u8 *str, s32 totalWidth);
extern bool8 sub_81A6BF4();
extern bool8 sub_81B9E94();
extern void UnkTextUtil_Reset();
@@ -1433,7 +1419,7 @@ void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId)
*ppBonusesPtr = localPpBonuses;
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId)
{
asm(".syntax unified\n\
@@ -1644,7 +1630,7 @@ void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId)
*ppBonusesPtr = localPpBonuses;
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId)
{
asm(".syntax unified\n\
@@ -2055,7 +2041,7 @@ void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d)
Free(alloced);
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d)
{
asm(".syntax unified\n\
@@ -2357,7 +2343,7 @@ void sub_81C2194(u16 *a, u16 b, u8 c)
}
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C2194(u16 *a, u16 b, u8 c)
{
asm(".syntax unified\n\
@@ -2806,7 +2792,7 @@ u8 sub_81C2D2C(struct WindowTemplate *template, u8 a)
return r4[a];
}
#else
-__attribute__((naked))
+ASM_DIRECT
u8 sub_81C2D2C(struct WindowTemplate *template, u8 a)
{
asm(".syntax unified\n\
@@ -2851,7 +2837,7 @@ void sub_81C2D68(u8 a)
}
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C2D68(u8 a)
{
asm(".syntax unified\n\
@@ -3108,7 +3094,7 @@ void sub_81C335C()
sub_81C25A4(r4, gText_FiveMarks, r5, 1, 0, 1);
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C335C()
{
asm(".syntax unified\n\
@@ -3451,7 +3437,7 @@ void sub_81C3B08(u8 a)
sub_81C25A4(sp, text, offset, (a<<4), 0, r5);
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_81C3B08(u8 a)
{
asm(".syntax unified\n\
diff --git a/src/recorded_battle.c b/src/recorded_battle.c
index e60457257..4cb2eab49 100644
--- a/src/recorded_battle.c
+++ b/src/recorded_battle.c
@@ -100,7 +100,6 @@ EWRAM_DATA static u16 sUnknown_0203CCDC[6] = {0};
EWRAM_DATA static u8 sUnknown_0203CCE8 = 0;
extern u32 sub_81A513C(void);
-extern void PlayMapChosenOrBattleBGM(bool8);
// this file's functions
static u8 sub_8185278(u8 *arg0, u8 *arg1, u8 *arg2);
@@ -476,7 +475,7 @@ u32 MoveRecordedBattleToSaveData(void)
}
#else
-__attribute__((naked))
+ASM_DIRECT
u32 MoveRecordedBattleToSaveData(void)
{
asm(".syntax unified\n\
diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c
index b12917c61..cedd3aee4 100644
--- a/src/reshow_battle_screen.c
+++ b/src/reshow_battle_screen.c
@@ -22,7 +22,6 @@ extern u16 gBattle_BG2_X;
extern u16 gBattle_BG2_Y;
extern u16 gBattle_BG3_X;
extern u16 gBattle_BG3_Y;
-extern struct SpriteTemplate gUnknown_0202499C;
extern const union AnimCmd * const * const gMonAnimationsSpriteAnimsPtrTable[];
@@ -162,10 +161,10 @@ static void CB2_ReshowBattleScreenAfterMenu(void)
ActionSelectionCreateCursorAt(gActionSelectionCursor[gBattlerInMenuId], 0);
- if (gLinkVSyncDisabled != 0 && gReceivedRemoteLinkPlayers != 0)
+ if (gWirelessCommType != 0 && gReceivedRemoteLinkPlayers != 0)
{
sub_800E0E8();
- sub_800DFB4(0, 0);
+ CreateWirelessStatusIndicatorSprite(0, 0);
}
}
break;
diff --git a/src/rom_8011DC0.c b/src/rom_8011DC0.c
new file mode 100644
index 000000000..9076b611a
--- /dev/null
+++ b/src/rom_8011DC0.c
@@ -0,0 +1,18 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA u32 gUnknown_03000DA0;
+IWRAM_DATA u32 gUnknown_03000DA4;
+IWRAM_DATA void *gUnknown_03000DA8;
+IWRAM_DATA void *gUnknown_03000DAC;
+IWRAM_DATA bool32 gUnknown_03000DB0;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/scrcmd.c b/src/scrcmd.c
index d2e9c13c9..deb170c68 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -31,7 +31,6 @@
#include "mystery_event_script.h"
#include "palette.h"
#include "party_menu.h"
-#include "pokemon_3.h"
#include "pokemon_storage_system.h"
#include "random.h"
#include "overworld.h"
@@ -1529,7 +1528,7 @@ bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
CopyWindowToVram(gUnknown_03000F30, 3);
return FALSE;
}*/
-__attribute__((naked))
+ASM_DIRECT
bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
{
asm("push {r4-r7,lr}\n\
diff --git a/src/text.c b/src/text.c
index 6a83d5d15..a2495d068 100644
--- a/src/text.c
+++ b/src/text.c
@@ -379,7 +379,7 @@ void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor)
*(current++) = (shadowColor << 12) | (shadowColor << 8) | (shadowColor << 4) | shadowColor;
}
#else
-__attribute__((naked))
+ASM_DIRECT
void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor)
{
asm("push {r4-r7,lr}\n\
@@ -875,7 +875,7 @@ void DecompressGlyphTile(const u16 *src, u16 *dest)
*(dest) = (gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] & 0xFF]] << 16) | gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] >> 8]];
}
#else
-__attribute__((naked))
+ASM_DIRECT
void DecompressGlyphTile(const u16 *src, u16 *dest)
{
asm("push {r4-r7,lr}\n\
@@ -1056,7 +1056,7 @@ u8 GetLastTextColor(u8 colorType)
}
}
-__attribute__((naked))
+ASM_DIRECT
void CopyGlyphToWindow(struct TextPrinter *x)
{
asm("push {r4-r7,lr}\n\
@@ -2285,7 +2285,6 @@ u16 RenderText(struct TextPrinter *textPrinter)
else
textPrinter->subPrinter.currentX += gUnknown_03002F90[0x80];
}
-
return 0;
case 1: // _08005C78
if (TextPrinterWait(textPrinter))
diff --git a/src/tv.c b/src/tv.c
index ddcff9f1d..fbe39fde0 100644
--- a/src/tv.c
+++ b/src/tv.c
@@ -2154,7 +2154,7 @@ void sub_80EDE98(TVShow *show)
}
}
#else
-__attribute__((naked))
+ASM_DIRECT
void sub_80EDE98(TVShow *show)
{
asm_unified("\tpush {r4-r7,lr}\n"
@@ -4110,7 +4110,7 @@ void sub_80F0708(void) // FIXME: register allocation shenanigans
}
}
#else
-__attribute__((naked)) void sub_80F0708(void)
+ASM_DIRECT void sub_80F0708(void)
{
asm_unified("\tpush {r4-r7,lr}\n"
"\tmov r7, r9\n"
diff --git a/src/util.c b/src/util.c
index 58088c3ee..4f9241b21 100644
--- a/src/util.c
+++ b/src/util.c
@@ -230,7 +230,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
}
#else
-__attribute__((naked)) void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
+ASM_DIRECT void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
{
asm("\n\
.syntax unified\n\
diff --git a/src/window.c b/src/window.c
index 9a892d079..589557d43 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2,8 +2,11 @@
#include "window.h"
#include "malloc.h"
-extern u8 gUnknown_03002F60;
-extern void* gUnknown_03002F70[];
+u32 filler_03002F58;
+u32 filler_03002F5C;
+u8 gUnknown_03002F60;
+u32 filler_03002F64;
+void *gUnknown_03002F70[4];
extern u32 gUnneededFireRedVariable;
#define WINDOWS_MAX 32