mirror of
https://github.com/pret/pokeruby.git
synced 2025-01-19 11:12:26 +00:00
task.c
This commit is contained in:
parent
ae21f32d61
commit
5b648ca259
@ -2,7 +2,7 @@
|
||||
.align 2, 0
|
||||
.global \name
|
||||
.arm
|
||||
.type \name, %function
|
||||
.type \name, function
|
||||
.endm
|
||||
|
||||
.macro arm_func_end name
|
||||
@ -14,14 +14,14 @@
|
||||
.global \name
|
||||
.thumb
|
||||
.thumb_func
|
||||
.type \name, %function
|
||||
.type \name, function
|
||||
.endm
|
||||
|
||||
.macro non_word_aligned_thumb_func_start name
|
||||
.global \name
|
||||
.thumb
|
||||
.thumb_func
|
||||
.type \name, %function
|
||||
.type \name, function
|
||||
.endm
|
||||
|
||||
.macro thumb_func_end name
|
||||
|
27
include/task.h
Normal file
27
include/task.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef GUARD_TASK_H
|
||||
#define GUARD_TASK_H
|
||||
|
||||
typedef void (*TaskFunc)(u8 taskId);
|
||||
|
||||
struct Task
|
||||
{
|
||||
TaskFunc func;
|
||||
bool8 isActive;
|
||||
u8 prev;
|
||||
u8 next;
|
||||
u8 priority;
|
||||
u16 data[16];
|
||||
};
|
||||
|
||||
void ResetTasks();
|
||||
u8 CreateTask(TaskFunc func, u8 priority);
|
||||
void DestroyTask(u8 taskId);
|
||||
void RunTasks();
|
||||
void TaskDummy(u8 taskId);
|
||||
void SetTaskFuncWithFollowupFunc(u8 taskId, TaskFunc func, TaskFunc followupFunc);
|
||||
void SwitchTaskToFollowupFunc(u8 taskId);
|
||||
bool8 FuncIsActiveTask(TaskFunc func);
|
||||
u8 FindTaskIdByFunc(TaskFunc func);
|
||||
u8 GetTaskCount();
|
||||
|
||||
#endif // GUARD_TASK_H
|
@ -10,3 +10,5 @@ gRtcLocked = 0x3000F36;
|
||||
gUnknownStringVar = 0x3002900;
|
||||
|
||||
gLocalTime = 0x3004038;
|
||||
|
||||
gTasks = 0x3004B20;
|
||||
|
295
src/task.c
Normal file
295
src/task.c
Normal file
@ -0,0 +1,295 @@
|
||||
#include "global.h"
|
||||
#include "task.h"
|
||||
|
||||
#define NUM_TASKS 16
|
||||
|
||||
#define HEAD_SENTINEL 0xFE
|
||||
#define TAIL_SENTINEL 0xFF
|
||||
|
||||
extern struct Task gTasks[];
|
||||
|
||||
static void InsertTask(u8 newTaskId);
|
||||
static u8 FindFirstActiveTask();
|
||||
|
||||
void ResetTasks()
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < NUM_TASKS; i++)
|
||||
{
|
||||
gTasks[i].isActive = FALSE;
|
||||
gTasks[i].func = TaskDummy;
|
||||
gTasks[i].prev = i;
|
||||
gTasks[i].next = i + 1;
|
||||
gTasks[i].priority = -1;
|
||||
memset(gTasks[i].data, 0, sizeof(gTasks[i].data));
|
||||
}
|
||||
|
||||
gTasks[0].prev = HEAD_SENTINEL;
|
||||
gTasks[NUM_TASKS - 1].next = TAIL_SENTINEL;
|
||||
}
|
||||
|
||||
u8 CreateTask(TaskFunc func, u8 priority)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < NUM_TASKS; i++)
|
||||
{
|
||||
if (!gTasks[i].isActive)
|
||||
{
|
||||
gTasks[i].func = func;
|
||||
gTasks[i].priority = priority;
|
||||
InsertTask(i);
|
||||
memset(gTasks[i].data, 0, sizeof(gTasks[i].data));
|
||||
gTasks[i].isActive = TRUE;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NONMATCHING
|
||||
static void InsertTask(u8 newTaskId)
|
||||
{
|
||||
u8 taskId = FindFirstActiveTask();
|
||||
|
||||
if (taskId == NUM_TASKS)
|
||||
{
|
||||
// The new task is the only task.
|
||||
gTasks[newTaskId].prev = HEAD_SENTINEL;
|
||||
gTasks[newTaskId].next = TAIL_SENTINEL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (gTasks[newTaskId].priority < gTasks[taskId].priority)
|
||||
{
|
||||
// We've found a task with a higher priority value,
|
||||
// so we insert the new task before it.
|
||||
gTasks[newTaskId].prev = gTasks[taskId].prev;
|
||||
gTasks[newTaskId].next = taskId;
|
||||
|
||||
if (gTasks[taskId].prev != HEAD_SENTINEL)
|
||||
gTasks[gTasks[taskId].prev].next = newTaskId;
|
||||
|
||||
gTasks[taskId].prev = newTaskId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gTasks[taskId].next != TAIL_SENTINEL)
|
||||
taskId = gTasks[taskId].next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// We've reached the end.
|
||||
gTasks[newTaskId].prev = taskId;
|
||||
gTasks[newTaskId].next = gTasks[taskId].next;
|
||||
gTasks[taskId].next = newTaskId;
|
||||
}
|
||||
#else
|
||||
__attribute__((naked))
|
||||
static void InsertTask(u8 newTaskId)
|
||||
{
|
||||
asm("push {r4, r5, r6, r7, lr}\n\
|
||||
mov r7, r8\n\
|
||||
push {r7}\n\
|
||||
lsl r0, r0, #24\n\
|
||||
lsr r4, r0, #24\n\
|
||||
bl FindFirstActiveTask\n\
|
||||
lsl r0, r0, #24\n\
|
||||
lsr r1, r0, #24\n\
|
||||
cmp r1, #16\n\
|
||||
bne .LInsertTask_foundActiveTask\n\
|
||||
ldr r1, .LInsertTask_gTasks1\n\
|
||||
lsl r0, r4, #2\n\
|
||||
add r0, r0, r4\n\
|
||||
lsl r0, r0, #3\n\
|
||||
add r0, r0, r1\n\
|
||||
mov r1, #254\n\
|
||||
strb r1, [r0, #5]\n\
|
||||
mov r1, #255\n\
|
||||
strb r1, [r0, #6]\n\
|
||||
b .LInsertTask_done\n\
|
||||
.align 2\n\
|
||||
.LInsertTask_gTasks1:\n\
|
||||
.word gTasks\n\
|
||||
.LInsertTask_foundActiveTask:\n\
|
||||
ldr r6, .LInsertTask_gTasks2\n\
|
||||
lsl r0, r4, #2\n\
|
||||
mov r12, r0\n\
|
||||
mov r8, r6\n\
|
||||
add r0, r0, r4\n\
|
||||
lsl r0, r0, #3\n\
|
||||
add r2, r0, r6\n\
|
||||
.LInsertTask_loop:\n\
|
||||
lsl r0, r1, #2\n\
|
||||
add r0, r0, r1\n\
|
||||
lsl r5, r0, #3\n\
|
||||
mov r7, r8\n\
|
||||
add r3, r5, r7\n\
|
||||
ldrb r0, [r2, #7]\n\
|
||||
ldrb r7, [r3, #7]\n\
|
||||
cmp r0, r7\n\
|
||||
bcs .LInsertTask_next\n\
|
||||
ldrb r0, [r3, #5]\n\
|
||||
strb r0, [r2, #5]\n\
|
||||
strb r1, [r2, #6]\n\
|
||||
ldrb r0, [r3, #5]\n\
|
||||
cmp r0, #254\n\
|
||||
beq .LInsertTask_insertAtHead\n\
|
||||
add r1, r0, #0\n\
|
||||
lsl r0, r1, #2\n\
|
||||
add r0, r0, r1\n\
|
||||
lsl r0, r0, #3\n\
|
||||
add r0, r0, r8\n\
|
||||
strb r4, [r0, #6]\n\
|
||||
.LInsertTask_insertAtHead:\n\
|
||||
strb r4, [r3, #5]\n\
|
||||
b .LInsertTask_done\n\
|
||||
.align 2\n\
|
||||
.LInsertTask_gTasks2:\n\
|
||||
.word gTasks\n\
|
||||
.LInsertTask_next:\n\
|
||||
ldrb r0, [r3, #6]\n\
|
||||
cmp r0, #255\n\
|
||||
beq .LInsertTask_insertAtTail\n\
|
||||
add r1, r0, #0\n\
|
||||
b .LInsertTask_loop\n\
|
||||
.LInsertTask_insertAtTail:\n\
|
||||
mov r2, r12\n\
|
||||
add r0, r2, r4\n\
|
||||
lsl r0, r0, #3\n\
|
||||
add r0, r0, r6\n\
|
||||
strb r1, [r0, #5]\n\
|
||||
add r2, r5, r6\n\
|
||||
ldrb r1, [r2, #6]\n\
|
||||
strb r1, [r0, #6]\n\
|
||||
strb r4, [r2, #6]\n\
|
||||
.LInsertTask_done:\n\
|
||||
pop {r3}\n\
|
||||
mov r8, r3\n\
|
||||
pop {r4, r5, r6, r7}\n\
|
||||
pop {r0}\n\
|
||||
bx r0\n");
|
||||
}
|
||||
#endif // NONMATCHING
|
||||
|
||||
void DestroyTask(u8 taskId)
|
||||
{
|
||||
if (gTasks[taskId].isActive)
|
||||
{
|
||||
gTasks[taskId].isActive = FALSE;
|
||||
|
||||
if (gTasks[taskId].prev == HEAD_SENTINEL)
|
||||
{
|
||||
if (gTasks[taskId].next != TAIL_SENTINEL)
|
||||
gTasks[gTasks[taskId].next].prev = HEAD_SENTINEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gTasks[taskId].next == TAIL_SENTINEL)
|
||||
{
|
||||
gTasks[gTasks[taskId].prev].next = TAIL_SENTINEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gTasks[gTasks[taskId].prev].next = gTasks[taskId].next;
|
||||
gTasks[gTasks[taskId].next].prev = gTasks[taskId].prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunTasks()
|
||||
{
|
||||
u8 taskId = FindFirstActiveTask();
|
||||
|
||||
if (taskId != NUM_TASKS)
|
||||
{
|
||||
do
|
||||
{
|
||||
gTasks[taskId].func(taskId);
|
||||
taskId = gTasks[taskId].next;
|
||||
} while (taskId != TAIL_SENTINEL);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 FindFirstActiveTask()
|
||||
{
|
||||
u8 taskId;
|
||||
|
||||
for (taskId = 0; taskId < NUM_TASKS; taskId++)
|
||||
if (gTasks[taskId].isActive == TRUE && gTasks[taskId].prev == HEAD_SENTINEL)
|
||||
break;
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
void TaskDummy(u8 taskId)
|
||||
{
|
||||
}
|
||||
|
||||
#define TASK_DATA_OP(taskId, offset, op) \
|
||||
{ \
|
||||
u32 tasksAddr = (u32)gTasks; \
|
||||
u32 addr = taskId * sizeof(struct Task) + offset; \
|
||||
u32 dataAddr = tasksAddr + offsetof(struct Task, data); \
|
||||
addr += dataAddr; \
|
||||
op; \
|
||||
}
|
||||
|
||||
void SetTaskFuncWithFollowupFunc(u8 taskId, TaskFunc func, TaskFunc followupFunc)
|
||||
{
|
||||
TASK_DATA_OP(taskId, 28, *((u16 *)addr) = (u32)followupFunc)
|
||||
TASK_DATA_OP(taskId, 30, *((u16 *)addr) = (u32)followupFunc >> 16)
|
||||
gTasks[taskId].func = func;
|
||||
}
|
||||
|
||||
void SwitchTaskToFollowupFunc(u8 taskId)
|
||||
{
|
||||
s32 func;
|
||||
|
||||
gTasks[taskId].func = NULL;
|
||||
|
||||
TASK_DATA_OP(taskId, 28, func = *((u16 *)addr))
|
||||
TASK_DATA_OP(taskId, 30, func |= *((s16 *)addr) << 16)
|
||||
|
||||
gTasks[taskId].func = (TaskFunc)func;
|
||||
}
|
||||
|
||||
bool8 FuncIsActiveTask(TaskFunc func)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < NUM_TASKS; i++)
|
||||
if (gTasks[i].isActive == TRUE && gTasks[i].func == func)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u8 FindTaskIdByFunc(TaskFunc func)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < NUM_TASKS; i++)
|
||||
if (gTasks[i].isActive == TRUE && gTasks[i].func == func)
|
||||
return (u8)i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
u8 GetTaskCount()
|
||||
{
|
||||
u8 i;
|
||||
u8 count = 0;
|
||||
|
||||
for (i = 0; i < NUM_TASKS; i++)
|
||||
if (gTasks[i].isActive == TRUE)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user