SBSPSS/source/mem/memory.cpp

694 lines
14 KiB
C++
Raw Normal View History

2000-08-29 21:54:22 +02:00
/**************************/
/*** 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;
2000-09-15 19:20:48 +02:00
#ifdef __VERSION_DEBUG__
2000-09-15 18:51:09 +02:00
#define USE_MEM_GUARDS
2000-09-15 19:20:48 +02:00
#endif
2000-09-15 18:51:09 +02:00
#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 */
2000-08-29 21:54:22 +02:00
/*****************************************************************************/
#ifdef __DEBUG_MEM__
#ifndef __PRIM_HEADER__
#include "gfx/prim.h"
#endif
2000-09-18 17:33:19 +02:00
#ifndef __PAD_PADS_H__
2000-08-29 21:54:22 +02:00
#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;
2000-09-15 18:51:09 +02:00
2000-08-29 21:54:22 +02:00
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++;
}
2000-11-20 16:58:32 +01:00
if (s_currentMemPart < 0) s_currentMemPart = MAX_MEM_DUMP - 2;
2000-08-29 21:54:22 +02:00
if (s_currentMemPart >= MAX_MEM_DUMP-1) s_currentMemPart = 0;
while( !memDump[s_currentMemPart].addr )
{
s_currentMemPart += dir;
2000-11-20 16:58:32 +01:00
if (s_currentMemPart < 0) s_currentMemPart = MAX_MEM_DUMP - 2;
2000-08-29 21:54:22 +02:00
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;i<MAX_MEM_DUMP;i++)
{
if (mem->addr)
{
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 ];
2000-11-20 16:45:17 +01:00
if (mem->addr)
#ifdef USE_MEM_GUARDS
len = *(((u32 *)mem->addr) - 3);
#else
len = *(((u32 *)mem->addr) - 1);
#endif
else
len = 0;
2000-08-29 21:54:22 +02:00
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 );
}
2000-11-20 16:45:17 +01:00
s_debugFont.print( s_dumpTextX, s_dumpTextY, Text );
2000-08-29 21:54:22 +02:00
}
}
void resetDebugMem()
{
for (int i=0;i<MAX_MEM_DUMP;i++)
{
memDump[i].addr = NULL;
}
}
void addDebugMem( void * addr, const char * name, const char * file, int line )
{
int id;
char * sname;
CScene * scene;
scene = GameState::getCurrentScene();
if (scene)
{
2000-11-20 16:45:17 +01:00
sname = scene->getSceneName();
2000-08-29 21:54:22 +02:00
id = -1;
for (int i=0;i<s_nbSceneNames;i++)
{
if (!strcmp( sname, s_sceneNames[i] ))
{
id = i;
}
}
if (id == -1) id = MEM_SYSTEM;
}
else
{
id = MEM_SYSTEM;
}
for (int i=0;i<MAX_MEM_DUMP;i++)
{
if (!memDump[i].addr)
{
memDump[i].addr = addr;
memDump[i].id = MEM_ID( id );
memDump[i].name = name;
memDump[i].file = file;
memDump[i].line = line;
memDump[i].frameTime = VidGetTickCount();
return;
}
}
ASSERT( !"Out of debug mem slots" );
}
void freeDebugMem( void * addr )
{
ASSERT( addr );
for (int i=0;i<MAX_MEM_DUMP;i++)
{
if (memDump[i].addr == addr)
{
memDump[i].addr = NULL;
return;
}
}
ASSERT( !"Can't find debug mem node" );
}
#endif
/*****************************************************************************/
void MemInit()
{
u16 stack = LListLen - 1;
sLList * mem = &MainRam;
char * addr = (char*)OPT_LinkerOpts.FreeMemAddress;
u32 len = OPT_LinkerOpts.FreeMemSize - 4;
mem->SP = stack;
mem->Head = 0xffff;
mem->Tail = 0xffff;
for (int i=0;i<LListLen;i++)
{
mem->Stack[ 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 !
2000-09-15 18:51:09 +02:00
#ifdef USE_MEM_GUARDS
Len+=(MEM_GUARD_SIZE*2);
#endif /* USE_MEM_GUARDS */
2000-08-29 21:54:22 +02:00
// Find First (and possably only)
while (Head != 0xffff && mem->Nodes[ Head ].Len<Len) Head = mem->Nodes[ 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].Len<mem->Nodes[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);
2000-09-15 18:51:09 +02:00
2000-08-29 21:54:22 +02:00
*(u32*)Addr = Len;
Addr += 4;
2000-09-15 18:51:09 +02:00
#ifdef USE_MEM_GUARDS
unsigned int i;
for(i=0;i<MEM_GUARD_SIZE;i+=sizeof(int))
{
*(int*)(Addr+i)=HEAD_GUARD_FILL_PATTERN;
}
Addr+=MEM_GUARD_SIZE;
for(i=0;i<((TLen+3)&0xfffffffc);i+=sizeof(int))
{
*(int*)(Addr+i)=MEM_FILL_PATTERN;
}
for(i=0;i<MEM_GUARD_SIZE;i+=sizeof(int))
{
*(int*)(Addr+((TLen+3)&0xfffffffc)+i)=TAIL_GUARD_FILL_PATTERN;
}
#endif /* USE_MEM_GUARDS */
2000-08-29 21:54:22 +02:00
mem->RamUsed += 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;
2000-09-15 18:51:09 +02:00
#ifdef USE_MEM_GUARDS
Addr-=MEM_GUARD_SIZE;
#endif /* USE_MEM_GUARDS */
2000-08-29 21:54:22 +02:00
Addr -= 4;
Len = *(u32*)Addr;
2000-09-15 18:51:09 +02:00
#ifdef USE_MEM_GUARDS
// Check that the guards are intact
unsigned int i;
unsigned int *guardAddr;
guardAddr=(unsigned int*)(Addr+4);
for(i=0;i<MEM_GUARD_SIZE;i+=sizeof(unsigned int),guardAddr++)
{
if(*guardAddr!=HEAD_GUARD_FILL_PATTERN)
{
ASSERT(!"Memory guard trashed (head)");
break;
}
}
guardAddr=(unsigned int*)(Addr+Len-MEM_GUARD_SIZE);
for(i=0;i<MEM_GUARD_SIZE;i+=sizeof(unsigned int),guardAddr++)
{
if(*guardAddr!=TAIL_GUARD_FILL_PATTERN)
{
ASSERT(!"Memory guard trashed (tail)");
break;
}
}
#endif /* USE_MEM_GUARDS */
2000-08-29 21:54:22 +02:00
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 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);
}
/*****************************************************************************/