diff options
Diffstat (limited to 'arm9/lib')
-rw-r--r-- | arm9/lib/include/OS_context.h | 6 | ||||
-rw-r--r-- | arm9/lib/include/OS_init.h | 3 | ||||
-rw-r--r-- | arm9/lib/include/OS_interrupt.h | 1 | ||||
-rw-r--r-- | arm9/lib/include/OS_message.h | 28 | ||||
-rw-r--r-- | arm9/lib/include/OS_valarm.h | 25 | ||||
-rw-r--r-- | arm9/lib/include/OS_vramExclusive.h | 10 | ||||
-rw-r--r-- | arm9/lib/include/gx.h | 2 | ||||
-rw-r--r-- | arm9/lib/include/registers.h | 1 | ||||
-rw-r--r-- | arm9/lib/src/OS_context.c | 92 | ||||
-rw-r--r-- | arm9/lib/src/OS_init.c | 2 | ||||
-rw-r--r-- | arm9/lib/src/OS_message.c | 123 | ||||
-rw-r--r-- | arm9/lib/src/OS_valarm.c | 30 | ||||
-rw-r--r-- | arm9/lib/src/OS_vramExclusive.c | 88 |
13 files changed, 405 insertions, 6 deletions
diff --git a/arm9/lib/include/OS_context.h b/arm9/lib/include/OS_context.h index 7a58a2b1..7c25ce2e 100644 --- a/arm9/lib/include/OS_context.h +++ b/arm9/lib/include/OS_context.h @@ -15,8 +15,8 @@ typedef struct OSContext CPContext cp_context; } OSContext; -extern u32 OS_SaveContext(OSContext *context); -extern void OS_LoadContext(OSContext *context); -extern void OS_InitContext(OSContext *context, u32 func, u32 stack); +void OS_InitContext(register OSContext *context, register u32 newpc, register u32 newsp); +BOOL OS_SaveContext(OSContext *context); +void OS_LoadContext(OSContext *context); #endif //POKEDIAMOND_OS_CONTEXT_H diff --git a/arm9/lib/include/OS_init.h b/arm9/lib/include/OS_init.h index 499c9f6c..f0b80220 100644 --- a/arm9/lib/include/OS_init.h +++ b/arm9/lib/include/OS_init.h @@ -24,6 +24,9 @@ #include "OS_interrupt.h" #include "OS_reset.h" #include "OS_exception.h" +#include "OS_message.h" +#include "OS_valarm.h" +#include "OS_vramExclusive.h" void OS_Init(void); diff --git a/arm9/lib/include/OS_interrupt.h b/arm9/lib/include/OS_interrupt.h index d84cae00..893e6d65 100644 --- a/arm9/lib/include/OS_interrupt.h +++ b/arm9/lib/include/OS_interrupt.h @@ -4,6 +4,7 @@ #include "consts.h" #include "nitro/OS_interrupt_shared.h" +#define OS_IE_V_COUNT (1UL << REG_OS_IE_VE_SHIFT) #define OS_IE_TIMER0 (1UL << REG_OS_IE_T0_SHIFT) #define OS_IE_TIMER1 (1UL << REG_OS_IE_T1_SHIFT) diff --git a/arm9/lib/include/OS_message.h b/arm9/lib/include/OS_message.h new file mode 100644 index 00000000..2dc26d50 --- /dev/null +++ b/arm9/lib/include/OS_message.h @@ -0,0 +1,28 @@ +#ifndef POKEDIAMOND_OS_MESSAGE_H +#define POKEDIAMOND_OS_MESSAGE_H + +#include "nitro/types.h" +#include "OS_thread.h" + +typedef void *OSMessage; + +typedef struct OSMessageQueue +{ + OSThreadQueue queueSend; + OSThreadQueue queueReceive; + OSMessage *msgArray; + s32 msgCount; + s32 firstIndex; + s32 usedCount; +} OSMessageQueue; + +#define OS_MESSAGE_NOBLOCK 0 +#define OS_MESSAGE_BLOCK 1 + +void OS_InitMessageQueue(OSMessageQueue *mq, OSMessage *msgArray, s32 msgCount); +BOOL OS_SendMessage(OSMessageQueue *mq, OSMessage msg, s32 flags); +BOOL OS_ReceiveMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags); +BOOL OS_JamMessage(OSMessageQueue *mq, OSMessage msg, s32 flags); +BOOL OS_ReadMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags); + +#endif //POKEDIAMOND_OS_MESSAGE_H diff --git a/arm9/lib/include/OS_valarm.h b/arm9/lib/include/OS_valarm.h new file mode 100644 index 00000000..b4850f9d --- /dev/null +++ b/arm9/lib/include/OS_valarm.h @@ -0,0 +1,25 @@ +#ifndef POKEDIAMOND_OS_VALARM_H +#define POKEDIAMOND_OS_VALARM_H + +#include "nitro/types.h" +#include "OS_alarm.h" + +typedef struct OSiVAlarm OSVAlarm; +struct OSiVAlarm +{ + OSAlarmHandler handler; + void *arg; + u32 tag; + u32 frame; + s16 fire; + s16 delay; + OSVAlarm *prev; + OSVAlarm *next; + BOOL period; + BOOL finish; + BOOL canceled; +}; + +void OS_InitVAlarm(void); + +#endif //POKEDIAMOND_OS_VALARM_H diff --git a/arm9/lib/include/OS_vramExclusive.h b/arm9/lib/include/OS_vramExclusive.h new file mode 100644 index 00000000..d7c3ef92 --- /dev/null +++ b/arm9/lib/include/OS_vramExclusive.h @@ -0,0 +1,10 @@ +#ifndef POKEDIAMOND_OS_VRAMEXCLUSIVE_H +#define POKEDIAMOND_OS_VRAMEXCLUSIVE_H + +#include "nitro/types.h" + +void OSi_InitVramExclusive(void); +BOOL OSi_TryLockVram(u16 bank, u16 lockId); +void OSi_UnlockVram(u16 bank, u16 lockId); + +#endif //POKEDIAMOND_OS_VRAMEXCLUSIVE_H diff --git a/arm9/lib/include/gx.h b/arm9/lib/include/gx.h index bc89aa04..f9478851 100644 --- a/arm9/lib/include/gx.h +++ b/arm9/lib/include/gx.h @@ -4,6 +4,7 @@ #include "fx.h" #include "MI_memory.h" #include "MI_dma.h" +#include "OS_vramExclusive.h" //temporary while other files aren't decompiled @@ -11,7 +12,6 @@ void GXi_NopClearFifo128_(void *); void MI_Copy16B(const void *, void *); void MI_Copy64B(void *src, void *dst); void MIi_CpuCopy32(const void *src, void *dst, u32 size); -void OSi_UnlockVram(u16, u16); #include "GXcommon.h" #include "GX_struct_2d.h" diff --git a/arm9/lib/include/registers.h b/arm9/lib/include/registers.h index 6bfb52ac..b2915f8c 100644 --- a/arm9/lib/include/registers.h +++ b/arm9/lib/include/registers.h @@ -345,6 +345,7 @@ #define reg_MI_MCD1 (*(REGType32v *)0x4100010) #define reg_CARD_DATA (*(REGType32v *)0x4100010) //? +#define REG_OS_IE_VE_SHIFT 2 #define REG_OS_IE_T0_SHIFT 3 #define REG_OS_IE_T1_SHIFT 4 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); +} |