pokeemerald/src/script.c

435 lines
9.5 KiB
C
Raw Normal View History

2017-09-10 23:05:23 +02:00
#include "global.h"
#include "script.h"
#include "event_data.h"
2019-03-25 00:13:32 +01:00
#include "mevent.h"
2017-09-10 23:05:23 +02:00
#include "util.h"
#include "constants/map_scripts.h"
2017-09-10 23:05:23 +02:00
#define RAM_SCRIPT_MAGIC 51
2018-10-17 04:47:08 +02:00
extern const u8* gUnknown_020375C0;
2017-09-10 23:05:23 +02:00
// ewram bss
static u8 sScriptContext1Status;
static u32 sUnusedVariable1;
static struct ScriptContext sScriptContext1;
static u32 sUnusedVariable2;
static struct ScriptContext sScriptContext2;
static bool8 sScriptContext2Enabled;
2017-09-10 23:05:23 +02:00
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];
}
2017-10-12 21:36:26 +02:00
void ScriptJump(struct ScriptContext *ctx, const u8 *ptr)
2017-09-10 23:05:23 +02:00
{
ctx->scriptPtr = ptr;
}
2017-10-12 21:36:26 +02:00
void ScriptCall(struct ScriptContext *ctx, const u8 *ptr)
2017-09-10 23:05:23 +02:00
{
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 *MapHeaderGetScriptTable(u8 tag)
2017-09-10 23:05:23 +02:00
{
2018-02-15 23:09:52 +01:00
const u8 *mapScripts = gMapHeader.mapScripts;
2017-09-10 23:05:23 +02:00
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 MapHeaderRunScriptType(u8 tag)
2017-09-10 23:05:23 +02:00
{
u8 *ptr = MapHeaderGetScriptTable(tag);
2017-09-10 23:05:23 +02:00
if (ptr)
ScriptContext2_RunNewScript(ptr);
}
u8 *MapHeaderCheckScriptTable(u8 tag)
2017-09-10 23:05:23 +02:00
{
u8 *ptr = MapHeaderGetScriptTable(tag);
2017-09-10 23:05:23 +02:00
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 RunOnLoadMapScript(void)
2017-09-10 23:05:23 +02:00
{
MapHeaderRunScriptType(MAP_SCRIPT_ON_LOAD);
2017-09-10 23:05:23 +02:00
}
void RunOnTransitionMapScript(void)
2017-09-10 23:05:23 +02:00
{
MapHeaderRunScriptType(MAP_SCRIPT_ON_TRANSITION);
2017-09-10 23:05:23 +02:00
}
void RunOnResumeMapScript(void)
2017-09-10 23:05:23 +02:00
{
MapHeaderRunScriptType(MAP_SCRIPT_ON_RESUME);
2017-09-10 23:05:23 +02:00
}
void RunOnReturnToFieldMapScript(void)
2017-09-10 23:05:23 +02:00
{
MapHeaderRunScriptType(MAP_SCRIPT_ON_RETURN_TO_FIELD);
2017-09-10 23:05:23 +02:00
}
void RunOnDiveWarpMapScript(void)
2017-09-10 23:05:23 +02:00
{
MapHeaderRunScriptType(MAP_SCRIPT_ON_DIVE_WARP);
2017-09-10 23:05:23 +02:00
}
bool8 TryRunOnFrameMapScript(void)
2017-09-10 23:05:23 +02:00
{
u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE);
2017-09-10 23:05:23 +02:00
if (!ptr)
return FALSE;
2017-09-10 23:05:23 +02:00
ScriptContext1_SetupScript(ptr);
return TRUE;
2017-09-10 23:05:23 +02:00
}
void TryRunOnWarpIntoMapScript(void)
2017-09-10 23:05:23 +02:00
{
u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_WARP_INTO_MAP_TABLE);
2017-09-10 23:05:23 +02:00
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));
}
2018-10-17 04:47:08 +02:00
bool8 InitRamScript(const u8 *script, u16 scriptSize, u8 mapGroup, u8 mapNum, u8 objectId)
2017-09-10 23:05:23 +02:00
{
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;
}
2018-10-17 04:47:08 +02:00
const u8 *GetRamScript(u8 objectId, const u8 *script)
2017-09-10 23:05:23 +02:00
{
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;
}
}
2019-04-02 19:57:03 +02:00
bool32 ValidateSavedRamScript(void)
2017-09-10 23:05:23 +02:00
{
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;
}
2019-04-02 19:57:03 +02:00
u8 *GetSavedRamScriptIfValid(void)
2017-09-10 23:05:23 +02:00
{
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
2019-04-01 00:59:52 +02:00
if (!ValidateReceivedWonderCard())
2017-09-10 23:05:23 +02:00
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;
}
}
2019-04-02 19:57:03 +02:00
void InitRamScript_NoEventObject(u8 *script, u16 scriptSize)
2017-09-10 23:05:23 +02:00
{
if (scriptSize > sizeof(gSaveBlock1Ptr->ramScript.data.script))
scriptSize = sizeof(gSaveBlock1Ptr->ramScript.data.script);
InitRamScript(script, scriptSize, 0xFF, 0xFF, 0xFF);
}