mirror of
https://github.com/JezuzLizard/T4SP-Server-Plugin.git
synced 2025-07-03 17:51:51 +00:00
The decomp is compiling!
This commit is contained in:
525
src/codsrc/clientscript/cscr_memorytree.cpp
Normal file
525
src/codsrc/clientscript/cscr_memorytree.cpp
Normal file
@ -0,0 +1,525 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "clientscript_public.hpp"
|
||||
|
||||
namespace codsrc
|
||||
{
|
||||
// Restored
|
||||
game::RefVector* GetRefVector(game::scriptInstance_t inst, unsigned int id)
|
||||
{
|
||||
assert(id);
|
||||
|
||||
assert((id * MT_NODE_SIZE) < MT_SIZE);
|
||||
|
||||
return (game::RefVector*)&game::gScrMemTreePub[inst].mt_buffer->nodes[id];
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
int MT_GetSubTreeSize(game::scriptInstance_t inst, int nodeNum)
|
||||
{
|
||||
int treeSize;
|
||||
|
||||
if (nodeNum)
|
||||
{
|
||||
treeSize = game::MT_GetSubTreeSize(inst, game::gScrMemTreeGlob[inst].nodes[nodeNum].next);
|
||||
return treeSize + game::MT_GetSubTreeSize(inst, game::gScrMemTreeGlob[inst].nodes[nodeNum].prev) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_DumpTree(game::scriptInstance_t inst)
|
||||
{
|
||||
int size;
|
||||
|
||||
//assert(game::gScrMemTreeGlob[inst].totalAlloc == totalAlloc);
|
||||
//assert(game::gScrMemTreeGlob[inst].totalAllocBuckets == totalAllocBuckets);
|
||||
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "********************************\n");
|
||||
for (int i = 0; i <= MT_NODE_BITS; ++i)
|
||||
{
|
||||
size = game::MT_GetSubTreeSize(inst, game::gScrMemTreeGlob[inst].head[i]);
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "%d subtree has %d * %d = %d free buckets\n", i, size, 1 << i, size << i);
|
||||
}
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "********************************\n");
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "********************************\n");
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "********************************\n");
|
||||
|
||||
//assert(totalBuckets == (1 << MEMORY_NODE_BITS) - 1);
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_InitBits(game::scriptInstance_t inst)
|
||||
{
|
||||
char bits;
|
||||
int temp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MT_NUM_BUCKETS; ++i)
|
||||
{
|
||||
bits = 0;
|
||||
|
||||
for (temp = i; temp; temp >>= 1)
|
||||
{
|
||||
if (temp & 1)
|
||||
{
|
||||
++bits;
|
||||
}
|
||||
}
|
||||
|
||||
game::gScrMemTreeGlob[inst].numBits[i] = bits;
|
||||
|
||||
for (bits = 8; i & ((1 << bits) - 1); --bits);
|
||||
|
||||
game::gScrMemTreeGlob[inst].leftBits[i] = bits;
|
||||
bits = 0;
|
||||
|
||||
for (temp = i; temp; temp >>= 1)
|
||||
{
|
||||
++bits;
|
||||
}
|
||||
|
||||
game::gScrMemTreeGlob[inst].logBits[i] = bits;
|
||||
}
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
int MT_GetScore(game::scriptInstance_t inst, int num)
|
||||
{
|
||||
char bits;
|
||||
|
||||
union MTnum_t
|
||||
{
|
||||
int i;
|
||||
uint8_t b[4];
|
||||
};
|
||||
|
||||
assert(num);
|
||||
|
||||
assert(MT_NODE_COUNT - num);
|
||||
|
||||
MTnum_t mtnum;
|
||||
|
||||
mtnum.i = MT_NODE_COUNT - num;
|
||||
|
||||
bits = game::gScrMemTreeGlob[inst].leftBits[mtnum.b[0]];
|
||||
|
||||
if (!mtnum.b[0])
|
||||
{
|
||||
bits += game::gScrMemTreeGlob[inst].leftBits[mtnum.b[1]];
|
||||
}
|
||||
|
||||
return mtnum.i - (game::gScrMemTreeGlob[inst].numBits[mtnum.b[1]] + game::gScrMemTreeGlob[inst].numBits[mtnum.b[0]]) + (1 << bits);
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_AddMemoryNode(game::scriptInstance_t inst, int newNode, int size)
|
||||
{
|
||||
int node;
|
||||
int nodeNum;
|
||||
int newScore;
|
||||
uint16_t* parentNode;
|
||||
int level;
|
||||
int score;
|
||||
|
||||
assert(size >= 0 && size <= MT_NODE_BITS);
|
||||
|
||||
parentNode = &game::gScrMemTreeGlob[inst].head[size];
|
||||
node = game::gScrMemTreeGlob[inst].head[size];
|
||||
if (game::gScrMemTreeGlob[inst].head[size])
|
||||
{
|
||||
newScore = game::MT_GetScore(inst, newNode);
|
||||
nodeNum = 0;
|
||||
level = MT_NODE_COUNT;
|
||||
do
|
||||
{
|
||||
assert(newNode != node);
|
||||
|
||||
score = game::MT_GetScore(inst, node);
|
||||
|
||||
assert(score != newScore);
|
||||
|
||||
if (score < newScore)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
*parentNode = (short)newNode;
|
||||
game::gScrMemTreeGlob[inst].nodes[newNode] = game::gScrMemTreeGlob[inst].nodes[node];
|
||||
if (!node)
|
||||
{
|
||||
break;
|
||||
}
|
||||
level >>= 1;
|
||||
|
||||
assert(node != nodeNum);
|
||||
|
||||
if (node >= nodeNum)
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[newNode].next;
|
||||
nodeNum += level;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[newNode].prev;
|
||||
nodeNum -= level;
|
||||
}
|
||||
|
||||
newNode = node;
|
||||
node = *parentNode;
|
||||
}
|
||||
return;
|
||||
}
|
||||
level >>= 1;
|
||||
|
||||
assert(newNode != nodeNum);
|
||||
|
||||
if (newNode >= nodeNum)
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[node].next;
|
||||
nodeNum += level;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[node].prev;
|
||||
nodeNum -= level;
|
||||
}
|
||||
|
||||
node = *parentNode;
|
||||
} while (node);
|
||||
}
|
||||
|
||||
*parentNode = (short)newNode;
|
||||
|
||||
game::gScrMemTreeGlob[inst].nodes[newNode].prev = 0;
|
||||
game::gScrMemTreeGlob[inst].nodes[newNode].next = 0;
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
char MT_RemoveMemoryNode(game::scriptInstance_t inst, int oldNode, int size)
|
||||
{
|
||||
game::MemoryNode tempNodeValue;
|
||||
int node;
|
||||
game::MemoryNode oldNodeValue;
|
||||
int nodeNum;
|
||||
uint16_t* parentNode;
|
||||
int prevScore;
|
||||
int nextScore;
|
||||
int level;
|
||||
|
||||
assert(size >= 0 && size <= MT_NODE_BITS);
|
||||
|
||||
nodeNum = 0;
|
||||
level = MT_NODE_COUNT;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].head[size];
|
||||
|
||||
for (node = *parentNode; node; node = *parentNode)
|
||||
{
|
||||
if (oldNode == node)
|
||||
{
|
||||
oldNodeValue = game::gScrMemTreeGlob[inst].nodes[oldNode];
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (oldNodeValue.prev)
|
||||
{
|
||||
if (oldNodeValue.next)
|
||||
{
|
||||
prevScore = game::MT_GetScore(inst, oldNodeValue.prev);
|
||||
nextScore = game::MT_GetScore(inst, oldNodeValue.next);
|
||||
|
||||
assert(prevScore != nextScore);
|
||||
|
||||
if (prevScore >= nextScore)
|
||||
{
|
||||
oldNode = oldNodeValue.prev;
|
||||
*parentNode = oldNodeValue.prev;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNodeValue.prev].prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldNode = oldNodeValue.next;
|
||||
*parentNode = oldNodeValue.next;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNodeValue.next].next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldNode = oldNodeValue.prev;
|
||||
*parentNode = oldNodeValue.prev;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNodeValue.prev].prev;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldNode = oldNodeValue.next;
|
||||
*parentNode = oldNodeValue.next;
|
||||
|
||||
if (!oldNodeValue.next)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNodeValue.next].next;
|
||||
}
|
||||
|
||||
assert(oldNode);
|
||||
|
||||
tempNodeValue = oldNodeValue;
|
||||
oldNodeValue = game::gScrMemTreeGlob[inst].nodes[oldNode];
|
||||
game::gScrMemTreeGlob[inst].nodes[oldNode] = tempNodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldNode == nodeNum)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
level >>= 1;
|
||||
|
||||
if (oldNode >= nodeNum)
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[node].next;
|
||||
nodeNum += level;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[node].prev;
|
||||
nodeNum -= level;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_RemoveHeadMemoryNode(game::scriptInstance_t inst, int size)
|
||||
{
|
||||
game::MemoryNode tempNodeValue;
|
||||
int oldNode;
|
||||
game::MemoryNode oldNodeValue;
|
||||
uint16_t* parentNode;
|
||||
int prevScore;
|
||||
int nextScore;
|
||||
|
||||
assert(size >= 0 && size <= MT_NODE_BITS);
|
||||
|
||||
parentNode = &game::gScrMemTreeGlob[inst].head[size];
|
||||
oldNodeValue = game::gScrMemTreeGlob[inst].nodes[*parentNode];
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!oldNodeValue.prev)
|
||||
{
|
||||
oldNode = oldNodeValue.next;
|
||||
*parentNode = oldNodeValue.next;
|
||||
if (!oldNode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNode].next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldNodeValue.next)
|
||||
{
|
||||
prevScore = game::MT_GetScore(inst, oldNodeValue.prev);
|
||||
nextScore = game::MT_GetScore(inst, oldNodeValue.next);
|
||||
|
||||
assert(prevScore != nextScore);
|
||||
|
||||
if (prevScore >= nextScore)
|
||||
{
|
||||
oldNode = oldNodeValue.prev;
|
||||
*parentNode = (short)oldNode;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNode].prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldNode = oldNodeValue.next;
|
||||
*parentNode = (short)oldNode;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNode].next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldNode = oldNodeValue.prev;
|
||||
*parentNode = (short)oldNode;
|
||||
parentNode = &game::gScrMemTreeGlob[inst].nodes[oldNode].prev;
|
||||
}
|
||||
}
|
||||
assert(oldNode != 0);
|
||||
|
||||
tempNodeValue = oldNodeValue;
|
||||
oldNodeValue = game::gScrMemTreeGlob[inst].nodes[oldNode];
|
||||
game::gScrMemTreeGlob[inst].nodes[oldNode] = tempNodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_Init(game::scriptInstance_t inst)
|
||||
{
|
||||
game::Sys_EnterCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
|
||||
game::scrMemTreeGlob_t* memTreeBuffer = &game::gScrMemTreeGlob[inst];
|
||||
game::gScrMemTreePub[inst].mt_buffer = memTreeBuffer;
|
||||
|
||||
game::MT_InitBits(inst);
|
||||
|
||||
for (int i = 0; i <= MT_NODE_BITS; ++i)
|
||||
{
|
||||
memTreeBuffer->head[i] = 0;
|
||||
}
|
||||
|
||||
memTreeBuffer->nodes[0].next = 0;
|
||||
memTreeBuffer->nodes[0].prev = 0;
|
||||
|
||||
for (int i = 0; i < MT_NODE_BITS; ++i)
|
||||
{
|
||||
game::MT_AddMemoryNode(inst, 1 << i, i);
|
||||
}
|
||||
|
||||
game::Sys_LeaveCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_Error(game::scriptInstance_t inst, const char* funcName, int numBytes)
|
||||
{
|
||||
game::MT_DumpTree(inst);
|
||||
game::Com_Printf(game::CON_CHANNEL_PARSERSCRIPT, "%s: failed memory allocation of %d bytes for script usage\n", funcName, numBytes);
|
||||
game::Scr_DumpScriptThreads(inst);
|
||||
game::gScrVmPub[inst].terminal_error = 1;
|
||||
game::Scr_Error("failed memory allocation for script usage", inst, 0);
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
int MT_GetSize(int numBytes, game::scriptInstance_t inst)
|
||||
{
|
||||
int numBuckets;
|
||||
int result;
|
||||
|
||||
assert(numBytes > 0);
|
||||
|
||||
if (numBytes >= MT_NODE_COUNT)
|
||||
{
|
||||
game::MT_Error(inst, "MT_GetSize: max allocation exceeded", numBytes);
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
numBuckets = (numBytes + MT_NODE_SIZE - 1) / MT_NODE_SIZE - 1;
|
||||
if (numBuckets > MT_NUM_BUCKETS - 1)
|
||||
{
|
||||
result = game::gScrMemTreeGlob[inst].logBits[numBuckets >> 8] + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = game::gScrMemTreeGlob[inst].logBits[numBuckets];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
unsigned __int16 MT_AllocIndex(game::scriptInstance_t inst, int numBytes)
|
||||
{
|
||||
int nodeNum;
|
||||
int size = game::MT_GetSize(numBytes, inst);
|
||||
int newSize;
|
||||
|
||||
assert(size >= 0 && size <= MT_NODE_BITS);
|
||||
|
||||
game::Sys_EnterCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
|
||||
for (newSize = size; ; ++newSize)
|
||||
{
|
||||
if (newSize > MT_NODE_BITS)
|
||||
{
|
||||
game::Sys_LeaveCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
game::MT_Error(inst, "MT_AllocIndex", numBytes);
|
||||
return 0;
|
||||
}
|
||||
nodeNum = game::gScrMemTreeGlob[inst].head[newSize];
|
||||
if (game::gScrMemTreeGlob[inst].head[newSize])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
game::MT_RemoveHeadMemoryNode(inst, newSize);
|
||||
|
||||
while (newSize != size)
|
||||
{
|
||||
--newSize;
|
||||
game::MT_AddMemoryNode(inst, nodeNum + (1 << newSize), newSize);
|
||||
}
|
||||
|
||||
//assert(type);
|
||||
|
||||
//assert(!game::gScrMemTreeDebugGlob[inst].mt_usage[nodeNum]);
|
||||
|
||||
//assert(!game::gScrMemTreeDebugGlob[inst].mt_usage_size[nodeNum]);
|
||||
|
||||
game::Sys_LeaveCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
return (short)nodeNum;
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_FreeIndex(int numBytes, game::scriptInstance_t inst, int nodeNum)
|
||||
{
|
||||
int size = game::MT_GetSize(numBytes, inst);
|
||||
|
||||
assert(size >= 0 && size <= MT_NODE_BITS);
|
||||
|
||||
assert(nodeNum > 0 && nodeNum < MT_NODE_COUNT);
|
||||
|
||||
game::Sys_EnterCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
|
||||
//assert(game::gScrMemTreeDebugGlob[inst].mt_usage[nodeNum]);
|
||||
|
||||
//assert(game::gScrMemTreeDebugGlob[inst].mt_usage_size[nodeNum] == size);
|
||||
|
||||
for (int i = 1 << size; size != MT_NODE_BITS; i = 1 << ++size)
|
||||
{
|
||||
assert(size <= MT_NODE_BITS);
|
||||
|
||||
assert(nodeNum == (nodeNum & ~((1 << size) - 1)));
|
||||
|
||||
if (!game::MT_RemoveMemoryNode(inst, nodeNum ^ i, size))
|
||||
{
|
||||
break;
|
||||
}
|
||||
nodeNum &= ~i;
|
||||
}
|
||||
game::MT_AddMemoryNode(inst, nodeNum, size);
|
||||
|
||||
game::Sys_LeaveCriticalSection(game::CRITSECT_MEMORY_TREE);
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
char* MT_Alloc(int numBytes, game::scriptInstance_t inst)
|
||||
{
|
||||
return (char*)(game::gScrMemTreeGlob[inst].nodes + game::MT_AllocIndex(inst, numBytes));
|
||||
}
|
||||
|
||||
// Decomp Status: Tested, Completed
|
||||
void MT_Free(void* p, int numBytes, game::scriptInstance_t inst)
|
||||
{
|
||||
assert((game::MemoryNode*)p - game::gScrMemTreeGlob[inst].nodes >= 0 && (game::MemoryNode*)p - game::gScrMemTreeGlob[inst].nodes < MT_NODE_COUNT);
|
||||
|
||||
game::MT_FreeIndex(numBytes, inst, (game::MemoryNode*)p - game::gScrMemTreeGlob[inst].nodes);
|
||||
}
|
||||
|
||||
// Restored inlined function
|
||||
char* MT_GetRefByIndex(game::scriptInstance_t inst, int index)
|
||||
{
|
||||
if (index > MT_NODE_COUNT)
|
||||
{
|
||||
game::MT_Error(inst, "MT_GetRefByIndex: out of bounds index", index);
|
||||
return NULL;
|
||||
}
|
||||
return (char*)&game::gScrMemTreeGlob[inst].nodes[index];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user