# pragma once
# include "skse64_common/Utilities.h"
# include "skse64/GameTypes.h"
# include "skse64/GameUtilities.h"
# include "skse64/PapyrusValue.h"
# include "skse64/PapyrusInterfaces.h"
class IFunction ;
class VMIdentifier ;
class VMValue ;
class VMClassRegistry ;
class IFunctionArguments ;
class DelayFunctor ;
class VMClassFunctionVisitor
{
public :
virtual bool Accept ( IFunction * func ) = 0 ;
} ;
// ??
class VMClassInfo
{
public :
SInt32 refCount ; // 00
UInt32 unk04 ; // 04
StringCache : : Ref name ; // 08
VMClassInfo * parent ; // 10
StringCache : : Ref * unk0C ; // 18
// ... More
//UInt32 unk10; // 10
//UInt32 unk14; // 14
//UInt32 numFuncs; // 18
//UInt32 funcPtr; // 1C
/*IFunction** GetFunctions() const
{
return ( IFunction * * ) ( funcPtr +
4 * (
( ( unk14 > > 10 ) & 0x3FF ) * 10 +
( ( unk10 > > 8 ) & 0x3FF ) * 2 +
( ( unk10 > > 2 ) & 0x3F ) +
( unk14 & 0x3FF ) * 3
)
) ;
}
UInt32 GetNumMemberFunctions ( ) const
{
return numFuncs & 0x1FF ;
}
UInt32 GetNumGlobalFunctions ( ) const
{
return ( unk14 > > 20 ) & 0x1FF ;
}
void Visit ( VMClassFunctionVisitor & visitor )
{
UInt32 globalFns = GetNumGlobalFunctions ( ) ;
UInt32 memberFns = GetNumMemberFunctions ( ) ;
IFunction * * funcPtr = GetFunctions ( ) ;
for ( UInt32 i = 0 ; i < globalFns + memberFns ; i + + ) {
IFunction * func = funcPtr [ i ] ;
if ( func ) {
if ( visitor . Accept ( func ) )
break ;
}
}
} */
void AddRef ( void ) ;
void Release ( void ) ;
MEMBER_FN_PREFIX ( VMClassInfo ) ;
DEFINE_MEMBER_FN ( Destroy , void , 0x013626F0 ) ;
DEFINE_MEMBER_FN ( GetVariable , SInt32 , 0x01363980 , BSFixedString * name ) ;
//
DEFINE_MEMBER_FN ( GetFunction , IFunction * , 0x013670C0 , const char * fnName ) ;
} ;
// This type is not fully decoded or correctly sized, just enough to use the functor
class VMScriptInstance
{
public :
UInt32 unk00 ;
VMClassInfo * classInfo ;
void * unk08 ;
UInt32 unk0C ;
UInt32 formId ;
UInt32 unk14 ;
UInt32 unk18 ;
} ;
// 04
class IForEachScriptObjectFunctor
{
public :
IForEachScriptObjectFunctor ( ) { } ;
virtual ~ IForEachScriptObjectFunctor ( ) { } ;
// return true to continue
virtual bool Visit ( VMScriptInstance * arg , void * arg2 ) { return false ; } ;
// void ** _vtbl; // 00
} ;
// 48+
class VMUnlinkedClassList
{
virtual ~ VMUnlinkedClassList ( ) { }
virtual VMUnlinkedClassList * Create ( void ) ;
virtual void SetUnk0C ( void * arg ) ;
virtual bool Link ( StringCache : : Ref * className ) ;
// void ** _vtbl; // 00
VMClassRegistry * unk04 ; // 04
void * unk08 ; // 08
void * unk0C ; // 0C - loader
UInt8 unk10 ; // 10
UInt8 pad11 [ 3 ] ; // 11
UInt32 unk14 ; // 14
UInt32 unk18 ; // 18
UInt32 unk1C ; // 1C
void * unk20 ; // 20
UInt32 unk24 ; // 24
UInt32 unk28 ; // 28
UInt32 unk2C ; // 2C
void * unk30 ; // 30
UInt32 unk34 ; // 34
UInt32 unk38 ; // 38
UInt32 unk3C ; // 3C
void * unk40 ; // 40
UInt32 unk44 ; // 44
} ;
// 044
class VMStackInfo
{
public :
virtual ~ VMStackInfo ( ) ;
// more virtual functions ...
//void** _vtbl; // 000
SInt32 refCount ; // 004
const char * rootCallName ; // 008 - not sure if BSFixedString
const char * scriptName ; // 00C - not sure if BSFixedString
// ...
} ;
// ??
class UnkVMStackData1
{
public :
UInt32 unk000 ; // 000
void * unk004 ; // 004
UInt32 unk008 ; // 008
VMStackInfo * stackInfo ; // 00C
// ...
} ;
// ??
class UnkVMStackData2
{
public :
UInt32 unk000 ; // 000 - refCount?
void * unk004 ; // 004
UInt32 unk008 ; // 008
UInt32 unk00C ; // 00C
UnkVMStackData1 * unkData ; // 010
// ...
} ;
// 00C
class VMStackTableItem
{
public :
UInt32 stackId ;
UnkVMStackData2 * data ;
operator UInt32 ( ) const { return stackId ; }
static inline UInt32 GetHash ( UInt32 * pStackId )
{
UInt32 hash ;
CalculateCRC32_32 ( & hash , * pStackId ) ;
return hash ;
}
} ;
// 4B04
// this does more than hold on to class registrations, but for now that's all we care about
class VMClassRegistry
{
public :
enum
{
kFunctionFlag_NoWait = 0x01 // set this only if your function is thread-safe
} ;
enum
{
kLogLevel_Info = 0 ,
kLogLevel_Warning ,
kLogLevel_Error ,
kLogLevel_Fatal
} ;
typedef tHashSet < VMStackTableItem , UInt32 > StackTableT ;
VMClassRegistry ( ) ;
virtual ~ VMClassRegistry ( ) ;
// ### indices are from 1.5.26
virtual void Unk_01 ( void ) ;
virtual void PrintToDebugLog ( const char * text , UInt32 stackId , UInt32 logLevel ) ;
virtual void Unk_03 ( void ) ;
virtual void Unk_04 ( void ) ;
virtual void Unk_05 ( void ) ;
virtual void Unk_06 ( void ) ;
virtual void Unk_07 ( void ) ;
virtual void RegisterForm ( UInt32 typeID , const char * papyrusClassName ) ;
virtual void Unk_09 ( void ) ;
virtual bool GetFormTypeClass ( UInt32 formType , VMClassInfo * * outClass ) ;
virtual void Unk_0B ( void ) ;
virtual void Unk_0C ( void ) ;
virtual bool Unk_0D ( StringCache : : Ref * className , UInt32 * unk ) ;
virtual void Unk_0E ( void ) ;
virtual void Unk_0F ( void ) ;
virtual void Unk_10 ( void ) ;
virtual void Unk_11 ( void ) ;
virtual void Unk_12 ( void ) ;
virtual void Unk_13 ( void ) ;
virtual void Unk_14 ( void ) ;
virtual bool Unk_15 ( StringCache : : Ref * className , VMIdentifier * * identifier ) ;
virtual bool CreateArray ( VMValue * value , UInt32 size , VMValue : : ArrayData * * unk1 ) ;
virtual void Unk_17 ( void ) ;
virtual void RegisterFunction ( IFunction * fn ) ;
virtual void SetFunctionFlagsEx ( const char * className , UInt32 unk0 , const char * fnName , UInt32 flags ) ;
virtual void SetFunctionFlags ( const char * className , const char * fnName , UInt32 flags ) ;
virtual void VisitScripts ( UInt64 handle , IForEachScriptObjectFunctor * functor ) ;
virtual bool Unk_1C ( UInt64 handle , const char * className , VMIdentifier * * identifier ) ;
virtual void Unk_1D ( void ) ;
virtual void Unk_1E ( void ) ;
virtual void Unk_1F ( void ) ;
virtual void Unk_20 ( void ) ;
virtual void Unk_21 ( void ) ;
virtual void Unk_22 ( void ) ;
virtual bool ExtractValue ( UInt64 handle , StringCache : : Ref * className , SInt32 variableIndex , VMValue * out ) ; // unk probably script context object?
virtual void QueueEvent ( UInt64 handle , const StringCache : : Ref * eventName , IFunctionArguments * args ) ;
virtual void Unk_25 ( void ) ;
virtual void Unk_26 ( void ) ;
virtual void Unk_27 ( void ) ;
virtual void Unk_28 ( void ) ;
virtual void Unk_29 ( void ) ;
virtual void Unk_2A ( void ) ;
virtual void ResumeStack ( UInt32 stackId , VMValue * result ) ;
virtual void Unk_2C ( void ) ;
virtual IObjectHandlePolicy * GetHandlePolicy ( void ) ;
virtual void Unk_2E ( void ) ;
virtual ObjectBindPolicy * GetObjectBindPolicy ( void ) ;
virtual void Unk_30 ( void ) ;
virtual void Unk_31 ( void ) ;
virtual void Unk_32 ( void ) ;
virtual void Unk_33 ( void ) ;
virtual void Unk_34 ( void ) ;
virtual void Unk_35 ( void ) ;
// void ** _vtbl; // 0000
UInt64 unk0008 ; // 0008 - refcount?
void * * vtbl0008 ; // 0010
void * * vtbl000C ; // 0018
void * * vtbl0010 ; // 0020
UInt64 unk9310 [ ( 0x9310 - 0x20 ) > > 3 ] ; // 9310
SimpleLock stackLock ; // 9318
StackTableT allStacks ; // 9320
StackTableT waitingStacks ; // 9350
// More...
VMStackInfo * GetStackInfo ( UInt32 stackId ) ;
void LogError ( const char * message , UInt32 stackId ) { PrintToDebugLog ( message , stackId , kLogLevel_Error ) ; }
void LogWarning ( const char * message , UInt32 stackId ) { PrintToDebugLog ( message , stackId , kLogLevel_Warning ) ; }
} ;
STATIC_ASSERT ( offsetof ( VMClassRegistry , stackLock ) = = 0x9318 ) ;
STATIC_ASSERT ( offsetof ( VMClassRegistry , allStacks ) = = 0x9320 ) ;
STATIC_ASSERT ( offsetof ( VMClassRegistry , waitingStacks ) = = 0x9350 ) ;
class IStackCallbackSaveInterface
{
public :
virtual ~ IStackCallbackSaveInterface ( ) ;
virtual void Unk_01 ( void ) ;
virtual void Unk_02 ( void ) ;
} ;
// 45D0
class SkyrimVM
{
public :
SkyrimVM ( ) ;
virtual ~ SkyrimVM ( ) ;
virtual void Unk_01 ( void ) ;
enum
{
kEventSink_Activate = 0 ,
kEventSink_ActiveEffectApplyRemove ,
kEventSink_ActorLocationChange ,
kEventSink_BookRead ,
kEventSink_CellAttachDetach ,
kEventSink_CellFullyLoaded ,
kEventSink_Combat ,
kEventSink_ContainerChanged ,
kEventSink_Death ,
kEventSink_DestructionStateChanged ,
kEventSink_EnterBleedout ,
kEventSink_Equip ,
kEventSink_FormDelete ,
kEventSink_Furniture ,
kEventSink_GrabRelease ,
kEventSink_Hit ,
kEventSink_InitScript ,
kEventSink_LoadGame ,
kEventSink_LockChanged ,
kEventSink_MagicEffectApply ,
kEventSink_MagicWardHit ,
kEventSink_MoveAttachDetach ,
kEventSink_ObjectLoaded ,
kEventSink_ObjectREFRTranslation ,
kEventSink_OpenClose ,
kEventSink_Package ,
kEventSink_PerkEntryRun ,
kEventSink_QuestInit ,
kEventSink_QuestStage ,
kEventSink_Reset ,
kEventSink_ResolveNPCTemplates ,
kEventSink_Scene ,
kEventSink_SceneAction ,
kEventSink_ScenePhase ,
kEventSink_Sell ,
kEventSink_SleepStart ,
kEventSink_SleepStop ,
kEventSink_SpellCast ,
kEventSink_TopicInfo ,
kEventSink_TrackedStats ,
kEventSink_TrapHit ,
kEventSink_Trigger ,
kEventSink_TriggerEnter ,
kEventSink_TriggerLeave ,
kEventSink_UniqueIDChange ,
kEventSink_SwitchRaceComplete ,
kEventSink_PlayerBowShot ,
kEventSink_FastTravelEnd , // added in 1.5.3
kEventSink_PositionPlayer ,
kEventSink_Stats ,
kEventSink_NumEvents
} ;
// void ** _vtbl; // 0000
IStackCallbackSaveInterface m_callbackSaveInterface ; // 0008
void * eventSinks [ kEventSink_NumEvents ] ; // 0010
UInt64 unk1A0 [ ( 0x200 - 0x1A0 ) > > 3 ] ; // 01A0
VMClassRegistry * m_classRegistry ; // 0200
UInt8 pad200 [ 0x714 - 0x208 ] ; // 0208
SimpleLock m_updateLock ; // 0714
UInt8 pad71C [ 0x720 - 0x71C ] ; // 071C
UpdateRegistrationHolder m_updateRegHolder ; // 0720
UpdateRegistrationHolder m_updateGameTimeRegHolder ; // 0738
VMClassRegistry * GetClassRegistry ( void ) { return m_classRegistry ; }
UInt32 ClearInvalidRegistrations ( void ) ;
MEMBER_FN_PREFIX ( SkyrimVM ) ;
// Used by Hooks_Papyrus
//
DEFINE_MEMBER_FN ( UnregisterFromSleep_Internal , void , 0x009520A0 , UInt64 handle ) ; // AE: using one function earlier due to inlining
DEFINE_MEMBER_FN ( RevertGlobalData_Internal , bool , 0x0095BD90 ) ;
// 4DF4B0288419C72FBF262CE2DBBAAFE7D9713C51+390
DEFINE_MEMBER_FN ( SaveRegSleepEventHandles_Internal , bool , 0x0095D150 , void * handleReaderWriter , void * saveStorageWrapper ) ;
// 4F9ECB23ABD5935D4160213D8A06DB7A94E6B988+2FB
DEFINE_MEMBER_FN ( LoadRegSleepEventHandles_Internal , bool , 0x0095E3F0 , void * handleReaderWriter , void * loadStorageWrapper ) ; // AE: using one function earlier due to inlining
// 96B4034421813AABF0DBF8B2B00A84CC25FB9CA0+112
DEFINE_MEMBER_FN ( QueueDelayFunctor_Internal , bool , 0x00952F10 , void * * pFunctor ) ;
bool QueueDelayFunctor ( void * * pFunctor )
{
return CALL_MEMBER_FN ( this , QueueDelayFunctor_Internal ) ( pFunctor ) ;
}
void OnFormDelete_Hook ( UInt64 handle ) ;
void RevertGlobalData_Hook ( void ) ;
bool SaveGlobalData_Hook ( void * handleReaderWriter , void * saveStorageWrapper ) ;
bool LoadGlobalData_Hook ( void * handleReaderWriter , void * loadStorageWrapper ) ;
} ;
STATIC_ASSERT ( offsetof ( SkyrimVM , m_classRegistry ) = = 0x200 ) ;
STATIC_ASSERT ( offsetof ( SkyrimVM , m_updateLock ) = = 0x714 ) ;
STATIC_ASSERT ( offsetof ( SkyrimVM , m_updateRegHolder ) = = 0x720 ) ;
STATIC_ASSERT ( offsetof ( SkyrimVM , m_updateGameTimeRegHolder ) = = 0x738 ) ;
extern RelocPtr < SkyrimVM * > g_skyrimVM ;
// ??
class IFunctionArguments
{
public :
virtual ~ IFunctionArguments ( ) { }
// ??
struct Output
{
UInt32 unk00 ; // 00
UInt32 unk04 ; // 04
VMValue * m_data ; // 08 - confirmed offset
UInt64 unk08 ; // 10
UInt32 m_size ; // 18 - confirmed offset
void Resize ( UInt32 len ) { CALL_MEMBER_FN ( this , Resize ) ( len ) ; }
VMValue * Get ( UInt32 idx ) { return ( idx < m_size ) ? & m_data [ idx ] : NULL ; }
MEMBER_FN_PREFIX ( Output ) ;
DEFINE_MEMBER_FN ( Resize , bool , 0x0094D7B0 , UInt32 len ) ;
} ;
virtual bool Copy ( Output * dst ) = 0 ;
} ;