diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/oak_speech.c | 8 | ||||
-rw-r--r-- | src/pokemon.c | 1213 | ||||
-rw-r--r-- | src/trainer_tower.c | 8 |
3 files changed, 1096 insertions, 133 deletions
diff --git a/src/oak_speech.c b/src/oak_speech.c index 26736604e..c00335136 100644 --- a/src/oak_speech.c +++ b/src/oak_speech.c @@ -14,7 +14,7 @@ #include "menu.h" #include "help_system.h" #include "new_menu_helpers.h" -#include "pokemon_3.h" +#include "pokemon.h" #include "sound.h" #include "event_scripts.h" #include "scanline_effect.h" @@ -500,7 +500,7 @@ static void Task_OaksSpeech1(u8 taskId) break; case 1: sOakSpeechResources = AllocZeroed(sizeof(*sOakSpeechResources)); - SetUpMonSpriteManagerMaybe(1, 1); + OakSpeechNidoranFSetup(1, 1); break; case 2: SetGpuReg(REG_OFFSET_WIN0H, 0); @@ -1513,7 +1513,7 @@ static void Task_OakSpeech41(u8 taskId) static void Task_OakSpeech42(u8 taskId) { FreeAllWindowBuffers(); - sub_8044D80(); + OakSpeechNidoranFFreeResources(); Free(sOakSpeechResources); sOakSpeechResources = NULL; gTextFlags.canABSpeedUpPrint = FALSE; @@ -1612,7 +1612,7 @@ static void CreateNidoranFSprite(u8 taskId) { u8 spriteId; - DecompressPicFromTable(gUnknown_8235194, sub_8044E00(0), SPECIES_NIDORAN_F); + DecompressPicFromTable(gUnknown_8235194, OakSpeechNidoranFGetBuffer(0), SPECIES_NIDORAN_F); LoadCompressedSpritePaletteUsingHeap(&gUnknown_82373F4); SetMultiuseSpriteTemplateToPokemon(SPECIES_NIDORAN_F, 0); spriteId = CreateSprite(&gMultiuseSpriteTemplate, 0x60, 0x60, 1); diff --git a/src/pokemon.c b/src/pokemon.c index b9b5e6d76..f4150d5b6 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5,8 +5,10 @@ #include "random.h" #include "main.h" #include "text.h" +#include "data2.h" #include "string_util.h" #include "battle.h" +#include "battle_2.h" #include "item.h" #include "event_data.h" #include "util.h" @@ -16,9 +18,17 @@ #include "battle_controllers.h" #include "evolution_scene.h" #include "battle_message.h" +#include "battle_util.h" +#include "battle_ai_script_commands.h" #include "link.h" #include "m4a.h" #include "sound.h" +#include "pokedex.h" +#include "strings.h" +#include "malloc.h" +#include "overworld.h" +#include "party_menu.h" +#include "field_specials.h" #include "constants/items.h" #include "constants/species.h" #include "constants/pokemon.h" @@ -34,63 +44,304 @@ // Extracts the lower 16 bits of a 32-bit number #define LOHALF(n) ((n) & 0xFFFF) -// TODO: what is this -struct UnkStruct20244F4 +struct OakSpeechNidoranFStruct { - u8 unk0:4; - u8 unk0_2:4; - u8 filler1[0xF]; - struct SpriteTemplate *unk10; + u8 spriteCount:4; + u8 battlePosition:4; + u8 frameCount; + u8 enable; + bool8 enable2; + u32 sizePerSprite; + u8 *dataBuffer; + u8 **bufferPtrs; + struct SpriteTemplate *templates; + struct SpriteFrameImage *frameImages; }; -// External symbols -extern struct UnkStruct20244F4 *gUnknown_20244F4; -extern struct SpriteTemplate gUnknown_825DEF0[]; -extern struct SpriteTemplate gUnknown_825DF50[]; -extern const union AnimCmd *const *const gTrainerBackAnimsPtrTable[]; -extern struct SpriteTemplate gUnknown_825DEF0[]; -extern const union AnimCmd *const *const gTrainerFrontAnimsPtrTable[]; -extern const union AnimCmd *const gUnknown_82349BC[]; -extern const u8 gUnknown_825DEA1[]; -extern const u8 gPPUpWriteMasks[]; -extern u8 *gUnknown_83FD5D0[]; -extern const u8 gUnknown_825DFF0[]; -extern const u8 gText_EggNickname[]; -extern const u8 gText_BadEgg[]; -extern const u8 BattleText_Rose[]; -extern const u8 BattleText_UnknownString3[]; -extern const u8 BattleText_GetPumped[]; -extern const u8 BattleText_MistShroud[]; -extern const u8 gText_PkmnsXPreventsSwitching[]; -extern const u8 sHoldEffectToType[][2]; +// TODO: move sLearningMoveTableID, gPlayerPartyCount, gEnemyPartyCount, +// gEnemyParty, gPlayerParty here after resolving symbol ref in between. extern u8 sLearningMoveTableID; -extern const u8 sSecretBaseFacilityClasses[2][5]; -extern u16 gUnknown_8251CB8[]; -extern u16 gUnknown_8251FEE[]; -extern u16 gUnknown_8252324[]; -extern u16 gUnknown_82539D4[]; -extern struct SpindaSpot gSpindaSpotGraphics[]; -extern s8 gNatureStatTable[][5]; -extern const s8 sFriendshipEventDeltas[][3]; -extern u32 gTMHMLearnsets[][2]; -extern u8 gBattleMonForms[4]; -extern const struct CompressedSpritePalette gMonPaletteTable[]; -extern const struct CompressedSpritePalette gMonShinyPaletteTable[]; -extern const u16 sHMMoves[]; -extern s8 gPokeblockFlavorCompatibilityTable[]; - -// External functions -extern u8 GetCurrentRegionMapSectionId(void); // overworld -extern const struct BattleMove gBattleMoves[]; -extern u8 sBattler_AI; // battle_ai -extern void set_unknown_box_id(u8); // field_specials -extern u8 pokemon_order_func(u8); -extern u16 get_unknown_box_id(void); // field_specials -extern u8 StorageGetCurrentBox(void); // pokemon_storage_system -extern void sub_80174B8(u8 battlerId); - -union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); -s32 GetDeoxysStat(struct Pokemon *mon, s32 statId); + +EWRAM_DATA struct SpriteTemplate gMultiuseSpriteTemplate = {0}; +static EWRAM_DATA struct OakSpeechNidoranFStruct *sOakSpeechNidoranResources = NULL; + +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); +static u16 GetDeoxysStat(struct Pokemon *mon, s32 statId); +static bool8 IsShinyOtIdPersonality(u32 otId, u32 personality); +static u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex); +static u8 GetNatureFromPersonality(u32 personality); +static bool8 sub_8042BE8(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId); +static bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId); +static bool8 IsPokemonStorageFull(void); +static u8 SendMonToPC(struct Pokemon* mon); +static void EncryptBoxMon(struct BoxPokemon *boxMon); +static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); +static void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon); +static u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); +static u8 GetLevelFromMonExp(struct Pokemon *mon); +static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); + +const s8 gPokeblockFlavorCompatibilityTable[] = +{ + // Cool, Beauty, Cute, Smart, Tough + 0, 0, 0, 0, 0, // Hardy + 1, 0, 0, 0, -1, // Lonely + 1, 0, -1, 0, 0, // Brave + 1, -1, 0, 0, 0, // Adamant + 1, 0, 0, -1, 0, // Naughty + -1, 0, 0, 0, 1, // Bold + 0, 0, 0, 0, 0, // Docile + 0, 0, -1, 0, 1, // Relaxed + 0, -1, 0, 0, 1, // Impish + 0, 0, 0, -1, 1, // Lax + -1, 0, 1, 0, 0, // Timid + 0, 0, 1, 0, -1, // Hasty + 0, 0, 0, 0, 0, // Serious + 0, -1, 1, 0, 0, // Jolly + 0, 0, 1, -1, 0, // Naive + -1, 1, 0, 0, 0, // Modest + 0, 1, 0, 0, -1, // Mild + 0, 1, -1, 0, 0, // Quiet + 0, 0, 0, 0, 0, // Bashful + 0, 1, 0, -1, 0, // Rash + -1, 0, 0, 1, 0, // Calm + 0, 0, 0, 1, -1, // Gentle + 0, 0, -1, 1, 0, // Sassy + 0, -1, 0, 1, 0, // Careful + 0, 0, 0, 0, 0 // Quirky +}; + +const u8 gPPUpGetMask[] = { 0x03, 0x0c, 0x30, 0xc0 }; // Masks for getting PP Up count, also PP Max values + +const u8 gPPUpSetMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; // Masks for setting PP Up count + +const u8 gPPUpAddMask[] = { 0x01, 0x04, 0x10, 0x40 }; // Values added to PP Up count + +const u8 gStatStageRatios[][2] = +{ + { 10, 40 }, + { 10, 35 }, + { 10, 30 }, + { 10, 25 }, + { 10, 20 }, + { 10, 15 }, + { 10, 10 }, + { 15, 10 }, + { 20, 10 }, + { 25, 10 }, + { 30, 10 }, + { 35, 10 }, + { 40, 10 }, + { 138, 174 }, + { 108, 120 }, +}; + +static const u8 sFiller = _(""); + +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_825DEF0[] = +{ + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_8234698, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F010, + .anims = NULL, + .images = gUnknown_82346B8, + .affineAnims = gUnknown_8234944, + .callback = oac_poke_opponent, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_82346D8, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F010, + .anims = NULL, + .images = gUnknown_82346F8, + .affineAnims = gUnknown_8234944, + .callback = oac_poke_opponent, + }, +}; + +const struct SpriteTemplate gUnknown_825DF50[] = +{ + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_8234718, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_8234740, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_82347A8, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_82347C8, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_8234768, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, + { + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = 0, + .oam = &gUnknown_824F018, + .anims = NULL, + .images = gUnknown_8234788, + .affineAnims = gUnknown_82348C8, + .callback = sub_80120C4, + }, +}; + +static const u8 sSecretBaseFacilityClasses[][5] = +{ + { 0x58, 0x58, 0x58, 0x58, 0x58 }, + { 0x58, 0x58, 0x58, 0x58, 0x58 }, +}; + +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_825DFF0[] = +{ + STAT_ATK, STAT_ATK, STAT_SPEED, STAT_DEF, STAT_SPATK, STAT_ACC +}; + +static const s8 sFriendshipEventDeltas[][3] = +{ + { 5, 3, 2 }, + { 5, 3, 2 }, + { 1, 1, 0 }, + { 3, 2, 1 }, + { 1, 1, 0 }, + { 1, 1, 1 }, + { 3, 3, 3 }, + {-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 u16 sDeoxysBaseStats[] = +{ + 50, // Hp + 180, // Attack + 20, // Defense + 150, // Speed + 180, // Sp.Attack + 20, // Sp.Defense +}; + +const u16 gLinkPlayerFacilityClasses[] = +{ + 0x74, 0x6F, 0x5C, 0x58, 0x6A, + 0x59, 0x6D, 0x6C, 0x75, 0x7D, + 0x5D, 0x5A, 0x89, 0x8A, 0x8C, + 0x68, 0x0, +}; + +const static struct OamData sOakSpeechNidoranFDummyOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, +}; + +const struct SpriteTemplate sOakSpeechNidoranFDummyTemplate = +{ + .tileTag = SPRITE_INVALID_TAG, + .paletteTag = SPRITE_INVALID_TAG, + .oam = &sOakSpeechNidoranFDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; // code void ZeroBoxMonData(struct BoxPokemon *boxMon) @@ -307,7 +558,7 @@ void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 CalculateMonStats(mon); } -void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId) +static 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]); @@ -351,7 +602,7 @@ void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedI CalculateMonStats(mon); } -void sub_803E0A4(struct Pokemon *mon, struct BattleTowerPokemon *src) +void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src) { s32 i; u8 value; @@ -402,7 +653,7 @@ void sub_803E0A4(struct Pokemon *mon, struct BattleTowerPokemon *src) CalculateMonStats(mon); } -void CreateObedientMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +static void CreateObedientMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) { bool32 obedient = TRUE; @@ -447,7 +698,7 @@ void sub_803E23C(struct Pokemon *mon, struct BattleTowerPokemon *dest) GetMonData(mon, MON_DATA_NICKNAME, dest->nickname); } -u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) +static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) { u16 checksum = 0; union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0); @@ -476,7 +727,7 @@ u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) 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); \ + n = ModifyStatByNature(nature, n, statIndex); \ SetMonData(mon, field, &n); \ } @@ -556,7 +807,7 @@ void BoxMonToMon(struct BoxPokemon *src, struct Pokemon *dest) CalculateMonStats(dest); } -u8 GetLevelFromMonExp(struct Pokemon *mon) +static u8 GetLevelFromMonExp(struct Pokemon *mon) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u32 exp = GetMonData(mon, MON_DATA_EXP, NULL); @@ -585,7 +836,7 @@ u16 GiveMoveToMon(struct Pokemon *mon, u16 move) return GiveMoveToBoxMon(&mon->box, move); } -u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) +static u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) { s32 i; for (i = 0; i < 4; i++) @@ -632,7 +883,7 @@ void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) mon->pp[slot] = gBattleMoves[move].pp; } -void GiveMonInitialMoveset(struct Pokemon *mon) +static void GiveMonInitialMoveset(struct Pokemon *mon) { GiveBoxMonInitialMoveset(&mon->box); } @@ -640,7 +891,7 @@ void GiveMonInitialMoveset(struct Pokemon *mon) // TODO: make level_up_learnsets.h in src/data and move this to there. #define LEVEL_UP_END 0xffff -void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) +static void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) { u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); s32 level = GetLevelFromBoxMonExp(boxMon); @@ -722,7 +973,7 @@ void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move) SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); } -void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) +static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) { s32 i; u16 moves[4]; @@ -1122,7 +1373,7 @@ u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality) return MON_MALE; } -void SetMultiuseSpriteTemplateToPokemon(u16 trainerSpriteId, u8 battlerPosition) +void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) { if(gMonSpritesGfxPtr != NULL) { @@ -1133,12 +1384,12 @@ void SetMultiuseSpriteTemplateToPokemon(u16 trainerSpriteId, u8 battlerPosition) } else { - if(gUnknown_20244F4) + if(sOakSpeechNidoranResources) { - if(battlerPosition >= (s8)gUnknown_20244F4->unk0_2) // why a cast?!? changing the unk0_2 type to s8 causes extra shifts, but a cast is the correct fix. why, compiler? + if(battlerPosition >= (s8)sOakSpeechNidoranResources->battlePosition) // why a cast?!? changing the unk0_2 type to s8 causes extra shifts, but a cast is the correct fix. why, compiler? battlerPosition = 0; - gMultiuseSpriteTemplate = gUnknown_20244F4->unk10[battlerPosition]; + gMultiuseSpriteTemplate = sOakSpeechNidoranResources->templates[battlerPosition]; } else { @@ -1148,7 +1399,7 @@ void SetMultiuseSpriteTemplateToPokemon(u16 trainerSpriteId, u8 battlerPosition) gMultiuseSpriteTemplate = gUnknown_825DEF0[battlerPosition]; } } - gMultiuseSpriteTemplate.paletteTag = trainerSpriteId; + gMultiuseSpriteTemplate.paletteTag = speciesTag; gMultiuseSpriteTemplate.anims = gUnknown_82349BC; } @@ -1170,7 +1421,7 @@ void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosit } } -void EncryptBoxMon(struct BoxPokemon *boxMon) +static void EncryptBoxMon(struct BoxPokemon *boxMon) { u32 i; for (i = 0; i < 12; i++) @@ -1180,7 +1431,7 @@ void EncryptBoxMon(struct BoxPokemon *boxMon) } } -void DecryptBoxMon(struct BoxPokemon *boxMon) +static void DecryptBoxMon(struct BoxPokemon *boxMon) { u32 i; for (i = 0; i < 12; i++) @@ -1236,7 +1487,7 @@ case n: \ break; \ } \ -union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) { union PokemonSubstruct *substruct = NULL; @@ -1290,27 +1541,27 @@ u32 GetMonData(struct Pokemon *mon, s32 field, u8* data) ret = mon->maxHP; break; case MON_DATA_ATK: - ret = (u16)GetDeoxysStat(mon, STAT_ATK); + ret = GetDeoxysStat(mon, STAT_ATK); if (!ret) ret = mon->attack; break; case MON_DATA_DEF: - ret = (u16)GetDeoxysStat(mon, STAT_DEF); + ret = GetDeoxysStat(mon, STAT_DEF); if (!ret) ret = mon->defense; break; case MON_DATA_SPEED: - ret = (u16)GetDeoxysStat(mon, STAT_SPEED); + ret = GetDeoxysStat(mon, STAT_SPEED); if (!ret) ret = mon->speed; break; case MON_DATA_SPATK: - ret = (u16)GetDeoxysStat(mon, STAT_SPATK); + ret = GetDeoxysStat(mon, STAT_SPATK); if (!ret) ret = mon->spAttack; break; case MON_DATA_SPDEF: - ret = (u16)GetDeoxysStat(mon, STAT_SPDEF); + ret = GetDeoxysStat(mon, STAT_SPDEF); if (!ret) ret = mon->spDefense; break; @@ -2065,7 +2316,7 @@ u8 GiveMonToPlayer(struct Pokemon *mon) return MON_GIVEN_TO_PARTY; } -u8 SendMonToPC(struct Pokemon* mon) +static u8 SendMonToPC(struct Pokemon* mon) { s32 boxNo, boxPos; @@ -2165,7 +2416,7 @@ u8 GetMonAbility(struct Pokemon *mon) return GetAbilityBySpecies(species, altAbility); } -void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord) +static void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord) { s32 i, j; @@ -2224,7 +2475,7 @@ bool8 IsPlayerPartyAndPokemonStorageFull(void) return IsPokemonStorageFull(); } -bool8 IsPokemonStorageFull(void) +static bool8 IsPokemonStorageFull(void) { s32 i, j; @@ -2258,22 +2509,22 @@ void GetSpeciesName(u8 *name, u16 species) u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex) { u8 basePP = gBattleMoves[move].pp; - return basePP + ((basePP * 20 * ((gUnknown_825DEA1[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100); + return basePP + ((basePP * 20 * ((gPPUpGetMask[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100); } void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex) { u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - ppBonuses &= gPPUpWriteMasks[moveIndex]; + ppBonuses &= gPPUpSetMask[moveIndex]; SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); } void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex) { - mon->ppBonuses &= gPPUpWriteMasks[moveIndex]; + mon->ppBonuses &= gPPUpSetMask[moveIndex]; } -void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex) +static void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex) { u16* hpSwitchout; s32 i; @@ -2333,10 +2584,6 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, return PokemonUseItemEffects(mon, item, partyIndex, moveIndex, 0); } -extern const u8 gUnknown_825DEA1[]; -extern const u8 gUnknown_825DEA9[]; -extern const u8 sGetMonDataEVConstants[]; - bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 moveIndex, u8 e) { u32 data; @@ -2512,11 +2759,11 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo if (r10 & 0x20) { r10 &= ~0x20; - data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gUnknown_825DEA1[moveIndex]) >> (moveIndex * 2); + data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gPPUpGetMask[moveIndex]) >> (moveIndex * 2); sp28 = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), moveIndex); if (data < 3 && sp28 > 4) { - data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) + gUnknown_825DEA9[moveIndex]; + data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) + gPPUpAddMask[moveIndex]; SetMonData(pkmn, MON_DATA_PP_BONUSES, &data); data = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), data, moveIndex) - sp28; @@ -2741,13 +2988,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo } break; case 4: - data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gUnknown_825DEA1[moveIndex]) >> (moveIndex * 2); + data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gPPUpGetMask[moveIndex]) >> (moveIndex * 2); if (data < 3) { r4 = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), moveIndex); data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL); - data &= gPPUpWriteMasks[moveIndex]; - data += gUnknown_825DEA9[moveIndex] * 3; + data &= gPPUpSetMask[moveIndex]; + data += gPPUpAddMask[moveIndex] * 3; SetMonData(pkmn, MON_DATA_PP_BONUSES, &data); data = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), data, moveIndex) - r4; @@ -2840,7 +3087,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo return retVal; } -bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId) +static bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId) { u32 status = GetMonData(mon, MON_DATA_STATUS, 0); @@ -2858,8 +3105,6 @@ bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 bat } } -extern bool8 sub_8042BE8(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId); - #ifdef NONMATCHING /* * This is nonmatching due to the compiler's insistence on avoiding the u8 cast @@ -3047,11 +3292,11 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m if (r10 & 0x20) { r10 &= ~0x20; - data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gUnknown_825DEA1[moveIndex]) >> (moveIndex * 2); + data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gPPUpGetMask[moveIndex]) >> (moveIndex * 2); sp28 = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), moveIndex); if (data < 3 && sp28 > 4) { - //data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) + gUnknown_825DEA9[moveIndex]; + //data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) + gPPUpAddMask[moveIndex]; //SetMonData(pkmn, MON_DATA_PP_BONUSES, &data); // //data = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), data, moveIndex) - sp28; @@ -3286,7 +3531,7 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m } break; case 4: - data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gUnknown_825DEA1[moveIndex]) >> (moveIndex * 2); + data = (GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL) & gPPUpGetMask[moveIndex]) >> (moveIndex * 2); r4 = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL), moveIndex); if (data < 3) { @@ -3295,8 +3540,8 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m /* data = GetMonData(pkmn, MON_DATA_PP_BONUSES, NULL); - data &= gPPUpWriteMasks[moveIndex]; - data += gUnknown_825DEA9[moveIndex] * 3; + data &= gPPUpSetMask[moveIndex]; + data += gPPUpAddMask[moveIndex] * 3; SetMonData(pkmn, MON_DATA_PP_BONUSES, &data); data = CalculatePPWithBonus(GetMonData(pkmn, MON_DATA_MOVE1 + moveIndex, NULL), data, moveIndex) - r4; @@ -3957,7 +4202,7 @@ _08042850:\n\ movs r2, 0\n\ bl GetMonData\n\ adds r5, r0, 0\n\ - ldr r0, _080428DC @ =gUnknown_825DEA1\n\ + ldr r0, _080428DC @ =gPPUpGetMask\n\ ldr r1, [sp, 0x8]\n\ adds r0, r1, r0\n\ ldrb r0, [r0]\n\ @@ -4013,7 +4258,7 @@ _080428D2:\n\ ldr r0, [r0]\n\ mov pc, r0\n\ .align 2, 0\n\ -_080428DC: .4byte gUnknown_825DEA1\n\ +_080428DC: .4byte gPPUpGetMask\n\ _080428E0: .4byte _080428E4\n\ .align 2, 0\n\ _080428E4:\n\ @@ -4275,7 +4520,7 @@ _08042AF4:\n\ movs r2, 0\n\ bl GetMonData\n\ adds r5, r0, 0\n\ - ldr r0, _08042B48 @ =gUnknown_825DEA1\n\ + ldr r0, _08042B48 @ =gPPUpGetMask\n\ ldr r1, [sp, 0x8]\n\ adds r0, r1, r0\n\ ldrb r0, [r0]\n\ @@ -4309,7 +4554,7 @@ _08042AF4:\n\ str r2, [sp, 0x10]\n\ b _08042BBE\n\ .align 2, 0\n\ -_08042B48: .4byte gUnknown_825DEA1\n\ +_08042B48: .4byte gPPUpGetMask\n\ _08042B4C:\n\ mov r0, r8\n\ movs r1, 0x20\n\ @@ -4397,7 +4642,7 @@ _08042BD8:\n\ } #endif -bool8 sub_8042BE8(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId) +static bool8 sub_8042BE8(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId) { if((GetMonData(mon, MON_DATA_STATUS, NULL) & healMask) != 0) return TRUE; @@ -4518,7 +4763,7 @@ u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit) return offset; } -void sub_8042D50(int stat) +static void sub_8042D50(int stat) { gBattlerTarget = gBattlerInMenuId; StringCopy(gBattleTextBuff1, gUnknown_83FD5D0[gUnknown_825DFF0[stat]]); @@ -4581,13 +4826,11 @@ u8 GetNature(struct Pokemon *mon) return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25; } -u8 GetNatureFromPersonality(u32 personality) +static u8 GetNatureFromPersonality(u32 personality) { return personality % 25; } -extern bool32 sub_806E25C(void); - u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem) { int i; @@ -4718,7 +4961,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem) // HoennPokedexNumToSpecies, but is it really Hoenn or Kanto its checking // TODO: Figure this out -u16 sub_80431B4(u16 var) +static u16 sub_80431B4(u16 var) { u16 species; @@ -4755,7 +4998,7 @@ u16 NationalPokedexNumToSpecies(u16 nationalNum) } // NationalToKantoOrder? -u16 sub_804324C(u16 nationalNum) +static u16 sub_804324C(u16 nationalNum) { u16 hoennNum; @@ -4783,7 +5026,7 @@ u16 SpeciesToNationalPokedexNum(u16 species) // these 2 functions are probably kanto and not hoenn // TODO: figure this out -u16 SpeciesToHoennPokedexNum(u16 species) +static u16 SpeciesToHoennPokedexNum(u16 species) { if (!species) return 0; @@ -4810,7 +5053,7 @@ u16 SpeciesToCryId(u16 species) return gUnknown_82539D4[species - ((SPECIES_OLD_UNOWN_Z + 1) - 1)]; } -void sub_8043338(u16 species, u32 personality, u8 *dest) +static void sub_8043338(u16 species, u32 personality, u8 *dest) { if (species == SPECIES_SPINDA && dest != gMonSpritesGfxPtr->sprites[0] @@ -4928,10 +5171,10 @@ bool8 sub_80435E0(void) return retVal; } -bool8 sub_8043620(u8 id) +bool8 GetLinkTrainerFlankId(u8 linkPlayerId) { bool8 retVal = FALSE; - switch (gLinkPlayers[id].id) + switch (gLinkPlayers[linkPlayerId].id) { case 0: case 3: @@ -4954,12 +5197,12 @@ s32 GetBankMultiplayerId(u16 a1) return id; } -u8 sub_804367C(u16 trainer) +u8 GetTrainerEncounterMusicId(u16 trainer) { return gTrainers[trainer].encounterMusic_gender & 0x7F; } -u16 nature_stat_mod(u8 nature, u16 n, u8 statIndex) +static u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex) { if (statIndex < 1 || statIndex > 5) { @@ -5204,7 +5447,7 @@ u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection) return retVal; } -void sub_8043B38(void) +static void sub_8043B38(void) { u8 foo[4]; // huh? } @@ -5214,7 +5457,7 @@ void sub_8043B40(void) u8 foo[4]; // huh? } -void sub_8043B48(struct Pokemon *mon, int species, u8 unused, u32 data) +static void SetMonExpWithMaxLevelCheck(struct Pokemon *mon, int species, u8 unused, u32 data) { if (data > gExperienceTables[gBaseStats[species].growthRate][100]) { @@ -5235,7 +5478,7 @@ bool8 TryIncrementMonLevel(struct Pokemon *mon) if(exp > gExperienceTables[gBaseStats[species].growthRate][newLevel]) { SetMonData(mon, MON_DATA_LEVEL, &newLevel); - sub_8043B48(mon, species, newLevel, exp); + SetMonExpWithMaxLevelCheck(mon, species, newLevel, exp); return TRUE; } else @@ -5243,7 +5486,7 @@ bool8 TryIncrementMonLevel(struct Pokemon *mon) } else { - sub_8043B48(mon, species, level, exp); + SetMonExpWithMaxLevelCheck(mon, species, level, exp); return FALSE; } } @@ -5377,7 +5620,7 @@ void ClearBattleMonForms(void) gBattleMonForms[i] = 0; } -u16 GetMUS_ForBattle(void) +static u16 GetMUS_ForBattle(void) { if(gBattleTypeFlags & 0x1000) return 0x12A; @@ -5480,7 +5723,7 @@ bool8 IsPokeSpriteNotFlipped(u16 species) return gBaseStats[species].noFlip; } -s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor) +static s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor) { u8 nature = GetNature(mon); return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor]; @@ -5595,7 +5838,7 @@ bool8 IsMonShiny(struct Pokemon *mon) return IsShinyOtIdPersonality(otId, personality); } -bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) +static bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) { bool8 retVal = FALSE; u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); @@ -5604,8 +5847,728 @@ bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) return retVal; } -u8 *sub_80444C4(void) +u8 *GetTrainerPartnerName(void) { u8 id = GetMultiplayerId(); return gLinkPlayers[GetBankMultiplayerId(gLinkPlayers[id].id ^ 2)].name; } + +u8 GetPlayerPartyHighestLevel(void) +{ + s32 slot; + u8 level, monLevel; + + level = 1; + for(slot = 0; slot < PARTY_SIZE; ++slot) + { + if (GetMonData(&gPlayerParty[slot], MON_DATA_SANITY_HAS_SPECIES, NULL) == 1 && !GetMonData(&gPlayerParty[slot], MON_DATA_SANITY_IS_EGG, NULL)) + { + monLevel = GetMonData(&gPlayerParty[slot], MON_DATA_LEVEL, NULL); + if (monLevel > level) + level = monLevel; + } + } + return level; +} + +u16 FacilityClassToPicIndex(u16 facilityClass) +{ + return gFacilityClassToPicIndex[facilityClass]; +} + +bool8 sub_804455C(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()].id == 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()].id == 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 u16 GetDeoxysStat(struct Pokemon *mon, s32 statId) +{ + s32 ivVal, evVal; + u16 statValue; + u8 nature; + + if (gBattleTypeFlags & BATTLE_TYPE_20 || GetMonData(mon, MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS) + { + return statValue = 0; + } + else + { + ivVal = GetMonData(mon, MON_DATA_HP_IV + statId, NULL); + evVal = GetMonData(mon, MON_DATA_HP_EV + statId, NULL); + statValue = ((sDeoxysBaseStats[statId] * 2 + ivVal + evVal / 4) * mon->level) / 100 + 5; + nature = GetNature(mon); + statValue = ModifyStatByNature(nature, statValue, (u8)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_80447AC(void) +{ + u8 linkId = GetMultiplayerId() ^ 1; + u32 arrId = gLinkPlayers[linkId].trainerId & 7; + + arrId |= gLinkPlayers[linkId].gender << 3; + return FacilityClassToPicIndex(gLinkPlayerFacilityClasses[arrId]); +} + +u16 sub_80447F0(void) +{ + u8 linkId = GetMultiplayerId() ^ 1; + u32 arrId = gLinkPlayers[linkId].trainerId & 7; + + arrId |= gLinkPlayers[linkId].gender << 3; + return gFacilityClassToTrainerClass[gLinkPlayerFacilityClasses[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); + } +} + +void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality) +{ + u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT; + + if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) + { + GetSetPokedexFlag(nationalNum, caseId); + if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN) + gSaveBlock2Ptr->pokedex.unownPersonality = personality; + if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA) + gSaveBlock2Ptr->pokedex.spindaPersonality = personality; + } +} + +bool8 CheckBattleTypeGhost(struct Pokemon *mon, u8 bank) +{ + u8 buffer[12]; + + if (gBattleTypeFlags & BATTLE_TYPE_GHOST && GetBattlerSide(bank)) + { + GetMonData(mon, MON_DATA_NICKNAME, buffer); + StringGetEnd10(buffer); + if (!StringCompare(buffer, gUnknown_841D148)) + return TRUE; + } + return FALSE; +} + +static void OakSpeechNidoranFSetupTemplate(struct OakSpeechNidoranFStruct *structPtr, u8 battlePosition) +{ + u16 i = 0, j = 0; + + if (battlePosition > 3) + { + for (i = 0; i < (s8)structPtr->spriteCount; ++i) + { + structPtr->templates[i] = gUnknown_825DEF0[i]; + for (j = 0; j < structPtr->frameCount; ++j) + structPtr->frameImages[i * structPtr->frameCount + j].data = &structPtr->bufferPtrs[i][j * 0x800]; + structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->frameCount]; + } + } + else + { + const struct SpriteTemplate *template = &gUnknown_825DEF0[battlePosition]; + + structPtr->templates[0] = *template; + for (j = 0; j < structPtr->frameCount; ++j) + structPtr->frameImages[j].data = &structPtr->bufferPtrs[0][j * 0x800]; + structPtr->templates[0].images = structPtr->frameImages; + } +} + +// not used +static void OakSpeechNidoranFSetupTemplateDummy(struct OakSpeechNidoranFStruct *structPtr) +{ + u16 i, j; + + for (i = 0; i < (s8)structPtr->spriteCount; ++i) + { + structPtr->templates[i] = sOakSpeechNidoranFDummyTemplate; + for (j = 0; j < structPtr->frameCount; ++j) + structPtr->frameImages[i * structPtr->spriteCount + j].data = &structPtr->bufferPtrs[i][j * 0x800]; + structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->spriteCount]; // should be frameCount logically + structPtr->templates[i].anims = gUnknown_82349BC; + structPtr->templates[i].paletteTag = i; + } +} + +#ifdef NONMATCHING +struct OakSpeechNidoranFStruct *OakSpeechNidoranFSetup(u8 battlePosition, bool8 enable) +{ + s32 size; + u8 i, flags = 0; + + if (sOakSpeechNidoranResources != NULL) + { + if (sOakSpeechNidoranResources->enable == 0xA3) + return NULL; + memset(sOakSpeechNidoranResources, 0, sizeof(struct OakSpeechNidoranFStruct)); + sOakSpeechNidoranResources = NULL; + } + sOakSpeechNidoranResources = AllocZeroed(0x18); + if (sOakSpeechNidoranResources == NULL) + return NULL; + switch (enable) + { + case TRUE: + if (battlePosition == 4) + { + sOakSpeechNidoranResources->spriteCount = 4; + sOakSpeechNidoranResources->battlePosition = 4; + } + else + { + if (battlePosition > 4) + battlePosition = 0; + sOakSpeechNidoranResources->spriteCount = 1; + sOakSpeechNidoranResources->battlePosition = 1; + } + sOakSpeechNidoranResources->frameCount = 4; + sOakSpeechNidoranResources->enable2 = TRUE; + break; + case FALSE: + default: + if (!battlePosition) + battlePosition = 1; + if (battlePosition > 8) + battlePosition = 8; + // The following two statements refused to cooperate. + sOakSpeechNidoranResources->spriteCount = battlePosition; + sOakSpeechNidoranResources->battlePosition = battlePosition; + sOakSpeechNidoranResources->frameCount = 4; + sOakSpeechNidoranResources->enable2 = FALSE; + break; + } + size = sOakSpeechNidoranResources->frameCount * 0x800; + sOakSpeechNidoranResources->sizePerSprite = size; + sOakSpeechNidoranResources->dataBuffer = AllocZeroed(sOakSpeechNidoranResources->spriteCount * size); + sOakSpeechNidoranResources->bufferPtrs = AllocZeroed(sOakSpeechNidoranResources->spriteCount * 0x20); + if (sOakSpeechNidoranResources->dataBuffer == NULL || sOakSpeechNidoranResources->bufferPtrs == NULL) + { + flags |= 1; + } + else + { + for (i = 0; i < (s8)sOakSpeechNidoranResources->spriteCount; ++i) + sOakSpeechNidoranResources->bufferPtrs[i] = &sOakSpeechNidoranResources->dataBuffer[sOakSpeechNidoranResources->sizePerSprite * i]; + } + sOakSpeechNidoranResources->templates = AllocZeroed(sizeof(struct SpriteTemplate) * sOakSpeechNidoranResources->spriteCount); + sOakSpeechNidoranResources->frameImages = AllocZeroed(sOakSpeechNidoranResources->spriteCount * sizeof(struct SpriteFrameImage) * sOakSpeechNidoranResources->frameCount); + if (sOakSpeechNidoranResources->templates == NULL || sOakSpeechNidoranResources->frameImages == NULL) + { + flags |= 2; + } + else + { + for (i = 0; i < sOakSpeechNidoranResources->frameCount * sOakSpeechNidoranResources->spriteCount; ++i) + sOakSpeechNidoranResources->frameImages[i].size = 0x800; + switch (sOakSpeechNidoranResources->enable2) + { + case TRUE: + OakSpeechNidoranFSetupTemplate(sOakSpeechNidoranResources, battlePosition); + break; + case FALSE: + default: + OakSpeechNidoranFSetupTemplateDummy(sOakSpeechNidoranResources); + break; + } + } + if (flags & 2) + { + if (sOakSpeechNidoranResources->frameImages != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->frameImages); + if (sOakSpeechNidoranResources->templates != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->templates); + } + if (flags & 1) + { + if (sOakSpeechNidoranResources->bufferPtrs != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->bufferPtrs); + if (sOakSpeechNidoranResources->dataBuffer != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->dataBuffer); + } + if (flags) + { + memset(sOakSpeechNidoranResources, 0, sizeof(struct OakSpeechNidoranFStruct)); + FREE_AND_SET_NULL(sOakSpeechNidoranResources); + } + else + { + sOakSpeechNidoranResources->enable = 0xA3; + } + return sOakSpeechNidoranResources; +} +#else +NAKED +struct OakSpeechNidoranFStruct *OakSpeechNidoranFSetup(u8 battlePosition, bool8 enable) +{ + asm_unified("\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + lsls r1, 24\n\ + lsrs r5, r1, 24\n\ + movs r0, 0\n\ + mov r8, r0\n\ + ldr r4, _08044B34 @ =sOakSpeechNidoranResources\n\ + ldr r1, [r4]\n\ + cmp r1, 0\n\ + beq _08044B1E\n\ + ldrb r0, [r1, 0x2]\n\ + cmp r0, 0xA3\n\ + beq _08044B2E\n\ + adds r0, r1, 0\n\ + movs r1, 0\n\ + movs r2, 0x18\n\ + bl memset\n\ + mov r1, r8\n\ + str r1, [r4]\n\ + _08044B1E:\n\ + ldr r4, _08044B34 @ =sOakSpeechNidoranResources\n\ + movs r0, 0x18\n\ + bl AllocZeroed\n\ + adds r2, r0, 0\n\ + str r2, [r4]\n\ + cmp r2, 0\n\ + bne _08044B38\n\ + _08044B2E:\n\ + movs r0, 0\n\ + b _08044D70\n\ + .align 2, 0\n\ + _08044B34: .4byte sOakSpeechNidoranResources\n\ + _08044B38:\n\ + cmp r5, 0\n\ + beq _08044B94\n\ + cmp r5, 0x1\n\ + bne _08044B94\n\ + cmp r6, 0x4\n\ + bne _08044B5E\n\ + ldrb r1, [r2]\n\ + movs r0, 0x10\n\ + negs r0, r0\n\ + ands r0, r1\n\ + movs r1, 0x4\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, [r4]\n\ + ldrb r1, [r2]\n\ + movs r0, 0xF\n\ + ands r0, r1\n\ + movs r1, 0x40\n\ + b _08044B7C\n\ + _08044B5E:\n\ + cmp r6, 0x4\n\ + bls _08044B64\n\ + movs r6, 0\n\ + _08044B64:\n\ + ldrb r1, [r2]\n\ + movs r0, 0x10\n\ + negs r0, r0\n\ + ands r0, r1\n\ + movs r1, 0x1\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, [r4]\n\ + ldrb r1, [r2]\n\ + movs r0, 0xF\n\ + ands r0, r1\n\ + movs r1, 0x10\n\ + _08044B7C:\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, _08044B90 @ =sOakSpeechNidoranResources\n\ + ldr r1, [r2]\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x1]\n\ + ldr r1, [r2]\n\ + movs r0, 0x1\n\ + strb r0, [r1, 0x3]\n\ + b _08044BD0\n\ + .align 2, 0\n\ + _08044B90: .4byte sOakSpeechNidoranResources\n\ + _08044B94:\n\ + cmp r6, 0\n\ + bne _08044B9A\n\ + movs r6, 0x1\n\ + _08044B9A:\n\ + cmp r6, 0x8\n\ + bls _08044BA0\n\ + movs r6, 0x8\n\ + _08044BA0:\n\ + ldr r4, _08044C10 @ =sOakSpeechNidoranResources\n\ + ldr r3, [r4]\n\ + movs r0, 0xF\n\ + adds r1, r6, 0\n\ + ands r1, r0\n\ + ldrb r2, [r3]\n\ + movs r0, 0x10\n\ + negs r0, r0\n\ + ands r0, r2\n\ + orrs r0, r1\n\ + strb r0, [r3]\n\ + ldr r2, [r4]\n\ + lsls r3, r6, 4\n\ + ldrb r1, [r2]\n\ + movs r0, 0xF\n\ + ands r0, r1\n\ + orrs r0, r3\n\ + strb r0, [r2]\n\ + ldr r1, [r4]\n\ + movs r2, 0\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x1]\n\ + ldr r0, [r4]\n\ + strb r2, [r0, 0x3]\n\ + _08044BD0:\n\ + ldr r5, _08044C10 @ =sOakSpeechNidoranResources\n\ + ldr r0, [r5]\n\ + ldrb r1, [r0, 0x1]\n\ + lsls r1, 11\n\ + str r1, [r0, 0x4]\n\ + ldrb r0, [r0]\n\ + lsls r0, 28\n\ + lsrs r0, 28\n\ + muls r0, r1\n\ + bl AllocZeroed\n\ + ldr r1, [r5]\n\ + str r0, [r1, 0x8]\n\ + ldrb r0, [r1]\n\ + lsls r0, 28\n\ + lsrs r0, 23\n\ + bl AllocZeroed\n\ + adds r2, r0, 0\n\ + ldr r1, [r5]\n\ + str r2, [r1, 0xC]\n\ + ldr r0, [r1, 0x8]\n\ + cmp r0, 0\n\ + beq _08044C04\n\ + cmp r2, 0\n\ + bne _08044C14\n\ + _08044C04:\n\ + movs r0, 0x1\n\ + mov r1, r8\n\ + orrs r1, r0\n\ + mov r8, r1\n\ + b _08044C44\n\ + .align 2, 0\n\ + _08044C10: .4byte sOakSpeechNidoranResources\n\ + _08044C14:\n\ + ldrb r0, [r1]\n\ + lsls r0, 28\n\ + movs r4, 0\n\ + adds r3, r5, 0\n\ + cmp r0, 0\n\ + beq _08044C44\n\ + _08044C20:\n\ + ldr r3, [r5]\n\ + ldr r0, [r3, 0xC]\n\ + lsls r1, r4, 2\n\ + adds r1, r0\n\ + ldr r0, [r3, 0x4]\n\ + adds r2, r0, 0\n\ + muls r2, r4\n\ + ldr r0, [r3, 0x8]\n\ + adds r0, r2\n\ + str r0, [r1]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldrb r0, [r3]\n\ + lsls r0, 28\n\ + lsrs r0, 28\n\ + cmp r4, r0\n\ + blt _08044C20\n\ + _08044C44:\n\ + ldr r5, _08044C8C @ =sOakSpeechNidoranResources\n\ + ldr r0, [r5]\n\ + ldrb r1, [r0]\n\ + lsls r1, 28\n\ + lsrs r1, 28\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 3\n\ + bl AllocZeroed\n\ + ldr r2, [r5]\n\ + str r0, [r2, 0x10]\n\ + ldrb r1, [r2]\n\ + lsls r1, 28\n\ + lsrs r1, 28\n\ + ldrb r0, [r2, 0x1]\n\ + lsls r0, 3\n\ + muls r0, r1\n\ + bl AllocZeroed\n\ + adds r2, r0, 0\n\ + ldr r1, [r5]\n\ + str r2, [r1, 0x14]\n\ + ldr r0, [r1, 0x10]\n\ + cmp r0, 0\n\ + beq _08044C7C\n\ + cmp r2, 0\n\ + bne _08044C90\n\ + _08044C7C:\n\ + movs r0, 0x2\n\ + mov r1, r8\n\ + orrs r1, r0\n\ + lsls r0, r1, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + b _08044CE2\n\ + .align 2, 0\n\ + _08044C8C: .4byte sOakSpeechNidoranResources\n\ + _08044C90:\n\ + movs r4, 0\n\ + ldrb r0, [r1, 0x1]\n\ + ldrb r1, [r1]\n\ + lsls r1, 28\n\ + lsrs r1, 28\n\ + muls r0, r1\n\ + adds r3, r5, 0\n\ + cmp r4, r0\n\ + bge _08044CC6\n\ + adds r7, r3, 0\n\ + movs r5, 0x80\n\ + lsls r5, 4\n\ + _08044CA8:\n\ + ldr r2, [r7]\n\ + ldr r1, [r2, 0x14]\n\ + lsls r0, r4, 3\n\ + adds r0, r1\n\ + strh r5, [r0, 0x4]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2]\n\ + lsls r0, 28\n\ + lsrs r0, 28\n\ + muls r0, r1\n\ + cmp r4, r0\n\ + blt _08044CA8\n\ + _08044CC6:\n\ + ldr r0, [r3]\n\ + ldrb r4, [r0, 0x3]\n\ + cmp r4, 0\n\ + beq _08044CDA\n\ + cmp r4, 0x1\n\ + bne _08044CDA\n\ + adds r1, r6, 0\n\ + bl OakSpeechNidoranFSetupTemplate\n\ + b _08044CE2\n\ + _08044CDA:\n\ + ldr r0, _08044D60 @ =sOakSpeechNidoranResources\n\ + ldr r0, [r0]\n\ + bl OakSpeechNidoranFSetupTemplateDummy\n\ + _08044CE2:\n\ + movs r0, 0x2\n\ + mov r1, r8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08044D12\n\ + ldr r4, _08044D60 @ =sOakSpeechNidoranResources\n\ + ldr r0, [r4]\n\ + ldr r0, [r0, 0x14]\n\ + cmp r0, 0\n\ + beq _08044D00\n\ + bl Free\n\ + ldr r1, [r4]\n\ + movs r0, 0\n\ + str r0, [r1, 0x14]\n\ + _08044D00:\n\ + ldr r0, [r4]\n\ + ldr r0, [r0, 0x10]\n\ + cmp r0, 0\n\ + beq _08044D12\n\ + bl Free\n\ + ldr r1, [r4]\n\ + movs r0, 0\n\ + str r0, [r1, 0x10]\n\ + _08044D12:\n\ + movs r0, 0x1\n\ + mov r1, r8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08044D42\n\ + ldr r4, _08044D60 @ =sOakSpeechNidoranResources\n\ + ldr r0, [r4]\n\ + ldr r0, [r0, 0xC]\n\ + cmp r0, 0\n\ + beq _08044D30\n\ + bl Free\n\ + ldr r1, [r4]\n\ + movs r0, 0\n\ + str r0, [r1, 0xC]\n\ + _08044D30:\n\ + ldr r0, [r4]\n\ + ldr r0, [r0, 0x8]\n\ + cmp r0, 0\n\ + beq _08044D42\n\ + bl Free\n\ + ldr r1, [r4]\n\ + movs r0, 0\n\ + str r0, [r1, 0x8]\n\ + _08044D42:\n\ + mov r0, r8\n\ + cmp r0, 0\n\ + beq _08044D64\n\ + ldr r4, _08044D60 @ =sOakSpeechNidoranResources\n\ + ldr r0, [r4]\n\ + movs r1, 0\n\ + movs r2, 0x18\n\ + bl memset\n\ + ldr r0, [r4]\n\ + bl Free\n\ + movs r0, 0\n\ + str r0, [r4]\n\ + b _08044D6C\n\ + .align 2, 0\n\ + _08044D60: .4byte sOakSpeechNidoranResources\n\ + _08044D64:\n\ + ldr r0, _08044D7C @ =sOakSpeechNidoranResources\n\ + ldr r1, [r0]\n\ + movs r0, 0xA3\n\ + strb r0, [r1, 0x2]\n\ + _08044D6C:\n\ + ldr r0, _08044D7C @ =sOakSpeechNidoranResources\n\ + ldr r0, [r0]\n\ + _08044D70:\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ + _08044D7C: .4byte sOakSpeechNidoranResources\n\ + "); +} +#endif + +void OakSpeechNidoranFFreeResources(void) +{ + if (sOakSpeechNidoranResources != NULL) + { + if (sOakSpeechNidoranResources->enable != 0xA3) + { + memset(sOakSpeechNidoranResources, 0, sizeof(struct OakSpeechNidoranFStruct)); + sOakSpeechNidoranResources = NULL; + } + else + { + if (sOakSpeechNidoranResources->frameImages != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->frameImages); + if (sOakSpeechNidoranResources->templates != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->templates); + if (sOakSpeechNidoranResources->bufferPtrs != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->bufferPtrs); + if (sOakSpeechNidoranResources->dataBuffer != NULL) + FREE_AND_SET_NULL(sOakSpeechNidoranResources->dataBuffer); + memset(sOakSpeechNidoranResources, 0, sizeof(struct OakSpeechNidoranFStruct)); + FREE_AND_SET_NULL(sOakSpeechNidoranResources); + } + + } +} + +void *OakSpeechNidoranFGetBuffer(u8 bufferId) +{ + if (sOakSpeechNidoranResources->enable != 0xA3) + { + return NULL; + } + else + { + if (bufferId >= (s8)sOakSpeechNidoranResources->spriteCount) + bufferId = 0; + return sOakSpeechNidoranResources->bufferPtrs[bufferId]; + } +} diff --git a/src/trainer_tower.c b/src/trainer_tower.c index b7b9c096d..cdb42ca96 100644 --- a/src/trainer_tower.c +++ b/src/trainer_tower.c @@ -1378,21 +1378,21 @@ void sub_815E9FC(void) { r2 = gUnknown_847A2EE[r5][r6]; gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2].level = r9; - sub_803E0A4(&gEnemyParty[r6], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]); + CreateBattleTowerMon(&gEnemyParty[r6], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]); } break; case 1: r2 = gUnknown_847A2FE[r5][0]; gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_040[r2].level = r9; - sub_803E0A4(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_040[r2]); + CreateBattleTowerMon(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_040[r2]); r2 = gUnknown_847A2FE[r5][1]; gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[1].unk_040[r2].level = r9; - sub_803E0A4(&gEnemyParty[1], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[1].unk_040[r2]); + CreateBattleTowerMon(&gEnemyParty[1], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[1].unk_040[r2]); break; case 2: r2 = gUnknown_847A30E[r5][r4]; gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2].level = r9; - sub_803E0A4(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]); + CreateBattleTowerMon(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]); break; } } |