mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 07:00:53 +01:00
351 lines
12 KiB
C++
351 lines
12 KiB
C++
#pragma once
|
|
|
|
#include <Misc/BSFixedString.h>
|
|
#include <tuple>
|
|
|
|
struct BSScript
|
|
{
|
|
struct Object
|
|
{
|
|
uint64_t GetHandle();
|
|
};
|
|
|
|
struct Variable
|
|
{
|
|
Variable();
|
|
~Variable() noexcept;
|
|
|
|
void Reset() noexcept;
|
|
void Clear() noexcept;
|
|
Object* GetObject() const noexcept;
|
|
|
|
template <class T> void Set(T aValue) noexcept
|
|
{
|
|
// static_assert(false);
|
|
}
|
|
|
|
template <class T> T* ExtractComplexType() noexcept;
|
|
|
|
enum Type : uint64_t
|
|
{
|
|
kEmpty,
|
|
kObject,
|
|
kString,
|
|
kInteger,
|
|
kFloat,
|
|
kBoolean,
|
|
|
|
kMax = 16
|
|
};
|
|
|
|
union Data
|
|
{
|
|
int32_t i;
|
|
const char* s;
|
|
float f;
|
|
bool b;
|
|
Object* pObj;
|
|
};
|
|
|
|
Type type;
|
|
Data data;
|
|
};
|
|
|
|
// https://github.com/Ryan-rsm-McKenzie/CommonLibSSE/blob/master/include/RE/I/IFunction.h
|
|
|
|
enum class FunctionType
|
|
{
|
|
kNormal = 0,
|
|
kGetter = 1,
|
|
kSetter = 2
|
|
};
|
|
|
|
enum class CallResult
|
|
{
|
|
kCompleted = 0,
|
|
kSetupForVM = 1,
|
|
kInProgress = 2,
|
|
kFailedRetry = 3,
|
|
kFailedAbort = 4
|
|
};
|
|
|
|
struct StackFrame;
|
|
struct Stack;
|
|
struct IVirtualMachine;
|
|
|
|
struct IFunction : BSIntrusiveRefCounted
|
|
{
|
|
virtual ~IFunction() = default;
|
|
virtual BSFixedString& GetName() = 0;
|
|
virtual BSFixedString& GetObjectTypeName() = 0;
|
|
virtual BSFixedString& GetStateName() = 0;
|
|
virtual Variable::Type& GetReturnType() = 0;
|
|
virtual uint32_t GetParamCount() = 0;
|
|
virtual void GetParam(uint32_t aIndex, BSFixedString& apNameOut, Variable::Type& apTypeOut) = 0;
|
|
virtual uint32_t GetStackFrameSize() = 0;
|
|
virtual bool GetIsNative() = 0;
|
|
virtual bool GetIsStatic() = 0;
|
|
virtual bool GetIsEmpty() = 0;
|
|
virtual FunctionType GetFunctionType() = 0;
|
|
virtual uint32_t GetUserFlags() = 0;
|
|
virtual BSFixedString& GetDocString() = 0;
|
|
virtual void InsertLocals(StackFrame* apFrame) = 0;
|
|
// TODO: is actually GameVM
|
|
virtual CallResult Call(Stack* apStack, void* apLogger, IVirtualMachine* apVm, bool aArg4) = 0;
|
|
virtual BSFixedString& GetSourceFilename() = 0;
|
|
virtual bool TranslateIPToLineNumber(uint32_t aIndexPtr, uint32_t& aLineNumberOut) = 0;
|
|
virtual bool GetVarNameForStackIndex(uint32_t aIndex, BSFixedString& aNameOut) = 0;
|
|
virtual bool CanBeCalledFromTasklets() = 0;
|
|
virtual void SetCallableFromTasklets(bool aCallable) = 0;
|
|
};
|
|
|
|
struct IFunctionArguments
|
|
{
|
|
struct Statement
|
|
{
|
|
void SetSize(uint32_t aCount) noexcept;
|
|
|
|
uint8_t pad0[8];
|
|
Variable* vars;
|
|
};
|
|
|
|
virtual ~IFunctionArguments() {}
|
|
|
|
virtual void Prepare(Statement* apUnk) noexcept = 0;
|
|
};
|
|
|
|
struct Stack
|
|
{
|
|
uint32_t GetPageForFrame(StackFrame* apFrame)
|
|
{
|
|
TP_THIS_FUNCTION(TGetPageForFrame, uint32_t, Stack, StackFrame*);
|
|
POINTER_SKYRIMSE(TGetPageForFrame, getPageForFrame, 104483);
|
|
return TiltedPhoques::ThisCall(getPageForFrame, this, apFrame);
|
|
}
|
|
|
|
Variable* GetStackFrameVariable(StackFrame* apFrame, uint32_t aIndex, uint32_t aPageHint)
|
|
{
|
|
TP_THIS_FUNCTION(TGetStackFrameVariable, Variable*, Stack, StackFrame*, uint32_t, uint32_t);
|
|
POINTER_SKYRIMSE(TGetStackFrameVariable, getStackFrameVariable, 104484);
|
|
return TiltedPhoques::ThisCall(getStackFrameVariable, this, apFrame, aIndex, aPageHint);
|
|
}
|
|
};
|
|
|
|
struct StackFrame
|
|
{
|
|
uint32_t GetPageForFrame() { return pParent->GetPageForFrame(this); }
|
|
|
|
Variable* GetStackFrameVariable(uint32_t aIndex, uint32_t aPageHint) { return pParent->GetStackFrameVariable(this, aIndex, aPageHint); }
|
|
|
|
Stack* pParent;
|
|
};
|
|
|
|
struct IObjectHandlePolicy
|
|
{
|
|
static IObjectHandlePolicy* Get() noexcept;
|
|
|
|
virtual ~IObjectHandlePolicy();
|
|
virtual bool HandleIsType(uint32_t aType, uint64_t aHandle);
|
|
virtual bool IsHandleObjectAvailable(uint64_t aHandle);
|
|
virtual void sub_03();
|
|
virtual void sub_04();
|
|
virtual void sub_05();
|
|
virtual void sub_06();
|
|
virtual void sub_07();
|
|
virtual void* GetObjectForHandle(uint32_t aType, uint64_t aHandle);
|
|
|
|
template <class T> T* GetObjectForHandle(uint64_t aHandle) { return (T*)(BSScript::IObjectHandlePolicy::Get()->GetObjectForHandle((uint32_t)T::Type, aHandle)); }
|
|
};
|
|
|
|
struct IVirtualMachine
|
|
{
|
|
virtual ~IVirtualMachine() = 0;
|
|
|
|
virtual void sub_01();
|
|
virtual void sub_02();
|
|
virtual void sub_03();
|
|
virtual void sub_04();
|
|
virtual void sub_05();
|
|
virtual void sub_06();
|
|
virtual void sub_07();
|
|
virtual void sub_08();
|
|
virtual void GetScriptObjectType1(BSFixedString* apClassName, void** apOutTypeInfoPtr);
|
|
virtual void sub_0A();
|
|
virtual void sub_0B();
|
|
virtual void sub_0C();
|
|
virtual void sub_0D();
|
|
virtual void sub_0E();
|
|
virtual void sub_0F();
|
|
virtual void sub_10();
|
|
virtual void sub_11();
|
|
virtual void sub_12();
|
|
virtual void sub_13();
|
|
virtual void sub_14();
|
|
virtual void sub_15();
|
|
virtual void sub_16();
|
|
virtual void sub_17();
|
|
virtual void BindNativeMethod(IFunction* apFunction);
|
|
virtual void sub_19();
|
|
virtual void sub_1A();
|
|
virtual void sub_1B();
|
|
virtual void sub_1C();
|
|
virtual void sub_1D();
|
|
virtual void sub_1E();
|
|
virtual void sub_1F();
|
|
virtual void sub_20();
|
|
virtual void sub_21();
|
|
virtual void sub_22();
|
|
virtual void sub_23();
|
|
virtual void SendEvent(uint64_t aId, const BSFixedString& acEventName, IFunctionArguments* apArgs) const noexcept;
|
|
virtual void sub_25();
|
|
virtual void sub_26();
|
|
virtual void sub_27();
|
|
virtual void sub_28();
|
|
virtual void sub_29();
|
|
virtual void sub_2A();
|
|
virtual void sub_2B();
|
|
virtual void sub_2C();
|
|
virtual IObjectHandlePolicy* GetObjectHandlePolicy();
|
|
};
|
|
|
|
struct NativeFunctionBase : IFunction
|
|
{
|
|
BSFixedString& GetName() override;
|
|
BSFixedString& GetObjectTypeName() override;
|
|
BSFixedString& GetStateName() override;
|
|
Variable::Type& GetReturnType() override;
|
|
std::uint32_t GetParamCount() override;
|
|
void GetParam(uint32_t aIndex, BSFixedString& apNameOut, Variable::Type& a_typeOut) override;
|
|
uint32_t GetStackFrameSize() override;
|
|
bool GetIsNative() override;
|
|
bool GetIsStatic() override;
|
|
bool GetIsEmpty() override;
|
|
FunctionType GetFunctionType() override;
|
|
std::uint32_t GetUserFlags() override;
|
|
BSFixedString& GetDocString() override;
|
|
void InsertLocals(StackFrame* apFrame) override;
|
|
CallResult Call(Stack* apStack, void* apLogger, IVirtualMachine* apVm, bool aArg4) override;
|
|
BSFixedString& GetSourceFilename() override;
|
|
bool TranslateIPToLineNumber(uint32_t aTaskletExecutionOffset, uint32_t& aLineNumberOut) override;
|
|
bool GetVarNameForStackIndex(uint32_t aIndex, BSFixedString& aNameOut) override;
|
|
bool CanBeCalledFromTasklets() override;
|
|
void SetCallableFromTasklets(bool aCallable) override;
|
|
|
|
virtual bool HasCallback() { return false; }
|
|
virtual bool MarshallAndDispatch(Variable* apBaseVar, IVirtualMachine* apVm, uint32_t aStackID, Variable* apResult, StackFrame* apStackFrame) { return false; }
|
|
|
|
struct Parameters
|
|
{
|
|
struct Entry
|
|
{
|
|
const char* name;
|
|
union
|
|
{
|
|
Variable::Type type;
|
|
void* pType;
|
|
};
|
|
};
|
|
|
|
Entry* data;
|
|
uint16_t size;
|
|
uint16_t capacity;
|
|
};
|
|
|
|
BSFixedString name;
|
|
BSFixedString objectName;
|
|
BSFixedString stateName;
|
|
Variable::Type returnType;
|
|
Parameters parameters;
|
|
bool isStatic;
|
|
bool isCallableFromTask;
|
|
bool isLatent;
|
|
uint8_t pad43;
|
|
uint32_t flags;
|
|
BSFixedString documentation;
|
|
};
|
|
static_assert(sizeof(NativeFunctionBase) == 0x50);
|
|
|
|
struct NativeFunction : NativeFunctionBase
|
|
{
|
|
virtual ~NativeFunction()
|
|
{
|
|
TP_THIS_FUNCTION(TNativeFunctionDtor, void, NativeFunction);
|
|
// TODO: not sure about this address
|
|
POINTER_SKYRIMSE(TNativeFunctionDtor, dtor, 104655);
|
|
TiltedPhoques::ThisCall(dtor, this);
|
|
}
|
|
|
|
NativeFunction(const char* apFunctionName, const char* apClassName, bool aIsStatic, uint32_t aParameterCount)
|
|
{
|
|
TP_THIS_FUNCTION(TNativeFunctionCtor, void, NativeFunction, const char*, const char*, bool, uint32_t);
|
|
POINTER_SKYRIMSE(TNativeFunctionCtor, ctor, 104653);
|
|
TiltedPhoques::ThisCall(ctor, this, apFunctionName, apClassName, aIsStatic, aParameterCount);
|
|
}
|
|
|
|
bool HasCallback() override { return pFunction != nullptr; }
|
|
|
|
void* pFunction;
|
|
};
|
|
|
|
// TODO: template stuff for a cleaner implementation
|
|
// https://github.com/Ryan-rsm-McKenzie/CommonLibSSE/blob/master/include/RE/N/NativeFunction.h
|
|
|
|
struct IsRemotePlayerFunc : NativeFunction
|
|
{
|
|
using FunctionType = bool(Actor* pBase);
|
|
|
|
IsRemotePlayerFunc(const char* apFunctionName, const char* apClassName, FunctionType aFunction, Variable::Type aType);
|
|
|
|
bool MarshallAndDispatch(Variable* apBaseVar, IVirtualMachine* apVm, uint32_t aStackID, Variable* apResult, StackFrame* apStackFrame) override;
|
|
};
|
|
|
|
struct IsPlayerFunc : NativeFunction
|
|
{
|
|
using FunctionType = bool(Actor* pBase);
|
|
|
|
IsPlayerFunc(const char* apFunctionName, const char* apClassName, FunctionType aFunction, Variable::Type aType);
|
|
|
|
bool MarshallAndDispatch(Variable* apBaseVar, IVirtualMachine* apVm, uint32_t aStackID, Variable* apResult, StackFrame* apStackFrame) override;
|
|
};
|
|
|
|
struct DidLaunchSkyrimTogetherFunc : NativeFunction
|
|
{
|
|
using FunctionType = bool();
|
|
|
|
DidLaunchSkyrimTogetherFunc(const char* apFunctionName, const char* apClassName, FunctionType aFunction, Variable::Type aType);
|
|
|
|
bool MarshallAndDispatch(Variable* apBaseVar, IVirtualMachine* apVm, uint32_t aStackID, Variable* apResult, StackFrame* apStackFrame) override;
|
|
};
|
|
|
|
// Bad PoC code
|
|
#if 0
|
|
template <class... T> struct EventArguments : IFunctionArguments
|
|
{
|
|
using Tuple = std::tuple<EventArguments...>;
|
|
|
|
EventArguments(T... args)
|
|
: args(std::forward<T>(args)...)
|
|
{
|
|
}
|
|
|
|
virtual ~EventArguments(){};
|
|
|
|
virtual void Prepare(IFunctionArguments::Statement* apStatement) noexcept
|
|
{
|
|
apStatement->SetSize(std::tuple_size_v<std::remove_reference_t<Tuple>>);
|
|
|
|
PrepareImplementation(apStatement, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
|
|
}
|
|
|
|
private:
|
|
template <std::size_t... Is> void PrepareImplementation(IFunctionArguments::Statement* apStatement, std::index_sequence<Is...>) noexcept { ((apStatement->vars[Is].Set(std::get<Is>(args))), ...); }
|
|
|
|
Tuple args;
|
|
};
|
|
#endif
|
|
};
|
|
|
|
template <> void BSScript::Variable::Set(int32_t aValue) noexcept;
|
|
template <> void BSScript::Variable::Set(float aValue) noexcept;
|
|
template <> void BSScript::Variable::Set(bool aValue) noexcept;
|
|
template <> void BSScript::Variable::Set(const char* acpValue) noexcept;
|