pokeplatinum/src/field_script_context.c
Gudf 541fca37db
Tag previously untagged enums (#477)
This leaves out undocumented enums and a few enums I couldn't find a
name for and feel would fit better as `#define`s instead.
2025-04-20 12:49:54 -07:00

163 lines
3.5 KiB
C

#include "field_script_context.h"
#include <nitro.h>
#include <string.h>
enum FieldScriptState {
SCRIPT_STATE_STOPPED,
SCRIPT_STATE_RUNNING,
SCRIPT_STATE_WAITING,
};
void ScriptContext_Init(ScriptContext *ctx, const ScrCmdFunc *cmdTable, u32 cmdTableSize)
{
ctx->state = SCRIPT_STATE_STOPPED;
ctx->scriptPtr = NULL;
ctx->stackPointer = 0;
ctx->shouldResume = NULL;
ctx->cmdTable = cmdTable;
ctx->cmdTableSize = cmdTableSize;
u32 i;
for (i = 0; i < NELEMS(ctx->data); i++) {
ctx->data[i] = 0;
}
for (i = 0; i < NELEMS(ctx->stack); i++) {
ctx->stack[i] = NULL;
}
ctx->task = NULL;
}
BOOL ScriptContext_Start(ScriptContext *ctx, const u8 *ptr)
{
ctx->scriptPtr = ptr;
ctx->state = SCRIPT_STATE_RUNNING;
return TRUE;
}
void ScriptContext_Pause(ScriptContext *ctx, ShouldResumeScriptFunc shouldResume)
{
ctx->state = SCRIPT_STATE_WAITING;
ctx->shouldResume = shouldResume;
}
void ScriptContext_Stop(ScriptContext *ctx)
{
ctx->state = SCRIPT_STATE_STOPPED;
ctx->scriptPtr = NULL;
}
void ScriptContext_SetTask(ScriptContext *ctx, FieldTask *task)
{
ctx->task = task;
}
BOOL ScriptContext_Run(ScriptContext *ctx)
{
if (ctx->state == SCRIPT_STATE_STOPPED) {
return FALSE;
}
switch (ctx->state) {
case SCRIPT_STATE_STOPPED:
// this branch is never taken due to the above check
return FALSE;
case SCRIPT_STATE_WAITING:
if (ctx->shouldResume != NULL) {
if (ctx->shouldResume(ctx) == TRUE) {
ctx->state = SCRIPT_STATE_RUNNING;
}
return TRUE;
}
ctx->state = SCRIPT_STATE_RUNNING;
// fallthrough
case SCRIPT_STATE_RUNNING:
while (TRUE) {
if (ctx->scriptPtr == NULL) {
ctx->state = SCRIPT_STATE_STOPPED;
return FALSE;
}
u16 cmdCode = ScriptContext_ReadHalfWord(ctx);
if (cmdCode >= ctx->cmdTableSize) {
GF_ASSERT(FALSE);
ctx->state = SCRIPT_STATE_STOPPED;
return FALSE;
}
if (ctx->cmdTable[cmdCode](ctx) == TRUE) {
break;
}
}
}
return TRUE;
}
static BOOL ScriptContext_Push(ScriptContext *ctx, const u8 *ptr)
{
if (ctx->stackPointer + 1 >= (int)NELEMS(ctx->stack)) {
return TRUE;
}
ctx->stack[ctx->stackPointer] = ptr;
ctx->stackPointer++;
return FALSE;
}
static const u8 *ScriptContext_Pop(ScriptContext *ctx)
{
if (ctx->stackPointer == 0) {
return NULL;
}
return ctx->stack[--ctx->stackPointer];
}
void ScriptContext_Jump(ScriptContext *ctx, const u8 *ptr)
{
ctx->scriptPtr = ptr;
}
void ScriptContext_Call(ScriptContext *ctx, const u8 *ptr)
{
ScriptContext_Push(ctx, ctx->scriptPtr);
ctx->scriptPtr = ptr;
}
void ScriptContext_Return(ScriptContext *ctx)
{
ctx->scriptPtr = ScriptContext_Pop(ctx);
}
u16 ScriptContext_ReadHalfWord(ScriptContext *ctx)
{
u16 value = ScriptContext_ReadByte(ctx);
value += ScriptContext_ReadByte(ctx) << 8;
return value;
}
u32 ScriptContext_ReadWord(ScriptContext *ctx)
{
u8 byte0 = ScriptContext_ReadByte(ctx);
u8 byte1 = ScriptContext_ReadByte(ctx);
u8 byte2 = ScriptContext_ReadByte(ctx);
u8 byte3 = ScriptContext_ReadByte(ctx);
u32 value = 0;
value += byte3;
value <<= 8;
value += byte2;
value <<= 8;
value += byte1;
value <<= 8;
value += byte0;
return value;
}