summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartmists <martmists@gmail.com>2020-04-23 14:28:27 +0200
committerMartmists <martmists@gmail.com>2020-04-23 14:28:27 +0200
commit4e2316c01dea50716173a97f36228d2b9607964f (patch)
treecca579f8e74b24f1f95ec2dc2e184b156f26be44
parent9b3107c478c9f39c17ef4171c9c5330adcb1385a (diff)
Estimate file boundaries for os_alloc
-rw-r--r--include/nitro/os.c223
-rw-r--r--include/nitro/os.h60
-rw-r--r--include/nitro/os_alloc.c517
-rw-r--r--include/nitro/os_alloc.h79
-rw-r--r--include/nitro/os_system.c34
-rw-r--r--include/nitro/os_system.h39
6 files changed, 702 insertions, 250 deletions
diff --git a/include/nitro/os.c b/include/nitro/os.c
index 3ecffb34..2531a636 100644
--- a/include/nitro/os.c
+++ b/include/nitro/os.c
@@ -3,199 +3,36 @@
//
#include "os.h"
-#include "consts.h"
-OSProcMode OS_GetProcMode() {
- __asm {
- mrs r0, cpsr
- and r0, r0, #HW_PSR_CPU_MODE_MASK
- bx lr
- }
+extern void PXI_Init();
+extern void OS_InitLock();
+extern void OS_InitIrqTable();
+extern void OS_SetIrqStackChecker();
+extern void OS_InitException();
+extern void MI_Init();
+extern void OS_InitVAlarm();
+extern void OSi_InitVramExclusive();
+extern void OS_InitThread();
+extern void OS_InitReset();
+extern void CTRDG_Init();
+extern void CARD_Init();
+extern void PM_Init();
+
+void OS_Init(void) {
+ OS_InitArena();
+ PXI_Init();
+ OS_InitLock();
+ OS_InitArenaEx();
+ OS_InitIrqTable();
+ OS_SetIrqStackChecker();
+ OS_InitException();
+ MI_Init();
+ OS_InitVAlarm();
+ OSi_InitVramExclusive();
+ OS_InitThread();
+ OS_InitReset();
+ CTRDG_Init();
+ CARD_Init();
+ PM_Init();
}
-OSIntrMode OS_DisableInterrupts() {
- __asm {
- mrs r0, cpsr
- orr r1, r0, #HW_PSR_IRQ_DISABLE
- msr cpsr_c, r1
- and r0, r0, #HW_PSR_IRQ_DISABLE
- bx lr
- }
-}
-
-OSIntrMode OS_RestoreInterrupts(OSIntrMode state) {
- __asm {
- mrs r1, cpsr
- bic r2, r1, #HW_PSR_IRQ_DISABLE
- orr r2, r2, r0
- msr cpsr_c, r2
- and r0, r1, #HW_PSR_IRQ_DISABLE
- bx lr
- }
-}
-
-void* OS_AllocFromArenaLo(OSArenaId id, u32 size, u32 align) {
-#ifdef MATCH_ASM
- __asm {
- stmdb sp!,{ r4 r5 r6 r7 lr }
- sub sp,sp,#0x4
- mov r7,r0
- mov r6,r1
- mov r5,r2
- bl OS_GetArenaLo
- cmp r0,#0x0
- addeq sp,sp,#0x4
- moveq r0,#0x0
- ldmeqia sp!,{ r4 r5 r6 r7 lr }
- bxeq lr
- add r0,r0,r5
- sub r1,r5,#0x1
- mvn r2,r1
- sub r0,r0,#0x1
- and r4,r2,r0
- add r0,r4,r6
- add r0,r0,r5
- sub r1,r0,#0x1
- mov r0,r7
- and r5,r2,r1
- bl OS_GetArenaHi
- cmp r5,r0
- addhi sp,sp,#0x4
- movhi r0,#0x0
- ldmhiia sp!,{ r4 r5 r6 r7 lr }
- bxhi lr
- mov r0,r7
- mov r1,r5
- bl OS_SetArenaLo
- mov r0,r4
- add sp,sp,#0x4
- ldmia sp!,{ r4 r5 r6 r7 lr }
- bx lr
- }
-#else
- void* ptr;
- u8* arenaLo;
- ptr = OS_GetArenaLo(id);
- if (!ptr) {
- return NULL;
- }
- arenaLo = ptr = (void *)OSi_ROUND(ptr, align);
- arenaLo += size;
- arenaLo = (u8 *)OSi_ROUND(arenaLo, align);
- if (arenaLo > (u8*)OS_GetArenaHi(id)) {
- return NULL;
- }
- OS_SetArenaLo(id, arenaLo);
-
- return ptr;
-#endif
-}
-
-void* OS_AllocFromArenaHi(OSArenaId id, u32 size, u32 align) {
-#ifdef MATCH_ASM
- __asm {
- stmdb sp!,{ r4 r5 r6 lr }
- mov r4,r0
- mov r6,r1
- mov r5,r2
- bl OS_GetArenaHi
- cmp r0,#0x0
- moveq r0,#0x0
- ldmeqia sp!,{ r4 r5 r6 lr }
- bxeq lr
- sub r1,r5,#0x1
- mvn r2,r1
- and r0,r0,r2
- sub r1,r0,r6
- mov r0,r4
- and r5,r1,r2
- bl OS_GetArenaLo
- cmp r5,r0
- movcc r0,#0x0
- ldmccia sp!,{ r4 r5 r6 lr }
- bxcc lr
- mov r0,r4
- mov r1,r5
- bl OS_SetArenaHi
- mov r0,r5
- ldmia sp!,{ r4 r5 r6 lr }
- bx lr
- };
-#else
- void* ptr;
- u8* arenaHi;
-
- arenaHi = OS_GetArenaHi(id);
- if (!arenaHi) {
- return NULL;
- }
-
- arenaHi = (u8 *)OSi_TRUNC(arenaHi, align);
- arenaHi -= size;
- arenaHi = ptr = (void *)OSi_TRUNC(arenaHi, align);
-
- if (arenaHi < (u8*)OS_GetArenaLo(id)) {
- return NULL;
- }
-
- OS_SetArenaHi(id, arenaHi);
-
- return ptr;
-#endif
-}
-
-void OS_SetArenaHi(OSArenaId id, void *newHi) {
-#ifdef MATCH_ASM
- __asm {
- mov r0,r0, lsl #0x2
- add r0,r0,#0x2700000
- add r0,r0,#0xff000
- str r1,[r0,#0xdc4]
- bx lr
- }
-#else
- OSi_GetArenaInfo().lo[id] = newHi;
-#endif
-}
-
-void OS_SetArenaLo(OSArenaId id, void *newLo) {
-#ifdef MATCH_ASM
- __asm {
- mov r0,r0, lsl #0x2
- add r0,r0,#0x2700000
- add r0,r0,#0xff000
- str r1,[r0,#0xda0]
- bx lr
- }
-#else
- OSi_GetArenaInfo().lo[id] = newLo;
-#endif
-}
-
-void* OS_GetArenaHi(OSArenaId id) {
-#ifdef MATCH_ASM
- __asm {
- mov r0,r0, lsl #0x2
- add r0,r0,#0x2700000
- add r0,r0,#0xff000
- ldr r0,[r0,#0xdc4]
- bx lr
- }
-#else
- return OSi_GetArenaInfo().hi[id];
-#endif
-}
-
-void* OS_GetArenaLo(OSArenaId id) {
-#ifdef MATCH_ASM
- __asm {
- mov r0,r0, lsl #0x2
- add r0,r0,#0x2700000
- add r0,r0,#0xff000
- ldr r0,[r0,#0xda0]
- bx lr
- }
-#else
- return OSi_GetArenaInfo().lo[id];
-#endif
-}
diff --git a/include/nitro/os.h b/include/nitro/os.h
index 84425631..f1422647 100644
--- a/include/nitro/os.h
+++ b/include/nitro/os.h
@@ -7,63 +7,9 @@
#include "types.h"
#include "consts.h"
+#include "os_alloc.h"
+#include "os_system.h"
-typedef enum {
- OS_PROCMODE_USER=16,
- OS_PROCMODE_FIQ=17,
- OS_PROCMODE_IRQ=18,
- OS_PROCMODE_SVC=19,
- OS_PROCMODE_ABORT=23,
- OS_PROCMODE_UNDEF=27,
- OS_PROCMODE_SYS=31
-} OSProcMode;
-
-typedef enum {
- OS_ARENA_MAIN = 0,
- OS_ARENA_MAIN_SUBPRIV = 1,
- OS_ARENA_MAINEX = 2,
- OS_ARENA_ITCM = 3,
- OS_ARENA_DTCM = 4,
- OS_ARENA_SHARED = 5,
- OS_ARENA_WRAM_MAIN = 6,
- OS_ARENA_WRAM_SUB = 7,
- OS_ARENA_WRAM_SUBPRIV = 8,
- OS_ARENA_MAX = 9
-} OSArenaId;
-
-typedef enum {
- OS_INTRMODE_IRQ_DISABLE = HW_PSR_IRQ_DISABLE,
- OS_INTRMODE_IRQ_ENABLE = 0
-} OSIntrMode_Irq;
-
-typedef enum {
- OS_INTRMODE_FIQ_DISABLE = HW_PSR_FIQ_DISABLE,
- OS_INTRMODE_FIQ_ENABLE = 0
-} OSIntrMode_Fiq;
-
-typedef union {
- OSIntrMode_Fiq mode_fiq;
- OSIntrMode_Irq mode_irq;
-} OSIntrMode;
-
-typedef struct {
- void *lo[OS_ARENA_MAX];
- void *hi[OS_ARENA_MAX];
- u16 initialized;
- u8 padding[2];
-} OSArenaInfo;
-
-OSProcMode OS_GetProcMode();
-OSIntrMode OS_DisableInterrupts();
-OSIntrMode OS_RestoreInterrupts(register OSIntrMode state);
-
-void* OS_AllocFromArenaLo(OSArenaId id, u32 size, u32 align);
-void* OS_AllocFromArenaHi(OSArenaId id, u32 size, u32 align);
-
-void OS_SetArenaHi(OSArenaId id, void *newHi);
-void OS_SetArenaLo(OSArenaId id, void *newLo);
-
-void* OS_GetArenaHi(OSArenaId id);
-void* OS_GetArenaLo(OSArenaId id);
+void OS_Init();
#endif //POKEDIAMOND_OS_H
diff --git a/include/nitro/os_alloc.c b/include/nitro/os_alloc.c
new file mode 100644
index 00000000..022932ec
--- /dev/null
+++ b/include/nitro/os_alloc.c
@@ -0,0 +1,517 @@
+//
+// Created by mart on 4/23/20.
+//
+
+#include "os_alloc.h"
+#include "consts.h"
+#include "os_system.h"
+
+extern BOOL OSi_MainExArenaEnabled; // TODO: located at 0x021d36f4
+extern BOOL OSi_Initialized; // TODO: located at 0x021d36f0
+extern u32 OS_GetConsoleType();
+extern u32 OS_CONSOLE_SIZE_MASK;
+extern u32 OS_CONSOLE_SIZE_4MB;
+extern Cell* DLExtract(Cell* list, Cell* cell);
+extern Cell* DLInsert(Cell* list, Cell* cell);
+extern Cell* DLAddFront(Cell* list, Cell* cell);
+
+void* OS_AllocFromArenaHi(OSArenaId id, u32 size, u32 align) {
+#ifdef MATCH_ASM
+ __asm {
+ stmdb sp!,{ r4 r5 r6 lr }
+ mov r4,r0
+ mov r6,r1
+ mov r5,r2
+ bl OS_GetArenaHi
+ cmp r0,#0x0
+ moveq r0,#0x0
+ ldmeqia sp!,{ r4 r5 r6 lr }
+ bxeq lr
+ sub r1,r5,#0x1
+ mvn r2,r1
+ and r0,r0,r2
+ sub r1,r0,r6
+ mov r0,r4
+ and r5,r1,r2
+ bl OS_GetArenaLo
+ cmp r5,r0
+ movcc r0,#0x0
+ ldmccia sp!,{ r4 r5 r6 lr }
+ bxcc lr
+ mov r0,r4
+ mov r1,r5
+ bl OS_SetArenaHi
+ mov r0,r5
+ ldmia sp!,{ r4 r5 r6 lr }
+ bx lr
+ };
+#else
+ void* ptr;
+ u8* arenaHi;
+
+ arenaHi = OS_GetArenaHi(id);
+ if (!arenaHi) {
+ return NULL;
+ }
+
+ arenaHi = (u8 *)OSi_TRUNC(arenaHi, align);
+ arenaHi -= size;
+ arenaHi = ptr = (void *)OSi_TRUNC(arenaHi, align);
+
+ if (arenaHi < (u8*)OS_GetArenaLo(id)) {
+ return NULL;
+ }
+
+ OS_SetArenaHi(id, arenaHi);
+
+ return ptr;
+#endif
+}
+
+void* OS_AllocFromArenaLo(OSArenaId id, u32 size, u32 align) {
+#ifdef MATCH_ASM
+ __asm {
+ stmdb sp!,{ r4 r5 r6 r7 lr }
+ sub sp,sp,#0x4
+ mov r7,r0
+ mov r6,r1
+ mov r5,r2
+ bl OS_GetArenaLo
+ cmp r0,#0x0
+ addeq sp,sp,#0x4
+ moveq r0,#0x0
+ ldmeqia sp!,{ r4 r5 r6 r7 lr }
+ bxeq lr
+ add r0,r0,r5
+ sub r1,r5,#0x1
+ mvn r2,r1
+ sub r0,r0,#0x1
+ and r4,r2,r0
+ add r0,r4,r6
+ add r0,r0,r5
+ sub r1,r0,#0x1
+ mov r0,r7
+ and r5,r2,r1
+ bl OS_GetArenaHi
+ cmp r5,r0
+ addhi sp,sp,#0x4
+ movhi r0,#0x0
+ ldmhiia sp!,{ r4 r5 r6 r7 lr }
+ bxhi lr
+ mov r0,r7
+ mov r1,r5
+ bl OS_SetArenaLo
+ mov r0,r4
+ add sp,sp,#0x4
+ ldmia sp!,{ r4 r5 r6 r7 lr }
+ bx lr
+ }
+#else
+ void* ptr;
+ u8* arenaLo;
+ ptr = OS_GetArenaLo(id);
+ if (!ptr) {
+ return NULL;
+ }
+ arenaLo = ptr = (void *)OSi_ROUND(ptr, align);
+ arenaLo += size;
+ arenaLo = (u8 *)OSi_ROUND(arenaLo, align);
+ if (arenaLo > (u8*)OS_GetArenaHi(id)) {
+ return NULL;
+ }
+ OS_SetArenaLo(id, arenaLo);
+
+ return ptr;
+#endif
+}
+
+void OS_SetArenaLo(OSArenaId id, void* newLo) {
+#ifdef MATCH_ASM
+ __asm {
+ mov r0,r0, lsl #0x2
+ add r0,r0,#0x2700000
+ add r0,r0,#0xff000
+ str r1,[r0,#0xda0]
+ bx lr
+ }
+#else
+ OSi_GetArenaInfo().lo[id] = newLo;
+#endif
+}
+
+void OS_SetArenaHi(OSArenaId id, void* newHi) {
+#ifdef MATCH_ASM
+ __asm {
+ mov r0,r0, lsl #0x2
+ add r0,r0,#0x2700000
+ add r0,r0,#0xff000
+ str r1,[r0,#0xdc4]
+ bx lr
+ }
+#else
+ OSi_GetArenaInfo().lo[id] = newHi;
+#endif
+}
+
+void* OS_GetInitArenaLo(OSArenaId id) {
+#ifdef MATCH_ASM
+ __asm {
+ // TODO: idk how to do switch case stuff properly in asm
+ }
+#else
+ switch (id) {
+ case OS_ARENA_MAIN:
+ return (void *)0x0225ffa0;
+ case OS_ARENA_MAINEX:
+ if (!OSi_MainExArenaEnabled || (OS_GetConsoleType() & OS_CONSOLE_SIZE_MASK) == OS_CONSOLE_SIZE_4MB) {
+ return NULL;
+ } else {
+ return (void *)0x023e0000;
+ }
+ case OS_ARENA_ITCM:
+ return (void *)0x01ff8720;
+ case OS_ARENA_DTCM:
+ return (void *)0x027e0080;
+ case OS_ARENA_SHARED:
+ return (void *)0x027ff000;
+ case OS_ARENA_WRAM_MAIN:
+ return (void *)0x037f8000;
+ default:
+ return NULL;
+ }
+#endif
+}
+
+void* OS_GetInitArenaHi(OSArenaId id) {
+#ifdef MATCH_ASM
+ __asm {
+ // TODO: idk how to do switch case stuff properly in asm
+ }
+#else
+ switch (id) {
+ case OS_ARENA_MAIN:
+ return (void *)0x023e0000;
+ case OS_ARENA_MAINEX:
+ if (!OSi_MainExArenaEnabled || (OS_GetConsoleType() & OS_CONSOLE_SIZE_MASK) == OS_CONSOLE_SIZE_4MB) {
+ return (void *)0;
+ } else {
+ return (void *)0x02700000;
+ }
+ case OS_ARENA_ITCM:
+ return (void *)0x02000000;
+ case OS_ARENA_DTCM:
+ return (void *)0x027e0080;
+ case OS_ARENA_SHARED:
+ return (void *)0x027ff680;
+ case OS_ARENA_WRAM_MAIN:
+ return (void *)0x037f8000;
+ default:
+ return NULL;
+ }
+#endif
+}
+
+void* OS_GetArenaLo(OSArenaId id) {
+#ifdef MATCH_ASM
+ __asm {
+ mov r0,r0, lsl #0x2
+ add r0,r0,#0x2700000
+ add r0,r0,#0xff000
+ ldr r0,[r0,#0xda0]
+ bx lr
+ }
+#else
+ return OSi_GetArenaInfo().lo[id];
+#endif
+}
+
+void* OS_GetArenaHi(OSArenaId id) {
+#ifdef MATCH_ASM
+ __asm {
+ mov r0,r0, lsl #0x2
+ add r0,r0,#0x2700000
+ add r0,r0,#0xff000
+ ldr r0,[r0,#0xdc4]
+ bx lr
+ }
+#else
+ return OSi_GetArenaInfo().hi[id];
+#endif
+}
+
+void OS_InitArenaEx() {
+#ifdef MATCH_ASM
+ __asm {
+ stmdb sp!,{ lr }
+ sub sp,sp,#0x4
+ mov r0,#0x2
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x2
+ bl OS_SetArenaHi
+ mov r0,#0x2
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x2
+ bl OS_SetArenaLo
+ ldr r0,OSi_MainExArenaEnabled
+ ldr r0,[r0,#0x0]
+ cmp r0,#0x0
+ beq LAB_020cc5b8
+ bl OS_GetConsoleType
+ and r0,r0,#0x3
+ cmp r0,#0x1
+ addne sp,sp,#0x4
+ ldmneia sp!,{ lr }
+ bxne lr
+ LAB_020cc5b8:
+ ldr r0,#0200002b
+ bl OS_SetProtectionRegion1
+ ldr r0,#0x023e0021
+ bl OS_SetProtectionRegion2
+ add sp,sp,#0x4
+ ldmia sp!,{ lr }
+ bx lr
+ }
+#else
+ void* uVar1;
+
+ uVar1 = OS_GetInitArenaHi(OS_ARENA_MAINEX);
+ OS_SetArenaHi(2,uVar1);
+ uVar1 = OS_GetInitArenaLo(OS_ARENA_MAINEX);
+ OS_SetArenaLo(2,uVar1);
+ if (!OSi_MainExArenaEnabled || (OS_GetConsoleType() & OS_CONSOLE_SIZE_MASK) == OS_CONSOLE_SIZE_4MB) {
+ return;
+ }
+ // TODO:
+ // OS_SetProtectionRegion1(&UNK_0200002b);
+ // OS_SetProtectionRegion2(0x023e0021);
+#endif
+}
+
+void OS_InitArena() {
+#ifdef MATCH_ASM
+ __asm {
+ stmdb sp!,{ lr }
+ sub sp,sp,#0x4
+ ldr r1,OSi_Initialized
+ ldr r0,[r1,#0x0]
+ cmp r0,#0x0
+ addne sp,sp,#0x4
+ ldmneia sp!,{ lr }
+ bxne lr
+ mov r2,#0x1
+ mov r0,#0x0
+ str r2,[r1,#0x0]
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x0
+ bl OS_SetArenaHi
+ mov r0,#0x0
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x0
+ bl OS_SetArenaLo
+ mov r0,#0x2
+ mov r1,#0x0
+ bl OS_SetArenaLo
+ mov r0,#0x2
+ mov r1,#0x0
+ bl OS_SetArenaHi
+ mov r0,#0x3
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x3
+ bl OS_SetArenaHi
+ mov r0,#0x3
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x3
+ bl OS_SetArenaLo
+ mov r0,#0x4
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x4
+ bl OS_SetArenaHi
+ mov r0,#0x4
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x4
+ bl OS_SetArenaLo
+ mov r0,#0x5
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x5
+ bl OS_SetArenaHi
+ mov r0,#0x5
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x5
+ bl OS_SetArenaLo
+ mov r0,#0x6
+ bl OS_GetInitArenaHi
+ mov r1,r0
+ mov r0,#0x6
+ bl OS_SetArenaHi
+ mov r0,#0x6
+ bl OS_GetInitArenaLo
+ mov r1,r0
+ mov r0,#0x6
+ bl OS_SetArenaLo
+ add sp,sp,#0x4
+ ldmia sp!,{ lr }
+ bx lr
+ }
+#else
+ if (OSi_Initialized) {
+ return;
+ }
+ OSi_Initialized = TRUE;
+
+ OS_SetArenaHi(OS_ARENA_MAIN, OS_GetInitArenaHi(OS_ARENA_MAIN));
+ OS_SetArenaLo(OS_ARENA_MAIN, OS_GetInitArenaLo(OS_ARENA_MAIN));
+
+ OS_SetArenaLo(OS_ARENA_MAINEX, (void *)0);
+ OS_SetArenaHi(OS_ARENA_MAINEX, (void *)0);
+
+ OS_SetArenaHi(OS_ARENA_ITCM, OS_GetInitArenaHi(OS_ARENA_ITCM));
+ OS_SetArenaLo(OS_ARENA_ITCM, OS_GetInitArenaLo(OS_ARENA_ITCM));
+
+ OS_SetArenaHi(OS_ARENA_DTCM, OS_GetInitArenaHi(OS_ARENA_DTCM));
+ OS_SetArenaLo(OS_ARENA_DTCM, OS_GetInitArenaLo(OS_ARENA_DTCM));
+
+ OS_SetArenaHi(OS_ARENA_SHARED, OS_GetInitArenaHi(OS_ARENA_SHARED));
+ OS_SetArenaLo(OS_ARENA_SHARED, OS_GetInitArenaLo(OS_ARENA_SHARED));
+
+ OS_SetArenaHi(OS_ARENA_WRAM_MAIN, OS_GetInitArenaHi(OS_ARENA_WRAM_MAIN));
+ OS_SetArenaLo(OS_ARENA_WRAM_MAIN, OS_GetInitArenaLo(OS_ARENA_WRAM_MAIN));
+#endif
+}
+
+#define HEADERSIZE OSi_ROUND(sizeof(Cell), 32)
+#define MINOBJSIZE (HEADERSIZE+32)
+
+void OS_FreeToHeap(OSArenaId id, OSHeapHandle heap, void* ptr) {
+#ifdef MATCH_ASM
+ __asm {
+ stmdb sp!,{ r4 r5 r6 r7 lr }
+ sub sp,sp,#0x4
+ mov r7,param_1
+ mov r5,param_2
+ mov r4,param_3
+ bl OS_DisableInterrupts
+ ldr param_2,OSiHeapInfo
+ mov r6,param_1
+ ldr param_1,[param_2,r7,lsl #0x2]
+ cmp r5,#0x0
+ ldrlt r5,[param_1,#0x0]
+ ldr param_2,[param_1,#0x10]
+ mov param_1,#0xc
+ mla r7,r5,param_1,param_2
+ sub r4,r4,#0x20
+ ldr param_1,[r7,#0x8]
+ mov param_2,r4
+ bl DLExtract
+ str param_1,[r7,#0x8]
+ ldr param_1,[r7,#0x4]
+ mov param_2,r4
+ bl DLInsert
+ str param_1,[r7,#0x4]
+ mov param_1,r6
+ bl OS_RestoreInterrupts
+ add sp,sp,#0x4
+ ldmia sp!,{ r4 r5 r6 r7 lr }
+ bx lr
+ }
+#else
+ OSHeapInfo *heapInfo;
+ HeapDesc *hd;
+ Cell *cell;
+
+ OSIntrMode enabled = OS_DisableInterrupts();
+ heapInfo = OSiHeapInfo[id];
+
+ if (heap < 0) {
+ heap = heapInfo->currentHeap;
+ }
+
+ cell = (Cell *) ((char *)ptr - HEADERSIZE);
+ hd = &heapInfo->heapArray[heap];
+
+ hd->allocated = DLExtract(hd->allocated, cell);
+ hd->free = DLInsert(hd->free, cell);
+
+ OS_RestoreInterrupts(enabled);
+
+#endif
+}
+
+void* OS_AllocFromHeap(OSArenaId id, OSHeapHandle heap, u32 size) {
+#ifdef MATCH_ASM
+ __asm {
+
+ }
+#else
+ OSHeapInfo* heapInfo;
+ HeapDesc* hd;
+ Cell* cell;
+ Cell* newCell;
+ long leftoverSize;
+
+ OSIntrMode enabled = OS_DisableInterrupts();
+ heapInfo = OSiHeapInfo[id];
+ if (!heapInfo) {
+ OS_RestoreInterrupts(enabled);
+ return NULL;
+ }
+
+ if (heap < 0) {
+ heap = heapInfo->currentHeap;
+ }
+
+ hd = &heapInfo->heapArray[heap];
+
+ size += HEADERSIZE;
+ size = OSi_ROUND(size, 32);
+
+ for (cell = hd->free; cell != NULL; cell = cell->next) {
+ if ((long)size <= cell->size) {
+ break;
+ }
+ }
+
+ if (cell == NULL) {
+ OS_RestoreInterrupts(enabled);
+ return NULL;
+ }
+
+ leftoverSize = cell->size - (long)size;
+ if (leftoverSize < MINOBJSIZE) {
+ hd->free = DLExtract(hd->free, cell);
+ } else {
+ cell->size = (long)size;
+
+ newCell = (Cell *) ((char *)cell + size);
+ newCell->size = leftoverSize;
+
+ newCell->prev = cell->prev;
+ newCell->next = cell->next;
+
+ if (newCell->next != NULL) {
+ newCell->next->prev = newCell;
+ }
+
+ if (newCell->prev != NULL) {
+ newCell->prev->next = newCell;
+ } else {
+ hd->free = newCell;
+ }
+ }
+
+ hd->allocated = DLAddFront(hd->allocated, cell);
+
+ OS_RestoreInterrupts(enabled);
+ return (void *)((char *)cell + HEADERSIZE);
+
+#endif
+} \ No newline at end of file
diff --git a/include/nitro/os_alloc.h b/include/nitro/os_alloc.h
new file mode 100644
index 00000000..904b3e9e
--- /dev/null
+++ b/include/nitro/os_alloc.h
@@ -0,0 +1,79 @@
+//
+// Created by mart on 4/23/20.
+//
+
+#ifndef POKEDIAMOND_OS_ALLOC_H
+#define POKEDIAMOND_OS_ALLOC_H
+
+#include "types.h"
+
+typedef enum {
+ OS_ARENA_MAIN = 0,
+ OS_ARENA_MAIN_SUBPRIV = 1,
+ OS_ARENA_MAINEX = 2,
+ OS_ARENA_ITCM = 3,
+ OS_ARENA_DTCM = 4,
+ OS_ARENA_SHARED = 5,
+ OS_ARENA_WRAM_MAIN = 6,
+ OS_ARENA_WRAM_SUB = 7,
+ OS_ARENA_WRAM_SUBPRIV = 8,
+ OS_ARENA_MAX = 9
+} OSArenaId;
+
+typedef struct {
+ void* lo[OS_ARENA_MAX];
+ void* hi[OS_ARENA_MAX];
+ u16 initialized;
+ u8 padding[2];
+} OSArenaInfo;
+
+typedef int OSHeapHandle;
+
+typedef struct Cell Cell;
+
+struct Cell {
+ Cell* prev;
+ Cell* next;
+ long size;
+};
+
+typedef struct {
+ long size;
+ Cell *free;
+ Cell *allocated;
+} HeapDesc;
+
+typedef struct {
+ volatile OSHeapHandle currentHeap;
+ int numHeaps;
+ void* arenaStart;
+ void* arenaEnd;
+ HeapDesc* heapArray;
+} OSHeapInfo;
+
+void* OSiHeapInfo[OS_ARENA_MAX] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void* OS_AllocFromArenaHi(OSArenaId id, u32 size, u32 align);
+void* OS_AllocFromArenaLo(OSArenaId id, u32 size, u32 align);
+void OS_SetArenaLo(OSArenaId id, void *newLo);
+void OS_SetArenaHi(OSArenaId id, void *newHi);
+void* OS_GetInitArenaLo(OSArenaId id);
+void* OS_GetInitArenaHi(OSArenaId id);
+void* OS_GetArenaLo(OSArenaId id);
+void* OS_GetArenaHi(OSArenaId id);
+void OS_InitArenaEx();
+void OS_InitArena();
+void OS_FreeToHeap(OSArenaId id, OSHeapHandle heap, void *ptr);
+void* OS_AllocFromHeap(OSArenaId id, OSHeapHandle heap, u32 size);
+
+#endif //POKEDIAMOND_OS_ALLOC_H
diff --git a/include/nitro/os_system.c b/include/nitro/os_system.c
new file mode 100644
index 00000000..08ebeff9
--- /dev/null
+++ b/include/nitro/os_system.c
@@ -0,0 +1,34 @@
+//
+// Created by mart on 4/23/20.
+//
+
+#include "os_system.h"
+
+OSProcMode OS_GetProcMode() {
+ __asm {
+ mrs r0, cpsr
+ and r0, r0, #HW_PSR_CPU_MODE_MASK
+ bx lr
+ }
+}
+
+OSIntrMode OS_DisableInterrupts() {
+ __asm {
+ mrs r0, cpsr
+ orr r1, r0, #HW_PSR_IRQ_DISABLE
+ msr cpsr_c, r1
+ and r0, r0, #HW_PSR_IRQ_DISABLE
+ bx lr
+ }
+}
+
+OSIntrMode OS_RestoreInterrupts(OSIntrMode state) {
+ __asm {
+ mrs r1, cpsr
+ bic r2, r1, #HW_PSR_IRQ_DISABLE
+ orr r2, r2, r0
+ msr cpsr_c, r2
+ and r0, r1, #HW_PSR_IRQ_DISABLE
+ bx lr
+ }
+}
diff --git a/include/nitro/os_system.h b/include/nitro/os_system.h
new file mode 100644
index 00000000..0c4e37d8
--- /dev/null
+++ b/include/nitro/os_system.h
@@ -0,0 +1,39 @@
+//
+// Created by mart on 4/23/20.
+//
+
+#ifndef POKEDIAMOND_OS_SYSTEM_H
+#define POKEDIAMOND_OS_SYSTEM_H
+
+#include "consts.h"
+
+typedef enum {
+ OS_PROCMODE_USER=16,
+ OS_PROCMODE_FIQ=17,
+ OS_PROCMODE_IRQ=18,
+ OS_PROCMODE_SVC=19,
+ OS_PROCMODE_ABORT=23,
+ OS_PROCMODE_UNDEF=27,
+ OS_PROCMODE_SYS=31
+} OSProcMode;
+
+typedef enum {
+ OS_INTRMODE_IRQ_DISABLE = HW_PSR_IRQ_DISABLE,
+ OS_INTRMODE_IRQ_ENABLE = 0
+} OSIntrMode_Irq;
+
+typedef enum {
+ OS_INTRMODE_FIQ_DISABLE = HW_PSR_FIQ_DISABLE,
+ OS_INTRMODE_FIQ_ENABLE = 0
+} OSIntrMode_Fiq;
+
+typedef union {
+ OSIntrMode_Fiq mode_fiq;
+ OSIntrMode_Irq mode_irq;
+} OSIntrMode;
+
+OSProcMode OS_GetProcMode();
+OSIntrMode OS_DisableInterrupts();
+OSIntrMode OS_RestoreInterrupts(OSIntrMode state);
+
+#endif //POKEDIAMOND_OS_SYSTEM_H