4
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

132 lines
3.3 KiB

#include "skse64/NiObjects.h"
#include "skse64/NiExtraData.h"
// 2789403034E226069B9EC04A8AC7BD367AF61384+BC
RelocPtr<float> g_worldToCamMatrix(0x02FE8840);
// 2789403034E226069B9EC04A8AC7BD367AF61384+13E
RelocPtr<NiRect<float>> g_viewPort(0x02FE9DE8);
RelocAddr<_WorldPtToScreenPt3_Internal> WorldPtToScreenPt3_Internal(0x00C8F5B0);
RelocAddr<_NiAllocate> NiAllocate(0x00C4AF80);
RelocAddr<_NiFree> NiFree(0x00C4B220);
void NiRefObject::IncRef(void)
{
InterlockedIncrement(&m_uiRefCount);
}
bool NiRefObject::Release(void)
{
return InterlockedDecrement(&m_uiRefCount) == 0;
}
void NiRefObject::DecRef(void)
{
if (Release())
DeleteThis();
}
int ExtraDataCompare(const void * ls, const void * rs)
{
return (int)((*(NiExtraData**)ls)->m_pcName - (*(NiExtraData**)rs)->m_pcName);
}
void NiObjectNET::AddExtraData(NiExtraData * extraData)
{
extraData->IncRef();
// No capacity, allocate and grow
UInt32 newSize = 0;
if (m_extraDataCapacity == 0) {
newSize = 1;
NiExtraData ** extraDataList = (NiExtraData **)Heap_Allocate(newSize * sizeof(NiExtraData*));
extraDataList[0] = extraData;
m_extraData = extraDataList;
m_extraDataCapacity = newSize;
m_extraDataLen = m_extraDataCapacity;
return;
}
// Reached capacity, reallocate and grow
if (m_extraDataLen == m_extraDataCapacity) {
newSize = (m_extraDataCapacity * 2) + 1;
NiExtraData ** extraDataList = (NiExtraData **)Heap_Allocate(newSize * sizeof(NiExtraData*));
// Copy the entries over
memcpy_s(extraDataList, newSize * sizeof(NiExtraData*), m_extraData, m_extraDataLen * sizeof(NiExtraData*));
// Zero the allocated entries
for (UInt16 i = m_extraDataLen; i < newSize; i++)
extraDataList[i] = NULL;
Heap_Free(m_extraData);
m_extraData = extraDataList;
m_extraDataCapacity = newSize;
}
m_extraData[m_extraDataLen++] = extraData;
qsort(m_extraData, m_extraDataLen, sizeof(NiExtraData*), ExtraDataCompare);
}
SInt32 NiObjectNET::GetIndexOf(NiExtraData * extraData)
{
if (!extraData)
return -1;
if (!extraData->m_pcName)
return -1;
SInt16 min = 0;
SInt16 max = (SInt16)m_extraDataLen - 1;
while (max >= min) { // Iterative binary search
SInt16 mid = (min + max) >> 1;
if (m_extraData[mid]->m_pcName == extraData->m_pcName)
return mid; // Found entry
else if (m_extraData[mid]->m_pcName < extraData->m_pcName)
min = mid + 1;
else
max = mid - 1;
}
return -1;
}
bool NiObjectNET::RemoveExtraData(NiExtraData * extraData)
{
SInt32 index = GetIndexOf(extraData);
if (index >= 0) { // Remove the entry
extraData->DecRef();
// Shift everything up
for (UInt16 i = index; i < m_extraDataLen - 1; i++)
m_extraData[i] = m_extraData[i + 1];
// Remove the duplicate tail entry
m_extraData[--m_extraDataLen] = NULL;
if (m_extraDataLen == 0)
{
Heap_Free(m_extraData);
m_extraData = NULL;
m_extraDataLen = 0;
m_extraDataCapacity = 0;
}
return true;
}
return false;
}
// This should be a BSFixedString before passing to this
NiExtraData * NiObjectNET::GetExtraData(BSFixedString name)
{
SInt16 min = 0;
SInt16 max = (SInt16)m_extraDataLen - 1;
while (max >= min) { // Iterative binary search
SInt16 mid = (min + max) >> 1;
if (m_extraData[mid]->m_pcName == name.data)
return m_extraData[mid];
else if (m_extraData[mid]->m_pcName < name.data)
min = mid + 1;
else
max = mid - 1;
}
return NULL;
}