2020-11-25 14:03:44 -05:00
|
|
|
#pragma once
|
|
|
|
|
2020-11-25 16:49:50 -05:00
|
|
|
// some windows shit
|
|
|
|
#ifdef MoveMemory
|
|
|
|
#undef MoveMemory
|
|
|
|
#endif
|
|
|
|
|
2020-11-26 10:47:19 -05:00
|
|
|
#ifdef USE_CUSTOM_ALLOCATOR
|
|
|
|
#define PUSH_MEMID(id) gMainHeap.PushMemId(id)
|
|
|
|
#define POP_MEMID() gMainHeap.PopMemId()
|
|
|
|
#define REGISTER_MEMPTR(ptr) gMainHeap.RegisterMemPointer(ptr)
|
|
|
|
#else
|
|
|
|
#define PUSH_MEMID(id)
|
|
|
|
#define POP_MEMID()
|
|
|
|
#define REGISTER_MEMPTR(ptr)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
enum {
|
|
|
|
MEMID_FREE,
|
|
|
|
// IDs from LCS:
|
|
|
|
/*
|
|
|
|
MEMID_GAME = 1, // "Game"
|
|
|
|
MEMID_WORLD = 2, // "World"
|
|
|
|
MEMID_ANIMATION = 3, // "Animation"
|
|
|
|
MEMID_POOLS = 4, // "Pools"
|
|
|
|
MEMID_DEF_MODELS = 5, // "Default Models"
|
|
|
|
MEMID_STREAM = 6, // "Streaming"
|
|
|
|
MEMID_STREAM_MODELS = 7, // "Streamed Models"
|
|
|
|
MEMID_STREAM_LODS = 8, // "Streamed LODs"
|
|
|
|
MEMID_STREAM_TEXUTRES = 9, // "Streamed Textures"
|
|
|
|
MEMID_STREAM_COLLISION = 10, // "Streamed Collision"
|
|
|
|
MEMID_STREAM_ANIMATION = 11, // "Streamed Animation"
|
|
|
|
MEMID_TEXTURES = 12, // "Textures"
|
|
|
|
MEMID_COLLISION = 13, // "Collision"
|
|
|
|
MEMID_PRE_ALLOC = 14, // "PreAlloc"
|
|
|
|
MEMID_GAME_PROCESS = 15, // "Game Process"
|
|
|
|
MEMID_SCRIPT = 16, // "Script"
|
|
|
|
MEMID_CARS = 17, // "Cars"
|
|
|
|
MEMID_RENDER = 18, // "Render"
|
|
|
|
MEMID_PED_ATTR = 19, // "Ped Attr"
|
|
|
|
*/
|
|
|
|
// III:
|
|
|
|
MEMID_GAME = 1, // "Game"
|
|
|
|
MEMID_WORLD = 2, // "World"
|
|
|
|
MEMID_ANIMATION = 3, // "Animation"
|
|
|
|
MEMID_POOLS = 4, // "Pools"
|
|
|
|
MEMID_DEF_MODELS = 5, // "Default Models"
|
|
|
|
MEMID_STREAM = 6, // "Streaming"
|
|
|
|
MEMID_STREAM_MODELS = 7, // "Streamed Models" (instance)
|
|
|
|
MEMID_STREAM_TEXUTRES = 8, // "Streamed Textures"
|
|
|
|
MEMID_TEXTURES = 9, // "Textures"
|
|
|
|
MEMID_COLLISION = 10, // "Collision"
|
|
|
|
MEMID_RENDERLIST = 11, // ?
|
|
|
|
MEMID_GAME_PROCESS = 12, // "Game Process"
|
|
|
|
MEMID_SCRIPT = 13, // "Script"
|
|
|
|
MEMID_CARS = 14, // "Cars"
|
|
|
|
MEMID_RENDER = 15, // "Render"
|
|
|
|
MEMID_FRONTEND = 17, // ?
|
|
|
|
|
|
|
|
NUM_MEMIDS,
|
|
|
|
|
|
|
|
NUM_FIXED_MEMBLOCKS = 6
|
|
|
|
};
|
|
|
|
|
2020-11-25 14:03:44 -05:00
|
|
|
template<typename T, uint32 N>
|
|
|
|
class CStack
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
T values[N];
|
|
|
|
uint32 sp;
|
|
|
|
|
|
|
|
CStack() : sp(0) {}
|
|
|
|
void push(const T& val) { values[sp++] = val; }
|
2020-11-26 10:47:19 -05:00
|
|
|
T& pop() { return values[--sp]; }
|
2020-11-25 14:03:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct HeapBlockDesc
|
|
|
|
{
|
|
|
|
uint32 m_size;
|
|
|
|
int16 m_memId;
|
|
|
|
int16 m_ptrListIndex;
|
|
|
|
HeapBlockDesc *m_next;
|
|
|
|
HeapBlockDesc *m_prev;
|
|
|
|
|
|
|
|
HeapBlockDesc *GetNextConsecutive(void)
|
|
|
|
{
|
|
|
|
return (HeapBlockDesc*)((uintptr)this + sizeof(HeapBlockDesc) + m_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *GetDataPointer(void)
|
|
|
|
{
|
|
|
|
return (void*)((uintptr)this + sizeof(HeapBlockDesc));
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveHeapFreeBlock(void)
|
|
|
|
{
|
|
|
|
m_next->m_prev = m_prev;
|
|
|
|
m_prev->m_next = m_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// after node
|
|
|
|
void InsertHeapFreeBlock(HeapBlockDesc *node)
|
|
|
|
{
|
|
|
|
m_next = node->m_next;
|
|
|
|
node->m_next->m_prev = this;
|
|
|
|
m_prev = node;
|
|
|
|
node->m_next = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapBlockDesc *FindSmallestFreeBlock(uint32 size)
|
|
|
|
{
|
|
|
|
HeapBlockDesc *b;
|
|
|
|
for(b = m_next; b->m_size < size; b = b->m_next);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-11-25 16:49:50 -05:00
|
|
|
#ifdef USE_CUSTOM_ALLOCATOR
|
|
|
|
// TODO: figure something out for 64 bit pointers
|
2020-11-25 14:03:44 -05:00
|
|
|
static_assert(sizeof(HeapBlockDesc) == 0x10, "HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense");
|
2020-11-25 16:49:50 -05:00
|
|
|
#endif
|
2020-11-25 14:03:44 -05:00
|
|
|
|
|
|
|
struct HeapBlockList
|
|
|
|
{
|
|
|
|
HeapBlockDesc m_first;
|
|
|
|
HeapBlockDesc m_last;
|
|
|
|
|
|
|
|
void Init(void)
|
|
|
|
{
|
|
|
|
m_first.m_next = &m_last;
|
|
|
|
m_last.m_prev = &m_first;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Insert(HeapBlockDesc *node)
|
|
|
|
{
|
|
|
|
node->InsertHeapFreeBlock(&m_first);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CommonSize
|
|
|
|
{
|
|
|
|
HeapBlockList m_freeList;
|
|
|
|
uint32 m_size;
|
|
|
|
uint32 m_failed;
|
|
|
|
uint32 m_remaining;
|
|
|
|
|
|
|
|
void Init(uint32 size);
|
|
|
|
void Free(HeapBlockDesc *node)
|
|
|
|
{
|
|
|
|
m_freeList.Insert(node);
|
|
|
|
m_remaining++;
|
|
|
|
}
|
|
|
|
HeapBlockDesc *Malloc(void)
|
|
|
|
{
|
|
|
|
if(m_freeList.m_first.m_next == &m_freeList.m_last){
|
|
|
|
m_failed++;
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
HeapBlockDesc *block = m_freeList.m_first.m_next;
|
|
|
|
m_remaining--;
|
|
|
|
block->RemoveHeapFreeBlock();
|
|
|
|
block->m_ptrListIndex = -1;
|
|
|
|
return block;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CMemoryHeap
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
HeapBlockDesc *m_start;
|
|
|
|
HeapBlockDesc *m_end;
|
|
|
|
HeapBlockList m_freeList;
|
|
|
|
CommonSize m_fixedSize[NUM_FIXED_MEMBLOCKS];
|
|
|
|
uint32 m_totalMemUsed;
|
|
|
|
CStack<int32, 16> m_idStack;
|
|
|
|
uint32 m_currentMemID;
|
|
|
|
uint32 *m_memUsed;
|
|
|
|
uint32 m_totalBlocksUsed;
|
|
|
|
uint32 *m_blocksUsed;
|
|
|
|
uint32 m_unkMemId;
|
|
|
|
|
|
|
|
CMemoryHeap(void) : m_start(nil) {}
|
|
|
|
void Init(uint32 total);
|
|
|
|
void RegisterMalloc(HeapBlockDesc *block);
|
|
|
|
void RegisterFree(HeapBlockDesc *block);
|
|
|
|
void *Malloc(uint32 size);
|
|
|
|
void *Realloc(void *ptr, uint32 size);
|
|
|
|
void Free(void *ptr);
|
|
|
|
void FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size);
|
|
|
|
uint32 CombineFreeBlocks(HeapBlockDesc *block);
|
|
|
|
void *MoveMemory(void *ptr);
|
|
|
|
HeapBlockDesc *WhereShouldMemoryMove(void *ptr);
|
|
|
|
void *MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src);
|
|
|
|
void PopMemId(void);
|
|
|
|
void PushMemId(int32 id);
|
|
|
|
void RegisterMemPointer(void *ptr);
|
|
|
|
void TidyHeap(void);
|
|
|
|
uint32 GetMemoryUsed(int32 id);
|
|
|
|
uint32 GetBlocksUsed(int32 id);
|
|
|
|
|
|
|
|
void ParseHeap(void);
|
|
|
|
|
|
|
|
HeapBlockDesc *GetDescFromHeapPointer(void *block)
|
|
|
|
{
|
|
|
|
return (HeapBlockDesc*)((uintptr)block - sizeof(HeapBlockDesc));
|
|
|
|
}
|
|
|
|
uint32 GetSizeBetweenBlocks(HeapBlockDesc *first, HeapBlockDesc *second)
|
|
|
|
{
|
|
|
|
return (uintptr)second - (uintptr)first - sizeof(HeapBlockDesc);
|
|
|
|
}
|
|
|
|
void FreeBlock(HeapBlockDesc *block){
|
|
|
|
for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){
|
|
|
|
if(m_fixedSize[i].m_size == block->m_size){
|
|
|
|
m_fixedSize[i].Free(block);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-11-25 16:49:50 -05:00
|
|
|
HeapBlockDesc *b = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);
|
|
|
|
block->InsertHeapFreeBlock(b->m_prev);
|
2020-11-25 14:03:44 -05:00
|
|
|
}
|
|
|
|
};
|
2020-11-26 10:47:19 -05:00
|
|
|
|
|
|
|
extern CMemoryHeap gMainHeap;
|