summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYamaArashi <shadow962@live.com>2016-09-08 20:25:40 -0700
committerYamaArashi <shadow962@live.com>2016-09-08 20:25:40 -0700
commit06bed8be90c865057378482f2b179749b082619c (patch)
tree6f9b516a00841e7225290a0d71e9e5d97dd58777 /src
parent9ba7169baaee0645f406d95b426f1b2bf750c72e (diff)
starting decompliation of pokemon functions
Diffstat (limited to 'src')
-rw-r--r--src/pokemon.c607
1 files changed, 607 insertions, 0 deletions
diff --git a/src/pokemon.c b/src/pokemon.c
new file mode 100644
index 000000000..a2c98a71b
--- /dev/null
+++ b/src/pokemon.c
@@ -0,0 +1,607 @@
+#include "global.h"
+#include "text.h"
+#include "string_util.h"
+#include "pokemon.h"
+
+struct PokemonSubstruct0
+{
+ u16 species;
+ u16 heldItem;
+ u32 experience;
+ u8 ppBonuses;
+ u8 friendship;
+};
+
+struct PokemonSubstruct1
+{
+ u16 moves[4];
+ u8 pp[4];
+};
+
+struct PokemonSubstruct2
+{
+ u8 hpEV;
+ u8 attackEV;
+ u8 defenseEV;
+ u8 speedEV;
+ u8 spAttackEV;
+ u8 spDefenseEV;
+ u8 cool;
+ u8 beauty;
+ u8 cute;
+ u8 smart;
+ u8 tough;
+ u8 sheen;
+};
+
+struct PokemonSubstruct3
+{
+ u8 pokerus;
+ u8 metLocation;
+
+ u16 metLevel:7;
+ u16 metGame:4;
+ u16 pokeball:4;
+ u16 otGender:1;
+
+ u32 hpIV:5;
+ u32 attackIV:5;
+ u32 defenseIV:5;
+ u32 speedIV:5;
+ u32 spAttackIV:5;
+ u32 spDefenseIV:5;
+ u32 isEgg:1;
+ u32 altAbility:1;
+
+ u32 coolRibbon:3;
+ u32 beautyRibbon:3;
+ u32 cuteRibbon:3;
+ u32 smartRibbon:3;
+ u32 toughRibbon:3;
+ u32 championRibbon:1;
+ u32 winningRibbon:1;
+ u32 victoryRibbon:1;
+ u32 artistRibbon:1;
+ u32 effortRibbon:1;
+ u32 giftRibbon1:1;
+ u32 giftRibbon2:1;
+ u32 giftRibbon3:1;
+ u32 giftRibbon4:1;
+ u32 giftRibbon5:1;
+ u32 giftRibbon6:1;
+ u32 giftRibbon7:1;
+ u32 fatefulEncounter:5; // unused in Ruby/Sapphire, but the high bit must be set for Mew/Deoxys to obey in FR/LG/Emerald
+};
+
+union PokemonSubstruct
+{
+ struct PokemonSubstruct0 type0;
+ struct PokemonSubstruct1 type1;
+ struct PokemonSubstruct2 type2;
+ struct PokemonSubstruct3 type3;
+};
+
+struct BoxPokemon
+{
+ u32 personality;
+ u32 otId;
+ u8 nickname[10];
+ u8 language;
+ u8 isBadEgg:1;
+ u8 sanity2:1;
+ u8 sanity3:1;
+ u8 unused:5;
+ u8 otName[7];
+ u8 markings;
+ u16 checksum;
+ u16 unknown;
+
+ union
+ {
+ u32 raw[12];
+ union PokemonSubstruct substructs[4];
+ } secure;
+};
+
+struct Pokemon
+{
+ struct BoxPokemon box;
+ u32 status;
+ u8 level;
+ u8 pokerus;
+ u16 hp;
+ u16 maxHP;
+ u16 attack;
+ u16 defense;
+ u16 speed;
+ u16 spAttack;
+ u16 spDefense;
+};
+
+void ZeroPokemonBoxData(struct BoxPokemon *mon);
+
+u16 pokemon_calc_checksum(struct Pokemon *mon);
+
+void EncryptMon(struct Pokemon *mon);
+void DecryptMon(struct Pokemon *mon);
+union PokemonSubstruct *GetSubstruct(struct Pokemon *mon, u32 personality, u8 substructType);
+u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data);
+u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data);
+
+extern u8 gBadEggNickname[];
+extern u8 gEggNickname[];
+extern u32 gBitTable[];
+
+/*
+void ZeroPokemonBoxData(struct BoxPokemon *mon)
+{
+ u8 *raw = (u8 *)mon;
+ u32 i;
+ for (i = 0; i < sizeof(struct BoxPokemon); i++)
+ raw[i] = 0;
+}
+*/
+
+void EncryptMon(struct Pokemon *mon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ mon->box.secure.raw[i] ^= mon->box.personality;
+ mon->box.secure.raw[i] ^= mon->box.otId;
+ }
+}
+
+void DecryptMon(struct Pokemon *mon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ mon->box.secure.raw[i] ^= mon->box.otId;
+ mon->box.secure.raw[i] ^= mon->box.personality;
+ }
+}
+
+#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
+case n: \
+ 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 Pokemon *mon, u32 personality, u8 substructType)
+{
+ union PokemonSubstruct *substruct = NULL;
+
+ union PokemonSubstruct *substructs0 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs1 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs2 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs3 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs4 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs5 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs6 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs7 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs8 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs9 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs10 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs11 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs12 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs13 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs14 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs15 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs16 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs17 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs18 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs19 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs20 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs21 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs22 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs23 = mon->box.secure.substructs;
+
+ 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)
+{
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ return mon->status;
+ case MON_DATA_LEVEL:
+ return mon->level;
+ case MON_DATA_HP:
+ return mon->hp;
+ case MON_DATA_MAX_HP:
+ return mon->maxHP;
+ case MON_DATA_ATK:
+ return mon->attack;
+ case MON_DATA_DEF:
+ return mon->defense;
+ case MON_DATA_SPD:
+ return mon->speed;
+ case MON_DATA_SPATK:
+ return mon->spAttack;
+ case MON_DATA_SPDEF:
+ return mon->spDefense;
+ case MON_DATA_64:
+ return mon->pokerus;
+ default:
+ return GetMonBoxData(mon, field, data);
+ }
+}
+
+u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data)
+{
+ 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(mon, mon->box.personality, 0)->type0);
+ substruct1 = &(GetSubstruct(mon, mon->box.personality, 1)->type1);
+ substruct2 = &(GetSubstruct(mon, mon->box.personality, 2)->type2);
+ substruct3 = &(GetSubstruct(mon, mon->box.personality, 3)->type3);
+
+ DecryptMon(mon);
+
+ if (pokemon_calc_checksum(mon) != mon->box.checksum)
+ {
+ mon->box.isBadEgg = 1;
+ mon->box.sanity3 = 1;
+ substruct3->isEgg = 1;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ retVal = mon->box.personality;
+ break;
+ case MON_DATA_OT_ID:
+ retVal = mon->box.otId;
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ if (mon->box.isBadEgg)
+ {
+ StringCopy(data, gBadEggNickname);
+ retVal = StringLength(data);
+ }
+ else if (mon->box.sanity3)
+ {
+ StringCopy(data, gEggNickname);
+ retVal = StringLength(data);
+ }
+ else
+ {
+ retVal = 0;
+
+ while (retVal < 10 && mon->box.nickname[retVal] != EOS)
+ {
+ data[retVal] = mon->box.nickname[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ ConvertInternationalString(data, mon->box.language);
+ retVal = StringLength(data);
+ }
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ retVal = mon->box.language;
+ break;
+ case MON_DATA_SANITY_BIT1:
+ retVal = mon->box.isBadEgg;
+ break;
+ case MON_DATA_SANITY_BIT2:
+ retVal = mon->box.sanity2;
+ break;
+ case MON_DATA_SANITY_BIT3:
+ retVal = mon->box.sanity3;
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ retVal = 0;
+
+ while (retVal < 7 && mon->box.otName[retVal] != EOS)
+ {
+ data[retVal] = mon->box.otName[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ retVal = mon->box.markings;
+ break;
+ case MON_DATA_CHECKSUM:
+ retVal = mon->box.checksum;
+ break;
+ case MON_DATA_10:
+ retVal = mon->box.unknown;
+ break;
+ case MON_DATA_SPECIES:
+ retVal = mon->box.isBadEgg ? 412 : 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_SPD_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_SPD_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_SPECIES2:
+ retVal = substruct0->species;
+ if (substruct0->species && (substruct3->isEgg || mon->box.isBadEgg))
+ retVal = 412;
+ 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)
+ EncryptMon(mon);
+
+ return retVal;
+}