Skip to content

Commit

Permalink
Declarations for 2- and 3-argument GetMonData (#1756)
Browse files Browse the repository at this point in the history
* Type-safe GetMonData/GetBoxMonData

* Comments
  • Loading branch information
mrgriffin authored Jul 24, 2023
1 parent 56ec3b6 commit b53cca1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
7 changes: 7 additions & 0 deletions include/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
17 changes: 11 additions & 6 deletions include/pokemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/daycare.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 14 additions & 2 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit b53cca1

Please sign in to comment.