293 lines
7.3 KiB
C++
293 lines
7.3 KiB
C++
#include "skse64/PapyrusArgs.h"
|
|
#include "skse64/PapyrusNativeFunctions.h"
|
|
#include "skse64/PapyrusVM.h"
|
|
#include "skse64/GameForms.h"
|
|
|
|
//// type -> VMValue
|
|
|
|
template <> void PackValue <void>(VMValue * dst, void * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetNone();
|
|
}
|
|
|
|
template <> void PackValue <UInt32>(VMValue * dst, UInt32 * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetInt(*src);
|
|
}
|
|
|
|
template <> void PackValue <SInt32>(VMValue * dst, SInt32 * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetInt(*src);
|
|
}
|
|
|
|
template <> void PackValue <float>(VMValue * dst, float * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetFloat(*src);
|
|
}
|
|
|
|
template <> void PackValue <bool>(VMValue * dst, bool * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetBool(*src);
|
|
}
|
|
|
|
template <> void PackValue <BSFixedString>(VMValue * dst, BSFixedString * src, VMClassRegistry * registry)
|
|
{
|
|
dst->SetString(src->data);
|
|
}
|
|
|
|
void BindID(VMIdentifier ** identifier, void * srcData, VMClassRegistry * registry, IObjectHandlePolicy * handlePolicy, UInt32 typeID)
|
|
{
|
|
UInt32 unk = 0;
|
|
|
|
VMClassInfo * classInfo = (*identifier)->m_type;
|
|
if(classInfo)
|
|
classInfo->AddRef();
|
|
|
|
if(registry->Unk_0D(&classInfo->name, &unk))
|
|
{
|
|
UInt64 handle = handlePolicy->Create(typeID, srcData);
|
|
|
|
if( handlePolicy->IsType(unk, handle) ||
|
|
(handle == handlePolicy->GetInvalidHandle()))
|
|
{
|
|
CALL_MEMBER_FN(registry->GetObjectBindPolicy(), BindObject)(identifier, handle);
|
|
}
|
|
}
|
|
|
|
if(classInfo)
|
|
classInfo->Release();
|
|
}
|
|
|
|
void PackHandle(VMValue * dst, void * src, UInt32 typeID, VMClassRegistry * registry)
|
|
{
|
|
dst->SetNone();
|
|
|
|
if(!src) return;
|
|
|
|
VMClassInfo * classInfo = NULL;
|
|
|
|
// get class info
|
|
if(registry->GetFormTypeClass(typeID, &classInfo))
|
|
if(classInfo)
|
|
classInfo->Release();
|
|
|
|
if(!classInfo) return;
|
|
|
|
IObjectHandlePolicy * handlePolicy = registry->GetHandlePolicy();
|
|
|
|
UInt64 handle = handlePolicy->Create(typeID, src);
|
|
VMIdentifier * identifier = NULL;
|
|
|
|
// find existing identifier
|
|
if(!registry->Unk_1C(handle, classInfo->name.data, &identifier))
|
|
{
|
|
if(registry->Unk_15(&classInfo->name, &identifier))
|
|
{
|
|
if(identifier)
|
|
{
|
|
BindID(&identifier, src, registry, handlePolicy, typeID);
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy the identifier out
|
|
if(identifier)
|
|
{
|
|
VMValue tempValue;
|
|
|
|
tempValue.SetIdentifier(classInfo);
|
|
|
|
CALL_MEMBER_FN(dst, Set)(&tempValue);
|
|
dst->SetIdentifier(&identifier);
|
|
}
|
|
|
|
// release our reference
|
|
if(identifier)
|
|
{
|
|
if(!identifier->DecrementLock())
|
|
{
|
|
identifier->Destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
//// VMValue -> type
|
|
|
|
template <> void UnpackValue <float>(float * dst, VMValue * src)
|
|
{
|
|
switch(src->type)
|
|
{
|
|
case VMValue::kType_Int:
|
|
*dst = src->data.i;
|
|
break;
|
|
|
|
case VMValue::kType_Float:
|
|
*dst = src->data.f;
|
|
break;
|
|
|
|
case VMValue::kType_Bool:
|
|
*dst = src->data.b;
|
|
break;
|
|
|
|
default:
|
|
*dst = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
template <> void UnpackValue <UInt32>(UInt32 * dst, VMValue * src)
|
|
{
|
|
switch(src->type)
|
|
{
|
|
case VMValue::kType_Int:
|
|
*dst = src->data.u;
|
|
break;
|
|
|
|
case VMValue::kType_Float:
|
|
*dst = src->data.f;
|
|
break;
|
|
|
|
case VMValue::kType_Bool:
|
|
*dst = src->data.b;
|
|
break;
|
|
|
|
default:
|
|
*dst = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
template <> void UnpackValue <SInt32>(SInt32 * dst, VMValue * src)
|
|
{
|
|
switch(src->type)
|
|
{
|
|
case VMValue::kType_Int:
|
|
*dst = src->data.u;
|
|
break;
|
|
|
|
case VMValue::kType_Float:
|
|
*dst = src->data.f;
|
|
break;
|
|
|
|
case VMValue::kType_Bool:
|
|
*dst = src->data.b;
|
|
break;
|
|
|
|
default:
|
|
*dst = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
template <> void UnpackValue <bool>(bool * dst, VMValue * src)
|
|
{
|
|
switch(src->type)
|
|
{
|
|
case VMValue::kType_Int:
|
|
*dst = src->data.u != 0;
|
|
break;
|
|
|
|
case VMValue::kType_Float:
|
|
*dst = src->data.f != 0;
|
|
break;
|
|
|
|
case VMValue::kType_Bool:
|
|
*dst = src->data.b;
|
|
break;
|
|
|
|
default:
|
|
*dst = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
template <> void UnpackValue <BSFixedString>(BSFixedString * dst, VMValue * src)
|
|
{
|
|
const char * data = NULL;
|
|
|
|
if(src->type == VMValue::kType_String)
|
|
data = src->data.str;
|
|
|
|
CALL_MEMBER_FN(dst, Set)(data);
|
|
}
|
|
|
|
template <> void UnpackValue <VMArray<UInt32>>(VMArray<UInt32> * dst, VMValue * src)
|
|
{
|
|
UnpackArray(dst, src, VMValue::kType_IntArray);
|
|
}
|
|
|
|
template <> void UnpackValue <VMArray<SInt32>>(VMArray<SInt32> * dst, VMValue * src)
|
|
{
|
|
UnpackArray(dst, src, VMValue::kType_IntArray);
|
|
}
|
|
|
|
template <> void UnpackValue <VMArray<float>>(VMArray<float> * dst, VMValue * src)
|
|
{
|
|
UnpackArray(dst, src, VMValue::kType_FloatArray);
|
|
}
|
|
|
|
template <> void UnpackValue <VMArray<bool>>(VMArray<bool> * dst, VMValue * src)
|
|
{
|
|
UnpackArray(dst, src, VMValue::kType_BoolArray);
|
|
}
|
|
|
|
template <> void UnpackValue <VMArray<BSFixedString>>(VMArray<BSFixedString> * dst, VMValue * src)
|
|
{
|
|
UnpackArray(dst, src, VMValue::kType_StringArray);
|
|
}
|
|
|
|
void * UnpackHandle(VMValue * src, UInt32 typeID)
|
|
{
|
|
if(!src->IsIdentifier()) return NULL;
|
|
if(!src->data.id) return NULL;
|
|
|
|
UInt64 handle = src->data.id->GetHandle();
|
|
|
|
if(!(*g_objectHandlePolicy)->IsType(typeID, handle)) return NULL;
|
|
if(!(*g_objectHandlePolicy)->Unk_02(handle)) return NULL;
|
|
|
|
return (*g_objectHandlePolicy)->Resolve(typeID, handle);
|
|
}
|
|
|
|
//// type -> type ID
|
|
|
|
template <> UInt64 GetTypeID <void>(VMClassRegistry * registry) { return VMValue::kType_None; }
|
|
template <> UInt64 GetTypeID <UInt32>(VMClassRegistry * registry) { return VMValue::kType_Int; }
|
|
template <> UInt64 GetTypeID <SInt32>(VMClassRegistry * registry) { return VMValue::kType_Int; }
|
|
template <> UInt64 GetTypeID <int>(VMClassRegistry * registry) { return VMValue::kType_Int; }
|
|
template <> UInt64 GetTypeID <float>(VMClassRegistry * registry) { return VMValue::kType_Float; }
|
|
template <> UInt64 GetTypeID <bool>(VMClassRegistry * registry) { return VMValue::kType_Bool; }
|
|
template <> UInt64 GetTypeID <BSFixedString>(VMClassRegistry * registry) { return VMValue::kType_String; }
|
|
|
|
template <> UInt64 GetTypeID <VMArray<UInt32>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMArray<SInt32>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMArray<int>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMArray<float>>(VMClassRegistry * registry) { return VMValue::kType_FloatArray; }
|
|
template <> UInt64 GetTypeID <VMArray<bool>>(VMClassRegistry * registry) { return VMValue::kType_BoolArray; }
|
|
template <> UInt64 GetTypeID <VMArray<BSFixedString>>(VMClassRegistry * registry) { return VMValue::kType_StringArray; }
|
|
|
|
template <> UInt64 GetTypeID <VMResultArray<UInt32>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMResultArray<SInt32>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMResultArray<int>>(VMClassRegistry * registry) { return VMValue::kType_IntArray; }
|
|
template <> UInt64 GetTypeID <VMResultArray<float>>(VMClassRegistry * registry) { return VMValue::kType_FloatArray; }
|
|
template <> UInt64 GetTypeID <VMResultArray<bool>>(VMClassRegistry * registry) { return VMValue::kType_BoolArray; }
|
|
template <> UInt64 GetTypeID <VMResultArray<BSFixedString>>(VMClassRegistry * registry) { return VMValue::kType_StringArray; }
|
|
|
|
UInt64 GetTypeIDFromFormTypeID(UInt32 formTypeID, VMClassRegistry * registry)
|
|
{
|
|
UInt64 result = 0;
|
|
VMClassInfo * info = NULL;
|
|
|
|
if(registry->GetFormTypeClass(formTypeID, &info))
|
|
{
|
|
if(info)
|
|
{
|
|
result = (UInt64)info;
|
|
|
|
info->Release(); // yes, really
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|