diff --git a/include/global.h b/include/global.h index 0ca226c03..00b08f48f 100644 --- a/include/global.h +++ b/include/global.h @@ -134,6 +134,13 @@ #define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT) #define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS) +// This returns the number of arguments passed to it (up to 8). +#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N + +#define CAT(a, b) CAT_(a, b) +#define CAT_(a, b) a ## b + // This produces an error at compile-time if expr is zero. // It looks like file.c:line: size of array `id' is negative #define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1]; diff --git a/include/pokemon.h b/include/pokemon.h index 54b4841f7..f4f6d6989 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -436,12 +436,17 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition); -// These are full type signatures for GetMonData() and GetBoxMonData(), -// but they are not used since some code erroneously omits the third arg. -// u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data); -// u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data); -u32 GetMonData(); -u32 GetBoxMonData(); +/* GameFreak called Get(Box)MonData with either 2 or 3 arguments, for + * type safety we have a Get(Box)MonData macro which dispatches to + * either Get(Box)MonData2 or Get(Box)MonData3 based on the number of + * arguments. The two functions are aliases of each other, but they + * differ for matching purposes in the caller's codegen. */ +#define GetMonData(...) CAT(GetMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__) +#define GetBoxMonData(...) CAT(GetBoxMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__) +u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data); +u32 GetMonData2(struct Pokemon *mon, s32 field); +u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data); +u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field); void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg); void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg); diff --git a/src/daycare.c b/src/daycare.c index c3f4dd990..9d199f0f3 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -341,7 +341,7 @@ static void Debug_AddDaycareSteps(u16 numSteps) u8 GetNumLevelsGainedFromDaycare(void) { - if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0) + if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004].mon, MON_DATA_SPECIES) != 0) return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]); return 0; diff --git a/src/pokemon.c b/src/pokemon.c index fa2eee42c..b8f7ae48b 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3622,7 +3622,11 @@ static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 perso return substruct; } -u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) +/* GameFreak called GetMonData with either 2 or 3 arguments, for type + * safety we have a GetMonData macro (in include/pokemon.h) which + * dispatches to either GetMonData2 or GetMonData3 based on the number + * of arguments. */ +u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data) { u32 ret; @@ -3690,7 +3694,13 @@ u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) return ret; } -u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) +u32 GetMonData2(struct Pokemon *mon, s32 field) __attribute__((alias("GetMonData3"))); + +/* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type + * safety we have a GetBoxMonData macro (in include/pokemon.h) which + * dispatches to either GetBoxMonData2 or GetBoxMonData3 based on the + * number of arguments. */ +u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) { s32 i; u32 retVal = 0; @@ -4046,6 +4056,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) return retVal; } +u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) __attribute__((alias("GetBoxMonData3"))); + #define SET8(lhs) (lhs) = *data #define SET16(lhs) (lhs) = data[0] + (data[1] << 8) #define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)