Merge branch 'upcoming' into ghoulsaveblock

This commit is contained in:
Bassoonian
2024-02-06 23:36:46 +01:00
committed by GitHub
94 changed files with 2216 additions and 1062 deletions

View File

@@ -54,7 +54,8 @@ struct __attribute__((packed, aligned(2))) BattleMoveEffect
const u8 *battleScript;
u16 battleTvScore:3;
u16 encourageEncore:1;
u16 flags:12; // coming soon...
u16 semiInvulnerableEffect:1;
u16 flags:11; // coming soon...
};
#define GET_MOVE_BATTLESCRIPT(move) gBattleMoveEffects[gMovesInfo[move].effect].battleScript
@@ -846,10 +847,10 @@ struct BattleScripting
s32 bideDmg;
u8 multihitString[6];
bool8 expOnCatch;
u8 twoTurnsMoveStringId;
u8 unused;
u8 animArg1;
u8 animArg2;
u16 tripleKickPower;
u16 savedStringId;
u8 moveendState;
u8 savedStatChanger; // For further use, if attempting to change stat two times(ex. Moody)
u8 shiftSwitched; // When the game tells you the next enemy's pokemon and you switch. Option for noobs but oh well.

View File

@@ -108,7 +108,7 @@ bool32 IsStatLoweringMoveEffect(u32 moveEffect);
bool32 IsMoveRedirectionPrevented(u32 move, u32 atkAbility);
bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 IsHazardMoveEffect(u32 moveEffect);
bool32 IsChargingMove(u32 battlerAtk, u32 effect);
bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move);
void ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove, s32 *score);
bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect);
bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect);

View File

@@ -417,6 +417,7 @@ extern const struct OamData gOamData_AffineDouble_ObjNormal_64x64;
extern const struct OamData gOamData_AffineDouble_ObjBlend_64x64;
extern const struct OamData gOamData_AffineDouble_ObjBlend_64x32;
extern const struct OamData gOamData_AffineDouble_ObjNormal_8x16;
extern const struct OamData gOamData_AffineDouble_ObjNormal_64x32;
extern const struct OamData gOamData_AffineOff_ObjBlend_16x16;
extern const struct OamData gOamData_AffineDouble_ObjBlend_16x16;
extern const struct OamData gOamData_AffineNormal_ObjNormal_8x8;

View File

@@ -611,7 +611,6 @@ extern const u8 BattleScript_EffectSleepTalk[];
extern const u8 BattleScript_EffectDestinyBond[];
extern const u8 BattleScript_EffectSpite[];
extern const u8 BattleScript_EffectHealBell[];
extern const u8 BattleScript_EffectTripleKick[];
extern const u8 BattleScript_EffectMeanLook[];
extern const u8 BattleScript_EffectNightmare[];
extern const u8 BattleScript_EffectMinimize[];

View File

