mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-22 02:15:28 -05:00
178 lines
6.3 KiB
C
178 lines
6.3 KiB
C
#ifndef GUARD_SCRIPT_H
|
|
#define GUARD_SCRIPT_H
|
|
|
|
struct ScriptContext;
|
|
|
|
typedef bool8 (*ScrCmdFunc)(struct ScriptContext *);
|
|
typedef u8 Script[];
|
|
|
|
struct ScriptContext
|
|
{
|
|
u8 stackDepth;
|
|
u8 mode;
|
|
u8 comparisonResult;
|
|
bool8 breakOnTrainerBattle;
|
|
u8 (*nativePtr)(void);
|
|
const u8 *scriptPtr;
|
|
const u8 *stack[20];
|
|
ScrCmdFunc *cmdTable;
|
|
ScrCmdFunc *cmdTableEnd;
|
|
u32 data[4];
|
|
};
|
|
|
|
#define ScriptReadByte(ctx) (*(ctx->scriptPtr++))
|
|
|
|
void InitScriptContext(struct ScriptContext *ctx, void *cmdTable, void *cmdTableEnd);
|
|
u8 SetupBytecodeScript(struct ScriptContext *ctx, const u8 *ptr);
|
|
void SetupNativeScript(struct ScriptContext *ctx, bool8 (*ptr)(void));
|
|
void StopScript(struct ScriptContext *ctx);
|
|
bool8 RunScriptCommand(struct ScriptContext *ctx);
|
|
void ScriptJump(struct ScriptContext *ctx, const u8 *ptr);
|
|
void ScriptCall(struct ScriptContext *ctx, const u8 *ptr);
|
|
void ScriptReturn(struct ScriptContext *ctx);
|
|
u16 ScriptReadHalfword(struct ScriptContext *ctx);
|
|
u32 ScriptReadWord(struct ScriptContext *ctx);
|
|
u32 ScriptPeekWord(struct ScriptContext *ctx);
|
|
void LockPlayerFieldControls(void);
|
|
void UnlockPlayerFieldControls(void);
|
|
bool8 ArePlayerFieldControlsLocked(void);
|
|
void ScriptContext_Init(void);
|
|
bool8 ScriptContext_IsEnabled(void);
|
|
bool8 ScriptContext_RunScript(void);
|
|
void ScriptContext_SetupScript(const u8 *ptr);
|
|
void ScriptContext_ContinueScript(struct ScriptContext *ctx);
|
|
void ScriptContext_Stop(void);
|
|
void ScriptContext_Enable(void);
|
|
void RunScriptImmediately(const u8 *ptr);
|
|
const u8 *MapHeaderGetScriptTable(u8 tag);
|
|
void MapHeaderRunScriptType(u8 tag);
|
|
const u8 *MapHeaderCheckScriptTable(u8 tag);
|
|
void RunOnLoadMapScript(void);
|
|
void RunOnTransitionMapScript(void);
|
|
void RunOnResumeMapScript(void);
|
|
void RunOnReturnToFieldMapScript(void);
|
|
void RunOnDiveWarpMapScript(void);
|
|
bool8 TryRunOnFrameMapScript(void);
|
|
void TryRunOnWarpIntoMapScript(void);
|
|
u32 CalculateRamScriptChecksum(void);
|
|
void ClearRamScript(void);
|
|
bool8 InitRamScript(const u8 *script, u16 scriptSize, u8 mapGroup, u8 mapNum, u8 objectId);
|
|
const u8 *GetRamScript(u8 objectId, const u8 *script);
|
|
bool32 ValidateSavedRamScript(void);
|
|
u8 *GetSavedRamScriptIfValid(void);
|
|
void InitRamScript_NoObjectEvent(u8 *script, u16 scriptSize);
|
|
|
|
// srccmd.h
|
|
void SetMovingNpcId(u16 npcId);
|
|
|
|
extern u8 gMsgIsSignPost;
|
|
extern u8 gMsgBoxIsCancelable;
|
|
|
|
/* Script effects analysis.
|
|
*
|
|
* 'RunScriptImmediatelyUntilEffect' executes a script until it reaches
|
|
* the first command which calls 'Script_RequestEffects' with an
|
|
* effect in 'effects' in which case it returns 'TRUE' and stores the
|
|
* current state in 'ctx'; or until it reaches an 'end'/'return' in
|
|
* which case it returns 'FALSE'.
|
|
*
|
|
* 'Script_HasNoEffect' wraps 'RunScriptImmediatelyUntilEffect' and
|
|
* returns 'TRUE' if the script exits without an effect on the save or
|
|
* the hardware, or 'FALSE' if it would have an effect (the effect is
|
|
* not performed).
|
|
*
|
|
* Commands, natives, and specials which call 'Script_RequestEffects'
|
|
* must be explicitly tagged with 'requests_effects=1', and must call
|
|
* the function before any of those effects occur. An untagged function
|
|
* could cause any effect, so execution is stopped to be safe. If the
|
|
* code has no effects it must call 'Script_RequestEffects(SCREFF_V1)'
|
|
* to note that explicitly.
|
|
*
|
|
* Regular variables are in the save (so should use 'SCREFF_SAVE'), but
|
|
* special variables are not in the save, so 'Script_RequestWriteVar' is
|
|
* provided to only request the 'SCREFF_SAVE' effect for a non-special
|
|
* variable.
|
|
*
|
|
* The 'effects' parameter to 'RunScriptImmediatelyUntilEffect' and
|
|
* 'Script_RequestEffects' must be the bitwise or of an effects version
|
|
* (currently 'SCREFF_V1') and any number of effects. For example
|
|
* 'Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE)'. */
|
|
|
|
enum // effects
|
|
{
|
|
SCREFF_SAVE = 1 << 0, // writes to the save.
|
|
SCREFF_HARDWARE = 1 << 1, // writes to a hardware register.
|
|
SCREFF_TRAINERBATTLE = 1 << 2, // 'trainerbattle' command.
|
|
};
|
|
|
|
#define SCREFF_ANY (SCREFF_SAVE | SCREFF_HARDWARE | SCREFF_TRAINERBATTLE)
|
|
|
|
enum // effects versions
|
|
{
|
|
SCREFF_V1 = 0xFFFFFFF8,
|
|
};
|
|
|
|
extern struct ScriptEffectContext *gScriptEffectContext;
|
|
|
|
bool32 RunScriptImmediatelyUntilEffect_Internal(u32 effects, const u8 *ptr, struct ScriptContext *ctx);
|
|
bool32 Script_HasNoEffect(const u8 *ptr);
|
|
void Script_GotoBreak_Internal(void);
|
|
void Script_RequestEffects_Internal(u32 effects);
|
|
void Script_RequestWriteVar_Internal(u32 varId);
|
|
|
|
static inline bool32 Script_IsAnalyzingEffects(void)
|
|
{
|
|
return gScriptEffectContext != NULL;
|
|
}
|
|
|
|
#define RunScriptImmediatelyUntilEffect(effects, ptr, ctx) \
|
|
({ \
|
|
_Static_assert((effects) & 0x80000000, "RunScriptImmediatelyUntilEffect requires an effects version"); \
|
|
RunScriptImmediatelyUntilEffect_Internal(effects, ptr, ctx); \
|
|
})
|
|
|
|
/* Optimize 'Script_RequestEffects' to a no-op if it would have no
|
|
* effect. 'Script_RequestEffects' must be called in all commands and
|
|
* natives/specials with 'requests_effects=TRUE' even if it would have
|
|
* no effect to future-proof against new effects. */
|
|
#define Script_RequestEffects(effects) \
|
|
({ \
|
|
_Static_assert((effects) & 0x80000000, "Script_RequestEffects requires an effects version"); \
|
|
if ((effects) != SCREFF_V1) \
|
|
if (Script_IsAnalyzingEffects()) \
|
|
Script_RequestEffects_Internal((effects) & SCREFF_ANY); \
|
|
})
|
|
|
|
/* Optimize 'Script_RequestWriteVar' to a no-op if it would have no
|
|
* effect. */
|
|
#define Script_RequestWriteVar(varId) \
|
|
({ \
|
|
if (Script_IsAnalyzingEffects()) \
|
|
Script_RequestWriteVar_Internal(varId); \
|
|
})
|
|
|
|
static inline void Script_CheckEffectInstrumentedSpecial(u32 specialId)
|
|
{
|
|
typedef u16 (*SpecialFunc)(void);
|
|
extern const SpecialFunc gSpecials[];
|
|
// In ROM mirror 1.
|
|
if (Script_IsAnalyzingEffects() && (((uintptr_t)gSpecials[specialId]) & 0xE000000) != 0xA000000)
|
|
Script_GotoBreak_Internal();
|
|
}
|
|
|
|
static inline void Script_CheckEffectInstrumentedGotoNative(bool8 (*func)(void))
|
|
{
|
|
// In ROM mirror 1.
|
|
if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000)
|
|
Script_GotoBreak_Internal();
|
|
}
|
|
|
|
static inline void Script_CheckEffectInstrumentedCallNative(void (*func)(struct ScriptContext *))
|
|
{
|
|
// In ROM mirror 1.
|
|
if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000)
|
|
Script_GotoBreak_Internal();
|
|
}
|
|
|
|
#endif // GUARD_SCRIPT_H
|