summaryrefslogtreecommitdiff
path: root/arm9/lib/src
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/lib/src')
-rw-r--r--arm9/lib/src/OS_context.c92
-rw-r--r--arm9/lib/src/OS_init.c2
-rw-r--r--arm9/lib/src/OS_message.c123
-rw-r--r--arm9/lib/src/OS_valarm.c30
-rw-r--r--arm9/lib/src/OS_vramExclusive.c88
5 files changed, 333 insertions, 2 deletions
diff --git a/arm9/lib/src/OS_context.c b/arm9/lib/src/OS_context.c
new file mode 100644
index 00000000..38b722ba
--- /dev/null
+++ b/arm9/lib/src/OS_context.c
@@ -0,0 +1,92 @@
+#include "OS_context.h"
+#include "consts.h"
+#include "function_target.h"
+
+ARM_FUNC asm void OS_InitContext(register OSContext *context, register u32 newpc, register u32 newsp)
+{
+ add newpc, newpc, #4
+ str newpc, [context, #0x40]
+
+ str newsp, [context, #0x44]
+ sub newsp, newsp, #HW_SVC_STACK_SIZE
+
+ tst newsp, #4
+ subne newsp, newsp, #4
+ str newsp, [context, #0x38]
+
+ ands r1, newpc, #1
+ movne r1, #0x3f
+ moveq r1, #0x1f
+ str r1, [context]
+
+ mov r1, #0
+ str r1, [context, #0x4]
+ str r1, [context, #0x8]
+ str r1, [context, #0xc]
+ str r1, [context, #0x10]
+ str r1, [context, #0x14]
+ str r1, [context, #0x18]
+ str r1, [context, #0x1c]
+ str r1, [context, #0x20]
+ str r1, [context, #0x24]
+ str r1, [context, #0x28]
+ str r1, [context, #0x2c]
+ str r1, [context, #0x30]
+ str r1, [context, #0x34]
+ str r1, [context, #0x3c]
+
+ bx lr
+}
+
+ARM_FUNC asm BOOL OS_SaveContext(register OSContext* context)
+{
+ stmfd sp!, {lr, r0}
+ add r0, r0, #0x48
+ ldr r1, =CP_SaveContext
+ blx r1
+ ldmfd sp!, {lr, r0}
+
+ add r1, r0, #0
+
+ mrs r2, cpsr
+ str r2, [r1], #0x4
+
+ mov r0, #0xd3
+ msr cpsr_c, r0
+ str sp, [r1, #0x40]
+ msr cpsr_c, r2
+
+ mov r0, #1
+ stmia r1, {r0-r14}
+ add r0, pc, #8
+ str r0, [r1, #0x3c]
+
+ mov r0, #0
+ bx lr
+}
+
+ARM_FUNC asm void OS_LoadContext(register OSContext* context)
+{
+ stmfd sp!, {lr, r0}
+ add r0, r0, #0x48
+
+ ldr r1, =CPi_RestoreContext
+ blx r1
+ ldmfd sp!, {lr, r0}
+
+ mrs r1, cpsr
+ bic r1, r1, #HW_PSR_CPU_MODE_MASK
+ orr r1, r1, #0xd3
+ msr cpsr_c, r1
+
+ ldr r1, [r0], #0x4
+ msr spsr_fsxc, r1
+
+ ldr sp, [r0, #0x40]
+
+ ldr lr, [r0, #0x3c]
+ ldmia r0, {r0-r14}^
+ nop
+
+ subs pc, lr, #4
+}
diff --git a/arm9/lib/src/OS_init.c b/arm9/lib/src/OS_init.c
index c93b1584..5bd435e7 100644
--- a/arm9/lib/src/OS_init.c
+++ b/arm9/lib/src/OS_init.c
@@ -3,8 +3,6 @@
extern void PXI_Init(void);
extern void MI_Init(void);
-extern void OS_InitVAlarm(void);
-extern void OSi_InitVramExclusive(void);
extern void CTRDG_Init(void);
extern void CARD_Init(void);
extern void PM_Init(void);
diff --git a/arm9/lib/src/OS_message.c b/arm9/lib/src/OS_message.c
new file mode 100644
index 00000000..9f7beb8e
--- /dev/null
+++ b/arm9/lib/src/OS_message.c
@@ -0,0 +1,123 @@
+#include "OS_message.h"
+#include "function_target.h"
+#include "OS_system.h"
+
+ARM_FUNC void OS_InitMessageQueue(OSMessageQueue *mq, OSMessage *msgArray, s32 msgCount)
+{
+ OS_InitThreadQueue(&mq->queueSend);
+ OS_InitThreadQueue(&mq->queueReceive);
+ mq->msgArray = msgArray;
+ mq->msgCount = msgCount;
+ mq->firstIndex = 0;
+ mq->usedCount = 0;
+}
+
+ARM_FUNC BOOL OS_SendMessage(OSMessageQueue *mq, OSMessage msg, s32 flags)
+{
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ while (mq->msgCount <= mq->usedCount)
+ {
+ if (!(flags & OS_MESSAGE_BLOCK))
+ {
+ (void)OS_RestoreInterrupts(enabled);
+ return FALSE;
+ }
+ else
+ {
+ OS_SleepThread(&mq->queueSend);
+ }
+ }
+
+ s32 lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount;
+ mq->msgArray[lastIndex] = msg;
+ mq->usedCount++;
+
+ OS_WakeupThread(&mq->queueReceive);
+
+ (void)OS_RestoreInterrupts(enabled);
+ return TRUE;
+}
+
+ARM_FUNC BOOL OS_ReceiveMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags)
+{
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ while (mq->usedCount == 0)
+ {
+ if (!(flags & OS_MESSAGE_BLOCK))
+ {
+ (void)OS_RestoreInterrupts(enabled);
+ return FALSE;
+ }
+ else
+ {
+ OS_SleepThread(&mq->queueReceive);
+ }
+ }
+
+ if (msg != NULL)
+ {
+ *msg = mq->msgArray[mq->firstIndex];
+ }
+ mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount;
+ mq->usedCount--;
+
+ OS_WakeupThread(&mq->queueSend);
+
+ (void)OS_RestoreInterrupts(enabled);
+ return TRUE;
+}
+
+ARM_FUNC BOOL OS_JamMessage(OSMessageQueue *mq, OSMessage msg, s32 flags)
+{
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ while (mq->msgCount <= mq->usedCount)
+ {
+ if (!(flags & OS_MESSAGE_BLOCK))
+ {
+ (void)OS_RestoreInterrupts(enabled);
+ return FALSE;
+ }
+ else
+ {
+ OS_SleepThread(&mq->queueSend);
+ }
+ }
+
+ mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount;
+ mq->msgArray[mq->firstIndex] = msg;
+ mq->usedCount++;
+
+ OS_WakeupThread(&mq->queueReceive);
+
+ (void)OS_RestoreInterrupts(enabled);
+ return TRUE;
+}
+
+ARM_FUNC BOOL OS_ReadMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags)
+{
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ while (mq->usedCount == 0)
+ {
+ if (!(flags & OS_MESSAGE_BLOCK))
+ {
+ (void)OS_RestoreInterrupts(enabled);
+ return FALSE;
+ }
+ else
+ {
+ OS_SleepThread(&mq->queueReceive);
+ }
+ }
+
+ if (msg != NULL)
+ {
+ *msg = mq->msgArray[mq->firstIndex];
+ }
+
+ (void)OS_RestoreInterrupts(enabled);
+ return TRUE;
+}
diff --git a/arm9/lib/src/OS_valarm.c b/arm9/lib/src/OS_valarm.c
new file mode 100644
index 00000000..37329147
--- /dev/null
+++ b/arm9/lib/src/OS_valarm.c
@@ -0,0 +1,30 @@
+#include "OS_valarm.h"
+#include "function_target.h"
+#include "OS_interrupt.h"
+
+static struct OSiVAlarmQueue
+{
+ OSVAlarm *head;
+ OSVAlarm *tail;
+} OSi_VAlarmQueue;
+
+static u16 OSi_UseVAlarm = FALSE;
+
+static s32 OSi_VFrameCount;
+static s32 OSi_PreviousVCount;
+
+ARM_FUNC void OS_InitVAlarm(void)
+{
+ if (!OSi_UseVAlarm)
+ {
+ OSi_UseVAlarm = TRUE;
+
+ OSi_VAlarmQueue.head = NULL;
+ OSi_VAlarmQueue.tail = NULL;
+
+ (void)OS_DisableIrqMask(OS_IE_V_COUNT);
+
+ OSi_VFrameCount = 0;
+ OSi_PreviousVCount = 0;
+ }
+}
diff --git a/arm9/lib/src/OS_vramExclusive.c b/arm9/lib/src/OS_vramExclusive.c
new file mode 100644
index 00000000..5ce10f4a
--- /dev/null
+++ b/arm9/lib/src/OS_vramExclusive.c
@@ -0,0 +1,88 @@
+#include "OS_vramExclusive.h"
+#include "function_target.h"
+#include "OS_system.h"
+
+static u32 OSi_vramExclusive;
+static u16 OSi_vramLockId[9];
+
+static u32 OsCountZeroBits(register u32 bitmap);
+
+ARM_FUNC static asm u32 OsCountZeroBits(register u32 bitmap)
+{
+ clz r0, r0
+ bx lr
+}
+
+ARM_FUNC void OSi_InitVramExclusive(void)
+{
+ OSi_vramExclusive = 0x0000;
+
+ for (s32 i = 0; i < 9; i++)
+ {
+ OSi_vramLockId[i] = 0;
+ }
+}
+
+ARM_FUNC BOOL OSi_TryLockVram(u16 bank, u16 lockId)
+{
+ u32 workMap;
+ s32 zeroBits;
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ workMap = (u32)(bank & OSi_vramExclusive);
+ while (TRUE)
+ {
+ zeroBits = (s32)(31 - OsCountZeroBits(workMap));
+ if (zeroBits < 0)
+ {
+ break;
+ }
+ workMap &= ~(0x00000001 << zeroBits);
+ if (OSi_vramLockId[zeroBits] != lockId)
+ {
+ (void)OS_RestoreInterrupts(enabled);
+ return FALSE;
+ }
+ }
+
+ workMap = (u32)(bank & 0x01ff);
+ while (TRUE)
+ {
+ zeroBits = (s32)(31 - OsCountZeroBits(workMap));
+ if (zeroBits < 0)
+ {
+ break;
+ }
+ workMap &= ~(0x00000001 << zeroBits);
+ OSi_vramLockId[zeroBits] = lockId;
+ OSi_vramExclusive |= (0x00000001 << zeroBits);
+ }
+
+ (void)OS_RestoreInterrupts(enabled);
+ return TRUE;
+}
+
+ARM_FUNC void OSi_UnlockVram(u16 bank, u16 lockId)
+{
+ u32 workMap;
+ s32 zeroBits;
+ OSIntrMode enabled = OS_DisableInterrupts();
+
+ workMap = (u32)(bank & OSi_vramExclusive & 0x01ff);
+ while (TRUE)
+ {
+ zeroBits = (s32)(31- OsCountZeroBits((u32)workMap));
+ if (zeroBits < 0)
+ {
+ break;
+ }
+ workMap &= ~(0x00000001 << zeroBits);
+ if (OSi_vramLockId[zeroBits] == lockId)
+ {
+ OSi_vramLockId[zeroBits] = 0;
+ OSi_vramExclusive &= ~(0x00000001 << zeroBits);
+ }
+ }
+
+ (void)OS_RestoreInterrupts(enabled);
+}