@@ -225,6 +225,7 @@ bool32 MoveHasMoveEffect(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectWithChance(u32 move, u32 moveEffect, u32 chance);
bool32 MoveHasMoveEffectSelf(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
bool32 MoveHasChargeTurnMoveEffect(u32 move);
bool32 CanSleep(u32 battler);
bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget);

View File

@@ -179,15 +179,15 @@
// Var Settings
// To use the following features in scripting, replace the 0s with the var ID you're assigning it to.
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature.
#define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use B_VAR_TERRAIN for that feature.
#define B_VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active.
#define B_VAR_TERRAIN_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten.
#define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15)
// Sky Battles
#define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles.
#define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles.
#define B_SKY_BATTLE_STRICT_ELIGIBILITY FALSE //If TRUE, Sky Battles will use the eligibility from Pokémon XY. If FALSE, all Flying-types or Pokémon with Levitate are allowed.
#define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles.
#define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles.
#define B_SKY_BATTLE_STRICT_ELIGIBILITY FALSE // If TRUE, Sky Battles will use the eligibility from Pokémon XY. If FALSE, all Flying-types or Pokémon with Levitate are allowed.
// Flag and Var settings
#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out.

View File

@@ -129,7 +129,7 @@
#define STATUS2_FLINCHED (1 << 3)
#define STATUS2_UPROAR (1 << 4 | 1 << 5 | 1 << 6)
#define STATUS2_UPROAR_TURN(num) ((num) << 4)
#define STATUS2_UNUSED (1 << 7)
#define STATUS2_TORMENT (1 << 7)
#define STATUS2_BIDE (1 << 8 | 1 << 9)
#define STATUS2_BIDE_TURN(num) (((num) << 8) & STATUS2_BIDE)
#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash
@@ -139,7 +139,7 @@
#define STATUS2_POWDER (1 << 14)
#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler
#define STATUS2_INFATUATED_WITH(battler) (gBitTable[battler] << 16)
#define STATUS2_FOCUS_ENERGY (1 << 20)
#define STATUS2_DEFENSE_CURL (1 << 20)
#define STATUS2_TRANSFORMED (1 << 21)
#define STATUS2_RECHARGE (1 << 22)
#define STATUS2_RAGE (1 << 23)
@@ -149,8 +149,9 @@
#define STATUS2_NIGHTMARE (1 << 27)
#define STATUS2_CURSED (1 << 28)
#define STATUS2_FORESIGHT (1 << 29)
#define STATUS2_DEFENSE_CURL (1 << 30)
#define STATUS2_TORMENT (1 << 31)
#define STATUS2_DRAGON_CHEER (1 << 30)
#define STATUS2_FOCUS_ENERGY (1 << 31)
#define STATUS2_FOCUS_ENERGY_ANY (STATUS2_DRAGON_CHEER | STATUS2_FOCUS_ENERGY)
#define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed
#define STATUS3_LEECHSEED (1 << 2)

View File

@@ -414,8 +414,8 @@
// Below are used by AnimTask_ShakeMon2 and AnimTask_SetGrayscaleOrOriginalPal
#define ANIM_PLAYER_LEFT (MAX_BATTLERS_COUNT + 0)
#define ANIM_PLAYER_RIGHT (MAX_BATTLERS_COUNT + 1)
#define ANIM_OPPONENT_LEFT (MAX_BATTLERS_COUNT + 2)
#define ANIM_OPPONENT_LEFT (MAX_BATTLERS_COUNT + 1)
#define ANIM_PLAYER_RIGHT (MAX_BATTLERS_COUNT + 2)
#define ANIM_OPPONENT_RIGHT (MAX_BATTLERS_COUNT + 3)
#define ANIM_ATTACKER_FORCE (MAX_BATTLERS_COUNT + 4)

View File

@@ -117,10 +117,8 @@ enum {
EFFECT_BELLY_DRUM,
EFFECT_PSYCH_UP,
EFFECT_MIRROR_COAT,
EFFECT_SKULL_BASH,
EFFECT_EARTHQUAKE,
EFFECT_FUTURE_SIGHT,
EFFECT_GUST,
EFFECT_SOLAR_BEAM,
EFFECT_THUNDER,
EFFECT_TELEPORT,
@@ -172,7 +170,6 @@ enum {
EFFECT_WEATHER_BALL,
EFFECT_TICKLE,
EFFECT_COSMIC_POWER,
EFFECT_SKY_UPPERCUT,
EFFECT_BULK_UP,
EFFECT_WATER_SPORT,
EFFECT_CALM_MIND,
@@ -318,7 +315,6 @@ enum {
EFFECT_BOLT_BEAK,
EFFECT_SKY_DROP,
EFFECT_EXPANDING_FORCE,
EFFECT_METEOR_BEAM,
EFFECT_RISING_VOLTAGE,
EFFECT_BEAK_BLAST,
EFFECT_COURT_CHANGE,
@@ -352,6 +348,7 @@ enum {
EFFECT_RAIN_ALWAYS_HIT, // Unlike EFFECT_THUNDER, it doesn't get its accuracy reduced under sun.
EFFECT_SHED_TAIL,
EFFECT_UPPER_HAND,
EFFECT_DRAGON_CHEER,
NUM_BATTLE_MOVE_EFFECTS,
};

View File

@@ -6,10 +6,10 @@
#define sBIDE_DMG (gBattleScripting + 0x04) // bideDmg
#define sMULTIHIT_STRING (gBattleScripting + 0x08) // multihitString
#define sEXP_CATCH (gBattleScripting + 0x0E) // expOnCatch
#define sTWOTURN_STRINGID (gBattleScripting + 0x0F) // twoTurnsMoveStringId
#define sUNUSED (gBattleScripting + 0x0F) // unused
#define sB_ANIM_ARG1 (gBattleScripting + 0x10) // animArg1
#define sB_ANIM_ARG2 (gBattleScripting + 0x11) // animArg2
#define sTRIPLE_KICK_POWER (gBattleScripting + 0x12) // tripleKickPower
#define sSAVED_STRINID (gBattleScripting + 0x12) // savedStringId
#define sMOVEEND_STATE (gBattleScripting + 0x14) // moveendState
#define sSAVED_STAT_CHANGER (gBattleScripting + 0x15) // savedStatChanger
#define sSHIFT_SWITCHED (gBattleScripting + 0x16) // shiftSwitched
@@ -181,7 +181,7 @@
#define VARIOUS_TRY_FAIRY_LOCK 89
#define VARIOUS_JUMP_IF_NO_ALLY 90
#define VARIOUS_POISON_TYPE_IMMUNITY 91
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 92
#define VARIOUS_JUMP_IF_HOLD_EFFECT 92
#define VARIOUS_INFATUATE_WITH_BATTLER 93
#define VARIOUS_SET_LAST_USED_ITEM 94
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 95
@@ -220,25 +220,24 @@
#define VARIOUS_SET_SKY_DROP 128
#define VARIOUS_CLEAR_SKY_DROP 129
#define VARIOUS_SKY_DROP_YAWN 130
#define VARIOUS_JUMP_IF_HOLD_EFFECT 131
#define VARIOUS_CURE_CERTAIN_STATUSES 132
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 133
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 134
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 135
#define VARIOUS_SAVE_BATTLER_ITEM 136
#define VARIOUS_RESTORE_BATTLER_ITEM 137
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 138
#define VARIOUS_SET_BEAK_BLAST 139
#define VARIOUS_SWAP_SIDE_STATUSES 140
#define VARIOUS_SWAP_STATS 141
#define VARIOUS_TEATIME_INVUL 142
#define VARIOUS_TEATIME_TARGETS 143
#define VARIOUS_TRY_WIND_RIDER_POWER 144
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 145
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 146
#define VARIOUS_STORE_HEALING_WISH 147
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 148
#define VARIOUS_TRY_REVIVAL_BLESSING 149
#define VARIOUS_CURE_CERTAIN_STATUSES 131
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 132
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 133
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 134
#define VARIOUS_SAVE_BATTLER_ITEM 135
#define VARIOUS_RESTORE_BATTLER_ITEM 136
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 137
#define VARIOUS_SET_BEAK_BLAST 138
#define VARIOUS_SWAP_SIDE_STATUSES 139
#define VARIOUS_SWAP_STATS 140
#define VARIOUS_TEATIME_INVUL 141
#define VARIOUS_TEATIME_TARGETS 142
#define VARIOUS_TRY_WIND_RIDER_POWER 143
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 144
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 145
#define VARIOUS_STORE_HEALING_WISH 146
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 147
#define VARIOUS_TRY_REVIVAL_BLESSING 148
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@@ -697,13 +697,14 @@
#define STRINGID_THESWAMPDISAPPEARED 695
#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 696
#define STRINGID_HOSPITALITYRESTORATION 697
#define STRINGID_ELECTROSHOCKCHARGING 698
#define STRINGID_ELECTROSHOTCHARGING 698
#define STRINGID_ITEMWASUSEDUP 699
#define STRINGID_ATTACKERLOSTITSTYPE 700
#define STRINGID_SHEDITSTAIL 701
#define STRINGID_SUPERSWEETAROMAWAFTS 702
#define STRINGID_CLOAKEDINAHARSHLIGHT 702
#define STRINGID_SUPERSWEETAROMAWAFTS 703
#define BATTLESTRINGS_COUNT 703
#define BATTLESTRINGS_COUNT 704
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@@ -747,22 +748,6 @@
#define B_MSG_LEECH_SEED_DRAIN 3
#define B_MSG_LEECH_SEED_OOZE 4
// gFirstTurnOfTwoStringIds
#define B_MSG_TURN1_RAZOR_WIND 0
#define B_MSG_TURN1_SOLAR_BEAM 1
#define B_MSG_TURN1_SKULL_BASH 2
#define B_MSG_TURN1_SKY_ATTACK 3
#define B_MSG_TURN1_FLY 4
#define B_MSG_TURN1_DIG 5
#define B_MSG_TURN1_DIVE 6
#define B_MSG_TURN1_BOUNCE 7
#define B_MSG_TURN1_PHANTOM_FORCE 8
#define B_MSG_TURN1_GEOMANCY 9
#define B_MSG_TURN1_FREEZE_SHOCK 10
#define B_MSG_TURN1_SKY_DROP 11
#define B_MSG_TURN1_METEOR_BEAM 12
#define B_MSG_TURN1_ELECTRO_SHOCK 13
// gMoveWeatherChangeStringIds
#define B_MSG_STARTED_RAIN 0
#define B_MSG_STARTED_DOWNPOUR 1

View File

@@ -3,7 +3,7 @@
#define EXPANSION_VERSION_MAJOR 1
#define EXPANSION_VERSION_MINOR 7
#define EXPANSION_VERSION_PATCH 2
#define EXPANSION_VERSION_PATCH 3
// FALSE if this this version of Expansion is not a tagged commit, i.e.
// it contains unreleased changes.

View File

@@ -123,6 +123,7 @@ extern const union AffineAnimCmd *const gAffineAnims_BattleSpriteContest[];
extern const union AnimCmd sAnim_GeneralFrame0[];
extern const union AnimCmd sAnim_GeneralFrame3[];
extern const union AnimCmd *const gAnims_MonPic[];
extern const union AnimCmd *const sAnims_Trainer[];
extern const struct TrainerSprite gTrainerSprites[];
extern const struct TrainerBacksprite gTrainerBacksprites[];

View File

@@ -6,6 +6,7 @@
#include "config.h" // we need to define config before gba headers as print stuff needs the functions nulled before defines.
#include "gba/gba.h"
#include "fpmath.h"
#include "metaprogram.h"
#include "constants/global.h"
#include "constants/flags.h"
#include "constants/vars.h"
@@ -66,7 +67,7 @@
// Used in cases where division by 0 can occur in the retail version.
// Avoids invalid opcodes on some emulators, and the otherwise UB.
#ifdef UBFIX
#define SAFE_DIV(a, b) ((b) ? (a) / (b) : 0)
#define SAFE_DIV(a, b) (((b) != 0) ? (a) / (b) : 0)
#else
#define SAFE_DIV(a, b) ((a) / (b))
#endif
@@ -124,22 +125,6 @@
#define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT)
#define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS)
// Calls m0/m1/.../m8 depending on how many arguments are passed.
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
// 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
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) #__VA_ARGS__
// Converts a string to a compound literal, essentially making it a pointer to const u8
#define COMPOUND_STRING(str) (const u8[]) _(str)
// 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];

134
include/metaprogram.h Normal file
View File

@@ -0,0 +1,134 @@
/* Macros to aid with metaprogramming. */
#ifndef METAPROGRAM_H
#define METAPROGRAM_H
/* Calls m0/m1/.../m8 depending on how many arguments are passed. */
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
/* 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
/* Expands 'a' and 'b' and then concatenates them. */
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a ## b
/* Expands '__VA_ARGS__' and then stringizes them. */
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) #__VA_ARGS__
/* Converts a string to a compound literal, essentially making it a pointer to const u8 */
#define COMPOUND_STRING(str) (const u8[]) _(str)
/* Expands to the first/second/third/fourth argument. */
#define FIRST(a, ...) a
#define SECOND(a, ...) __VA_OPT__(FIRST(__VA_ARGS__))
#define THIRD(a, ...) __VA_OPT__(SECOND(__VA_ARGS__))
#define FOURTH(a, ...) __VA_OPT__(THIRD(__VA_ARGS__))
/* Expands to everything but the first x arguments */
#define EXCEPT_1(a, ...) __VA_OPT__(__VA_ARGS__)
#define EXCEPT_2(a, ...) __VA_OPT__(EXCEPT_1(__VA_ARGS__))
#define EXCEPT_3(a, ...) __VA_OPT__(EXCEPT_2(__VA_ARGS__))
#define EXCEPT_4(a, ...) __VA_OPT__(EXCEPT_3(__VA_ARGS__))
/* 'UNPACK (x, y, z)' expands to 'x, y, z'.
* Useful for passing arguments which may contain commas into a macro. */
#define UNPACK(...) __VA_ARGS__
/* Expands to 'macro(...args, ...)'. */
#define INVOKE_WITH(macro, args, ...) INVOKE_WITH_(macro, UNPACK args __VA_OPT__(, __VA_ARGS__))
#define INVOKE_WITH_(macro, ...) macro(__VA_ARGS__)
/* Recursive macros.
* Based on https://www.scs.stanford.edu/~dm/blog/va-opt.html
*
* Macros prefixed with R_ are recursive, to correctly expand them the
* top-level macro which references them should use 'RECURSIVELY' around
* them. 'RECURSIVELY' cannot be nested, hence the top-level macro must
* use it so that a recursive macro is able to reference another
* recursive macro. */
#define RECURSIVELY(...) RECURSIVELY_4(RECURSIVELY_4(RECURSIVELY_4(RECURSIVELY_4(__VA_ARGS__))))
#define RECURSIVELY_4(...) RECURSIVELY_3(RECURSIVELY_3(RECURSIVELY_3(RECURSIVELY_3(__VA_ARGS__))))
#define RECURSIVELY_3(...) RECURSIVELY_2(RECURSIVELY_2(RECURSIVELY_2(RECURSIVELY_2(__VA_ARGS__))))
#define RECURSIVELY_2(...) RECURSIVELY_1(RECURSIVELY_1(RECURSIVELY_1(RECURSIVELY_1(__VA_ARGS__))))
#define RECURSIVELY_1(...) __VA_ARGS__
/* Useful for deferring expansion until the second scan. See
* https://www.scs.stanford.edu/~dm/blog/va-opt.html for more info. */
#define PARENS ()
/* Expands to 'macro(a)' for each 'a' in '...' */
#define R_FOR_EACH(macro, ...) __VA_OPT__(R_FOR_EACH_(macro, __VA_ARGS__))
#define R_FOR_EACH_(macro, a, ...) macro(a) __VA_OPT__(R_FOR_EACH_P PARENS (macro, __VA_ARGS__))
#define R_FOR_EACH_P() R_FOR_EACH_
/* Expands to 'macro(...args, a)' for each 'a' in '...'. */
#define R_FOR_EACH_WITH(macro, args, ...) __VA_OPT__(R_FOR_EACH_WITH_(macro, args, __VA_ARGS__))
#define R_FOR_EACH_WITH_(macro, args, a, ...) INVOKE_WITH(macro, args, a) __VA_OPT__(R_FOR_EACH_WITH_P PARENS (macro, args, __VA_ARGS__))
#define R_FOR_EACH_WITH_P() R_FOR_EACH_WITH_
/* Picks the xth VA_ARG if it exists, otherwise returns a default value */
#define DEFAULT(_default, ...) FIRST(__VA_OPT__(__VA_ARGS__, ) _default)
#define DEFAULT_2(_default, ...) DEFAULT(_default __VA_OPT__(, SECOND(__VA_ARGS__)))
#define DEFAULT_3(_default, ...) DEFAULT(_default __VA_OPT__(, THIRD(__VA_ARGS__)))
#define DEFAULT_4(_default, ...) DEFAULT(_default __VA_OPT__(, FOURTH(__VA_ARGS__)))
/* (Credit to MGriffin) A rather monstrous way of finding the set bit in a word.
Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1hm7B */
#define BIT_INDEX(n) \
(n) == (1 << 0) ? 0 : \
(n) == (1 << 1) ? 1 : \
(n) == (1 << 2) ? 2 : \
(n) == (1 << 3) ? 3 : \
(n) == (1 << 4) ? 4 : \
(n) == (1 << 5) ? 5 : \
(n) == (1 << 6) ? 6 : \
(n) == (1 << 7) ? 7 : \
(n) == (1 << 8) ? 8 : \
(n) == (1 << 9) ? 9 : \
(n) == (1 << 10) ? 10 : \
(n) == (1 << 11) ? 11 : \
(n) == (1 << 12) ? 12 : \
(n) == (1 << 13) ? 13 : \
(n) == (1 << 14) ? 14 : \
(n) == (1 << 15) ? 15 : \
(n) == (1 << 16) ? 16 : \
(n) == (1 << 17) ? 17 : \
(n) == (1 << 18) ? 18 : \
(n) == (1 << 19) ? 19 : \
(n) == (1 << 20) ? 20 : \
(n) == (1 << 21) ? 21 : \
(n) == (1 << 22) ? 22 : \
(n) == (1 << 23) ? 23 : \
(n) == (1 << 24) ? 24 : \
(n) == (1 << 25) ? 25 : \
(n) == (1 << 26) ? 26 : \
(n) == (1 << 27) ? 27 : \
(n) == (1 << 28) ? 28 : \
(n) == (1 << 29) ? 29 : \
(n) == (1 << 30) ? 30 : \
(n) == (1 << 31) ? 31 : \
*(u32 *)NULL
#define COMPRESS_BITS_0 0, 1
#define COMPRESS_BITS_1 1, 1
#define COMPRESS_BITS_2 2, 1
#define COMPRESS_BITS_3 3, 1
#define COMPRESS_BITS_4 4, 1
#define COMPRESS_BITS_5 5, 1
#define COMPRESS_BITS_6 6, 1
#define COMPRESS_BITS_7 7, 1
/* Will try and compress a set bit (or up to three sequential bits) into a single byte
Input must be of the form (upper << lower) where upper can be up to 3, lower up to 31 */
#define COMPRESS_BITS(_val) COMPRESS_BITS_STEP_2 _val
#define COMPRESS_BITS_STEP_2(_unpacked) COMPRESS_BITS_STEP_3(COMPRESS_BITS_## _unpacked)
#define COMPRESS_BITS_STEP_3(...) COMPRESS_BITS_STEP_4(__VA_ARGS__)
#define COMPRESS_BITS_STEP_4(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower)))
/* Will read a compressed bit stored by COMPRESS_BIT into a single byte */
#define UNCOMPRESS_BITS(compressed) ((compressed >> 5) << (compressed & 0x1F))
#endif