pokeplatinum/src/field_script_context.c

163 lines
3.6 KiB
C

#include <nitro.h>
#include <string.h>
#include "field_script_context.h"
enum {
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->taskManager = 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_SetTaskManager (ScriptContext * ctx, TaskManager * taskManager)
{
ctx->taskManager = taskManager;
}
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;
}