diff options
Diffstat (limited to 'arm9/src')
-rw-r--r-- | arm9/src/pokemon.c | 291 |
1 files changed, 281 insertions, 10 deletions
diff --git a/arm9/src/pokemon.c b/arm9/src/pokemon.c index ccd6bf54..4376285e 100644 --- a/arm9/src/pokemon.c +++ b/arm9/src/pokemon.c @@ -41,26 +41,29 @@ BOOL FUN_02069E9C(struct BoxPokemon * boxmon); void FUN_02069ECC(struct BoxPokemon * boxmon); void LoadWotbl_HandleAlternateForme(int species, int forme, u16 * wotbl); void FUN_0206A054(struct BoxPokemon * boxmon, u32 a1, u32 pokeball, u32 a3, u32 encounterType, u32 a5); +BOOL MonHasMove(struct Pokemon * pokemon, u16 move); +BOOL FUN_0206A144(struct BoxPokemon * boxmon, u32 a1); +BOOL FUN_0206A16C(u16 species, int forme, u32 a2); +void FUN_0206A1CC(struct BoxPokemon * boxmon); u32 MaskOfFlagNo(int flagno); void LoadMonPersonal(int species, struct BaseStats * personal); void LoadMonEvolutionTable(u16 species, struct Evolution * dest); -BOOL MonHasMove(struct Pokemon * pokemon, u16 move); int ResolveMonForme(int species, int forme); -void MonEncryptSegment(void * datap, u32 size, u32 key); -void MonDecryptSegment(void * datap, u32 size, u32 key); +void MonEncryptSegment(u16 * datap, u32 size, u32 key); +void MonDecryptSegment(u16 * datap, u32 size, u32 key); u16 MonEncryptionLCRNG(u32 * seed); -u16 CalcMonChecksum(void * datap, u32 size); -PokemonDataBlock * GetSubstruct(struct BoxPokemon * boxmon, u32 personality, u32 which_struct); -void LoadMonBaseStats_HandleAlternateForme(u32 species, u32 forme, struct BaseStats * baseStats); +u16 CalcMonChecksum(u16 * datap, u32 size); +PokemonDataBlock * GetSubstruct(struct BoxPokemon * boxmon, u32 personality, u8 which_struct); +void LoadMonBaseStats_HandleAlternateForme(int species, int forme, struct BaseStats * baseStats); -#define ENCRY_ARGS_PTY(mon) &(mon)->party, sizeof((mon)->party), (mon)->box.pid -#define ENCRY_ARGS_BOX(boxmon) &(boxmon)->substructs, sizeof((boxmon)->substructs), (boxmon)->checksum +#define ENCRY_ARGS_PTY(mon) (u16 *)&(mon)->party, sizeof((mon)->party), (mon)->box.pid +#define ENCRY_ARGS_BOX(boxmon) (u16 *)&(boxmon)->substructs, sizeof((boxmon)->substructs), (boxmon)->checksum #define ENCRYPT_PTY(mon) MonEncryptSegment(ENCRY_ARGS_PTY(mon)) #define ENCRYPT_BOX(boxmon) MonEncryptSegment(ENCRY_ARGS_BOX(boxmon)) #define DECRYPT_PTY(mon) MonDecryptSegment(ENCRY_ARGS_PTY(mon)) #define DECRYPT_BOX(boxmon) MonDecryptSegment(ENCRY_ARGS_BOX(boxmon)) -#define CHECKSUM(boxmon) CalcMonChecksum((boxmon)->substructs, sizeof((boxmon)->substructs)) +#define CHECKSUM(boxmon) CalcMonChecksum((u16 *)(boxmon)->substructs, sizeof((boxmon)->substructs)) #define SHINY_CHECK(otid, pid) (( \ ((((otid) & 0xFFFF0000u) >> 16u)) ^ \ (((otid) & 0xFFFFu)) ^ \ @@ -255,7 +258,7 @@ void CreateMon(struct Pokemon * pokemon, int species, int level, int fixedIV, in ZeroMonData(pokemon); CreateBoxMon(&pokemon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId); // Not your average encryption call - MonEncryptSegment(&pokemon->party, sizeof(pokemon->party), 0); + MonEncryptSegment((u16 *)&pokemon->party, sizeof(pokemon->party), 0); ENCRYPT_PTY(pokemon); SetMonData(pokemon, MON_DATA_LEVEL, &level); seal = CreateNewSealsObject(0); @@ -3337,3 +3340,271 @@ void FUN_0206A054(struct BoxPokemon * boxmon, u32 a1, u32 pokeball, u32 a3, u32 SetBoxMonData(boxmon, MON_DATA_POKEBALL, &pokeball); SetBoxMonData(boxmon, MON_DATA_ENCOUNTER_TYPE, &encounterType); } + +void FUN_0206A094(struct Pokemon * pokemon, u32 a1, u32 a2) +{ + u32 chance; + u16 species; + u16 forme; + u16 item1; + u16 item2; + if (!(a1 & 0x81)) { + chance = rand_LC() % 100; + species = GetMonData(pokemon, MON_DATA_SPECIES, 0); + forme = GetMonData(pokemon, MON_DATA_FORME, 0); + item1 = GetMonBaseStat_HandleFormeConversion(species, forme, BASE_ITEM_1); + item2 = GetMonBaseStat_HandleFormeConversion(species, forme, BASE_ITEM_2); + if (item1 == item2 && item1 != ITEM_NONE) + { + SetMonData(pokemon, MON_DATA_HELD_ITEM, &item1); + } + else + { + if (chance >= sItemOdds[a2][0]) + { + if (chance < sItemOdds[a2][1]) + { + SetMonData(pokemon, MON_DATA_HELD_ITEM, &item1); + } + else + { + SetMonData(pokemon, MON_DATA_HELD_ITEM, &item2); + } + } + } + } +} + +BOOL FUN_0206A13C(struct Pokemon * pokemon, u32 a1) +{ + return FUN_0206A144(&pokemon->box, a1); +} + +BOOL FUN_0206A144(struct BoxPokemon * boxmon, u32 a1) +{ + u16 species = GetBoxMonData(boxmon, MON_DATA_SPECIES2, NULL); + int forme = GetBoxMonData(boxmon, MON_DATA_FORME, NULL); + return FUN_0206A16C(species, forme, a1); +} + +BOOL FUN_0206A16C(u16 species, int forme, u32 a2) +{ + u32 r4; + enum BaseStat r2; + if (species == SPECIES_EGG) + return FALSE; + if (a2 < 32) + { + r4 = 1 << a2; + r2 = BASE_UNKNOWN_29; + } + else if (a2 < 64) + { + r4 = 1 << (a2 - 32); + r2 = BASE_UNKNOWN_30; + } + else if (a2 < 96) + { + r4 = 1 << (a2 - 64); + r2 = BASE_UNKNOWN_31; + } + else + { + r4 = 1 << (a2 - 96); + r2 = BASE_UNKNOWN_32; + } + return !!(GetMonBaseStat_HandleFormeConversion(species, forme, r2) & r4); +} + +void FUN_0206A1C4(struct Pokemon * pokemon) +{ + FUN_0206A1CC(&pokemon->box); +} + +void FUN_0206A1CC(struct BoxPokemon * boxmon) +{ + BOOL decry = AcquireBoxMonLock(boxmon); + int species = GetBoxMonData(boxmon, MON_DATA_SPECIES, NULL); + int pid = GetBoxMonData(boxmon, MON_DATA_PERSONALITY, NULL); + int ability1 = GetMonBaseStat(species, BASE_ABILITY_1); + int ability2 = GetMonBaseStat(species, BASE_ABILITY_2); + + if (ability2 != ABILITY_NONE) + { + if (pid & 1) + SetBoxMonData(boxmon, MON_DATA_ABILITY, &ability2); + else + SetBoxMonData(boxmon, MON_DATA_ABILITY, &ability1); + } + else + SetBoxMonData(boxmon, MON_DATA_ABILITY, &ability1); + ReleaseBoxMonLock(boxmon, decry); +} + +void FUN_0206A23C(struct Pokemon * r5, u32 personality) +{ + PokemonDataBlockA * r4; + PokemonDataBlockB * r6; + PokemonDataBlockC * r7; + PokemonDataBlockD * sp8; + PokemonDataBlockA * spC; + PokemonDataBlockB * sp10; + PokemonDataBlockC * sp14; + PokemonDataBlockD * sp18; + struct Pokemon * sp4; + + sp4 = AllocMonZeroed(0); + FUN_02069B88(r5, sp4); + r4 = &GetSubstruct(&sp4->box, r5->box.pid, 0)->blockA; + r6 = &GetSubstruct(&sp4->box, r5->box.pid, 1)->blockB; + r7 = &GetSubstruct(&sp4->box, r5->box.pid, 2)->blockC; + sp8 = &GetSubstruct(&sp4->box, r5->box.pid, 3)->blockD; + spC = &GetSubstruct(&r5->box, personality, 0)->blockA; + sp10 = &GetSubstruct(&r5->box, personality, 1)->blockB; + sp14 = &GetSubstruct(&r5->box, personality, 2)->blockC; + sp18 = &GetSubstruct(&r5->box, personality, 3)->blockD; + + DECRYPT_BOX(&sp4->box); + DECRYPT_PTY(r5); + DECRYPT_BOX(&r5->box); + r5->box.pid = personality; + *spC = *r4; + *sp10 = *r6; + *sp14 = *r7; + *sp18 = *sp8; + r5->box.checksum = CHECKSUM(&r5->box); + ENCRYPT_BOX(&r5->box); + ENCRYPT_PTY(r5); + FreeToHeap(sp4); +} + +void LoadMonPersonal(int species, struct BaseStats * personal) +{ + ReadWholeNarcMemberByIdPair(personal, NARC_POKETOOL_PERSONAL_PERSONAL, species); +} + +void LoadMonBaseStats_HandleAlternateForme(int species, int forme, struct BaseStats * personal) +{ + ReadWholeNarcMemberByIdPair(personal, NARC_POKETOOL_PERSONAL_PERSONAL, ResolveMonForme(species, forme)); +} + +void LoadMonEvolutionTable(u16 species, struct Evolution * evo) +{ + ReadWholeNarcMemberByIdPair(evo, NARC_POKETOOL_PERSONAL_EVO, species); +} + + +void MonEncryptSegment(u16 * data, u32 size, u32 seed) { + int i; + for (i = 0; i < size / 2; i++) + { + data[i] ^= MonEncryptionLCRNG(&seed); + } +} + +void MonDecryptSegment(u16 * data, u32 size, u32 seed) { + MonEncryptSegment(data, size, seed); +} + +u16 MonEncryptionLCRNG(u32 * seed) +{ + *seed = *seed * 1103515245 + 24691; + return *seed >> 16; +} + +u16 CalcMonChecksum(u16 * data, u32 size) +{ + int i; + u16 ret = 0; + for (i = 0; i < size / 2; i++) + { + ret += data[i]; + } + return ret; +} + +#define SUBSTRUCT_CASE(v1, v2, v3, v4)({ \ + PokemonDataBlock *substructs = boxMon->substructs; \ + switch (substructType) \ + { \ + case 0: \ + result = &substructs[v1]; \ + break; \ + case 1: \ + result = &substructs[v2]; \ + break; \ + case 2: \ + result = &substructs[v3]; \ + break; \ + case 3: \ + result = &substructs[v4]; \ + break; \ + } \ +});\ + break; \ + +PokemonDataBlock *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) +{ + PokemonDataBlock *result; + + switch ((personality & 0x3E000) >> 13) + { + case 0: + case 24: + SUBSTRUCT_CASE(0,1,2,3) + case 1: + case 25: + SUBSTRUCT_CASE(0,1,3,2) + case 2: + case 26: + SUBSTRUCT_CASE(0,2,1,3) + case 3: + case 27: + SUBSTRUCT_CASE(0,3,1,2) + case 4: + case 28: + SUBSTRUCT_CASE(0,2,3,1) + case 5: + case 29: + SUBSTRUCT_CASE(0,3,2,1) + case 6: + case 30: + SUBSTRUCT_CASE(1,0,2,3) + case 7: + case 31: + SUBSTRUCT_CASE(1,0,3,2) + case 8: + SUBSTRUCT_CASE(2,0,1,3) + case 9: + SUBSTRUCT_CASE(3,0,1,2) + case 10: + SUBSTRUCT_CASE(2,0,3,1) + case 11: + SUBSTRUCT_CASE(3,0,2,1) + case 12: + SUBSTRUCT_CASE(1,2,0,3) + case 13: + SUBSTRUCT_CASE(1,3,0,2) + case 14: + SUBSTRUCT_CASE(2,1,0,3) + case 15: + SUBSTRUCT_CASE(3,1,0,2) + case 16: + SUBSTRUCT_CASE(2,3,0,1) + case 17: + SUBSTRUCT_CASE(3,2,0,1) + case 18: + SUBSTRUCT_CASE(1,2,3,0) + case 19: + SUBSTRUCT_CASE(1,3,2,0) + case 20: + SUBSTRUCT_CASE(2,1,3,0) + case 21: + SUBSTRUCT_CASE(3,1,2,0) + case 22: + SUBSTRUCT_CASE(2,3,1,0) + case 23: + SUBSTRUCT_CASE(3,2,1,0) + } + return result; +} |