summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcamthesaxman <cameronghall@cox.net>2018-01-14 20:39:52 -0600
committercamthesaxman <cameronghall@cox.net>2018-01-14 20:39:52 -0600
commit07f5db48c075f55a67136afb84ac804d525f5de3 (patch)
tree2daef3cfdbdaf66c7e91c629a75a9730c6a85191
parent20de25004946139a601cd2965afc2e9645a56b96 (diff)
start decompiling the behemoth that is sub_803E1B0
-rw-r--r--asm/pokemon_item_effect.s21
-rw-r--r--include/battle.h2
-rw-r--r--include/pokemon.h3
-rw-r--r--include/pokemon_item_effect.h2
-rw-r--r--ld_script.txt1
-rw-r--r--src/pokemon/pokemon_item_effect.c454
6 files changed, 459 insertions, 24 deletions
diff --git a/asm/pokemon_item_effect.s b/asm/pokemon_item_effect.s
index 6995dc62b..ba1b37dcb 100644
--- a/asm/pokemon_item_effect.s
+++ b/asm/pokemon_item_effect.s
@@ -5,27 +5,6 @@
.text
- thumb_func_start ExecuteTableBasedItemEffect_
-ExecuteTableBasedItemEffect_: @ 803E18C
- push {r4,lr}
- sub sp, 0x4
- lsls r1, 16
- lsrs r1, 16
- lsls r2, 24
- lsrs r2, 24
- lsls r3, 24
- lsrs r3, 24
- movs r4, 0
- str r4, [sp]
- bl sub_803E1B0
- lsls r0, 24
- lsrs r0, 24
- add sp, 0x4
- pop {r4}
- pop {r1}
- bx r1
- thumb_func_end ExecuteTableBasedItemEffect_
-
thumb_func_start sub_803E1B0
sub_803E1B0: @ 803E1B0
push {r4-r7,lr}
diff --git a/include/battle.h b/include/battle.h
index 27ed57045..c94325cd5 100644
--- a/include/battle.h
+++ b/include/battle.h
@@ -473,7 +473,7 @@ struct sideTimer
u8 lightscreenTimer; //0x1
u8 mistTimer; //0x2
u8 field3; //0x3
- u16 field4; //0x4
+ u16 field4; //0x4
u8 spikesAmount; //0x6
u8 safeguardTimer; //0x7
u8 followmeTimer; //0x8
diff --git a/include/pokemon.h b/include/pokemon.h
index 539323bdb..874ad7e09 100644
--- a/include/pokemon.h
+++ b/include/pokemon.h
@@ -628,5 +628,8 @@ void PartySpreadPokerus(struct Pokemon *party);
struct Sprite *sub_80F7920(u16, u16, const u16 *);
+bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId);
+
+
#endif // GUARD_POKEMON_H
diff --git a/include/pokemon_item_effect.h b/include/pokemon_item_effect.h
index c09649aff..014612b05 100644
--- a/include/pokemon_item_effect.h
+++ b/include/pokemon_item_effect.h
@@ -1,6 +1,6 @@
#ifndef GUARD_POKEMON_ITEM_EFFECT_H
#define GUARD_POKEMON_ITEM_EFFECT_H
-bool8 ExecuteTableBasedItemEffect_(struct Pokemon *mon, u16, u8, u16);
+bool8 ExecuteTableBasedItemEffect_(struct Pokemon *mon, u16, u8, u8);
#endif // GUARD_POKEMON_ITEM_EFFECT_H
diff --git a/ld_script.txt b/ld_script.txt
index 128eb4c20..3a6305509 100644
--- a/ld_script.txt
+++ b/ld_script.txt
@@ -61,6 +61,7 @@ SECTIONS {
src/pokemon/pokemon_1.o(.text);
src/battle/calculate_base_damage.o(.text);
src/pokemon/pokemon_2.o(.text);
+ src/pokemon/pokemon_item_effect.o(.text);
asm/pokemon_item_effect.o(.text);
src/pokemon/pokemon_3.o(.text);
src/de_rom_8040FE0.o(.text);
diff --git a/src/pokemon/pokemon_item_effect.c b/src/pokemon/pokemon_item_effect.c
index 66f2ff697..34a61a489 100644
--- a/src/pokemon/pokemon_item_effect.c
+++ b/src/pokemon/pokemon_item_effect.c
@@ -1,7 +1,29 @@
#include "global.h"
+#include "constants/items.h"
+#include "constants/species.h"
+#include "battle.h"
+#include "evolution_scene.h"
+#include "ewram.h"
+#include "item.h"
+#include "main.h"
#include "pokemon.h"
+#include "pokemon_item_effect.h"
+#include "rom_8077ABC.h"
+#include "rom_8094928.h"
+#include "util.h"
-const u8 gUnknown_082082F2[] = {
+extern s32 gBattleMoveDamage;
+extern u8 gAbsentBankFlags;
+extern u8 gBankInMenu;
+extern u8 gNoOfAllBanks;
+extern u16 gBattlePartyID[];
+extern u8 gActiveBank;
+extern u8 gStringBank;
+extern struct BattlePokemon gBattleMons[];
+extern struct BattleEnigmaBerry gEnigmaBerries[];
+
+const u8 gUnknown_082082F2[] =
+{
MON_DATA_HP_EV,
MON_DATA_ATK_EV,
MON_DATA_DEF_EV,
@@ -9,3 +31,433 @@ const u8 gUnknown_082082F2[] = {
MON_DATA_SPDEF_EV,
MON_DATA_SPATK_EV
};
+
+bool8 sub_803E1B0(struct Pokemon *pkmn, u16 b, u8 c, u8 d, u8 e);
+
+bool8 ExecuteTableBasedItemEffect_(struct Pokemon *pkmn, u16 b, u8 c, u8 d)
+{
+ return sub_803E1B0(pkmn, b, c, d, 0);
+}
+
+extern u8 gUnknown_08208238[];
+extern u8 gUnknown_08208240[];
+
+bool8 sub_803E1B0(struct Pokemon *pkmn, u16 b, u8 c, u8 d, u8 e)
+{
+ int r10;
+ int r5;
+ u8 sp18;
+ int sp1C = 1;
+ const u8 *sp20;
+ u8 sp24 = 6;
+ u32 sp28;
+ int sp2C = 0;
+ u8 sp30;
+ int sp34 = 4;
+ u16 item;
+ u16 r4;
+
+ item = GetMonData(pkmn, MON_DATA_HELD_ITEM);
+ if (item == 0xAF)
+ {
+ if (gMain.inBattle)
+ sp30 = gEnigmaBerries[gBankInMenu].holdEffect;
+ else
+ sp30 = gSaveBlock1.enigmaBerry.holdEffect;
+ }
+ //_0803E240
+ else
+ {
+ sp30 = ItemId_GetHoldEffect(item);
+ }
+ //_0803E248
+
+ gStringBank = gBankInMenu;
+ if (gMain.inBattle)
+ {
+ gActiveBank = gBankInMenu;
+ sp18 = (GetBankSide(gActiveBank) != 0);
+ r4 = b - 13;
+ while (sp18 < gNoOfAllBanks)
+ {
+ if (gBattlePartyID[sp18] == c)
+ {
+ sp34 = sp18;
+ break;
+ }
+ sp18 += 2;
+ }
+ }
+ //_0803E2E8
+ else
+ {
+ gActiveBank = 0;
+ sp34 = 4;
+ r4 = b - 13;
+ }
+ //_0803E2F4
+
+ if (r4 > 0xA5)
+ return 1;
+
+ if (gItemEffectTable[r4] == NULL && b != 0xAF)
+ return 1;
+ if (b == 0xAF)
+ {
+ //_0803E31E
+ if (gMain.inBattle)
+ sp20 = gEnigmaBerries[gActiveBank].itemEffect;
+ else
+ sp20 = gSaveBlock1.enigmaBerry.itemEffect;
+ }
+ //_0803E372
+ else
+ {
+ sp20 = gItemEffectTable[r4];
+ }
+
+ // Now, the HUGE loop!
+ for (sp18 = 0; sp18 < 6; sp18++)
+ {
+ switch (sp18)
+ {
+ case 0:
+ //_0803E3A8
+ if ((sp20[sp18] & 0x80) && gMain.inBattle
+ && sp34 != 4 && (gBattleMons[sp34].status2 & 0xF0000))
+ {
+ gBattleMons[sp34].status2 &= 0xFFF0FFFF;
+ sp1C = 0;
+ }
+ //_0803E3F0
+ if ((sp20[sp18] & 0x30) && !(gBattleMons[gActiveBank].status2 & 0x4000000))
+ {
+ gBattleMons[gActiveBank].status2 |= 0x4000000;
+ sp1C = 0;
+ }
+ //_0803E41E
+ if ((sp20[sp18] & 0xF) && gBattleMons[gActiveBank].statStages[1] < 12)
+ {
+ if (gBattleMons[gActiveBank].statStages[1] > 12)
+ gBattleMons[gActiveBank].statStages[1] = 12;
+ sp1C = 0;
+ break;
+ }
+ break;
+ case 1:
+ //_0803E474
+ // r3 might be a temporary variable
+ if ((sp20[sp18] & 0xF0) && gBattleMons[gActiveBank].statStages[2] < 12)
+ {
+ gBattleMons[gActiveBank].statStages[2] += sp20[sp18] & 0xF0;
+ if (gBattleMons[gActiveBank].statStages[2] > 12)
+ gBattleMons[gActiveBank].statStages[2] = 12;
+ sp1C = 0;
+ }
+ //_0803E4BA
+ if ((sp20[sp18] & 0xF) && gBattleMons[gActiveBank].statStages[3] < 12)
+ {
+ gBattleMons[gActiveBank].statStages[3] += sp20[sp18] & 0xF;
+ if (gBattleMons[gActiveBank].statStages[3] > 12)
+ gBattleMons[gActiveBank].statStages[3] = 12;
+ sp1C = 0;
+ }
+ break;
+ case 2:
+ //_0803E508
+ if ((sp20[sp18] & 0xF0) && gBattleMons[gActiveBank].statStages[4] < 12)
+ {
+ gBattleMons[gActiveBank].statStages[4] += sp20[sp18] & 0xF0;
+ if (gBattleMons[gActiveBank].statStages[4] > 12)
+ gBattleMons[gActiveBank].statStages[4] = 12;
+ sp1C = 0;
+ }
+ //_0803E54E
+ if ((sp20[sp18] & 0xF) && gBattleMons[gActiveBank].statStages[6] < 12)
+ {
+ gBattleMons[gActiveBank].statStages[6] += sp20[sp18] & 0xF;
+ if (gBattleMons[gActiveBank].statStages[6] > 12)
+ gBattleMons[gActiveBank].statStages[6] = 12;
+ sp1C = 0;
+ }
+ break;
+ case 3:
+ //_0803E59C
+ if ((sp20[sp18] & 0x80) && gSideTimers[GetBankSide(gActiveBank)].mistTimer == 0)
+ {
+ gSideTimers[GetBankSide(gActiveBank)].mistTimer = 5;
+ sp1C = 0;
+ }
+ //_0803E5E4
+ if ((sp20[sp18] & 0x40) && GetMonData(pkmn, MON_DATA_LEVEL) != 100)
+ {
+ u32 exp = gExperienceTables[gBaseStats[GetMonData(pkmn, MON_DATA_SPECIES)].growthRate][GetMonData(pkmn, MON_DATA_LEVEL) + 1];
+
+ SetMonData(pkmn, MON_DATA_EXP, &exp);
+ CalculateMonStats(pkmn);
+ sp1C = 0;
+ }
+ //_0803E646
+ if ((sp20[sp18] & 0x20) && HealStatusConditions(pkmn, c, 7, sp34) == 0)
+ {
+ if (sp34 != 4)
+ gBattleMons[sp34].status2 &= 0xF7FFFFFF;
+ sp1C = 0;
+ }
+ //_0803E682
+ if ((sp20[sp18] & 0x10) && HealStatusConditions(pkmn, c, 0xF88, sp34) == 0)
+ sp1C = 0;
+ //_0803E6A2
+ if ((sp20[sp18] & 8) && HealStatusConditions(pkmn, c, 16, sp34) == 0)
+ sp1C = 0;
+ //_0803E6C2
+ if ((sp20[sp18] & 4) && HealStatusConditions(pkmn, c, 32, sp34) == 0)
+ sp1C = 0;
+ //_0803E6E2
+ if ((sp20[sp18] & 2) && HealStatusConditions(pkmn, c, 64, sp34) == 0)
+ sp1C = 0;
+ //_0803E702
+ if ((sp20[sp18] & 1) && gMain.inBattle
+ && sp34 != 4 && (gBattleMons[sp34].status2 & 7))
+ {
+ gBattleMons[sp34].status2 &= ~7;
+ sp1C = 0;
+ }
+ break;
+ case 4:
+ //_0803E77C
+ r10 = sp20[sp18] & 0x20;
+ if (r10 != 0)
+ {
+ u32 sp0;
+ u16 r4;
+
+ r10 &= 0xDF;
+
+ sp0 = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gUnknown_08208238[d]) << (d * 2);
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + d, NULL);
+ sp28 = CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), d);
+ if (sp0 <= 2 && sp28 > 4)
+ {
+ sp0 = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) + gUnknown_08208240[d];
+ SetMonData(pkmn, MON_DATA_PP_BONUSES, &sp0);
+
+ sp0 = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + d), sp0, d) - sp28;
+ sp0 += GetMonData(pkmn, MON_DATA_PP1 + d, NULL);
+ SetMonData(pkmn, MON_DATA_PP1 + d, &sp0);
+ sp1C = 0;
+ }
+ }
+ //_0803E854
+ sp28 = 0;
+ while (r10 != 0)
+ {
+ if (r10 & 1)
+ {
+ u16 r5;
+ u32 r4;
+ u32 sp0;
+ u32 r1;
+
+ switch (sp28)
+ {
+ case 0:
+ case 1:
+ //_0803E8AC
+ r5 = GetMonEVCount(pkmn);
+ if (r5 >= 510)
+ return 1;
+ r1 = GetMonData(pkmn, gUnknown_082082F2[sp28], NULL);
+ sp0 = r1;
+ if (r1 < 100)
+ {
+ r1 += sp20[sp24];
+ if (r1 > 100)
+ r4 = 100 - r1;
+ else
+ r4 = sp20[sp24];
+ //_0803E8F6
+ if (r5 + r4 > 510)
+ r4 = (r4 - 510) - (r5 + r4);
+ sp0 += r4;
+ SetMonData(pkmn, gUnknown_082082F2[sp28], &sp0);
+ CalculateMonStats(pkmn);
+ sp24++;
+ sp1C = 0;
+ }
+ break;
+ case 2:
+ //_0803E934
+ if (r10 & 0x10)
+ {
+ if (GetMonData(pkmn, MON_DATA_HP, NULL) != 0)
+ {
+ sp24++;
+ break;
+ }
+ if (gMain.inBattle)
+ {
+ if (sp34 != 4)
+ {
+ gAbsentBankFlags &= ~gBitTable[sp34];
+ CopyPlayerPartyMonToBattleData(sp34, pokemon_order_func(gBattlePartyID[sp34]));
+ // tail merge, possibly?
+ }
+ //_0803E9B4
+ else
+ {
+ gAbsentBankFlags &= ~gBitTable[gActiveBank ^ 2];
+ }
+ //_0803E9CC
+ if (GetBankSide(gActiveBank) == 0 && gBattleResults.unk4 < 255)
+ gBattleResults.unk4++;
+ }
+ //to _0803EA0A
+ }
+ //_0803E9F4
+ else
+ {
+ if (GetMonData(pkmn, MON_DATA_HP, NULL) == 0)
+ {
+ sp24++;
+ break;
+ }
+ }
+ //_0803EA0A
+ sp0 = sp20[sp24++];
+ switch (sp0)
+ {
+ case 0xFF:
+ //_0803EA2C
+ if (sp0 == 0xFF) // wat?
+ sp0 = GetMonData(pkmn, MON_DATA_MAX_HP, NULL) - GetMonData(pkmn, MON_DATA_HP, NULL);
+ break;
+ case 0xFE:
+ sp0 = GetMonData(pkmn, MON_DATA_MAX_HP, NULL) * 2;
+ if (sp0 == 0)
+ sp0 = 1;
+ break;
+ case 0xFD:
+ sp0 = eStatHp;
+ break;
+ }
+ //_0803EA6C
+ if (GetMonData(pkmn, MON_DATA_MAX_HP) != GetMonData(pkmn, MON_DATA_HP))
+ {
+ if (e == 0)
+ {
+ sp0 += GetMonData(pkmn, MON_DATA_HP, NULL);
+ if (sp0 > GetMonData(pkmn, MON_DATA_MAX_HP, NULL))
+ sp0 = GetMonData(pkmn, MON_DATA_MAX_HP);
+ //_0803EAB8
+ SetMonData(pkmn, MON_DATA_HP, &sp0);
+ if (gMain.inBattle && sp34 != 4)
+ {
+ gBattleMons[sp34].hp = sp0;
+ if (!(r10 & 0x10) && GetBankSide(gActiveBank) == 0)
+ {
+ u8 r5;
+
+ if (gBattleResults.unk3 < 255)
+ gBattleResults.unk3++;
+ r5 = gActiveBank;
+ gActiveBank = sp34;
+ EmitGetAttributes(0, 0, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ gActiveBank = r5;
+ }
+ }
+ //to _0803EB48
+ }
+ //_0803EB40
+ else
+ {
+ gBattleMoveDamage *= -1;
+ }
+ //_0803EB48
+ sp1C = 0;
+ }
+ //_0803EB4C
+ r10 &= 0xEF;
+ break;
+ case 3:
+ if (!(r10 & 2))
+ {
+ for (r5 = 0; r5 < 4; r5++)
+ {
+ u16 r4;
+
+ sp0 = GetMonData(pkmn, MON_DATA_PP1 + r5, NULL);
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + r5, NULL);
+ if (sp0 != CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), r5))
+ {
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + r5, NULL);
+ if (sp0 > CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), r5))
+ {
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + r5, NULL);
+ sp0 = CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), r5);
+ }
+ //_0803EC28
+ SetMonData(pkmn, MON_DATA_PP1 + r5, &sp0);
+ if (gMain.inBattle
+ && sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000)
+ && !(gDisableStructs[sp34].unk18_b & gBitTable[r5]))
+ gBattleMons[sp34].pp[r5] = sp0;
+ //_0803EC8E
+ sp1C = 0;
+ }
+ //_0803EC92
+ }
+ //_0803EC9A
+ sp24++;
+ }
+ //_0803ECB8
+ else
+ {
+ u16 r4;
+
+ sp0 = GetMonData(pkmn, MON_DATA_PP1 + d, NULL);
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + d, NULL);
+ if (sp0 != CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), d))
+ {
+ //_0803ED00
+ sp0 = sp20[sp24++];
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + d, NULL);
+ if (sp0 > CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), d))
+ {
+ r4 = GetMonData(pkmn, MON_DATA_MOVE1 + d, NULL);
+ sp0 = CalculatePPWithBonus(r4, GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), d);
+ }
+ //_0803ED74
+ SetMonData(pkmn, MON_DATA_PP1 + d, &sp0);
+ if (gMain.inBattle
+ && sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000)
+ && !(gDisableStructs[sp34].unk18_b & gBitTable[d]))
+ gBattleMons[sp34].pp[d] = sp0;
+ //_0803EDD8
+ sp1C = 0;
+ }
+ }
+ break;
+ case 7:
+ //_0803EDF4
+ {
+ u16 targetSpecies = GetEvolutionTargetSpecies(pkmn, 2, d);
+
+ if (targetSpecies != SPECIES_NONE)
+ {
+ BeginEvolutionScene(pkmn, targetSpecies, 0, c);
+ return 0;
+ }
+ }
+ break;
+ }
+ }
+ //_0803EE0A
+ }
+ break;
+ }
+ }
+ //_0803F15A
+ return sp1C;
+}