■mymem.h // 「30日でできる!OS自作入門」のソースコードを使わせて頂いています // ライセンスは「川合堂ライセンス-01」です。http://hrb.osask.jp/ #ifndef __MYMEM_H__ #define __MYMEM_H__ #ifdef __cplusplus extern "C" { #endif #include "gba.h" //--------------------------------------------------------------------------- #define MYMEM_MAX_INFO_CNT 2048 #define MYMEM_SIZE 20480 // u32単位で定義してください //--------------------------------------------------------------------------- typedef struct { u32 addr; u32 size; } ST_MYMEM_INFO; typedef struct { u8 ram[MYMEM_SIZE]; u32 cnt; ST_MYMEM_INFO info[MYMEM_MAX_INFO_CNT]; } ST_MYMEM; //--------------------------------------------------------------------------- EWRAM_CODE void MyMemInit(); IWRAM_CODE bool MyMemFree(u32 addr, u32 size); IWRAM_CODE void* MyMemAlloc(u32 size); IWRAM_CODE void* MyMemCalloc(u32 size); EWRAM_CODE u32 MyMemGetFreeSize(); #ifdef __cplusplus } #endif #endif ■mymem.c #include "common.h" #include "mymem.h" //--------------------------------------------------------------------------- ST_MYMEM MyMem EWRAM_BSS; //--------------------------------------------------------------------------- EWRAM_CODE void MyMemInit() { _Memset((u8*)&MyMem, 0x00, sizeof(ST_MYMEM)); MyMemFree((u32)&MyMem.ram[0], MYMEM_SIZE); } //--------------------------------------------------------------------------- IWRAM_CODE bool MyMemFree(u32 addr, u32 size) { ST_MYMEM* p = &MyMem; u16 i, j; size += 3; size &= 0xfffffffc; //TRACEOUT("MemFree addr=0x%x size=%d\n", addr, size); // free[]をaddr順に並べる為、free[]の挿入場所を決めます for(i=0; icnt; i++) { if(p->info[i].addr > addr) { break; } } // 前の空き領域があるかチェックをします if((i > 0) && (p->info[i-1].addr + p->info[i-1].size == addr)) { p->info[i-1].size += size; // 後ろの空き領域があるかチェックをします if((i < p->cnt) && (addr + size == p->info[i].addr)) { p->info[i-1].size += p->info[i].size; p->cnt--; // free[i]がなくなったので前へ詰めます while(i < p->cnt) { p->info[i] = p->info[i + 1]; i++; } } return TRUE; } // 前の空き領域とまとめられなかった場合、後ろがあるかチェックをします if((i < p->cnt) && (addr + size == p->info[i].addr)) { p->info[i].addr = addr; p->info[i].size += size; return TRUE; } // 前にも後ろの領域にもまとめられない場合、free[i]より後にずらして隙間を作ります if(p->cnt < MYMEM_MAX_INFO_CNT) { for(j=p->cnt; j>i; j--) { p->info[j] = p->info[j-1]; } p->cnt++; p->info[i].addr = addr; p->info[i].size = size; return TRUE; } TRACEOUT("MyMemFree Error\n"); return FALSE; } //--------------------------------------------------------------------------- IWRAM_CODE void* MyMemAlloc(u32 size) { ST_MYMEM* p = &MyMem; u8* addr; u16 i; // u32単位で切り分けます size += 3; size &= 0xfffffffc; for(i=0; icnt; i++) { if(p->info[i].size >= size) { addr = (u8*)p->info[i].addr; p->info[i].addr += size; p->info[i].size -= size; if(p->info[i].size == 0) { p->cnt--; // free[i]がなくなったので前へ詰めます while(i < p->cnt) { p->info[i] = p->info[i + 1]; i++; } } // TRACEOUT("MemAlloc addr=0x%x size=%d\n", addr, size); return addr; } } TRACEOUT("MyMemAlloc Error\n"); return NULL; } //--------------------------------------------------------------------------- IWRAM_CODE void* MyMemCalloc(u32 size) { void* p = MyMemAlloc(size); _Memset(p, 0x00, size); return p; } //--------------------------------------------------------------------------- EWRAM_CODE u32 MyMemGetFreeSize() { ST_MYMEM* p = &MyMem; u32 freeSize = 0; u16 i; for(i=0; icnt; i++) { freeSize += p->info[i].size; } return freeSize; }