summaryrefslogtreecommitdiff
path: root/arm9/src
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/src')
-rw-r--r--arm9/src/mail_message.c6
-rw-r--r--arm9/src/pokemon.c201
-rw-r--r--arm9/src/save_arrays.c8
-rw-r--r--arm9/src/script_buffers.c29
-rw-r--r--arm9/src/seal_case.c59
-rw-r--r--arm9/src/trainer_data.c403
-rw-r--r--arm9/src/unk_020139D8.c106
-rw-r--r--arm9/src/unk_02021FF8.c176
-rw-r--r--arm9/src/unk_0206B688.c185
-rw-r--r--arm9/src/unk_0206BB28.c25
10 files changed, 1022 insertions, 176 deletions
diff --git a/arm9/src/mail_message.c b/arm9/src/mail_message.c
index 4d1b75c6..a5837d89 100644
--- a/arm9/src/mail_message.c
+++ b/arm9/src/mail_message.c
@@ -16,7 +16,7 @@ struct UnkStruct_020ED556
u16 unk_8;
};
-extern u16 FUN_02013A9C(s16 bank, u16 num);
+extern u16 GetECWordIndexByPair(s16 bank, u16 num);
const u16 UNK_020ED54C[] = {
397,
@@ -68,9 +68,9 @@ void MailMsg_init_fromTemplate(struct MailMessage * mailMsg, u32 a1)
MailMsg_init_withBank(mailMsg, UNK_020ED556[a1].unk_0);
mailMsg->msg_no = UNK_020ED556[a1].unk_1;
if (UNK_020ED556[a1].unk_2 != -1)
- mailMsg->fields[0] = FUN_02013A9C(UNK_020ED556[a1].unk_2, UNK_020ED556[a1].unk_4);
+ mailMsg->fields[0] = GetECWordIndexByPair(UNK_020ED556[a1].unk_2, UNK_020ED556[a1].unk_4);
if (UNK_020ED556[a1].unk_6 != -1)
- mailMsg->fields[1] = FUN_02013A9C(UNK_020ED556[a1].unk_6, UNK_020ED556[a1].unk_8);
+ mailMsg->fields[1] = GetECWordIndexByPair(UNK_020ED556[a1].unk_6, UNK_020ED556[a1].unk_8);
}
}
diff --git a/arm9/src/pokemon.c b/arm9/src/pokemon.c
index 48b1a225..b3e53d1a 100644
--- a/arm9/src/pokemon.c
+++ b/arm9/src/pokemon.c
@@ -10,7 +10,7 @@
#include "math_util.h"
#include "move_data.h"
#include "string_util.h"
-#include "text.h"
+#include "seal.h"
#include "msgdata.h"
#include "itemtool.h"
#include "constants/abilities.h"
@@ -21,8 +21,6 @@
#pragma thumb on
-extern void FUN_02029C74(const u8 *, u8 *);
-
u32 GetMonDataInternal(struct Pokemon * pokemon, int attr, void * ptr);
u32 GetBoxMonDataInternal(struct BoxPokemon * pokemon, int attr, void * ptr);
void SetMonDataInternal(struct Pokemon * pokemon, int attr, void * ptr);
@@ -39,12 +37,12 @@ u32 FUN_020696A8(struct BoxPokemon * boxmon, u16 move);
void FUN_02069718(struct BoxPokemon * boxmon, u16 move);
void BoxMonSetMoveInSlot(struct BoxPokemon * boxmon, u16 move, u8 slot);
void FUN_020698E8(struct BoxPokemon * boxmon, int slot1, int slot2);
-s8 FUN_02069BD0(struct BoxPokemon * boxmon, int flavor);
-s8 FUN_02069BE4(u32 personality, int flavor);
-u8 FUN_02069CF4(struct PlayerParty * party_p, u8 mask);
-BOOL FUN_02069E7C(struct BoxPokemon * boxmon);
-BOOL FUN_02069E9C(struct BoxPokemon * boxmon);
-void FUN_02069ECC(struct BoxPokemon * boxmon);
+s8 BoxMonGetFlavorPreference(struct BoxPokemon * boxmon, int flavor);
+s8 GetFlavorPreferenceFromPID(u32 personality, int flavor);
+u8 Party_MaskMonsWithPokerus(struct PlayerParty * party_p, u8 mask);
+BOOL BoxMon_HasPokerus(struct BoxPokemon * boxmon);
+BOOL BoxMon_IsImmuneToPokerus(struct BoxPokemon * boxmon);
+void BoxMon_UpdateArceusForme(struct BoxPokemon * boxmon);
void LoadWotbl_HandleAlternateForme(int species, int forme, u16 * wotbl);
void FUN_0206A054(struct BoxPokemon * boxmon, struct PlayerData * a1, u32 pokeball, u32 a3, u32 encounterType, u32 heap_id);
BOOL MonHasMove(struct Pokemon * pokemon, u16 move);
@@ -118,61 +116,62 @@ const u16 sLegendaryMonsList[] = {
SPECIES_ARCEUS,
};
-const s8 UNK_020F7F16[][5] = {
- // Atk, Def, Spd, SpA, SpD
- { 0, 0, 0, 0, 0},
- { 1, 0, 0, 0, -1},
- { 1, 0, -1, 0, 0},
- { 1, -1, 0, 0, 0},
- { 1, 0, 0, -1, 0},
- { -1, 0, 0, 0, 1},
- { 0, 0, 0, 0, 0},
- { 0, 0, -1, 0, 1},
- { 0, -1, 0, 0, 1},
- { 0, 0, 0, -1, 1},
- { -1, 0, 1, 0, 0},
- { 0, 0, 1, 0, -1},
- { 0, 0, 0, 0, 0},
- { 0, -1, 1, 0, 0},
- { 0, 0, 1, -1, 0},
- { -1, 1, 0, 0, 0},
- { 0, 1, 0, 0, -1},
- { 0, 1, -1, 0, 0},
- { 0, 0, 0, 0, 0},
- { 0, 1, 0, -1, 0},
- { -1, 0, 0, 1, 0},
- { 0, 0, 0, 1, -1},
- { 0, 0, -1, 1, 0},
- { 0, -1, 0, 1, 0},
- { 0, 0, 0, 0, 0},
+const s8 sFlavorPreferencesByNature[][5] = {
+ // Spicy, Dry, Sweet, Bitter, Sour
+ { 0, 0, 0, 0, 0 }, // NATURE_HARDY
+ { 1, 0, 0, 0, -1 }, // NATURE_LONELY
+ { 1, 0, -1, 0, 0 }, // NATURE_BRAVE
+ { 1, -1, 0, 0, 0 }, // NATURE_ADAMANT
+ { 1, 0, 0, -1, 0 }, // NATURE_NAUGHTY
+ { -1, 0, 0, 0, 1 }, // NATURE_BOLD
+ { 0, 0, 0, 0, 0 }, // NATURE_DOCILE
+ { 0, 0, -1, 0, 1 }, // NATURE_RELAXED
+ { 0, -1, 0, 0, 1 }, // NATURE_IMPISH
+ { 0, 0, 0, -1, 1 }, // NATURE_LAX
+ { -1, 0, 1, 0, 0 }, // NATURE_TIMID
+ { 0, 0, 1, 0, -1 }, // NATURE_HASTY
+ { 0, 0, 0, 0, 0 }, // NATURE_SERIOUS
+ { 0, -1, 1, 0, 0 }, // NATURE_JOLLY
+ { 0, 0, 1, -1, 0 }, // NATURE_NAIVE
+ { -1, 1, 0, 0, 0 }, // NATURE_MODEST
+ { 0, 1, 0, 0, -1 }, // NATURE_MILD
+ { 0, 1, -1, 0, 0 }, // NATURE_QUIET
+ { 0, 0, 0, 0, 0 }, // NATURE_BASHFUL
+ { 0, 1, 0, -1, 0 }, // NATURE_RASH
+ { -1, 0, 0, 1, 0 }, // NATURE_CALM
+ { 0, 0, 0, 1, -1 }, // NATURE_GENTLE
+ { 0, 0, -1, 1, 0 }, // NATURE_SASSY
+ { 0, -1, 0, 1, 0 }, // NATURE_CAREFUL
+ { 0, 0, 0, 0, 0 }, // NATURE_QUIRKY
};
const s8 sNatureStatMods[][5] = {
- { 0, 0, 0, 0, 0 },
- { 1, -1, 0, 0, 0 },
- { 1, 0, -1, 0, 0 },
- { 1, 0, 0, -1, 0 },
- { 1, 0, 0, 0, -1 },
- { -1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 0 },
- { 0, 1, -1, 0, 0 },
- { 0, 1, 0, -1, 0 },
- { 0, 1, 0, 0, -1 },
- { -1, 0, 1, 0, 0 },
- { 0, -1, 1, 0, 0 },
- { 0, 0, 0, 0, 0 },
- { 0, 0, 1, -1, 0 },
- { 0, 0, 1, 0, -1 },
- { -1, 0, 0, 1, 0 },
- { 0, -1, 0, 1, 0 },
- { 0, 0, -1, 1, 0 },
- { 0, 0, 0, 0, 0 },
- { 0, 0, 0, 1, -1 },
- { -1, 0, 0, 0, 1 },
- { 0, -1, 0, 0, 1 },
- { 0, 0, -1, 0, 1 },
- { 0, 0, 0, -1, 1 },
- { 0, 0, 0, 0, 0 },
+ // Atk, Def, Speed, SpAtk, SpDef
+ { 0, 0, 0, 0, 0 }, // NATURE_HARDY
+ { 1, -1, 0, 0, 0 }, // NATURE_LONELY
+ { 1, 0, -1, 0, 0 }, // NATURE_BRAVE
+ { 1, 0, 0, -1, 0 }, // NATURE_ADAMANT
+ { 1, 0, 0, 0, -1 }, // NATURE_NAUGHTY
+ { -1, 1, 0, 0, 0 }, // NATURE_BOLD
+ { 0, 0, 0, 0, 0 }, // NATURE_DOCILE
+ { 0, 1, -1, 0, 0 }, // NATURE_RELAXED
+ { 0, 1, 0, -1, 0 }, // NATURE_IMPISH
+ { 0, 1, 0, 0, -1 }, // NATURE_LAX
+ { -1, 0, 1, 0, 0 }, // NATURE_TIMID
+ { 0, -1, 1, 0, 0 }, // NATURE_HASTY
+ { 0, 0, 0, 0, 0 }, // NATURE_SERIOUS
+ { 0, 0, 1, -1, 0 }, // NATURE_JOLLY
+ { 0, 0, 1, 0, -1 }, // NATURE_NAIVE
+ { -1, 0, 0, 1, 0 }, // NATURE_MODEST
+ { 0, -1, 0, 1, 0 }, // NATURE_MILD
+ { 0, 0, -1, 1, 0 }, // NATURE_QUIET
+ { 0, 0, 0, 0, 0 }, // NATURE_BASHFUL
+ { 0, 0, 0, 1, -1 }, // NATURE_RASH
+ { -1, 0, 0, 0, 1 }, // NATURE_CALM
+ { 0, -1, 0, 0, 1 }, // NATURE_GENTLE
+ { 0, 0, -1, 0, 1 }, // NATURE_SASSY
+ { 0, 0, 0, -1, 1 }, // NATURE_CAREFUL
+ { 0, 0, 0, 0, 0 }, // NATURE_QUIRKY
};
void ZeroMonData(struct Pokemon * pokemon)
@@ -563,10 +562,10 @@ u32 GetMonDataInternal(struct Pokemon * pokemon, int attr, void * dest)
case MON_DATA_SPDEF:
return pokemon->party.spdef;
case MON_DATA_MAIL_STRUCT:
- Mail_copy(&pokemon->party.seal_something, dest);
+ Mail_copy(&pokemon->party.mail, dest);
return 1;
case MON_DATA_SEAL_COORDS:
- FUN_02029C74(pokemon->party.sealCoords, dest);
+ CapsuleArray_copy(&pokemon->party.sealCoords, dest);
return 1;
default:
return GetBoxMonDataInternal(&pokemon->box, attr, dest);
@@ -1051,10 +1050,10 @@ void SetMonDataInternal(struct Pokemon * pokemon, int attr, void * value)
pokemon->party.spdef = VALUE(u16);
break;
case MON_DATA_MAIL_STRUCT:
- Mail_copy((const struct Mail *)value, &pokemon->party.seal_something);
+ Mail_copy((const struct Mail *)value, &pokemon->party.mail);
break;
case MON_DATA_SEAL_COORDS:
- FUN_02029C74((const u8 *)value, pokemon->party.sealCoords);
+ CapsuleArray_copy((CapsuleArray *)value, &pokemon->party.sealCoords);
break;
default:
SetBoxMonDataInternal(&pokemon->box, attr, value);
@@ -2990,10 +2989,10 @@ BOOL MonHasMove(struct Pokemon * pokemon, u16 move)
return FALSE;
}
-void FUN_02069A64(struct BoxPokemon * src, struct Pokemon * dest)
+void CopyBoxPokemonToPokemon(struct BoxPokemon * src, struct Pokemon * dest)
{
u32 sp0 = 0;
- u8 sp4[12][2];
+ CapsuleArray sp4;
struct Mail * mail;
dest->box = *src;
if (dest->box.box_lock)
@@ -3005,12 +3004,12 @@ void FUN_02069A64(struct BoxPokemon * src, struct Pokemon * dest)
SetMonData(dest, MON_DATA_MAIL_STRUCT, mail);
FreeToHeap(mail);
SetMonData(dest, MON_DATA_CAPSULE, &sp0);
- MIi_CpuClearFast(0, sp4, sizeof(sp4));
- SetMonData(dest, MON_DATA_SEAL_COORDS, sp4);
+ MIi_CpuClearFast(0, &sp4, sizeof(sp4));
+ SetMonData(dest, MON_DATA_SEAL_COORDS, &sp4);
CalcMonLevelAndStats(dest);
}
-u8 FUN_02069AEC(struct PlayerParty * party)
+u8 Party_GetMaxLevel(struct PlayerParty * party)
{
int i;
int r7 = GetPartyCount(party);
@@ -3037,7 +3036,7 @@ u16 SpeciesToSinnohDexNo(u16 species)
return ret;
}
-u16 FUN_02069B60(u16 sinnoh_dex)
+u16 SinnohDexNoToSpecies(u16 sinnoh_dex)
{
u16 ret = SPECIES_NONE;
if (sinnoh_dex <= SINNOH_DEX_COUNT)
@@ -3045,38 +3044,38 @@ u16 FUN_02069B60(u16 sinnoh_dex)
return ret;
}
-void FUN_02069B88(struct Pokemon * src, struct Pokemon * dest)
+void CopyPokemonToPokemon(struct Pokemon * src, struct Pokemon * dest)
{
*dest = *src;
}
-void FUN_02069BA0(struct Pokemon * src, struct BoxPokemon * dest)
+void CopyPokemonToBoxPokemon(struct Pokemon * src, struct BoxPokemon * dest)
{
*dest = src->box;
}
-void FUN_02069BB4(struct BoxPokemon * src, struct BoxPokemon * dest)
+void CopyBoxPokemonToBoxPokemon(struct BoxPokemon * src, struct BoxPokemon * dest)
{
*dest = *src;
}
-s8 FUN_02069BC8(struct Pokemon * pokemon, int flavor)
+s8 MonGetFlavorPreference(struct Pokemon * pokemon, int flavor)
{
- return FUN_02069BD0(&pokemon->box, flavor);
+ return BoxMonGetFlavorPreference(&pokemon->box, flavor);
}
-s8 FUN_02069BD0(struct BoxPokemon * boxmon, int flavor)
+s8 BoxMonGetFlavorPreference(struct BoxPokemon * boxmon, int flavor)
{
u32 personality = GetBoxMonData(boxmon, MON_DATA_PERSONALITY, NULL);
- return FUN_02069BE4(personality, flavor);
+ return GetFlavorPreferenceFromPID(personality, flavor);
}
-s8 FUN_02069BE4(u32 personality, int flavor)
+s8 GetFlavorPreferenceFromPID(u32 personality, int flavor)
{
- return UNK_020F7F16[GetNatureFromPersonality(personality)][flavor];
+ return sFlavorPreferencesByNature[GetNatureFromPersonality(personality)][flavor];
}
-int FUN_02069BFC(u16 species, u32 forme, u16 * dest)
+int Species_LoadLearnsetTable(u16 species, u32 forme, u16 * dest)
{
int i;
u16 * wotbl = AllocFromHeap(0, 22 * sizeof(u16));
@@ -3089,7 +3088,7 @@ int FUN_02069BFC(u16 species, u32 forme, u16 * dest)
return i;
}
-void FUN_02069C4C(struct PlayerParty * party)
+void Party_GivePokerusAtRandom(struct PlayerParty * party)
{
int count = GetPartyCount(party);
int idx;
@@ -3105,7 +3104,7 @@ void FUN_02069C4C(struct PlayerParty * party)
idx = LCRandom() % count;
pokemon = GetPartyMonByIndex(party, idx);
} while (GetMonData(pokemon, MON_DATA_SPECIES, NULL) == SPECIES_NONE || GetMonData(pokemon, MON_DATA_IS_EGG, NULL));
- if (!FUN_02069CF4(party, (u8)MaskOfFlagNo(idx)))
+ if (!Party_MaskMonsWithPokerus(party, (u8)MaskOfFlagNo(idx)))
{
do
{
@@ -3121,7 +3120,7 @@ void FUN_02069C4C(struct PlayerParty * party)
}
}
-u8 FUN_02069CF4(struct PlayerParty * party, u8 mask)
+u8 Party_MaskMonsWithPokerus(struct PlayerParty * party, u8 mask)
{
int i = 0;
u32 flag = 1;
@@ -3152,7 +3151,7 @@ u8 FUN_02069CF4(struct PlayerParty * party, u8 mask)
return ret;
}
-void FUN_02069D50(struct PlayerParty * party, int r5)
+void Party_UpdatePokerus(struct PlayerParty * party, int r5)
{
int i;
u8 pokerus;
@@ -3178,7 +3177,7 @@ void FUN_02069D50(struct PlayerParty * party, int r5)
}
}
-void FUN_02069DC8(struct PlayerParty * party)
+void Party_SpreadPokerus(struct PlayerParty * party)
{
int count = GetPartyCount(party);
int i;
@@ -3215,22 +3214,22 @@ void FUN_02069DC8(struct PlayerParty * party)
}
}
-BOOL FUN_02069E74(struct Pokemon * pokemon)
+BOOL Pokemon_HasPokerus(struct Pokemon * pokemon)
{
- return FUN_02069E7C(&pokemon->box);
+ return BoxMon_HasPokerus(&pokemon->box);
}
-BOOL FUN_02069E7C(struct BoxPokemon * boxmon)
+BOOL BoxMon_HasPokerus(struct BoxPokemon * boxmon)
{
return !!(GetBoxMonData(boxmon, MON_DATA_POKERUS, NULL) & 0xF);
}
-BOOL FUN_02069E94(struct Pokemon * pokemon)
+BOOL Pokemon_IsImmuneToPokerus(struct Pokemon * pokemon)
{
- return FUN_02069E9C(&pokemon->box);
+ return BoxMon_IsImmuneToPokerus(&pokemon->box);
}
-BOOL FUN_02069E9C(struct BoxPokemon * boxmon)
+BOOL BoxMon_IsImmuneToPokerus(struct BoxPokemon * boxmon)
{
u8 pokerus = (u8)GetBoxMonData(boxmon, MON_DATA_POKERUS, NULL);
if (pokerus & 0xF)
@@ -3240,12 +3239,12 @@ BOOL FUN_02069E9C(struct BoxPokemon * boxmon)
return FALSE;
}
-void FUN_02069EC4(struct Pokemon * pokemon)
+void Pokemon_UpdateArceusForme(struct Pokemon * pokemon)
{
- FUN_02069ECC(&pokemon->box);
+ BoxMon_UpdateArceusForme(&pokemon->box);
}
-void FUN_02069ECC(struct BoxPokemon * boxmon)
+void BoxMon_UpdateArceusForme(struct BoxPokemon * boxmon)
{
u32 species = GetBoxMonData(boxmon, MON_DATA_SPECIES, NULL);
u32 ability = GetBoxMonData(boxmon, MON_DATA_ABILITY, NULL);
@@ -3460,7 +3459,7 @@ void FUN_0206A23C(struct Pokemon * r5, u32 personality)
struct Pokemon * sp4;
sp4 = AllocMonZeroed(0);
- FUN_02069B88(r5, sp4);
+ CopyPokemonToPokemon(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;
@@ -3711,7 +3710,7 @@ int FUN_0206AA30(int x)
case TRAINER_CLASS_PKMN_TRAINER_POKEKID:
return x - TRAINER_CLASS_COMMANDER_JUPITER;
default:
- if (FUN_0206AE00(x) == 1)
+ if (TrainerClass_GetGenderOrTrainerCount(x) == 1)
return 1;
else
return 0;
@@ -3721,13 +3720,13 @@ int FUN_0206AA30(int x)
}
}
-void FUN_0206AA84(struct Pokemon * pokemon)
+void Pokemon_RemoveCapsule(struct Pokemon * pokemon)
{
u8 sp0 = 0;
- u8 sp1[12][2];
- MIi_CpuClearFast(0, sp1, sizeof(sp1));
+ CapsuleArray sp1;
+ MIi_CpuClearFast(0, &sp1, sizeof(sp1));
SetMonData(pokemon, MON_DATA_CAPSULE, &sp0);
- SetMonData(pokemon, MON_DATA_SEAL_COORDS, sp1);
+ SetMonData(pokemon, MON_DATA_SEAL_COORDS, &sp1);
}
void RestoreBoxMonPP(struct BoxPokemon * boxmon)
diff --git a/arm9/src/save_arrays.c b/arm9/src/save_arrays.c
index 43e83403..397f1f69 100644
--- a/arm9/src/save_arrays.c
+++ b/arm9/src/save_arrays.c
@@ -12,6 +12,8 @@
#include "unk_020254B8.h"
#include "daycare.h"
#include "pokedex.h"
+#include "seal.h"
+#include "unk_020139D8.h"
extern u32 FUN_0202AC20(void);
extern u32 FUN_02034D7C(void);
@@ -24,7 +26,6 @@ extern u32 FUN_02028054(void);
extern u32 FUN_02028980(void);
extern u32 FUN_02029A84(void);
extern u32 FUN_02029FB0(void);
-extern u32 FUN_02029C58(void);
extern u32 FUN_02029EC4(void);
extern u32 FUN_0202A89C(void);
extern u32 FUN_0202A8F4(void);
@@ -36,7 +37,6 @@ extern u32 FUN_020281E0(void);
extern u32 FUN_02029AE0(void);
extern u32 FUN_0202BE98(void);
extern u32 FUN_0202C0E0(void);
-extern u32 FUN_02013B28(void);
extern void FUN_0202AC28(void *);
extern void FUN_02034D98(void *);
extern void FUN_02024E6C(void *);
@@ -48,7 +48,6 @@ extern void FUN_0202805C(void *);
extern void FUN_02028994(void *);
extern void FUN_02029A8C(void *);
extern void FUN_02029FB8(void *);
-extern void FUN_02029C60(void *);
extern void FUN_02029ECC(void *);
extern void FUN_0202A8A4(void *);
extern void FUN_0202A8F8(void *);
@@ -60,7 +59,6 @@ extern void FUN_020281E8(void *);
extern void FUN_02029AE8(void *);
extern void FUN_0202BEA0(void *);
extern void FUN_0202C0E4(void *);
-extern void FUN_02013B2C(void *);
const struct SaveChunkHeader UNK_020EE6E0[] = {
{ 0, 32, (SAVSIZEFN)Sav2_HOF_sizeof, (SAVINITFN)Sav2_HOF_init },
@@ -89,7 +87,7 @@ const struct SaveChunkHeader UNK_020EE700[] = {
{ 18, 0, (SAVSIZEFN)FUN_02028980, (SAVINITFN)FUN_02028994 },
{ 19, 0, (SAVSIZEFN)FUN_02029A84, (SAVINITFN)FUN_02029A8C },
{ 20, 0, (SAVSIZEFN)FUN_02029FB0, (SAVINITFN)FUN_02029FB8 },
- { 21, 0, (SAVSIZEFN)FUN_02029C58, (SAVINITFN)FUN_02029C60 },
+ { 21, 0, (SAVSIZEFN)Sav2_SealCase_sizeof, (SAVINITFN)Sav2_SealCase_init },
{ 22, 0, (SAVSIZEFN)FUN_02029EC4, (SAVINITFN)FUN_02029ECC },
{ 23, 0, (SAVSIZEFN)FUN_0202A89C, (SAVINITFN)FUN_0202A8A4 },
{ 24, 0, (SAVSIZEFN)FUN_0202A8F4, (SAVINITFN)FUN_0202A8F8 },
diff --git a/arm9/src/script_buffers.c b/arm9/src/script_buffers.c
index c29feed3..431f63b4 100644
--- a/arm9/src/script_buffers.c
+++ b/arm9/src/script_buffers.c
@@ -9,6 +9,7 @@
#include "unk_020286F8.h"
#include "filesystem.h"
#include "unk_0201B8B8.h"
+#include "trainer_data.h"
#include "script_buffers.h"
#pragma thumb on
@@ -16,8 +17,8 @@
extern void * FUN_02024EC0(struct SaveBlock2 * sav2);
extern u16 * FUN_02024EE8(void *);
extern u32 GetCityNamesMsgdataIdByCountry(u32);
-extern void FUN_02013A58(u32 a0, struct String * a1);
-extern void FUN_02022048(struct String * dest, const struct String * src);
+extern void GetECWordIntoStringByIndex(u32 a0, struct String * a1);
+extern void StringCat_HandleTrainerName(struct String * dest, const struct String * src);
extern void StrAddChar(struct String * str, u16 val);
extern void * FUN_02006BB0(NarcId, s32, s32, struct UnkStruct_0200B870_sub **, u32);
extern BOOL UncompressFromNarc(NarcId narcId, s32 memberNo, BOOL a2, u32 heap_id, BOOL a4);
@@ -363,18 +364,18 @@ void BufferTrainerClassNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 trc
}
}
-void BufferTrainerClassName2(struct ScrStrBufs * mgr, u32 idx, struct Trainer * tr)
+void BufferTrainerClassNameFromDataStruct(struct ScrStrBufs * mgr, u32 idx, struct TrainerDataLoaded * tr)
{
struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 560, mgr->heap_id);
if (msgData != NULL)
{
- ReadMsgDataIntoString(msgData, tr->unk1, mgr->tmpbuf);
+ ReadMsgDataIntoString(msgData, tr->data.trainerClass, mgr->tmpbuf);
SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
DestroyMsgData(msgData);
}
}
-void FUN_0200B10C(struct ScrStrBufs * mgr, u32 idx, u32 msgno)
+void BufferTrainerName(struct ScrStrBufs * mgr, u32 idx, u32 msgno)
{
struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 559, mgr->heap_id);
if (msgData != NULL)
@@ -385,9 +386,9 @@ void FUN_0200B10C(struct ScrStrBufs * mgr, u32 idx, u32 msgno)
}
}
-void FUN_0200B144(struct ScrStrBufs * mgr, u32 idx, void * unk_struct)
+void BufferTrainerNameFromDataStruct(struct ScrStrBufs * mgr, u32 idx, struct TrainerDataLoaded * trdata)
{
- CopyU16ArrayToString(mgr->tmpbuf, (u16 *)((char *)unk_struct + 20));
+ CopyU16ArrayToString(mgr->tmpbuf, trdata->name);
SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
}
@@ -587,7 +588,7 @@ void BufferCityName(struct ScrStrBufs * mgr, u32 idx, u32 a2, u32 a3)
void FUN_0200B518(struct ScrStrBufs * mgr, u32 idx, u32 a2)
{
- FUN_02013A58(a2, mgr->tmpbuf);
+ GetECWordIntoStringByIndex(a2, mgr->tmpbuf);
SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
}
@@ -684,7 +685,7 @@ void BufferContestBackgroundName(struct ScrStrBufs * mgr, u32 idx, u32 bg)
}
}
-void FUN_0200B708(struct ScrStrBufs * mgr, struct SaveBlock2 * sav2, u32 r5, u32 idx, u32 sp28)
+void BufferEasyChatWord(struct ScrStrBufs * mgr, struct SaveBlock2 * sav2, u32 r5, u32 idx, u32 sp28)
{
void * r6 = FUN_0202881C(sav2);
u8 sp10 = FUN_020287F8(r6, r5);
@@ -708,7 +709,7 @@ void BufferMonthNameAbbr(struct ScrStrBufs * mgr, u32 idx, u32 month)
}
}
-void FUN_0200B7A8(struct ScrStrBufs * mgr, u32 idx)
+void ScrStrBufs_UpperFirstChar(struct ScrStrBufs * mgr, u32 idx)
{
StrUpperFirstChar(mgr->array[idx].msg);
}
@@ -725,7 +726,7 @@ void StringExpandPlaceholders(struct ScrStrBufs * mgr, struct String * dest, str
{
u32 idx = MsgArray_ControlCodeGetField(cstr, 0);
GF_ASSERT(idx < mgr->count);
- FUN_02022048(dest, mgr->array[idx].msg);
+ StringCat_HandleTrainerName(dest, mgr->array[idx].msg);
cstr = MsgArray_SkipControlCode(cstr);
}
else
@@ -741,13 +742,13 @@ void StringExpandPlaceholders(struct ScrStrBufs * mgr, struct String * dest, str
}
}
-void FUN_0200B84C(struct ScrStrBufs * mgr)
+void ScrStrBufs_ResetBuffers(struct ScrStrBufs * mgr)
{
for (int i = 0; i < mgr->count; i++)
StringSetEmpty(mgr->array[i].msg);
}
-struct UnkStruct_0200B870 * FUN_0200B870(u32 r5, u32 r6, u32 sp4, u32 r4)
+struct UnkStruct_0200B870 * MessagePrinter_new(u32 r5, u32 r6, u32 sp4, u32 r4)
{
struct UnkStruct_0200B870 * sp8 = AllocFromHeap(r4, sizeof(struct UnkStruct_0200B870));
if (sp8 != NULL)
@@ -793,7 +794,7 @@ struct UnkStruct_0200B870 * FUN_0200B870(u32 r5, u32 r6, u32 sp4, u32 r4)
return sp8;
}
-void FUN_0200B990(struct UnkStruct_0200B870 * a0)
+void MessagePrinter_delete(struct UnkStruct_0200B870 * a0)
{
if (a0 != NULL)
{
diff --git a/arm9/src/seal_case.c b/arm9/src/seal_case.c
new file mode 100644
index 00000000..b1359a02
--- /dev/null
+++ b/arm9/src/seal_case.c
@@ -0,0 +1,59 @@
+#include "global.h"
+#include "save_block_2.h"
+#include "MI_memory.h"
+#include "seal.h"
+
+#pragma thumb on
+
+u32 Sav2_SealCase_sizeof(void)
+{
+ return sizeof(struct SealCase);
+}
+
+void Sav2_SealCase_init(struct SealCase * sealCase)
+{
+ MI_CpuClear8(sealCase, Sav2_SealCase_sizeof());
+}
+
+void CapsuleArray_copy(const CapsuleArray * a0, CapsuleArray * a1)
+{
+ MI_CpuCopy8(a0, a1, sizeof(CapsuleArray));
+}
+
+struct SealCase * Sav2_SealCase_get(struct SaveBlock2 * sav2)
+{
+ return (struct SealCase *)SavArray_get(sav2, 21);
+}
+
+CapsuleArray * SealCase_GetCapsuleI(struct SealCase * sealCase, s32 idx)
+{
+ GF_ASSERT(idx < 12);
+ return &sealCase->coords[idx];
+}
+
+void SealCase_SetCapsuleI(struct SealCase * sealCase, const CapsuleArray * src, s32 idx)
+{
+ GF_ASSERT(idx < 12);
+ CapsuleArray_copy(src, SealCase_GetCapsuleI(sealCase, idx));
+}
+
+Coords8 * Capsule_GetSealI(CapsuleArray * a0, s32 a1)
+{
+ GF_ASSERT(a1 < 8);
+ return &(*a0)[a1];
+}
+
+s32 Seal_GetId(Coords8 * a0)
+{
+ return (*a0)[0];
+}
+
+s32 Seal_GetXCoord(Coords8 * a0)
+{
+ return (*a0)[1];
+}
+
+s32 Seal_GetYCoord(Coords8 * a0)
+{
+ return (*a0)[2];
+}
diff --git a/arm9/src/trainer_data.c b/arm9/src/trainer_data.c
new file mode 100644
index 00000000..7af4b2ce
--- /dev/null
+++ b/arm9/src/trainer_data.c
@@ -0,0 +1,403 @@
+#include "global.h"
+#include "heap.h"
+#include "trainer_data.h"
+#include "math_util.h"
+#include "party.h"
+#include "proto.h"
+#include "msgdata.h"
+#include "constants/trainer_classes.h"
+
+#pragma thumb on
+
+extern void * FUN_02024EC0(struct SaveBlock2 *);
+extern u16 * FUN_02024EE8(void *);
+
+// Loads all battle opponents, including multi-battle partner if exists.
+void EnemyTrainerSet_Init(struct BattleSetupStruct * enemies, struct SaveBlock2 * sav2, u32 heap_id)
+{
+ struct TrainerDataLoaded trdata;
+ struct MsgData * msgData;
+ u16 * rivalName;
+ s32 i;
+ struct String * str;
+
+ // FIXME: String formatting in files/msgdata/msg/narc_0559.txt is abnormal.
+ msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 559, heap_id);
+ rivalName = FUN_02024EE8(FUN_02024EC0(sav2));
+ for (i = 0; i < 4; i++)
+ {
+ if (enemies->trainer_idxs[i] != 0)
+ {
+ TrainerData_ReadTrData(enemies->trainer_idxs[i], &trdata.data);
+ enemies->datas[i] = trdata;
+ if (trdata.data.trainerClass == TRAINER_CLASS_PKMN_TRAINER_BARRY)
+ {
+ CopyU16StringArray(enemies->datas[i].name, rivalName);
+ }
+ else
+ {
+ str = NewString_ReadMsgData(msgData, enemies->trainer_idxs[i]);
+ CopyStringToU16Array(str, enemies->datas[i].name, OT_NAME_LENGTH + 1);
+ String_dtor(str);
+ }
+ CreateNPCTrainerParty(enemies, i, heap_id);
+ }
+ }
+ enemies->flags |= trdata.data.doubleBattle;
+ DestroyMsgData(msgData);
+}
+
+s32 TrainerData_GetAttr(u32 tr_idx, u32 attr_no)
+{
+ struct TrainerDataLoaded trainer;
+ s32 ret;
+
+ TrainerData_ReadTrData(tr_idx, &trainer.data);
+ switch (attr_no)
+ {
+ case 0:
+ ret = trainer.data.trainerType;
+ break;
+ case 1:
+ ret = trainer.data.trainerClass;
+ break;
+ case 2:
+ ret = trainer.data.unk_2;
+ break;
+ case 3:
+ ret = trainer.data.npoke;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ attr_no -= 4;
+ ret = trainer.data.items[attr_no];
+ break;
+ case 8:
+ ret = (s32)trainer.data.unk_C;
+ break;
+ case 9:
+ ret = (s32)trainer.data.doubleBattle;
+ break;
+ }
+ return ret; // UB: uninitialized in event of invalid attr
+}
+
+// Relevant files:
+// files/poketool/trmsg/trtbl.narc
+// files/poketool/trmsg/trtblofs.narc
+// files/msgdata/msg/narc_0558.txt
+// trtbl is a single-member NARC whose entries are two shorts each. The first short
+// designates the trainer ID and the second the message ID. They are ordered the same
+// as the corresponding msgdata file. All messages for a given trainer are found together,
+// however the trainers are not in order in this file. trtblofs gives a pointer into trtbl
+// for each trainer. trtblofs is also a single-member NARC whose entries are shorts, one
+// per NPC trainer.
+BOOL TrainerMessageWithIdPairExists(u32 trainer_idx, u32 msg_id, u32 heap_id)
+{
+ u16 rdbuf[3];
+ struct NARC * trTblNarc;
+ BOOL ret = FALSE;
+ u32 trTblSize;
+
+ trTblSize = GetNarcMemberSizeByIdPair(NARC_POKETOOL_TRMSG_TRTBL, 0);
+ ReadFromNarcMemberByIdPair(&rdbuf[0], NARC_POKETOOL_TRMSG_TRTBLOFS, 0, trainer_idx * 2, 2);
+ trTblNarc = NARC_ctor(NARC_POKETOOL_TRMSG_TRTBL, heap_id);
+ while (rdbuf[0] != trTblSize)
+ {
+ NARC_ReadFromMember(trTblNarc, 0, rdbuf[0], 4, &rdbuf[1]);
+ if (rdbuf[1] == trainer_idx && rdbuf[2] == msg_id)
+ {
+ ret = TRUE;
+ break;
+ }
+ if (rdbuf[1] != trainer_idx)
+ break;
+ rdbuf[0] += 4;
+ }
+ NARC_dtor(trTblNarc);
+ return ret;
+}
+
+void GetTrainerMessageByIdPair(u32 trainer_idx, u32 msg_id, struct String * str, u32 heap_id)
+{
+ u16 rdbuf[3];
+ u32 trTblSize;
+ struct NARC * trTblNarc;
+
+ trTblSize = GetNarcMemberSizeByIdPair(NARC_POKETOOL_TRMSG_TRTBL, 0);
+ ReadFromNarcMemberByIdPair(&rdbuf[0], NARC_POKETOOL_TRMSG_TRTBLOFS, 0, trainer_idx * 2, 2);
+ trTblNarc = NARC_ctor(NARC_POKETOOL_TRMSG_TRTBL, heap_id);
+ while (rdbuf[0] != trTblSize)
+ {
+ NARC_ReadFromMember(trTblNarc, 0, rdbuf[0], 4, &rdbuf[1]);
+ if (rdbuf[1] == trainer_idx && rdbuf[2] == msg_id)
+ {
+ ReadMsgData_NewNarc_ExistingString(NARC_MSGDATA_MSG, 558, (u32)(rdbuf[0] / 4), heap_id, str);
+ break;
+ }
+ rdbuf[0] += 4;
+ }
+ NARC_dtor(trTblNarc);
+ if (rdbuf[0] == trTblSize)
+ StringSetEmpty(str);
+}
+
+void TrainerData_ReadTrData(u32 idx, struct TrainerData * dest)
+{
+ ReadWholeNarcMemberByIdPair(dest, NARC_POKETOOL_TRAINER_TRDATA, (s32)idx);
+}
+
+void TrainerData_ReadTrPoke(u32 idx, union TrainerMon * dest)
+{
+ ReadWholeNarcMemberByIdPair(dest, NARC_POKETOOL_TRAINER_TRPOKE, (s32)idx);
+}
+
+const u8 sTrainerClassGenderCountTbl[] = {
+ /*TRAINER_CLASS_PKMN_TRAINER_M*/ 0,
+ /*TRAINER_CLASS_PKMN_TRAINER_F*/ 1,
+ /*TRAINER_CLASS_YOUNGSTER*/ 0,
+ /*TRAINER_CLASS_LASS*/ 1,
+ /*TRAINER_CLASS_CAMPER*/ 0,
+ /*TRAINER_CLASS_PICNICKER*/ 1,
+ /*TRAINER_CLASS_BUG_CATCHER*/ 0,
+ /*TRAINER_CLASS_AROMA_LADY*/ 1,
+ /*TRAINER_CLASS_TWINS*/ 1,
+ /*TRAINER_CLASS_HIKER*/ 0,
+ /*TRAINER_CLASS_BATTLE_GIRL*/ 1,
+ /*TRAINER_CLASS_FISHERMAN*/ 0,
+ /*TRAINER_CLASS_CYCLIST_M*/ 0,
+ /*TRAINER_CLASS_CYCLIST_F*/ 1,
+ /*TRAINER_CLASS_BLACK_BELT*/ 0,
+ /*TRAINER_CLASS_ARTIST*/ 0,
+ /*TRAINER_CLASS_PKMN_BREEDER_M*/ 0,
+ /*TRAINER_CLASS_PKMN_BREEDER_F*/ 1,
+ /*TRAINER_CLASS_COWGIRL*/ 1,
+ /*TRAINER_CLASS_JOGGER*/ 0,
+ /*TRAINER_CLASS_POKEFAN_M*/ 0,
+ /*TRAINER_CLASS_POKEFAN_F*/ 1,
+ /*TRAINER_CLASS_POKE_KID*/ 1,
+ /*TRAINER_CLASS_YOUNG_COUPLE*/ 2,
+ /*TRAINER_CLASS_ACE_TRAINER_M*/ 0,
+ /*TRAINER_CLASS_ACE_TRAINER_F*/ 1,
+ /*TRAINER_CLASS_WAITRESS*/ 1,
+ /*TRAINER_CLASS_VETERAN*/ 0,
+ /*TRAINER_CLASS_NINJA_BOY*/ 0,
+ /*TRAINER_CLASS_DRAGON_TAMER*/ 0,
+ /*TRAINER_CLASS_BIRD_KEEPER*/ 1,
+ /*TRAINER_CLASS_DOUBLE_TEAM*/ 2,
+ /*TRAINER_CLASS_RICH_BOY*/ 0,
+ /*TRAINER_CLASS_LADY*/ 1,
+ /*TRAINER_CLASS_GENTLEMAN*/ 0,
+ /*TRAINER_CLASS_SOCIALITE*/ 1,
+ /*TRAINER_CLASS_BEAUTY*/ 1,
+ /*TRAINER_CLASS_COLLECTOR*/ 0,
+ /*TRAINER_CLASS_POLICEMAN*/ 0,
+ /*TRAINER_CLASS_PKMN_RANGER_M*/ 0,
+ /*TRAINER_CLASS_PKMN_RANGER_F*/ 1,
+ /*TRAINER_CLASS_SCIENTIST*/ 0,
+ /*TRAINER_CLASS_SWIMMER_M*/ 0,
+ /*TRAINER_CLASS_SWIMMER_F*/ 1,
+ /*TRAINER_CLASS_TUBER_M*/ 0,
+ /*TRAINER_CLASS_TUBER_F*/ 1,
+ /*TRAINER_CLASS_SAILOR*/ 0,
+ /*TRAINER_CLASS_SIS_AND_BRO*/ 2,
+ /*TRAINER_CLASS_RUIN_MANIAC*/ 0,
+ /*TRAINER_CLASS_PSYCHIC_M*/ 0,
+ /*TRAINER_CLASS_PSYCHIC_F*/ 1,
+ /*TRAINER_CLASS_PI*/ 0,
+ /*TRAINER_CLASS_GUITARIST*/ 0,
+ /*TRAINER_CLASS_ACE_TRAINER_SNOW_M*/ 0,
+ /*TRAINER_CLASS_ACE_TRAINER_SNOW_F*/ 1,
+ /*TRAINER_CLASS_SKIER_M*/ 0,
+ /*TRAINER_CLASS_SKIER_F*/ 1,
+ /*TRAINER_CLASS_ROUGHNECK*/ 0,
+ /*TRAINER_CLASS_CLOWN*/ 0,
+ /*TRAINER_CLASS_WORKER*/ 0,
+ /*TRAINER_CLASS_SCHOOL_KID_M*/ 0,
+ /*TRAINER_CLASS_SCHOOL_KID_F*/ 1,
+ /*TRAINER_CLASS_LEADER_ROARK*/ 0,
+ /*TRAINER_CLASS_PKMN_TRAINER_BARRY*/ 0,
+ /*TRAINER_CLASS_LEADER_BYRON*/ 0,
+ /*TRAINER_CLASS_ELITE_FOUR_AARON*/ 0,
+ /*TRAINER_CLASS_ELITE_FOUR_BERTHA*/ 1,
+ /*TRAINER_CLASS_ELITE_FOUR_FLINT*/ 0,
+ /*TRAINER_CLASS_ELITE_FOUR_LUCIEN*/ 0,
+ /*TRAINER_CLASS_CHAMPION*/ 1,
+ /*TRAINER_CLASS_BELLE__PA*/ 2,
+ /*TRAINER_CLASS_RANCHER*/ 0,
+ /*TRAINER_CLASS_COMMANDER_MARS*/ 1,
+ /*TRAINER_CLASS_GALACTIC*/ 0,
+ /*TRAINER_CLASS_LEADER_GARDENIA*/ 1,
+ /*TRAINER_CLASS_LEADER_WAKE*/ 0,
+ /*TRAINER_CLASS_LEADER_MAYLENE*/ 1,
+ /*TRAINER_CLASS_LEADER_FANTINA*/ 1,
+ /*TRAINER_CLASS_LEADER_CANDICE*/ 1,
+ /*TRAINER_CLASS_LEADER_VOLKNER*/ 0,
+ /*TRAINER_CLASS_PARASOL_LADY*/ 1,
+ /*TRAINER_CLASS_WAITER*/ 0,
+ /*TRAINER_CLASS_INTERVIEWERS*/ 2,
+ /*TRAINER_CLASS_CAMERAMAN*/ 0,
+ /*TRAINER_CLASS_REPORTER*/ 1,
+ /*TRAINER_CLASS_IDOL*/ 1,
+ /*TRAINER_CLASS_GALACTIC_BOSS*/ 0,
+ /*TRAINER_CLASS_COMMANDER_JUPITER*/ 1,
+ /*TRAINER_CLASS_COMMANDER_SATURN*/ 1,
+ /*TRAINER_CLASS_GALACTIC_F*/ 1,
+ /*TRAINER_CLASS_PKMN_TRAINER_AROMA_LADY*/ 1,
+ /*TRAINER_CLASS_PKMN_TRAINER_RICH_BOY*/ 0,
+ /*TRAINER_CLASS_PKMN_TRAINER_PICNICKER*/ 1,
+ /*TRAINER_CLASS_PKMN_TRAINER_CAMPER*/ 0,
+ /*TRAINER_CLASS_PKMN_TRAINER_POKEKID*/ 1,
+ /*TRAINER_CLASS_PKMN_TRAINER_LUCAS*/ 0,
+ /*TRAINER_CLASS_PKMN_TRAINER_DAWN*/ 1,
+ /*TRAINER_CLASS_TOWER_TYCOON*/ 0
+};
+
+// Returns 0 for male, 1 for female, 2 for doubles. See above vector.
+int TrainerClass_GetGenderOrTrainerCount(int a0)
+{
+ return sTrainerClassGenderCountTbl[a0];
+}
+
+void CreateNPCTrainerParty(struct BattleSetupStruct * enemies, s32 party_id, u32 heap_id)
+{
+ union TrainerMon * data;
+ s32 i;
+ s32 j;
+ u32 seed_bak;
+ struct Pokemon * pokemon;
+ struct TrainerMonSpeciesItemMoves * monSpeciesItemMoves;
+ struct TrainerMonSpeciesItem * monSpeciesItem;
+ struct TrainerMonSpeciesMoves * monSpeciesMoves;
+ struct TrainerMonSpecies * monSpecies;
+ u32 seed;
+ u32 personality;
+ u8 iv;
+ u32 pid_gender;
+
+ // We abuse the RNG for personality value generation, so back up the overworld
+ // state
+ seed_bak = GetLCRNGSeed();
+ InitPartyWithMaxSize(enemies->parties[party_id], PARTY_SIZE);
+ data = (union TrainerMon *)AllocFromHeap(heap_id, sizeof(union TrainerMon) * PARTY_SIZE);
+ pokemon = AllocMonZeroed(heap_id);
+ TrainerData_ReadTrPoke(enemies->trainer_idxs[party_id], data);
+
+ // If a Pokemon's gender ratio is 50/50, the generated Pokemon will be the same
+ // gender as its trainer. Otherwise, it will assume the more abundant gender
+ // according to its species gender ratio. In double battles, the behavior is
+ // identical to that of a solitary male opponent.
+ pid_gender = (u32)((TrainerClass_GetGenderOrTrainerCount(enemies->datas[party_id].data.trainerClass) == 1) ? 0x78 : 0x88);
+
+ // The trainer types can be more efficiently and expandibly treated as a flag
+ // array, with bit 0 being custom moveset and bit 1 being held item.
+ // Nintendo didn't do it that way, instead using a switch statement and a lot
+ // of code duplication. This has been the case since the 2nd generation games.
+ switch (enemies->datas[party_id].data.trainerType)
+ {
+ case TRTYPE_MON:
+ {
+ monSpecies = &data->species;
+ for (i = 0; i < enemies->datas[party_id].data.npoke; i++)
+ {
+ // Generate personality by seeding with a value based on the difficulty,
+ // level, species, and opponent ID. Roll the RNG N times, where N is
+ // the index of its trainer class. Finally, left shift the 16-bit
+ // pseudorandom value and add the gender selector.
+ // This guarantees that NPC trainers' Pokemon are generated in a
+ // consistent manner between attempts.
+ seed = monSpecies[i].difficulty + monSpecies[i].level + monSpecies[i].species + enemies->trainer_idxs[party_id];
+ SetLCRNGSeed(seed);
+ for (j = 0; j < enemies->datas[party_id].data.trainerClass; j++)
+ {
+ seed = LCRandom();
+ }
+ personality = (seed << 8);
+ personality += pid_gender;
+
+ // Difficulty is a number between 0 and 250 which directly corresponds
+ // to the (uniform) IV spread of the generated Pokemon.
+ iv = (u8)((monSpecies[i].difficulty * 31) / 255);
+ CreateMon(pokemon, monSpecies[i].species, monSpecies[i].level, iv, 1, (s32)personality, 2, 0);
+
+ // If you were treating the trainer type as a bitfield, you'd put the
+ // checks for held item and moves here. You'd also treat the trpoke
+ // data as a flat u16 array rather than an array of fixed-width structs.
+ AddMonToParty(enemies->parties[party_id], pokemon);
+ }
+ break;
+ }
+ case TRTYPE_MON_MOVES:
+ {
+ monSpeciesMoves = &data->species_moves;
+ for (i = 0; i < enemies->datas[party_id].data.npoke; i++)
+ {
+ seed = monSpeciesMoves[i].difficulty + monSpeciesMoves[i].level + monSpeciesMoves[i].species + enemies->trainer_idxs[party_id];
+ SetLCRNGSeed(seed);
+ for (j = 0; j < enemies->datas[party_id].data.trainerClass; j++)
+ {
+ seed = LCRandom();
+ }
+ personality = (seed << 8);
+ personality += pid_gender;
+ iv = (u8)((monSpeciesMoves[i].difficulty * 31) / 255);
+ CreateMon(pokemon, monSpeciesMoves[i].species, monSpeciesMoves[i].level, iv, 1, (s32)personality, 2, 0);
+ for (j = 0; j < 4; j++)
+ {
+ MonSetMoveInSlot(pokemon, monSpeciesMoves[i].moves[j], (u8)j);
+ }
+ AddMonToParty(enemies->parties[party_id], pokemon);
+ }
+ break;
+ }
+ case TRTYPE_MON_ITEM:
+ {
+ monSpeciesItem = &data->species_item;
+ for (i = 0; i < enemies->datas[party_id].data.npoke; i++)
+ {
+ seed = monSpeciesItem[i].difficulty + monSpeciesItem[i].level + monSpeciesItem[i].species + enemies->trainer_idxs[party_id];
+ SetLCRNGSeed(seed);
+ for (j = 0; j < enemies->datas[party_id].data.trainerClass; j++)
+ {
+ seed = LCRandom();
+ }
+ personality = (seed << 8);
+ personality += pid_gender;
+ iv = (u8)((monSpeciesItem[i].difficulty * 31) / 255);
+ CreateMon(pokemon, monSpeciesItem[i].species, monSpeciesItem[i].level, iv, 1, (s32)personality, 2, 0);
+ SetMonData(pokemon, MON_DATA_HELD_ITEM, &monSpeciesItem[i].item);
+ AddMonToParty(enemies->parties[party_id], pokemon);
+ }
+ break;
+ }
+ case TRTYPE_MON_ITEM_MOVES:
+ {
+ monSpeciesItemMoves = &data->species_item_moves;
+ for (i = 0; i < enemies->datas[party_id].data.npoke; i++)
+ {
+ seed = monSpeciesItemMoves[i].difficulty + monSpeciesItemMoves[i].level + monSpeciesItemMoves[i].species + enemies->trainer_idxs[party_id];
+ SetLCRNGSeed(seed);
+ for (j = 0; j < enemies->datas[party_id].data.trainerClass; j++)
+ {
+ seed = LCRandom();
+ }
+ personality = (seed << 8);
+ personality += pid_gender;
+ iv = (u8)((monSpeciesItemMoves[i].difficulty * 31) / 255);
+ CreateMon(pokemon, monSpeciesItemMoves[i].species, monSpeciesItemMoves[i].level, iv, 1, (s32)personality, 2, 0);
+ SetMonData(pokemon, MON_DATA_HELD_ITEM, &monSpeciesItemMoves[i].item);
+ for (j = 0; j < 4; j++)
+ {
+ MonSetMoveInSlot(pokemon, monSpeciesItemMoves[i].moves[j], (u8)j);
+ }
+ AddMonToParty(enemies->parties[party_id], pokemon);
+ }
+ break;
+ }
+ }
+ FreeToHeap(data);
+ FreeToHeap(pokemon);
+ SetLCRNGSeed(seed_bak);
+}
diff --git a/arm9/src/unk_020139D8.c b/arm9/src/unk_020139D8.c
index 82c96ea9..796190b2 100644
--- a/arm9/src/unk_020139D8.c
+++ b/arm9/src/unk_020139D8.c
@@ -7,7 +7,7 @@
#pragma thumb on
-const u8 UNK_020ED5B4[][2] = {
+const u8 sNarcLanguages[][2] = {
{ LANGUAGE_JAPANESE, 0 },
{ LANGUAGE_ENGLISH, 1 },
{ LANGUAGE_FRENCH, 2 },
@@ -16,32 +16,32 @@ const u8 UNK_020ED5B4[][2] = {
{ LANGUAGE_SPANISH, 5 },
};
-const u16 UNK_020ED5C0[] = {
- 362,
- 589,
- 565,
- 553,
- 388,
- 389,
- 390,
- 391,
- 392,
- 393,
- 394
+const u16 sNarcMsgBanks[] = {
+ 362, // Species names
+ 589, // Move names
+ 565, // Type names
+ 553, // Ability names
+ 388, // Trainer
+ 389, // People
+ 390, // Greetings
+ 391, // Lifestyle
+ 392, // Feelings
+ 393, // Tough words
+ 394 // Union
};
-const u16 UNK_020ED5D6[] = {
- 496,
- 468,
- 18,
- 124,
- 38,
- 38,
- 107,
- 104,
- 47,
- 32,
- 23
+const u16 sNarcMsgCounts[] = {
+ 496, // Species names
+ 468, // Move names
+ 18, // Type names
+ 124, // Ability names
+ 38, // Trainer
+ 38, // People
+ 107, // Greetings
+ 104, // Lifestyle
+ 47, // Feelings
+ 32, // Tough words
+ 23 // Union
};
const u16 UNK_020ED580[] = { 0x04C0, 0x04F0 };
@@ -76,19 +76,19 @@ const struct UnkStruct_020ED5EC
{ UNK_020ED594, NELEMS(UNK_020ED594) },
};
-struct UnkStruct_020139D8 * FUN_020139D8(u32 heap_id)
+struct UnkStruct_020139D8 * EasyChatManager_new(u32 heap_id)
{
struct UnkStruct_020139D8 * ret = (struct UnkStruct_020139D8 *)AllocFromHeap(heap_id, sizeof(struct UnkStruct_020139D8));
s32 i;
for (i = 0; i < 11; i++)
{
ret->heap_id = heap_id; // inadvertently inside the loop
- ret->msgDatas[i] = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, UNK_020ED5C0[i], heap_id);
+ ret->msgDatas[i] = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, sNarcMsgBanks[i], heap_id);
}
return ret;
}
-void FUN_02013A10(struct UnkStruct_020139D8 * unk)
+void EasyChatManager_delete(struct UnkStruct_020139D8 * unk)
{
s32 i;
for (i = 0; i < 11; i++)
@@ -98,61 +98,61 @@ void FUN_02013A10(struct UnkStruct_020139D8 * unk)
FreeToHeap(unk);
}
-void FUN_02013A30(struct UnkStruct_020139D8 * unk, u16 a1, struct String * str)
+void EasyChatManager_ReadWordIntoString(struct UnkStruct_020139D8 * unk, u16 wordIdx, struct String * str)
{
- s32 sp4;
- s32 sp0;
- FUN_02013AEC(a1, &sp4, &sp0);
- ReadMsgDataIntoString(unk->msgDatas[sp4], (u32)sp0, str);
+ s32 msgBank;
+ s32 msgNo;
+ GetCategoryAndMsgNoByECWordIdx(wordIdx, &msgBank, &msgNo);
+ ReadMsgDataIntoString(unk->msgDatas[msgBank], (u32)msgNo, str);
}
-void FUN_02013A58(u16 a0, struct String * a1)
+void GetECWordIntoStringByIndex(u16 wordIdx, struct String * a1)
{
- s32 sp8;
- s32 sp4;
- if (a0 != 0xFFFF)
+ s32 msgBank;
+ s32 msgNo;
+ if (wordIdx != 0xFFFF)
{
- FUN_02013AEC(a0, &sp8, &sp4);
- sp8 = UNK_020ED5C0[sp8];
- ReadMsgData_NewNarc_ExistingString(NARC_MSGDATA_MSG, (u32)sp8, (u32)sp4, 0, a1);
+ GetCategoryAndMsgNoByECWordIdx(wordIdx, &msgBank, &msgNo);
+ msgBank = sNarcMsgBanks[msgBank];
+ ReadMsgData_NewNarc_ExistingString(NARC_MSGDATA_MSG, (u32)msgBank, (u32)msgNo, 0, a1);
}
else
StringSetEmpty(a1);
}
-u16 FUN_02013A9C(u16 a0, u16 a1)
+u16 GetECWordIndexByPair(u16 msgBank, u16 msgNo)
{
u32 i;
u16 k;
u16 j;
for (i = 0; i < 11; i++)
{
- if (a0 == UNK_020ED5C0[i])
+ if (msgBank == sNarcMsgBanks[i])
{
for (j = 0, k = 0; j < i; j++)
- k += UNK_020ED5D6[j];
- return (u16)(k + a1);
+ k += sNarcMsgCounts[j];
+ return (u16)(k + msgNo);
}
}
return 0xFFFF;
}
-void FUN_02013AEC(u32 a0, s32 * a1, s32 * a2)
+void GetCategoryAndMsgNoByECWordIdx(u32 wordIdx, s32 * msgBank_p, s32 * msgNo_p)
{
s32 i;
s32 j;
u32 r3;
- r3 = a0 & 0xFFF;
+ r3 = wordIdx & 0xFFF;
j = 0;
- for (i = 0; i < NELEMS(UNK_020ED5D6); i++)
+ for (i = 0; i < NELEMS(sNarcMsgCounts); i++)
{
- j += UNK_020ED5D6[i];
+ j += sNarcMsgCounts[i];
if (r3 < j)
{
- *a1 = i;
- *a2 = (s32)(r3 - (j - UNK_020ED5D6[i]));
+ *msgBank_p = i;
+ *msgNo_p = (s32)(r3 - (j - sNarcMsgCounts[i]));
return;
}
}
@@ -170,9 +170,9 @@ void FUN_02013B2C(struct UnkStruct_02013B28 * unk)
unk->unk_4 = 0;
for (i = 0; i < 6; i++)
{
- if (UNK_020ED5B4[i][0] == GAME_LANGUAGE)
+ if (sNarcLanguages[i][0] == GAME_LANGUAGE)
{
- FUN_02013C18(unk, UNK_020ED5B4[i][1]);
+ FUN_02013C18(unk, sNarcLanguages[i][1]);
break;
}
}
@@ -233,7 +233,7 @@ u16 FUN_02013BE4(u16 a0)
s32 i;
u16 skip = 0;
for (i = 0; i < 9; i++)
- skip += UNK_020ED5D6[i];
+ skip += sNarcMsgCounts[i];
return (u16)(skip + a0);
}
diff --git a/arm9/src/unk_02021FF8.c b/arm9/src/unk_02021FF8.c
new file mode 100644
index 00000000..2fe37556
--- /dev/null
+++ b/arm9/src/unk_02021FF8.c
@@ -0,0 +1,176 @@
+#include "global.h"
+#include "string16.h"
+#include "heap.h"
+#include "unk_02021FF8.h"
+
+#pragma thumb on
+
+BOOL String_IsTrainerName(struct String * string)
+{
+ return string->size != 0 && string->data[0] == 0xF100;
+}
+
+void StringCat_HandleTrainerName(struct String * dest, struct String * src)
+{
+ if (String_IsTrainerName(src))
+ {
+ u16 * dest_p = &dest->data[dest->size];
+ u16 * src_p = &src->data[1];
+ s32 bit = 0;
+ u32 outsize = 0;
+ u16 cur_char = 0;
+
+ while (1)
+ {
+ cur_char = (u16)((*src_p >> bit) & 0x1FF);
+ bit += 9;
+ if (bit >= 15)
+ {
+ src_p++;
+ bit -= 15;
+ if (bit != 0)
+ {
+ cur_char |= (*src_p << (9 - bit)) & 0x1FF;
+ }
+ }
+ if (cur_char == 0x1FF)
+ break;
+ *dest_p++ = cur_char;
+ outsize++;
+ }
+ *dest_p = EOS;
+ dest->size += outsize;
+ }
+ else
+ StringCat(dest, src);
+}
+
+struct UnkStruct_020220C4 * FUN_020220C4(u8 * a0, u32 a1, void (*a2)(s32, s32, u32), u32 a3, u32 a4)
+{
+ struct UnkStruct_020220C4 * ret;
+ s32 i;
+ GF_ASSERT(a1 != 0);
+ ret = AllocFromHeap(a4, sizeof(struct UnkStruct_020220C4));
+ if (ret != NULL)
+ {
+ ret->field_0 = a0;
+ ret->field_4 = a1;
+ ret->field_8 = a2;
+ ret->field_C = a3;
+ ret->field_10 = AllocFromHeap(a4, a1 * sizeof(struct UnkStruct_020220C4_sub));
+ if (ret->field_10 != NULL)
+ {
+ for (i = 0; i < a1; i++)
+ {
+ FUN_02022120(&ret->field_10[i]);
+ }
+ }
+ else
+ {
+ FreeToHeap(ret);
+ ret = NULL;
+ }
+ }
+ return ret;
+}
+
+void FUN_02022120(struct UnkStruct_020220C4_sub * sub)
+{
+ sub->field_0 = 0;
+ sub->field_1 = 0;
+ sub->field_2 = 0;
+}
+
+void FUN_0202212C(struct UnkStruct_020220C4 * unk)
+{
+ GF_ASSERT(unk != NULL);
+ FreeToHeap(unk->field_10);
+ FreeToHeap(unk);
+}
+
+extern u16 FUN_02020A98(void);
+extern u16 FUN_02020AA4(void);
+extern u8 FUN_02020A40(u8 * a0);
+extern u8 FUN_02020A6C(u8 * a0);
+
+s32 (*const UNK_020EE6CC[])(struct UnkStruct_020220C4_sub * a0, u32 a1, u32 a2) = {
+ FUN_020221EC,
+ FUN_02022208
+};
+
+void FUN_02022144(struct UnkStruct_020220C4 * unk)
+{
+ u32 sp4;
+ u32 sp0 = FUN_02020A98();
+ s32 i;
+ s32 r1;
+ if (sp0 != 0)
+ {
+ sp4 = FUN_02020AA4();
+ for (i = 0; i < unk->field_4; i++)
+ {
+ u8 res;
+ if (unk->field_10[i].field_1 != 0)
+ {
+ res = FUN_02020A40(&unk->field_0[4 * i]);
+ }
+ else
+ {
+ res = FUN_02020A6C(&unk->field_0[4 * i]);
+ }
+ unk->field_10[i].field_1 = res;
+ }
+ }
+ else
+ {
+ sp4 = 0;
+ for (i = 0; i < unk->field_4; i++)
+ {
+ unk->field_10[i].field_1 = 0;
+ }
+ }
+ for (i = 0; i < unk->field_4; i++)
+ {
+ r1 = UNK_020EE6CC[unk->field_10[i].field_0](&unk->field_10[i], sp0, sp4);
+ if (r1 != -1)
+ {
+ unk->field_8(i, r1, unk->field_C);
+ }
+ }
+}
+
+s32 FUN_020221EC(struct UnkStruct_020220C4_sub * a0, u32 a1, u32 a2)
+{
+#pragma unused(a1)
+ if (a0->field_1 && a2)
+ {
+ FUN_0202223C(a0, 1);
+ return 0;
+ }
+ return -1;
+}
+
+s32 FUN_02022208(struct UnkStruct_020220C4_sub * a0, u32 a1, u32 a2)
+{
+#pragma unused(a2)
+ if (a0->field_1)
+ {
+ if (a0->field_2 < 0xFFFF)
+ a0->field_2++;
+ return 2;
+ }
+ else if (a1)
+ {
+ FUN_0202223C(a0, 0);
+ return 3;
+ }
+ FUN_0202223C(a0, 0);
+ return 1;
+}
+
+void FUN_0202223C(struct UnkStruct_020220C4_sub * a0, u8 a1)
+{
+ a0->field_0 = a1;
+ a0->field_2 = 0;
+}
+
diff --git a/arm9/src/unk_0206B688.c b/arm9/src/unk_0206B688.c
new file mode 100644
index 00000000..465fa842
--- /dev/null
+++ b/arm9/src/unk_0206B688.c
@@ -0,0 +1,185 @@
+#include "global.h"
+#include "pokemon.h"
+#include "unk_0206B688.h"
+
+#pragma thumb on
+
+u16 BoxMon_GetAlternateForme(struct BoxPokemon * boxmon);
+u32 FUN_0206B6D4(u32 species, u32 is_egg, u32 forme);
+
+u32 FUN_0206B688(struct BoxPokemon * boxmon)
+{
+ BOOL decry = AcquireBoxMonLock(boxmon);
+ u32 species = GetBoxMonData(boxmon, MON_DATA_SPECIES, NULL);
+ u32 is_egg = GetBoxMonData(boxmon, MON_DATA_IS_EGG, NULL);
+ u32 forme = BoxMon_GetAlternateForme(boxmon);
+ u32 ret = FUN_0206B6D4(species, is_egg, forme);
+ ReleaseBoxMonLock(boxmon, decry);
+ return ret;
+}
+
+u32 FUN_0206B6C8(struct Pokemon * pokemon)
+{
+ return FUN_0206B688(FUN_020690E4(pokemon));
+}
+
+u32 FUN_0206B6D4(u32 species, u32 is_egg, u32 forme)
+{
+ if (is_egg == TRUE)
+ {
+ if (species == SPECIES_MANAPHY)
+ return 502;
+ else
+ return 501;
+ }
+ if (forme != 0)
+ {
+ if (species == SPECIES_DEOXYS)
+ return 502 + forme;
+ if (species == SPECIES_UNOWN)
+ return 506 + forme;
+ if (species == SPECIES_BURMY)
+ return 533 + forme;
+ if (species == SPECIES_WORMADAM)
+ return 535 + forme;
+ if (species == SPECIES_SHELLOS)
+ return 537 + forme;
+ if (species == SPECIES_GASTRODON)
+ return 538 + forme;
+ }
+ return (species <= SPECIES_ARCEUS ? species : 0) + 7;
+}
+
+u16 BoxMon_GetAlternateForme(struct BoxPokemon * boxmon)
+{
+ u32 species = GetBoxMonData(boxmon, MON_DATA_SPECIES2, NULL);
+ switch (species)
+ {
+ case SPECIES_UNOWN:
+ return GetBoxMonUnownLetter(boxmon);
+ case SPECIES_DEOXYS:
+ case SPECIES_BURMY:
+ case SPECIES_WORMADAM:
+ case SPECIES_SHELLOS:
+ case SPECIES_GASTRODON:
+ return (u16) GetBoxMonData(boxmon, MON_DATA_FORME, NULL);
+ default:
+ return 0;
+ }
+}
+
+const u8 UNK_020F8074[] = {
+ 0, 1, 1, 1, 0, 0, 0, 0, 2, 2, 1, 1, 0, 1, 2, 2,
+ 0, 0, 0, 2, 1, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 2, 1, 0, 0, 2, 2, 1, 0, 0, 0, 0,
+ 0, 2, 2, 2, 1, 1, 1, 2, 1, 2, 0, 0, 0, 0, 0, 2,
+ 2, 2, 0, 2, 0, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 2, 2, 0, 0, 0, 1, 1, 1, 2, 2, 1, 2, 2, 1,
+ 1, 0, 0, 1, 0, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 2,
+ 2, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1,
+ 0, 0, 0, 0, 0, 2, 2, 0, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 1, 0, 2, 2, 0, 0, 0, 1, 2,
+ 2, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1,
+ 1, 1, 0, 0, 2, 2, 2, 0, 0, 0, 0, 1, 0, 2, 2, 2,
+ 0, 0, 2, 0, 0, 1, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 1,
+ 1, 1, 1, 0, 2, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 1, 1, 1,
+ 1, 1, 1, 0, 2, 2, 0, 0, 1, 1, 1, 2, 0, 1, 1, 2,
+ 2, 1, 1, 1, 1, 0, 2, 2, 2, 1, 2, 0, 0, 2, 2, 2,
+ 2, 2, 2, 0, 0, 1, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0,
+ 2, 0, 1, 0, 1, 0, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 2, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 2, 2, 0, 0, 0,
+ 0, 1, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0,
+ 1, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 2, 2, 2, 2, 2, 0, 1, 0,
+ 2, 0, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 1, 1, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1,
+ 0, 2, 1, 0, 2, 1, 1, 0, 2, 2, 0, 1, 0, 2, 2, 0,
+ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 1, 0, 0, 0, 0, 0, 0
+};
+
+u32 FUN_0206B7BC(u32 species, u32 forme, u32 is_egg)
+{
+ if (is_egg == TRUE)
+ {
+ if (species == SPECIES_MANAPHY)
+ species = 495;
+ else
+ species = 494;
+ }
+ else if (species > SPECIES_ARCEUS)
+ species = 0;
+ else if (forme != 0)
+ {
+ if (species == SPECIES_DEOXYS)
+ species = 495 + forme;
+ else if (species == SPECIES_UNOWN)
+ species = 498 + forme;
+ else if (species == SPECIES_BURMY)
+ species = 526 + forme;
+ else if (species == SPECIES_WORMADAM)
+ species = 528 + forme;
+ else if (species == SPECIES_SHELLOS)
+ species = 530 + forme;
+ else if (species == SPECIES_GASTRODON)
+ species = 531 + forme;
+ }
+ return UNK_020F8074[species];
+}
+
+u32 FUN_0206B83C(struct BoxPokemon * boxmon)
+{
+ BOOL decry = AcquireBoxMonLock(boxmon);
+ u32 forme = BoxMon_GetAlternateForme(boxmon);
+ u32 species = GetBoxMonData(boxmon, MON_DATA_SPECIES, NULL);
+ u32 is_egg = GetBoxMonData(boxmon, MON_DATA_IS_EGG, NULL);
+ ReleaseBoxMonLock(boxmon, decry);
+ return FUN_0206B7BC(species, forme, is_egg);
+}
+
+u32 FUN_0206B87C(struct Pokemon * pokemon)
+{
+ return FUN_0206B83C(FUN_020690E4(pokemon));
+}
+
+u32 FUN_0206B888(void)
+{
+ return 0;
+}
+
+u32 FUN_0206B88C(void)
+{
+ return 2;
+}
+
+u32 FUN_0206B890(void)
+{
+ return 4;
+}
+
+u32 FUN_0206B894(void)
+{
+ return 6;
+}
+
+u32 FUN_0206B898(void)
+{
+ return 1;
+}
+
+u32 FUN_0206B89C(void)
+{
+ return 3;
+}
+
+u32 FUN_0206B8A0(void)
+{
+ return 5;
+}
diff --git a/arm9/src/unk_0206BB28.c b/arm9/src/unk_0206BB28.c
new file mode 100644
index 00000000..baaecc6a
--- /dev/null
+++ b/arm9/src/unk_0206BB28.c
@@ -0,0 +1,25 @@
+#include "global.h"
+#include "save_block_2.h"
+#include "pokedex.h"
+#include "pokemon.h"
+#include "unk_0206BB28.h"
+
+#pragma thumb on
+
+BOOL FUN_0206BB28(struct SaveBlock2 * sav2)
+{
+ return FUN_0206BB34(Sav2_Pokedex_get(sav2));
+}
+
+BOOL FUN_0206BB34(struct Pokedex * pokedex)
+{
+ return Pokedex_GetNatDexFlag(pokedex) == TRUE;
+}
+
+u32 FUN_0206BB48(BOOL isNationalDex, u32 species)
+{
+ if (!isNationalDex)
+ species = SpeciesToSinnohDexNo((u16)species);
+ return species;
+}
+