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"
|
2019-02-25 08:09:02 +01:00
|
|
|
#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
|
2019-06-26 22:23:00 +02:00
|
|
|
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;
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
ctx->scriptPtr = 0;
|
2017-09-10 23:05:23 +02:00
|
|
|
ctx->stackDepth = 0;
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
ctx->nativePtr = 0;
|
2017-09-10 23:05:23 +02:00
|
|
|
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;
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
ctx->scriptPtr = 0;
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void MapHeaderRunScriptType(u8 tag)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-22 08:23:46 +01:00
|
|
|
u8 *ptr = MapHeaderGetScriptTable(tag);
|
2017-09-10 23:05:23 +02:00
|
|
|
if (ptr)
|
|
|
|
ScriptContext2_RunNewScript(ptr);
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
u8 *MapHeaderCheckScriptTable(u8 tag)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-22 08:23:46 +01: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void RunOnLoadMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
MapHeaderRunScriptType(MAP_SCRIPT_ON_LOAD);
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void RunOnTransitionMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
MapHeaderRunScriptType(MAP_SCRIPT_ON_TRANSITION);
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void RunOnResumeMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
MapHeaderRunScriptType(MAP_SCRIPT_ON_RESUME);
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void RunOnReturnToFieldMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
MapHeaderRunScriptType(MAP_SCRIPT_ON_RETURN_TO_FIELD);
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void RunOnDiveWarpMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
MapHeaderRunScriptType(MAP_SCRIPT_ON_DIVE_WARP);
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
bool8 TryRunOnFrameMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01:00
|
|
|
u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE);
|
2017-09-10 23:05:23 +02:00
|
|
|
|
|
|
|
if (!ptr)
|
2019-02-22 08:23:46 +01:00
|
|
|
return FALSE;
|
2017-09-10 23:05:23 +02:00
|
|
|
|
|
|
|
ScriptContext1_SetupScript(ptr);
|
2019-02-22 08:23:46 +01:00
|
|
|
return TRUE;
|
2017-09-10 23:05:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-22 08:23:46 +01:00
|
|
|
void TryRunOnWarpIntoMapScript(void)
|
2017-09-10 23:05:23 +02:00
|
|
|
{
|
2019-02-25 08:09:02 +01: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-11-21 04:55:44 +01:00
|
|
|
void InitRamScript_NoObjectEvent(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);
|
|
|
|
}
|