diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/safari_zone.c | 4 | ||||
-rw-r--r-- | src/script.c | 434 |
2 files changed, 436 insertions, 2 deletions
diff --git a/src/safari_zone.c b/src/safari_zone.c index 37ee664cd..fdfdd961a 100644 --- a/src/safari_zone.c +++ b/src/safari_zone.c @@ -34,7 +34,7 @@ extern void c2_exit_to_overworld_2_switch(void); extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void); extern void c2_load_new_map(void); extern void sub_80AF6F0(void); -extern void script_env_2_set_ctx_paused(void); +extern void ScriptContext1_Stop(void); extern void warp_in(void); extern void GetXYCoordsOneStepInFrontOfPlayer(s16* x, s16* y); extern void PlayerGetDestCoords(s16* x, s16* y); @@ -124,7 +124,7 @@ void sub_80FC190(void) else if (gBattleOutcome == BATTLE_CAUGHT) { ScriptContext1_SetupScript(gUnknown_082A4B9B); - script_env_2_set_ctx_paused(); + ScriptContext1_Stop(); SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); } } diff --git a/src/script.c b/src/script.c new file mode 100644 index 000000000..b2809a137 --- /dev/null +++ b/src/script.c @@ -0,0 +1,434 @@ +#include "global.h" +#include "script.h" +#include "event_data.h" +#include "util.h" + +#define RAM_SCRIPT_MAGIC 51 + +extern u8* gUnknown_020375C0; + +extern bool32 sub_801B27C(void); + +// ewram bss +IWRAM_DATA static u8 sScriptContext1Status; +IWRAM_DATA static u32 sUnusedVariable1; +IWRAM_DATA static struct ScriptContext sScriptContext1; +IWRAM_DATA static u32 sUnusedVariable2; +IWRAM_DATA static struct ScriptContext sScriptContext2; +IWRAM_DATA static bool8 sScriptContext2Enabled; + +extern ScrCmdFunc gScriptCmdTable[]; +extern ScrCmdFunc gScriptCmdTableEnd[]; +extern void *gNullScriptPtr; + +void InitScriptContext(struct ScriptContext *ctx, void *cmdTable, void *cmdTableEnd) +{ + s32 i; + + ctx->mode = 0; + ctx->scriptPtr = 0; + ctx->stackDepth = 0; + ctx->nativePtr = 0; + ctx->cmdTable = cmdTable; + ctx->cmdTableEnd = cmdTableEnd; + + for (i = 0; i < 4; i++) + ctx->data[i] = 0; + + for (i = 0; i < 20; i++) + ctx->stack[i] = 0; +} + +u8 SetupBytecodeScript(struct ScriptContext *ctx, const u8 *ptr) +{ + ctx->scriptPtr = ptr; + ctx->mode = 1; + return 1; +} + +void SetupNativeScript(struct ScriptContext *ctx, bool8 (*ptr)(void)) +{ + ctx->mode = 2; + ctx->nativePtr = ptr; +} + +void StopScript(struct ScriptContext *ctx) +{ + ctx->mode = 0; + ctx->scriptPtr = 0; +} + +bool8 RunScriptCommand(struct ScriptContext *ctx) +{ + if (ctx->mode == 0) + return FALSE; + + switch (ctx->mode) + { + case 0: + return FALSE; + case 2: + if (ctx->nativePtr) + { + if (ctx->nativePtr() == TRUE) + ctx->mode = 1; + return TRUE; + } + ctx->mode = 1; + case 1: + while (1) + { + u8 cmdCode; + ScrCmdFunc *func; + + if (!ctx->scriptPtr) + { + ctx->mode = 0; + return FALSE; + } + + if (ctx->scriptPtr == gNullScriptPtr) + { + while (1) + asm("svc 2"); // HALT + } + + cmdCode = *(ctx->scriptPtr); + ctx->scriptPtr++; + func = &ctx->cmdTable[cmdCode]; + + if (func >= ctx->cmdTableEnd) + { + ctx->mode = 0; + return FALSE; + } + + if ((*func)(ctx) == 1) + return TRUE; + } + } + + return TRUE; +} + +u8 ScriptPush(struct ScriptContext *ctx, const u8 *ptr) +{ + if (ctx->stackDepth + 1 >= 20) + { + return 1; + } + else + { + ctx->stack[ctx->stackDepth] = ptr; + ctx->stackDepth++; + return 0; + } +} + +const u8 *ScriptPop(struct ScriptContext *ctx) +{ + if (ctx->stackDepth == 0) + return NULL; + + ctx->stackDepth--; + return ctx->stack[ctx->stackDepth]; +} + +void ScriptJump(struct ScriptContext *ctx, u8 *ptr) +{ + ctx->scriptPtr = ptr; +} + +void ScriptCall(struct ScriptContext *ctx, u8 *ptr) +{ + ScriptPush(ctx, ctx->scriptPtr); + ctx->scriptPtr = ptr; +} + +void ScriptReturn(struct ScriptContext *ctx) +{ + ctx->scriptPtr = ScriptPop(ctx); +} + +u16 ScriptReadHalfword(struct ScriptContext *ctx) +{ + u16 value = *(ctx->scriptPtr++); + value |= *(ctx->scriptPtr++) << 8; + return value; +} + +u32 ScriptReadWord(struct ScriptContext *ctx) +{ + u32 value0 = *(ctx->scriptPtr++); + u32 value1 = *(ctx->scriptPtr++); + u32 value2 = *(ctx->scriptPtr++); + u32 value3 = *(ctx->scriptPtr++); + return (((((value3 << 8) + value2) << 8) + value1) << 8) + value0; +} + +void ScriptContext2_Enable(void) +{ + sScriptContext2Enabled = TRUE; +} + +void ScriptContext2_Disable(void) +{ + sScriptContext2Enabled = FALSE; +} + +bool8 ScriptContext2_IsEnabled(void) +{ + return sScriptContext2Enabled; +} + +bool8 ScriptContext1_IsScriptSetUp(void) +{ + if (sScriptContext1Status == 0) + return TRUE; + else + return FALSE; +} + +void ScriptContext1_Init(void) +{ + InitScriptContext(&sScriptContext1, gScriptCmdTable, gScriptCmdTableEnd); + sScriptContext1Status = 2; +} + +bool8 ScriptContext2_RunScript(void) +{ + if (sScriptContext1Status == 2) + return 0; + + if (sScriptContext1Status == 1) + return 0; + + ScriptContext2_Enable(); + + if (!RunScriptCommand(&sScriptContext1)) + { + sScriptContext1Status = 2; + ScriptContext2_Disable(); + return 0; + } + + return 1; +} + +void ScriptContext1_SetupScript(const u8 *ptr) +{ + InitScriptContext(&sScriptContext1, gScriptCmdTable, gScriptCmdTableEnd); + SetupBytecodeScript(&sScriptContext1, ptr); + ScriptContext2_Enable(); + sScriptContext1Status = 0; +} + +void ScriptContext1_Stop(void) +{ + sScriptContext1Status = 1; +} + +void EnableBothScriptContexts(void) +{ + sScriptContext1Status = 0; + ScriptContext2_Enable(); +} + +void ScriptContext2_RunNewScript(const u8 *ptr) +{ + InitScriptContext(&sScriptContext2, &gScriptCmdTable, &gScriptCmdTableEnd); + SetupBytecodeScript(&sScriptContext2, ptr); + while (RunScriptCommand(&sScriptContext2) == TRUE); +} + +u8 *mapheader_get_tagged_pointer(u8 tag) +{ + u8 *mapScripts = gMapHeader.mapScripts; + + if (!mapScripts) + return NULL; + + while (1) + { + if (!*mapScripts) + return NULL; + if (*mapScripts == tag) + { + mapScripts++; + return (u8 *)(mapScripts[0] + (mapScripts[1] << 8) + (mapScripts[2] << 16) + (mapScripts[3] << 24)); + } + mapScripts += 5; + } +} + +void mapheader_run_script_by_tag(u8 tag) +{ + u8 *ptr = mapheader_get_tagged_pointer(tag); + if (ptr) + ScriptContext2_RunNewScript(ptr); +} + +u8 *mapheader_get_first_match_from_tagged_ptr_list(u8 tag) +{ + u8 *ptr = mapheader_get_tagged_pointer(tag); + + if (!ptr) + return NULL; + + while (1) + { + u16 varIndex1; + u16 varIndex2; + varIndex1 = ptr[0] | (ptr[1] << 8); + if (!varIndex1) + return NULL; + ptr += 2; + varIndex2 = ptr[0] | (ptr[1] << 8); + ptr += 2; + if (VarGet(varIndex1) == VarGet(varIndex2)) + return (u8 *)(ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24)); + ptr += 4; + } +} + +void mapheader_run_script_with_tag_x1(void) +{ + mapheader_run_script_by_tag(1); +} + +void mapheader_run_script_with_tag_x3(void) +{ + mapheader_run_script_by_tag(3); +} + +void mapheader_run_script_with_tag_x5(void) +{ + mapheader_run_script_by_tag(5); +} + +void mapheader_run_script_with_tag_x7(void) +{ + mapheader_run_script_by_tag(7); +} + +void mapheader_run_script_with_tag_x6(void) +{ + mapheader_run_script_by_tag(6); +} + +bool8 mapheader_run_first_tag2_script_list_match(void) +{ + u8 *ptr = mapheader_get_first_match_from_tagged_ptr_list(2); + + if (!ptr) + return 0; + + ScriptContext1_SetupScript(ptr); + return 1; +} + +void mapheader_run_first_tag4_script_list_match(void) +{ + u8 *ptr = mapheader_get_first_match_from_tagged_ptr_list(4); + if (ptr) + ScriptContext2_RunNewScript(ptr); +} + +u32 CalculateRamScriptChecksum(void) +{ + return CalcCRC16WithTable((u8*)(&gSaveBlock1Ptr->ramScript.data), sizeof(gSaveBlock1Ptr->ramScript.data)); +} + +void ClearRamScript(void) +{ + CpuFill32(0, &gSaveBlock1Ptr->ramScript, sizeof(struct RamScript)); +} + +bool8 InitRamScript(u8 *script, u16 scriptSize, u8 mapGroup, u8 mapNum, u8 objectId) +{ + struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data; + + ClearRamScript(); + + if (scriptSize > sizeof(scriptData->script)) + return FALSE; + + scriptData->magic = RAM_SCRIPT_MAGIC; + scriptData->mapGroup = mapGroup; + scriptData->mapNum = mapNum; + scriptData->objectId = objectId; + memcpy(scriptData->script, script, scriptSize); + gSaveBlock1Ptr->ramScript.checksum = CalculateRamScriptChecksum(); + return TRUE; +} + +u8 *GetRamScript(u8 objectId, u8 *script) +{ + struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data; + gUnknown_020375C0 = NULL; + if (scriptData->magic != RAM_SCRIPT_MAGIC) + return script; + if (scriptData->mapGroup != gSaveBlock1Ptr->location.mapGroup) + return script; + if (scriptData->mapNum != gSaveBlock1Ptr->location.mapNum) + return script; + if (scriptData->objectId != objectId) + return script; + if (CalculateRamScriptChecksum() != gSaveBlock1Ptr->ramScript.checksum) + { + ClearRamScript(); + return script; + } + else + { + gUnknown_020375C0 = script; + return scriptData->script; + } +} + +bool32 sub_80991F8(void) +{ + struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data; + if (scriptData->magic != RAM_SCRIPT_MAGIC) + return FALSE; + if (scriptData->mapGroup != 0xFF) + return FALSE; + if (scriptData->mapNum != 0xFF) + return FALSE; + if (scriptData->objectId != 0xFF) + return FALSE; + if (CalculateRamScriptChecksum() != gSaveBlock1Ptr->ramScript.checksum) + return FALSE; + return TRUE; +} + +u8 *sub_8099244(void) +{ + struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data; + if (!sub_801B27C()) + return NULL; + if (scriptData->magic != RAM_SCRIPT_MAGIC) + return NULL; + if (scriptData->mapGroup != 0xFF) + return NULL; + if (scriptData->mapNum != 0xFF) + return NULL; + if (scriptData->objectId != 0xFF) + return NULL; + if (CalculateRamScriptChecksum() != gSaveBlock1Ptr->ramScript.checksum) + { + ClearRamScript(); + return NULL; + } + else + { + return scriptData->script; + } +} + +void sub_80992A0(u8 *script, u16 scriptSize) +{ + if (scriptSize > sizeof(gSaveBlock1Ptr->ramScript.data.script)) + scriptSize = sizeof(gSaveBlock1Ptr->ramScript.data.script); + InitRamScript(script, scriptSize, 0xFF, 0xFF, 0xFF); +} |