From 0b48cbfed8a3332d6b164c51a224b154fef858e6 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Fri, 9 Sep 2016 21:18:37 -0700 Subject: more decompilation of pokemon functions --- src/pokemon.c | 607 -------------------------------------------------- src/pokemon_1.c | 678 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pokemon_2.c | 474 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1152 insertions(+), 607 deletions(-) delete mode 100644 src/pokemon.c create mode 100644 src/pokemon_1.c create mode 100644 src/pokemon_2.c (limited to 'src') diff --git a/src/pokemon.c b/src/pokemon.c deleted file mode 100644 index a2c98a71b..000000000 --- a/src/pokemon.c +++ /dev/null @@ -1,607 +0,0 @@ -#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; -} diff --git a/src/pokemon_1.c b/src/pokemon_1.c new file mode 100644 index 000000000..1d5066c20 --- /dev/null +++ b/src/pokemon_1.c @@ -0,0 +1,678 @@ +#include "global.h" +#include "text.h" +#include "string_util.h" +#include "pokemon.h" +#include "species.h" +#include "main.h" + +extern u8 sav1_map_get_name(); + +extern struct Pokemon gPlayerParty[6]; // 0x3004360 +extern struct Pokemon gEnemyParty[6]; // 0x30045C0 + +extern u8 unk_2000000[]; +extern u16 word_2024E82; +extern u8 byte_2024E88; + +extern u32 gExperienceTables[8][101]; +extern struct BaseStats gBaseStats[]; +extern struct BattleMove gBattleMoves[]; +extern const u16 *gLevelUpLearnsetPointers[]; + +void ZeroPokemonBoxData(struct Pokemon *mon) +{ + u8 *raw = (u8 *)mon; + u32 i; + for (i = 0; i < sizeof(struct BoxPokemon); i++) + raw[i] = 0; +} + +void zero_pokemon_struct(struct Pokemon *mon) +{ + u32 arg; + ZeroPokemonBoxData(mon); + arg = 0; + SetMonData(mon, MON_DATA_STATUS, (u8 *)&arg); + SetMonData(mon, MON_DATA_LEVEL, (u8 *)&arg); + SetMonData(mon, MON_DATA_HP, (u8 *)&arg); + SetMonData(mon, MON_DATA_MAX_HP, (u8 *)&arg); + SetMonData(mon, MON_DATA_ATK, (u8 *)&arg); + SetMonData(mon, MON_DATA_DEF, (u8 *)&arg); + SetMonData(mon, MON_DATA_SPD, (u8 *)&arg); + SetMonData(mon, MON_DATA_SPATK, (u8 *)&arg); + SetMonData(mon, MON_DATA_SPDEF, (u8 *)&arg); + arg = 255; + SetMonData(mon, MON_DATA_64, (u8 *)&arg); +} + +void zero_player_party_data(void) +{ + s32 i; + for (i = 0; i < 6; i++) + zero_pokemon_struct(&gPlayerParty[i]); +} + +void zero_enemy_party_data(void) +{ + s32 i; + for (i = 0; i < 6; i++) + zero_pokemon_struct(&gEnemyParty[i]); +} + +void create_pokemon_set_level(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +{ + u32 arg; + zero_pokemon_struct(mon); + create_pokemon(mon, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId); + SetMonData(mon, MON_DATA_LEVEL, &level); + arg = 255; + SetMonData(mon, MON_DATA_64, (u8 *)&arg); + pokemon_calc_effective_stats(mon); +} + +void create_pokemon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +{ + u8 speciesName[10]; + u32 personality; + u32 value; + u16 checksum; + + ZeroPokemonBoxData(mon); + + if (hasFixedPersonality) + { + personality = fixedPersonality; + } + else + { + u32 r = Random(); + personality = (u16)r | (Random() << 16); + } + + SetMonBoxData(mon, MON_DATA_PERSONALITY, (u8 *)&personality); + + if (otIdType == 2) + { + u32 shinyValue; + do + { + u32 r = Random(); + value = (u16)r | (Random() << 16); + asm(""); // needed to match for some reason + shinyValue = ((value & 0xFFFF0000) >> 16) ^ (value & 0x0000FFFF) ^ ((personality & 0xFFFF0000) >> 16) ^ (personality & 0x0000FFFF); + } while (shinyValue < 8); + } + else if (otIdType == 1) + { + value = fixedOtId; + } + else + { + value = gSaveBlock2.playerTrainerId[0] + | (gSaveBlock2.playerTrainerId[1] << 8) + | (gSaveBlock2.playerTrainerId[2] << 16) + | (gSaveBlock2.playerTrainerId[3] << 24); + } + + SetMonBoxData(mon, MON_DATA_OT_ID, (u8 *)&value); + + checksum = pokemon_calc_checksum(mon); + SetMonBoxData(mon, MON_DATA_CHECKSUM, (u8 *)&checksum); + EncryptMon(mon); + GetSpeciesName(speciesName, species); + SetMonBoxData(mon, MON_DATA_NICKNAME, speciesName); + SetMonBoxData(mon, MON_DATA_LANGUAGE, &gGameLanguage); + SetMonBoxData(mon, MON_DATA_OT_NAME, gSaveBlock2.playerName); + SetMonBoxData(mon, MON_DATA_SPECIES, (u8 *)&species); + SetMonBoxData(mon, MON_DATA_EXP, (u8 *)&gExperienceTables[gBaseStats[species].growthRate][level]); + SetMonBoxData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship); + value = sav1_map_get_name(); + SetMonBoxData(mon, MON_DATA_MET_LOCATION, (u8 *)&value); + SetMonBoxData(mon, MON_DATA_MET_LEVEL, &level); + SetMonBoxData(mon, MON_DATA_MET_GAME, &gGameVersion); + value = 4; + SetMonBoxData(mon, MON_DATA_POKEBALL, (u8 *)&value); + SetMonBoxData(mon, MON_DATA_OT_GENDER, &gSaveBlock2.playerGender); + + if (fixedIV < 32) + { + SetMonBoxData(mon, MON_DATA_HP_IV, &fixedIV); + SetMonBoxData(mon, MON_DATA_ATK_IV, &fixedIV); + SetMonBoxData(mon, MON_DATA_DEF_IV, &fixedIV); + SetMonBoxData(mon, MON_DATA_SPD_IV, &fixedIV); + SetMonBoxData(mon, MON_DATA_SPATK_IV, &fixedIV); + SetMonBoxData(mon, MON_DATA_SPDEF_IV, &fixedIV); + } + else + { + u32 iv; + value = (u16)Random(); + + iv = value & 0x1F; + SetMonBoxData(mon, MON_DATA_HP_IV, (u8 *)&iv); + iv = (value & 0x3E0) >> 5; + SetMonBoxData(mon, MON_DATA_ATK_IV, (u8 *)&iv); + iv = (value &0x7C00) >> 10; + SetMonBoxData(mon, MON_DATA_DEF_IV, (u8 *)&iv); + + value = (u16)Random(); + + iv = value & 0x1F; + SetMonBoxData(mon, MON_DATA_SPD_IV, (u8 *)&iv); + iv = (value & 0x3E0) >> 5; + SetMonBoxData(mon, MON_DATA_SPATK_IV, (u8 *)&iv); + iv = (value &0x7C00) >> 10; + SetMonBoxData(mon, MON_DATA_SPDEF_IV, (u8 *)&iv); + } + + if (gBaseStats[species].ability2) + { + value = personality & 1; + SetMonBoxData(mon, MON_DATA_ALT_ABILITY, (u8 *)&value); + } + + sub_803B720(mon); +} + +void pokemon_make_with_nature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature) +{ + u32 personality; + + do + { + u32 r = Random(); + personality = (u16)r | (Random() << 16); + } + while (nature != GetNatureFromPersonality(personality)); + + create_pokemon_set_level(mon, species, level, fixedIV, 1, personality, 0, 0); +} + +void unref_sub_803AB44(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 + { + u32 r = Random(); + personality = (u16)r | (Random() << 16); + actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | personality & 0x3) % 28); + } + while (nature != GetNatureFromPersonality(personality) + || gender != pokemon_species_get_gender_info(species, personality) + || actualLetter != unownLetter - 1); + } + else + { + do + { + u32 r = Random(); + personality = (u16)r | (Random() << 16); + } + while (nature != GetNatureFromPersonality(personality) + || gender != pokemon_species_get_gender_info(species, personality)); + } + + create_pokemon_set_level(mon, species, level, fixedIV, 1, personality, 0, 0); +} + +void sub_803AC44(struct Pokemon *mon, u16 species, u8 level) +{ + u32 personality; + u32 otId; + + do + { + u32 r1, r2; + r1 = Random(); + otId = (u16)r1 | (Random() << 16); + r2 = Random(); + personality = (u16)r2 | (Random() << 16); + } + while (pokemon_species_get_gender_info(species, personality) != MALE); + create_pokemon_set_level(mon, species, level, 32, 1, personality, 1, otId); +} + +void sub_803ACAC(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality) +{ + create_pokemon_set_level(mon, species, level, 0, 1, personality, 0, 0); + SetMonData(mon, MON_DATA_IVS, (u8 *)&ivs); + pokemon_calc_effective_stats(mon); +} + +void unref_sub_803ACEC(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId) +{ + create_pokemon_set_level(mon, species, level, 0, 0, 0, 1, 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_SPD_IV, &ivs[3]); + SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]); + SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]); + pokemon_calc_effective_stats(mon); +} + +void pokemon_make_ev_something(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread) +{ + register s32 i asm("r5"); + register u32 temp asm("r4"); + s32 statCount = 0; + u16 evAmount; + register u32 mask1 asm("r1"); + u8 mask2; + + create_pokemon_set_level(mon, species, level, fixedIV, 0, 0, 0, 0); + + temp = evSpread; + mask1 = 1; + i = 5; + do + { + if (temp & mask1) + statCount++; + temp >>= 1; + i--; + } while (i >= 0); + + + evAmount = 510 / statCount; + mask2 = 1; + i = 0; + do + { + if (evSpread & mask2) + SetMonData(mon, MON_DATA_HP_EV + i, (u8 *)&evAmount); + mask2 <<= 1; + i++; + } while (i < 6); + + pokemon_calc_effective_stats(mon); +} + +void sub_803ADE8(struct Pokemon *mon, struct UnknownPokemonStruct *src) +{ + s32 i; + u8 nickname[11]; + u8 language; + u8 value; + + create_pokemon_set_level(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId); + + for (i = 0; i < 4; i++) + sub_803B6A4(mon, src->moves[i], i); + + SetMonData(mon, MON_DATA_PP_BONUSES, (u8 *)&(src->ppBonuses)); + SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&(src->heldItem)); + + StringCopy(nickname, src->nickname); + + if (nickname[0] == 0xFC && nickname[1] == 0x15) + language = 1; + else + language = 2; + + SetMonData(mon, MON_DATA_LANGUAGE, &language); + SkipExtCtrlCodes(nickname); + SetMonData(mon, MON_DATA_NICKNAME, nickname); + SetMonData(mon, MON_DATA_FRIENDSHIP, (u8 *)&(src->friendship)); + SetMonData(mon, MON_DATA_HP_EV, (u8 *)&(src->hpEV)); + SetMonData(mon, MON_DATA_ATK_EV, (u8 *)&(src->attackEV)); + SetMonData(mon, MON_DATA_DEF_EV, (u8 *)&(src->defenseEV)); + SetMonData(mon, MON_DATA_SPD_EV, (u8 *)&(src->speedEV)); + SetMonData(mon, MON_DATA_SPATK_EV, (u8 *)&(src->spAttackEV)); + SetMonData(mon, MON_DATA_SPDEF_EV, (u8 *)&(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_SPD_IV, &value); + value = src->spAttackIV; + SetMonData(mon, MON_DATA_SPATK_IV, &value); + value = src->spDefenseIV; + SetMonData(mon, MON_DATA_SPDEF_IV, &value); + pokemon_calc_effective_stats(mon); +} + +void sub_803AF78(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 == 175) + 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_SPD_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_SPD_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); +} + +u16 pokemon_calc_checksum(struct Pokemon *mon) +{ + u16 checksum = 0; + union PokemonSubstruct *substruct0 = GetSubstruct(mon, mon->box.personality, 0); + union PokemonSubstruct *substruct1 = GetSubstruct(mon, mon->box.personality, 1); + union PokemonSubstruct *substruct2 = GetSubstruct(mon, mon->box.personality, 2); + union PokemonSubstruct *substruct3 = GetSubstruct(mon, mon->box.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 = nature_stat_mod(nature, n, statIndex); \ + SetMonData(mon, field, (u8 *)&n); \ +} + +void pokemon_calc_effective_stats(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_SPD_IV, NULL); + s32 speedEV = GetMonData(mon, MON_DATA_SPD_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 = level_by_exp(mon); + s32 newMaxHP; + u8 nature; + + SetMonData(mon, MON_DATA_LEVEL, (u8 *)&level); + + if (species == SPECIES_SHEDINJA) + { + newMaxHP = 1; + } + else + { + s32 n = 2 * gBaseStats[species].baseHP + hpIV; + newMaxHP = (((n + hpEV / 4) * level) / 100) + level + 10; + } + + unk_2000000[0x160FA] = newMaxHP - oldMaxHP; + if (unk_2000000[0x160FA] == 0) + unk_2000000[0x160FA] = 1; + + SetMonData(mon, MON_DATA_MAX_HP, (u8 *)&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_SPD) + 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; + goto set_hp; + } + } + else + { + if (currentHP != 0 || oldMaxHP == 0) + { + if (currentHP != 0) + currentHP += newMaxHP - oldMaxHP; + else if (oldMaxHP == 0) + currentHP = newMaxHP; + set_hp: + SetMonData(mon, MON_DATA_HP, (u8 *)¤tHP); + } + } +} + +void sub_803B4B4(struct Pokemon *src, struct Pokemon *dest) +{ + u32 value = 0; + memcpy(&(dest->box), &(src->box), sizeof(struct BoxPokemon)); + SetMonData(dest, MON_DATA_STATUS, (u8 *)&value); + SetMonData(dest, MON_DATA_HP, (u8 *)&value); + SetMonData(dest, MON_DATA_MAX_HP, (u8 *)&value); + value = 255; + SetMonData(dest, MON_DATA_64, (u8 *)&value); + pokemon_calc_effective_stats(dest); +} + +u8 level_by_exp(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + u32 exp = GetMonData(mon, MON_DATA_EXP, NULL); + s32 level = 1; + + while (level <= 100 && gExperienceTables[gBaseStats[species].growthRate][level] <= exp) + level++; + + return level - 1; +} + +u8 sub_803B570(struct BoxPokemon *mon) +{ + u16 species = GetMonBoxData(mon, MON_DATA_SPECIES, NULL); + u32 exp = GetMonBoxData(mon, MON_DATA_EXP, NULL); + s32 level = 1; + + while (level <= 100 && gExperienceTables[gBaseStats[species].growthRate][level] <= exp) + level++; + + return level - 1; +} + +u16 pokemon_moveset_pad_(struct Pokemon *mon, u16 value) +{ + return pokemon_moveset_pad(mon, value); +} + +u16 pokemon_moveset_pad(struct Pokemon *mon, u16 value) +{ + s32 i; + for (i = 0; i < 4; i++) + { + u16 move = GetMonBoxData(&(mon->box), MON_DATA_MOVE1 + i, NULL); + if (!move) + { + SetMonBoxData(mon, MON_DATA_MOVE1 + i, (u8 *)&value); + SetMonBoxData(mon, MON_DATA_PP1 + i, &(gBattleMoves[value].pp)); + return value; + } + if (move == value) + return -2; + } + return -1; +} + +u16 sub_803B660(struct BattlePokemon *mon, u16 value) +{ + s32 i; + + for (i = 0; i < 4; i++) + { + if (!mon->moves[i]) + { + mon->moves[i] = value; + mon->pp[i] = gBattleMoves[value].pp; + return value; + } + } + + return -1; +} + +void sub_803B6A4(struct Pokemon *mon, u16 move, u8 slot) +{ + SetMonData(mon, MON_DATA_MOVE1 + slot, (u8 *)&move); + SetMonData(mon, MON_DATA_PP1 + slot, &(gBattleMoves[move].pp)); +} + +void sub_803B6E4(struct BattlePokemon *mon, u16 move, u8 slot) +{ + mon->moves[slot] = move; + mon->pp[slot] = gBattleMoves[move].pp; +} + +void unref_sub_803B714(struct Pokemon *mon) +{ + sub_803B720(mon); +} + +void sub_803B720(struct Pokemon *mon) +{ + u16 species = GetMonBoxData(&(mon->box), MON_DATA_SPECIES, NULL); + s32 level = sub_803B570(&(mon->box)); + s32 i; + + for (i = 0; gLevelUpLearnsetPointers[species][i] != (u16)-1; i++) + { + u16 moveLevel; + u16 move; + + moveLevel = (gLevelUpLearnsetPointers[species][i] & 0xFE00); + + if (moveLevel > (level << 9)) + break; + + move = (gLevelUpLearnsetPointers[species][i] & 0x1FF); + + if (pokemon_moveset_pad(mon, move) == (u16)-1) + sub_803B980(mon, move); + } +} + +u16 sub_803B7C8(struct Pokemon *mon, u8 a2) +{ + u32 retVal = 0; + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + u8 level = GetMonData(mon, MON_DATA_LEVEL, NULL); + + if (a2) + { + byte_2024E88 = retVal; + + while ((gLevelUpLearnsetPointers[species][byte_2024E88] & 0xFE00) != (level << 9)) + { + byte_2024E88++; + if (gLevelUpLearnsetPointers[species][byte_2024E88] == (u16)-1) + return 0; + } + } + + if ((gLevelUpLearnsetPointers[species][byte_2024E88] & 0xFE00) == (level << 9)) + { + word_2024E82 = (gLevelUpLearnsetPointers[species][byte_2024E88] & 0x1FF); + byte_2024E88++; + retVal = pokemon_moveset_pad_(mon, word_2024E82); + } + + return retVal; +} + +void sub_803B8D4(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, (u8 *)&moves[i]); + SetMonData(mon, MON_DATA_PP1 + i, &pp[i]); + } + + SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); +} + +void sub_803B980(struct Pokemon *mon, u16 move) +{ + s32 i; + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; + + for (i = 0; i < 3; i++) + { + moves[i] = GetMonBoxData(mon, MON_DATA_MOVE2 + i, NULL); + pp[i]= GetMonBoxData(mon, MON_DATA_PP2 + i, NULL); + } + + ppBonuses = GetMonBoxData(mon, MON_DATA_PP_BONUSES, NULL); + ppBonuses >>= 2; + moves[3] = move; + pp[3] = gBattleMoves[move].pp; + + for (i = 0; i < 4; i++) + { + SetMonBoxData(mon, MON_DATA_MOVE1 + i, (u8 *)&moves[i]); + SetMonBoxData(mon, MON_DATA_PP1 + i, &pp[i]); + } + + SetMonBoxData(mon, MON_DATA_PP_BONUSES, &ppBonuses); +} diff --git a/src/pokemon_2.c b/src/pokemon_2.c new file mode 100644 index 000000000..eb18f8840 --- /dev/null +++ b/src/pokemon_2.c @@ -0,0 +1,474 @@ +#include "global.h" +#include "text.h" +#include "string_util.h" +#include "pokemon.h" +#include "species.h" +#include "main.h" + +extern u8 gBadEggNickname[]; +extern u8 gEggNickname[]; +extern u32 gBitTable[]; + +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; +} -- cgit v1.2.3