pokeplatinum/src/field_task.c
2025-08-23 14:31:51 -07:00

167 lines
3.8 KiB
C

#include "field_task.h"
#include <nitro.h>
#include <string.h>
#include "field/field_system.h"
#include "field_system.h"
#include "heap.h"
typedef struct FieldTaskEnv {
int state;
const ApplicationManagerTemplate *appTemplate;
void *appArgs;
} FieldTaskEnv;
static FieldTask *CreateTaskManager(FieldSystem *fieldSys, FieldTaskFunc taskFunc, void *taskEnv)
{
FieldTask *task = Heap_AllocAtEnd(HEAP_ID_FIELD3, sizeof(FieldTask));
task->prev = NULL;
task->func = taskFunc;
task->state = 0;
task->env = taskEnv;
task->dummy10 = 0;
task->dummy14 = NULL;
task->fieldSys = fieldSys;
task->dummy1C = Heap_AllocAtEnd(HEAP_ID_FIELD3, sizeof(u32));
return task;
}
FieldTask *FieldSystem_CreateTask(FieldSystem *fieldSys, FieldTaskFunc taskFunc, void *taskEnv)
{
GF_ASSERT(fieldSys->task == NULL);
FieldTask *task = CreateTaskManager(fieldSys, taskFunc, taskEnv);
fieldSys->task = task;
return task;
}
void FieldTask_InitJump(FieldTask *task, FieldTaskFunc taskFunc, void *taskEnv)
{
task->func = taskFunc;
task->state = 0;
task->env = taskEnv;
if (task->dummy14 != 0 || task->dummy14 != NULL) { // Double-comparison required to match
Heap_Free(task->dummy14);
task->dummy10 = 0;
task->dummy14 = NULL;
}
}
FieldTask *FieldTask_InitCall(FieldTask *task, FieldTaskFunc taskFunc, void *taskEnv)
{
FieldTask *next = CreateTaskManager(task->fieldSys, taskFunc, taskEnv);
next->prev = task;
task->fieldSys->task = next;
return next;
}
BOOL FieldTask_Run(FieldSystem *fieldSys)
{
if (fieldSys->task == NULL) {
return FALSE;
}
// Run invocations through the call-stack until it is empty.
while (fieldSys->task->func(fieldSys->task) == TRUE) {
FieldTask *prev = fieldSys->task->prev;
if (fieldSys->task->dummy14) {
Heap_Free(fieldSys->task->dummy14);
}
Heap_Free(fieldSys->task->dummy1C);
Heap_Free(fieldSys->task);
fieldSys->task = prev;
if (prev == NULL) {
return TRUE;
}
}
return FALSE;
}
BOOL FieldSystem_IsRunningTask(FieldSystem *fieldSys)
{
return fieldSys->task != NULL;
}
BOOL FieldSystem_IsRunningApplication(FieldSystem *fieldSys)
{
return FieldSystem_HasParentProcess(fieldSys) || FieldSystem_HasChildProcess(fieldSys);
}
void FieldSystem_StartFieldMap(FieldSystem *fieldSys)
{
FieldSystem_StartFieldMapInner(fieldSys);
}
BOOL FieldSystem_IsRunningFieldMap(FieldSystem *fieldSys)
{
// Explicit conditional-branch required to match.
if (FieldSystem_IsRunningFieldMapInner(fieldSys)) {
return TRUE;
} else {
return FALSE;
}
}
static BOOL RunChildApplication(FieldTask *task)
{
FieldSystem *fieldSys = FieldTask_GetFieldSystem(task);
FieldTaskEnv *env = FieldTask_GetEnv(task);
switch (env->state) {
case 0:
FieldSystem_StartChildProcess(fieldSys, env->appTemplate, env->appArgs);
env->state++;
break;
case 1:
if (FieldSystem_IsRunningApplication(fieldSys)) {
break;
}
Heap_Free(env);
return TRUE;
}
return FALSE;
}
void FieldTask_RunApplication(FieldTask *task, const ApplicationManagerTemplate *appTemplate, void *appArgs)
{
FieldTaskEnv *env = Heap_AllocAtEnd(HEAP_ID_FIELD3, sizeof(FieldTaskEnv));
env->state = 0;
env->appTemplate = appTemplate;
env->appArgs = appArgs;
FieldTask_InitCall(task, RunChildApplication, env);
}
FieldSystem *FieldTask_GetFieldSystem(FieldTask *task)
{
return task->fieldSys;
}
void *FieldTask_GetEnv(FieldTask *task)
{
return task->env;
}
int *FieldTask_GetState(FieldTask *task)
{
return &task->state;
}
u32 FieldTask_GetDummy1CVal(FieldTask *task)
{
return *task->dummy1C;
}