/**************************/ /*** Memory Alloc Stuff ***/ /**************************/ #include "system\global.h" #include "mem\memory.h" #include "fileio/fileio.h" // Poo, need this for Databank stuff #if defined(__USER_daveo__) #define MemPrint #endif /*****************************************************************************/ void MemAddNode(sLList *LList,u_long Len,char *Addr); void MemRemoveNode(sLList *LList,u_short Node); /*****************************************************************************/ sLList MainRam; int MemNodeCount=0; #ifdef __VERSION_DEBUG__ #define USE_MEM_GUARDS #endif #ifdef USE_MEM_GUARDS static const unsigned int HEAD_GUARD_FILL_PATTERN =0x3c3c3c3c; static const unsigned int MEM_FILL_PATTERN =0x3d3d3d3d; static const unsigned int TAIL_GUARD_FILL_PATTERN =0x3e3e3e3e; static const unsigned int MEM_GUARD_SIZE=sizeof(int)*2; #endif /* USE_MEM_GUARDS */ /*****************************************************************************/ #ifdef __DEBUG_MEM__ #ifndef __PRIM_HEADER__ #include "gfx/prim.h" #endif #ifndef __PAD_PADS_H__ #include "pad/pads.h" #endif #ifndef __VID_HEADER_ #include "system/vid.h" #endif #ifndef __SYSTEM_GSTATE_H__ #include "system/gstate.h" #endif #ifndef __GFX_FONT_H__ #include "gfx/font.h" #endif #define MAX_MEM_DUMP 1024 enum MEM_ID { MEM_BACKEND, MEM_FRONTEND, MEM_GAME, MEM_GAMEOPTIONS, MEM_SYSTEM, MEM_ID_MAX }; struct MEM_PART { void * addr; MEM_ID id; const char * name; const char * file; int line; u32 frameTime; }; static MEM_PART memDump[ MAX_MEM_DUMP ]; static bool s_dumpMem = false; static const int s_dumpX = 16; static const int s_dumpY = 190; static const int s_dumpWidth = 400; static const int s_dumpHeight = 32; static const int s_dumpScale = ONE; static const int s_dumpTextX = 32; static const int s_dumpTextY = 120; static const int s_dumpShift = 20; static const int s_shadeX = 16; static const int s_shadeY = 110; static const int s_shadeW = 400; static const int s_shadeH = 80; static const CVECTOR s_shadeCol = { 0, 0, 0 }; static int s_currentMemPart = 0; static const CVECTOR s_colors[ MEM_ID_MAX ] = { { 255, 0, 0 }, // MEM_BACKEND { 0, 255, 0 }, // MEM_FRONTEND { 0, 0, 255 }, // MEM_GAME { 255, 0, 255 }, // MEM_GAMEOPTIONS { 255, 255, 255 }, // MEM_SYSTEM }; static const char * s_sceneNames[] = { "BackEnd", "FrontEnd", "Game", "GameOptions", "System", }; static const int s_nbSceneNames = sizeof(s_sceneNames) / sizeof(char *); static FontBank s_debugFont; void dumpDebugMem() { if (s_dumpMem) { int x, y; u16 padh, padd; u32 freeMem; u32 memBase; u32 byteWidth; MEM_PART * mem; CVECTOR black = {0, 0, 0}; padd = PadGetDown( 1 ); padh = PadGetHeld( 1 ); // if (padh & PAD_SQUARE) { int dir; dir = 0; if (padd & PAD_LEFT) { dir = -1; s_currentMemPart--; } if (padd & PAD_RIGHT) { dir = +1; s_currentMemPart++; } if (s_currentMemPart < 0) s_currentMemPart = MAX_MEM_DUMP - 2; if (s_currentMemPart >= MAX_MEM_DUMP-1) s_currentMemPart = 0; while( !memDump[s_currentMemPart].addr ) { s_currentMemPart += dir; if (s_currentMemPart < 0) s_currentMemPart = MAX_MEM_DUMP - 2; if (s_currentMemPart >= MAX_MEM_DUMP-1) s_currentMemPart = 0; } } /* else { if (padh & PAD_UP) s_dumpScale += 64; if (padh & PAD_DOWN) s_dumpScale -= 64; if (padh & PAD_LEFT) s_dumpX -= (2 * s_dumpScale) >> 12; if (padh & PAD_RIGHT) s_dumpX += (2 * s_dumpScale) >> 12; } */ memBase = (u32)OPT_LinkerOpts.FreeMemAddress; freeMem = OPT_LinkerOpts.FreeMemSize - 4; if (freeMem > 6*1024*1024) freeMem -= 6*1024*1024; byteWidth = ((s_dumpWidth << s_dumpShift) / freeMem); x = s_dumpX; y = s_dumpY; mem = memDump; /* for (int i=0;iaddr) { u32 len; u32 * addr; POLY_F4 * F4; CVECTOR * col; addr = (u32 *)mem->addr; x = (((u32)addr) - ((u32)memBase)); x *= s_dumpScale; x >>= 12; x *= byteWidth; x >>= s_dumpShift; x += s_dumpX; len = *(addr - 1); len *= s_dumpScale; len >>= 12; len *= byteWidth; len >>= s_dumpShift; col = &s_colors[ mem->id ]; if (i == s_currentMemPart) { col = &black; } F4 = GetPrimF4(); setPolyF4( F4 ); setXY4( F4, x, y, x + len, y, x, y + s_dumpHeight, x + len, y + s_dumpHeight ); setSemiTrans( F4, 0 ); setShadeTex( F4, 0 ); setRGB0( F4, col->r, col->g, col->b ); AddPrimToList( F4, 0 ); } mem++; } */ int len; char Text[ 2048 ]; char * name; char * file; POLY_F4 * F4; F4 = GetPrimF4(); setPolyF4( F4 ); setXYWH( F4, s_shadeX, s_shadeY, s_shadeW, s_shadeH ); setSemiTrans( F4, 1 ); setShadeTex( F4, 0 ); setRGB0( F4, s_shadeCol.r, s_shadeCol.g, s_shadeCol.b ); AddPrimToList( F4, 1 ); mem = &memDump[ s_currentMemPart ]; if (mem->addr) #ifdef USE_MEM_GUARDS len = *(((u32 *)mem->addr) - 3); #else len = *(((u32 *)mem->addr) - 1); #endif else len = 0; sprintf( Text, "%d\n", s_currentMemPart ); if (mem->addr) { sprintf( Text, "%sAddr - %X Len - %d\n", Text, (int)mem->addr, len ); sprintf( Text, "%sAddrEnd - %X\n\n", Text, (int)mem->addr+len ); if (mem->name) sprintf( Text, "%sName - %s\n", Text, mem->name ); else sprintf( Text, "%sName - Undefined", Text ); sprintf( Text, "%sFile - %s, Line - %d\n", Text, mem->file, mem->line ); sprintf( Text, "%sScene - %s\n", Text, s_sceneNames[ mem->id ] ); // sprintf( Text, "%sTime - %lu", Text, mem->frameTime ); } else { sprintf( Text, "%sAddr - NULL\nLen - 0\nName - Undefined\nFile - Undefined, Line - 0", Text ); } s_debugFont.print( s_dumpTextX, s_dumpTextY, Text ); } } void resetDebugMem() { for (int i=0;igetSceneName(); id = -1; for (int i=0;iSP = stack; mem->Head = 0xffff; mem->Tail = 0xffff; for (int i=0;iStack[ i ] = stack--; } MemAddNode( mem, len, addr ); mem->RamUsed = 0; mem->TotalRam = len; #ifdef __DEBUG_MEM__ resetDebugMem(); #endif } // hmm.. have to alloc this memory before the first scene, but have to wait until all the // systems are active so can't do it in the standard MemInit() thing void DebugMemFontInit() { #ifdef __DEBUG_MEM__ s_debugFont.initialise( &standardFont ); s_debugFont.setOt( 0 ); #endif } /*****************************************************************************/ // 030700 Dave - Implemented smart allocation // It now looks thru the whole node list, and takes from the smallest VALID node // I now understand how this memory stuff works, it aint all bad! char * MemAllocate( u32 TLen, char const *Name, char const * File, int LineNumber ) { sLList *mem = &MainRam; u16 Head = mem->Head; char *Addr = (char*)-1; u32 Len = ((TLen + 3) & 0xfffffffc); int BestNode,FirstNode; Len += 4; //add on 4 to store Addr ! #ifdef USE_MEM_GUARDS Len+=(MEM_GUARD_SIZE*2); #endif /* USE_MEM_GUARDS */ // Find First (and possably only) while (Head != 0xffff && mem->Nodes[ Head ].LenNodes[ Head ].Next; ASSERT(Head != 0xffff); BestNode=FirstNode=Head; // Check rest of list while (Head != 0xffff) { if (mem->Nodes[Head].Len>=Len) { if (mem->Nodes[Head].LenNodes[BestNode].Len) BestNode=Head; } Head = mem->Nodes[ Head ].Next; } //-------------------- // Alloc it if (mem->Nodes[BestNode].Len >= Len) { Addr = mem->Nodes[BestNode].Addr; mem->Nodes[BestNode].Len -= Len; mem->Nodes[BestNode].Addr += Len; if (mem->Nodes[BestNode].Len == 0) MemRemoveNode( mem, BestNode); *(u32*)Addr = Len; Addr += 4; #ifdef USE_MEM_GUARDS unsigned int i; for(i=0;iRamUsed += Len; } #ifdef __DEBUG_MEM__ addDebugMem( Addr, Name, File, LineNumber ); #endif ASSERT( (Addr != (char*)-1) ); return Addr; } /*****************************************************************************/ void MemFree( void * Address ) { u32 Len; sLLNode *node; sLList *mem = &MainRam; u16 Head = mem->Head; char *Addr = (char*)Address; // If file from Databank, dont try and clear it (simple!!) if (CFileIO::IsFromDataBank(Address)) return; #ifdef USE_MEM_GUARDS Addr-=MEM_GUARD_SIZE; #endif /* USE_MEM_GUARDS */ Addr -= 4; Len = *(u32*)Addr; #ifdef USE_MEM_GUARDS // Check that the guards are intact unsigned int i; unsigned int *guardAddr; guardAddr=(unsigned int*)(Addr+4); for(i=0;iRamUsed -= Len; node = &mem->Nodes[ Head ]; while (Head != 0xffff) { if (mem->Nodes[ Head ].Addr == Addr + Len) { Len += mem->Nodes[ Head ].Len; node = &mem->Nodes[ Head ]; MemRemoveNode( mem, Head ); Head = mem->Head; } else { if (mem->Nodes[ Head ].Addr + mem->Nodes[ Head ].Len == Addr) { node = &mem->Nodes[ Head ]; Addr = mem->Nodes[ Head ].Addr; Len += mem->Nodes[ Head ].Len; MemRemoveNode( mem, Head ); Head = mem->Head; } else { Head = mem->Nodes[ Head ].Next; } } } MemAddNode( mem, Len, Addr ); #ifdef __DEBUG_MEM__ freeDebugMem( Address ); #endif } /* void MemFree( void * Address ) { u32 Len; sLLNode * node; sLList * mem = &MainRam; u16 Head = mem->Head; char * Addr = (char*)Address; Addr -= 4; Len = *(u32*)Addr; mem->RamUsed -= Len; node = &mem->Nodes[ Head ]; while (Head != 0xffff) { if (mem->Nodes[ Head ].Addr == Addr + Len) { Len += mem->Nodes[ Head ].Len; node = &mem->Nodes[ Head ]; MemRemoveNode( mem, Head ); Head = mem->Head; } else { if (mem->Nodes[ Head ].Addr + mem->Nodes[ Head ].Len == Addr) { node = &mem->Nodes[ Head ]; Addr = mem->Nodes[ Head ].Addr; Len += mem->Nodes[ Head ].Len; MemRemoveNode( mem, Head ); Head = mem->Head; } else { Head = mem->Nodes[ Head ].Next; } } } MemAddNode( mem, Len, Addr ); #ifdef __DEBUG_MEM__ freeDebugMem( Address ); #endif } */ /*****************************************************************************/ void MemAddNode( sLList * LList, u32 Len, char * Addr ) { u16 Head = LList->Head; u16 Tail = LList->Tail; u16 Node = LList->Stack[ LList->SP-- ]; MemNodeCount++; if (Head == 0xffff && Tail == 0xffff) { LList->Head = Node; LList->Tail = Node; LList->Nodes[ Node ].Len = Len; LList->Nodes[ Node ].Addr = Addr; LList->Nodes[ Node ].Prev = 0xffff; LList->Nodes[ Node ].Next = 0xffff; } else { LList->Head = Node; LList->Nodes[ Node ].Len = Len; LList->Nodes[ Node ].Addr = Addr; LList->Nodes[ Head ].Prev = Node; LList->Nodes[ Node ].Prev = 0xffff; LList->Nodes[ Node ].Next = Head; } } /*****************************************************************************/ void MemRemoveNode ( sLList * LList, u16 Node ) { u16 Head = LList->Head; u16 Tail = LList->Tail; u16 Prev = LList->Nodes[ Node ].Prev; u16 Next = LList->Nodes[ Node ].Next; MemNodeCount--; if (Head == Tail) { LList->Head = 0xffff; LList->Tail = 0xffff; } else { if (Node == Head) { LList->Head = Next; LList->Nodes[ Next ].Prev = 0xffff; } else if (Node == Tail) { LList->Tail = Prev; LList->Nodes[ Prev ].Next = 0xffff; } else { LList->Nodes[ Next ].Prev = Prev; LList->Nodes[ Prev ].Next = Next; } } LList->Nodes[Node].Len=0; LList->SP++; LList->Stack[ LList->SP ] = Node; } /*****************************************************************************/ void *operator new(size_t Size, const char * name ) { return MemAlloc( Size, name ); } /*****************************************************************************/ void *operator new[](size_t Size, const char * name) { return MemAlloc( Size, name ); } /*****************************************************************************/ void operator delete(void *Ptr) { MemFree((char*)Ptr); } /*****************************************************************************/ void operator delete[](void *Ptr) { MemFree((char*)Ptr); } /*****************************************************************************/