From 93af96c10cd38bfde6fd7b2cd53f969bbe28095d Mon Sep 17 00:00:00 2001 From: Nephrite Date: Sat, 6 Apr 2024 02:42:11 +0900 Subject: [PATCH] Replaces VARARG_8 uses with recursive macros (#4232) --- include/battle.h | 20 ++++++++++++++ include/metaprogram.h | 3 ++ include/test/battle.h | 53 ++++++++++++------------------------ src/battle_dynamax.c | 15 ---------- src/battle_script_commands.c | 31 --------------------- 5 files changed, 40 insertions(+), 82 deletions(-) diff --git a/include/battle.h b/include/battle.h index fbe3f8b48b..58e8d71774 100644 --- a/include/battle.h +++ b/include/battle.h @@ -17,6 +17,26 @@ #include "battle_dynamax.h" #include "random.h" // for rng_value_t +// Helper for accessing command arguments and advancing gBattlescriptCurrInstr. +// +// For example accuracycheck is defined as: +// +// .macro accuracycheck failInstr:req, move:req +// .byte 0x1 +// .4byte \failInstr +// .2byte \move +// .endm +// +// Which corresponds to: +// +// CMD_ARGS(const u8 *failInstr, u16 move); +// +// The arguments can be accessed as cmd->failInstr and cmd->move. +// gBattlescriptCurrInstr = cmd->nextInstr; advances to the next instruction. +#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) const u8 nextInstr[0]; } *const cmd UNUSED = (const void *)gBattlescriptCurrInstr +#define VARIOUS_ARGS(...) CMD_ARGS(u8 battler, u8 id, ##__VA_ARGS__) +#define NATIVE_ARGS(...) CMD_ARGS(void (*func)(void), ##__VA_ARGS__) + // Used to exclude moves learned temporarily by Transform or Mimic #define MOVE_IS_PERMANENT(battler, moveSlot) \ (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) \ diff --git a/include/metaprogram.h b/include/metaprogram.h index 4bcc306b6f..67736cfbc0 100644 --- a/include/metaprogram.h +++ b/include/metaprogram.h @@ -26,6 +26,9 @@ #define STR(...) STR_(__VA_ARGS__) #define STR_(...) #__VA_ARGS__ +/* You'll never guess what this one does */ +#define APPEND_SEMICOLON(a) a; + /* Converts a string to a compound literal, essentially making it a pointer to const u8 */ #define COMPOUND_STRING(str) (const u8[]) _(str) diff --git a/include/test/battle.h b/include/test/battle.h index b44186ed3d..62b0680486 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -723,27 +723,8 @@ struct BattleTestRunnerState extern const struct TestRunner gBattleTestRunner; extern struct BattleTestRunnerState *const gBattleTestRunnerState; -#define MEMBERS(...) VARARG_8(MEMBERS_, __VA_ARGS__) -#define MEMBERS_0() -#define MEMBERS_1(a) a; -#define MEMBERS_2(a, b) a; b; -#define MEMBERS_3(a, b, c) a; b; c; -#define MEMBERS_4(a, b, c, d) a; b; c; d; -#define MEMBERS_5(a, b, c, d, e) a; b; c; d; e; -#define MEMBERS_6(a, b, c, d, e, f) a; b; c; d; e; f; -#define MEMBERS_7(a, b, c, d, e, f, g) a; b; c; d; e; f; g; -#define MEMBERS_8(a, b, c, d, e, f, g, h) a; b; c; d; e; f; g; h; - -#define APPEND_TRUE(...) VARARG_8(APPEND_TRUE_, __VA_ARGS__) -#define APPEND_TRUE_0() -#define APPEND_TRUE_1(a) a, TRUE -#define APPEND_TRUE_2(a, b) a, TRUE, b, TRUE -#define APPEND_TRUE_3(a, b, c) a, TRUE, b, TRUE, c, TRUE -#define APPEND_TRUE_4(a, b, c, d) a, TRUE, b, TRUE, c, TRUE, d, TRUE -#define APPEND_TRUE_5(a, b, c, d, e) a, TRUE, b, TRUE, c, TRUE, d, TRUE, e, TRUE -#define APPEND_TRUE_6(a, b, c, d, e, f) a, TRUE, b, TRUE, c, TRUE, d, TRUE, e, TRUE, f, TRUE -#define APPEND_TRUE_7(a, b, c, d, e, f, g) a, TRUE, b, TRUE, c, TRUE, d, TRUE, e, TRUE, f, TRUE, g, TRUE -#define APPEND_TRUE_8(a, b, c, d, e, f, g, h) a, TRUE, b, TRUE, c, TRUE, d, TRUE, e, TRUE, f, TRUE, g, TRUE, h, TRUE +#define APPEND_COMMA_TRUE(a) , a, TRUE +#define R_APPEND_TRUE(...) __VA_OPT__(FIRST(__VA_ARGS__), TRUE RECURSIVELY(R_FOR_EACH(APPEND_COMMA_TRUE, EXCEPT_1(__VA_ARGS__)))) /* Test */ @@ -754,7 +735,7 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; } #define BATTLE_TEST_ARGS_SINGLE(_name, _type, ...) \ - struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \ + struct CAT(Result, __LINE__) { RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) }; \ static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *); \ __attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \ { \ @@ -772,7 +753,7 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *player, struct BattlePokemon *opponent) #define BATTLE_TEST_ARGS_DOUBLE(_name, _type, ...) \ - struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \ + struct CAT(Result, __LINE__) { RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) }; \ static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ __attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \ { \ @@ -911,28 +892,28 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define TURN for (OpenTurn(__LINE__); gBattleTestRunnerState->data.turnState == TURN_OPEN; CloseTurn(__LINE__)) -#define MOVE(battler, ...) Move(__LINE__, battler, (struct MoveContext) { APPEND_TRUE(__VA_ARGS__) }) +#define MOVE(battler, ...) Move(__LINE__, battler, (struct MoveContext) { R_APPEND_TRUE(__VA_ARGS__) }) -#define EXPECT_MOVE(battler, ...) ExpectMove(__LINE__, battler, (struct MoveContext) { APPEND_TRUE(__VA_ARGS__) }) +#define EXPECT_MOVE(battler, ...) ExpectMove(__LINE__, battler, (struct MoveContext) { R_APPEND_TRUE(__VA_ARGS__) }) #define NOT_EXPECT_MOVE(battler, _move) ExpectMove(__LINE__, battler, (struct MoveContext) { .move = _move, .explicitMove = TRUE, .notExpected = TRUE, .explicitNotExpected = TRUE, }) #define EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, FALSE, (struct FourMoves) {{ __VA_ARGS__ }}) #define NOT_EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, TRUE, (struct FourMoves) {{ __VA_ARGS__ }}) #define EXPECT_SEND_OUT(battler, partyIndex) ExpectSendOut(__LINE__, battler, partyIndex) #define EXPECT_SWITCH(battler, partyIndex) ExpectSwitch(__LINE__, battler, partyIndex) -#define SCORE_EQ(battler, ...) Score(__LINE__, battler, CMP_EQUAL, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_NE(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_GT(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_LT(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_EQ_VAL(battler, ...) Score(__LINE__, battler, CMP_EQUAL, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_NE_VAL(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_GT_VAL(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) -#define SCORE_LT_VAL(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_EQ(battler, ...) Score(__LINE__, battler, CMP_EQUAL, FALSE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_NE(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, FALSE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_GT(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, FALSE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_LT(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, FALSE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_EQ_VAL(battler, ...) Score(__LINE__, battler, CMP_EQUAL, TRUE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_NE_VAL(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, TRUE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_GT_VAL(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, TRUE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) +#define SCORE_LT_VAL(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, TRUE, (struct TestAIScoreStruct) { R_APPEND_TRUE(__VA_ARGS__) } ) #define FORCED_MOVE(battler) ForcedMove(__LINE__, battler) #define SWITCH(battler, partyIndex) Switch(__LINE__, battler, partyIndex) #define SKIP_TURN(battler) SkipTurn(__LINE__, battler) #define SEND_OUT(battler, partyIndex) SendOut(__LINE__, battler, partyIndex) -#define USE_ITEM(battler, ...) UseItem(__LINE__, battler, (struct ItemContext) { APPEND_TRUE(__VA_ARGS__) }) +#define USE_ITEM(battler, ...) UseItem(__LINE__, battler, (struct ItemContext) { R_APPEND_TRUE(__VA_ARGS__) }) #define WITH_RNG(tag, value) rng: ((struct TurnRNG) { tag, value }) struct MoveContext @@ -998,8 +979,8 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); #define ABILITY_POPUP(battler, ...) QueueAbility(__LINE__, battler, (struct AbilityEventContext) { __VA_ARGS__ }) #define ANIMATION(type, id, ...) QueueAnimation(__LINE__, type, id, (struct AnimationEventContext) { __VA_ARGS__ }) -#define HP_BAR(battler, ...) QueueHP(__LINE__, battler, (struct HPEventContext) { APPEND_TRUE(__VA_ARGS__) }) -#define EXPERIENCE_BAR(battler, ...) QueueExp(__LINE__, battler, (struct ExpEventContext) { APPEND_TRUE(__VA_ARGS__) }) +#define HP_BAR(battler, ...) QueueHP(__LINE__, battler, (struct HPEventContext) { R_APPEND_TRUE(__VA_ARGS__) }) +#define EXPERIENCE_BAR(battler, ...) QueueExp(__LINE__, battler, (struct ExpEventContext) { R_APPEND_TRUE(__VA_ARGS__) }) // Static const is needed to make the modern compiler put the pattern variable in the .rodata section, instead of putting it on stack(which can break the game). #define MESSAGE(pattern) do {static const u8 msg[] = _(pattern); QueueMessage(__LINE__, msg);} while (0) #define STATUS_ICON(battler, status) QueueStatus(__LINE__, battler, (struct StatusEventContext) { status }) diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 7286045684..5075e18ea6 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -519,21 +519,6 @@ static u32 GetMaxMoveStatusEffect(u16 move) } } -// CALLNATIVE FUNCTIONS -#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; MEMBERS(__VA_ARGS__) const u8 nextInstr[0]; } *const cmd = (const void *)gBattlescriptCurrInstr -#define NATIVE_ARGS(...) CMD_ARGS(void (*func)(void), ##__VA_ARGS__) - -#define MEMBERS(...) VARARG_8(MEMBERS_, __VA_ARGS__) -#define MEMBERS_0() -#define MEMBERS_1(a) a; -#define MEMBERS_2(a, b) a; b; -#define MEMBERS_3(a, b, c) a; b; c; -#define MEMBERS_4(a, b, c, d) a; b; c; d; -#define MEMBERS_5(a, b, c, d, e) a; b; c; d; e; -#define MEMBERS_6(a, b, c, d, e, f) a; b; c; d; e; f; -#define MEMBERS_7(a, b, c, d, e, f, g) a; b; c; d; e; f; g; -#define MEMBERS_8(a, b, c, d, e, f, g, h) a; b; c; d; e; f; g; h; - // Updates Dynamax HP multipliers and healthboxes. void BS_UpdateDynamax(void) { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7ff8a9e772..8f870f946b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -66,37 +66,6 @@ #include "config/battle.h" #include "data/battle_move_effects.h" -// Helper for accessing command arguments and advancing gBattlescriptCurrInstr. -// -// For example accuracycheck is defined as: -// -// .macro accuracycheck failInstr:req, move:req -// .byte 0x1 -// .4byte \failInstr -// .2byte \move -// .endm -// -// Which corresponds to: -// -// CMD_ARGS(const u8 *failInstr, u16 move); -// -// The arguments can be accessed as cmd->failInstr and cmd->move. -// gBattlescriptCurrInstr = cmd->nextInstr; advances to the next instruction. -#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; MEMBERS(__VA_ARGS__) const u8 nextInstr[0]; } *const cmd UNUSED = (const void *)gBattlescriptCurrInstr -#define VARIOUS_ARGS(...) CMD_ARGS(u8 battler, u8 id, ##__VA_ARGS__) -#define NATIVE_ARGS(...) CMD_ARGS(void (*func)(void), ##__VA_ARGS__) - -#define MEMBERS(...) VARARG_8(MEMBERS_, __VA_ARGS__) -#define MEMBERS_0() -#define MEMBERS_1(a) a; -#define MEMBERS_2(a, b) a; b; -#define MEMBERS_3(a, b, c) a; b; c; -#define MEMBERS_4(a, b, c, d) a; b; c; d; -#define MEMBERS_5(a, b, c, d, e) a; b; c; d; e; -#define MEMBERS_6(a, b, c, d, e, f) a; b; c; d; e; f; -#define MEMBERS_7(a, b, c, d, e, f, g) a; b; c; d; e; f; g; -#define MEMBERS_8(a, b, c, d, e, f, g, h) a; b; c; d; e; f; g; h; - // table to avoid ugly powing on gba (courtesy of doesnt) // this returns (i^2.5)/4 // the quarters cancel so no need to re-quadruple them in actual calculation