Squirrel: add more types and functions

More reversed types, more functions.
This commit is contained in:
Kawe Mazidjatari 2024-03-16 11:36:49 +01:00
parent 4d0c5dd3da
commit 09b1e44dfe
14 changed files with 413 additions and 25 deletions

View File

@ -15,6 +15,11 @@ add_sources( SOURCE_GROUP "Squirrel_RE"
add_sources( SOURCE_GROUP "Squirrel_RE/squirrel"
"languages/squirrel_re/squirrel/sqapi.cpp"
#"languages/squirrel_re/squirrel/sqcompiler.cpp"
"languages/squirrel_re/squirrel/sqfuncstate.cpp"
#"languages/squirrel_re/squirrel/sqlexer.cpp"
"languages/squirrel_re/squirrel/sqobject.cpp"
"languages/squirrel_re/squirrel/sqstring.cpp"
"languages/squirrel_re/squirrel/sqvm.cpp"
)
@ -25,8 +30,14 @@ add_sources( SOURCE_GROUP "Squirrel_RE/sqstdlib"
add_sources( SOURCE_GROUP "Squirrel_RE/include"
"languages/squirrel_re/vsquirrel.cpp"
"languages/squirrel_re/vsquirrel.h"
#"languages/squirrel_re/include/sqcompiler.h"
"languages/squirrel_re/include/sqfuncstate.h"
#"languages/squirrel_re/include/sqlexer.h"
"languages/squirrel_re/include/sqobject.h"
"languages/squirrel_re/include/sqopcodes.h"
"languages/squirrel_re/include/sqstate.h"
"languages/squirrel_re/include/sqstdaux.h"
"languages/squirrel_re/include/sqstring.h"
"languages/squirrel_re/include/squirrel.h"
"languages/squirrel_re/include/sqvm.h"
)
@ -36,3 +47,5 @@ add_sources( SOURCE_GROUP "Public"
)
end_sources()
target_include_directories( ${PROJECT_NAME} PRIVATE "${ENGINE_SOURCE_DIR}/vscript/languages/squirrel_re/include/" )

View File

@ -0,0 +1,25 @@
#ifndef SQFUNCSTATE_H
#define SQFUNCSTATE_H
#include "squirrel.h"
#include "sqopcodes.h"
#include "sqobject.h"
struct SQFuncState
{
_BYTE gap0[17408];
sqvector<SQInstruction> _instructions;
_BYTE gap4418[88];
SQObjectPtr _sourcename;
SQObjectPtr _wuh;
_BYTE gap4478[120];
int _lastline;
char gap4504[4];
bool _optimization;
char gap4510[80];
};
static_assert(offsetof(SQFuncState, _optimization) == 0x4508);
#endif // SQFUNCSTATE_H

View File

@ -0,0 +1,103 @@
#ifndef SQOBJECT_H
#define SQOBJECT_H
#include "squirrel.h"
struct SQRefCounted
{
SQRefCounted() { _uiRef = 0; _weakref = NULL; }
virtual ~SQRefCounted();
virtual void Release() = 0;
//SQWeakRef* GetWeakRef(SQObjectType type);
SQUnsignedInteger _uiRef;
SQObject* _weakref; // this is not an sqobject!
};
#define __AddRef(type, unval) \
if(ISREFCOUNTED(type)) \
{ \
unval.pRefCounted->_uiRef++; \
}
#define __Release(type, unval) \
if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \
{ \
unval.pRefCounted->Release(); \
}
struct SQObjectPtr : public SQObject
{
SQObjectPtr()
{
_type = OT_NULL;
_unVal.pUserPointer = nullptr;
}
SQObjectPtr(const SQObjectPtr& o)
{
_type = o._type;
_unVal = o._unVal;
__AddRef(_type, _unVal);
}
SQObjectPtr(SQString* pString)
{
assert(pString);
_type = OT_STRING;
_unVal.pString = pString;
__AddRef(_type, _unVal);
}
SQObjectPtr(bool bBool)
{
_type = OT_BOOL;
_unVal.nInteger = bBool ? 1 : 0;
}
SQObjectPtr(SQInteger nInteger)
{
_type = OT_INTEGER;
_unVal.nInteger = nInteger;
}
SQObjectPtr(SQFloat fFloat)
{
_type = OT_FLOAT;
_unVal.fFloat = fFloat;
}
inline ~SQObjectPtr()
{
__Release(_type, _unVal);
}
inline SQObjectPtr& operator=(const SQObjectPtr& obj)
{
SQObjectType oldType = _type;
SQObjectValue oldVal = _unVal;
_type = obj._type;
_unVal = obj._unVal;
__AddRef(_type, _unVal);
__Release(oldType, oldVal);
return *this;
}
const char* GetCString() const;
SQString* GetSQString() const
{
assert(_type == OT_STRING);
return _unVal.pString;
}
};
static SQObjectPtr _null_;
#endif // SQOBJECT_H

View File

@ -0,0 +1,64 @@
#ifndef SQOPCODES_H
#define SQOPCODES_H
#include "squirrel.h"
enum SQOpcode
{
_OP_LINE,
_OP_LOAD_WHAR,
_OP_LOAD,
_OP_LOADINT,
_OP_LOADFLOAT,
_OP_DLOAD,
_OP_TAILCALL,
_OP_CALL,
_OP_PREPCALL,
_OP_PREPCALLK,
_OP_GETK,
_OP_MOVE,
_OP_NEWSLOT,
_OP_DELETE,
_OP_SET,
_OP_GET,
_OP_EQ,
_OP_NE,
_OP_ARITH,
_OP_BITW,
_OP_RETURN,
_OP_LOADNULLS,
_OP_LOADROOTTABLE,
_OP_LOADBOOL,
_OP_DMOVE,
_OP_JMP,
_OP_JNZ,
_OP_JZ,
_OP_LOADFREEVAR,
_OP_VARGC,
_OP_GETVARGV,
_OP_NEWTABLE,
_OP_NEWARRAY,
// there are more! there are a couple unknown ones around here, so i have left out the others
// for now since i'm not sure what order they are in
_OP_UNREACHABLE = 0x7B,
};
struct SQInstruction
{
SQInstruction() {};
SQInstruction(SQOpcode _op, SQInteger a0 = 0, SQInteger a1 = 0, SQInteger a2 = 0, SQInteger a3 = 0)
{
op = (unsigned char)_op;
_arg0 = (unsigned char)a0; _arg1 = (int)a1;
_arg2 = (unsigned char)a2; _arg3 = (unsigned char)a3;
}
int _arg1;
unsigned char op;
unsigned char _arg0;
unsigned char _arg2;
unsigned char _arg3;
};
#endif // SQOPCODES_H

View File

@ -1,19 +1,38 @@
#ifndef SQSTATE_H
#define SQSTATE_H
#include "squirrel.h"
//#include "sqcompiler.h"
struct SQCompiler;
#pragma pack(push, 1)
struct SQSharedState
{
uint8_t gap0[17256];
uint8_t gap1[32];
_BYTE gap0[16456];
void* _stringtable; // allocated with a size of 17488 in CSquirrelVM::Init - possibly stringtable
_BYTE gap4070[488];
SQCompiler* _compiler;
uint8_t gap1[320];
void* _compilererrorhandler;
void* _printfunc;
uint8_t gap4390[33];
SQChar _contextname[8];
char gap43b9[135];
char* _scratchpad;
int _scratchpadsize;
SQCompiler* GetCompiler()
{
return _compiler;
}
};
#pragma pack(pop)
static_assert(offsetof(SQSharedState, _compiler) == 0x4238);
static_assert(offsetof(SQSharedState, _printfunc) == 0x4388);
struct SQBufState
{
const SQChar* buf;

View File

@ -0,0 +1,25 @@
#ifndef SQSTRING_H
#define SQSTRING_H
#include "squirrel.h"
#include "sqobject.h"
#include "sqstate.h"
struct SQString : public SQRefCounted
{
char gap18[16];
SQSharedState* _sharedstate;
int _len;
char gap34[12];
SQChar _val[1];
static SQString* Create(SQSharedState* sharedstate, const SQChar* s, SQInteger len)
{
SQString* str = v_StringTable__Add(sharedstate->_stringtable, s, len);
str->_sharedstate = sharedstate;
return str;
}
};
static_assert(offsetof(SQString, _val) == 0x40);
#endif // SQSTRING_H

View File

@ -28,6 +28,73 @@ typedef int ScriptDataType_t;
typedef struct SQVM* HSQUIRRELVM;
struct SQBufState;
struct SQString;
#define SQOBJECT_REF_COUNTED 0x08000000
typedef enum tagSQObjectType
{
OT_VECTOR = 0x40000,
OT_NULL = 0x1000001,
OT_INTEGER = 0x5000002,
OT_FLOAT = 0x5000004,
OT_BOOL = 0x1000008,
OT_STRING = 0x8000010,
OT_TABLE = 0xA000020,
OT_ARRAY = 0x8000040,
OT_USERDATA = 0xA000080,
OT_CLOSURE = 0x8000100,
OT_NATIVECLOSURE = 0x8000200,
OT_ASSET = 0x8000400,
OT_USERPOINTER = 0x800,
OT_THREAD = 0x8001000,
OT_FUNCPROTO = 0x8002000,
OT_CLASS = 0x8004000,
OT_STRUCT = 0x8200000,
OT_INSTANCE = 0xA008000,
OT_ENTITY = 0xA400000,
OT_WEAKREF = 0x8010000,
} SQObjectType;
// does the type keep track of references?
#define ISREFCOUNTED(t) (t & SQOBJECT_REF_COUNTED)
typedef union tagSQObjectValue
{
struct SQTable* pTable;
struct SQArray* pArray;
struct SQClosure* pClosure;
struct SQGenerator* pGenerator;
struct SQNativeClosure* pNativeClosure;
struct SQString* pString;
struct SQUserData* pUserData;
int nInteger;
float fFloat;
void* pUserPointer;
struct SQFunctionProto* pFunctionProto;
struct SQRefCounted* pRefCounted;
struct SQDelegable* pDelegable;
struct SQVM* pThread;
struct SQClass* pClass;
struct SQInstance* pInstance;
struct SQWeakRef* pWeakRef;
unsigned int raw;
} SQObjectValue;
typedef struct tagSQObject
{
SQObjectType _type;
SQObjectValue _unVal;
} SQObject;
template<typename T> class sqvector
{
public:
T* _vals;
SQUnsignedInteger _size;
SQUnsignedInteger _allocated;
};
///////////////////////////////////////////////////////////////////////////////
SQRESULT sq_pushroottable(HSQUIRRELVM v);
SQChar* sq_getstring(HSQUIRRELVM v, SQInteger i);
@ -36,6 +103,7 @@ SQRESULT sq_pushroottable(HSQUIRRELVM v);
void sq_pushbool(HSQUIRRELVM v, SQBool b);
void sq_pushstring(HSQUIRRELVM v, const SQChar* string, SQInteger len);
void sq_pushinteger(HSQUIRRELVM v, SQInteger val);
void sq_pushfloat(HSQUIRRELVM v, SQFloat n);
void sq_newarray(HSQUIRRELVM v, SQInteger size);
void sq_newtable(HSQUIRRELVM v);
SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx);
@ -52,6 +120,7 @@ inline SQRESULT(*v_sq_pushroottable)(HSQUIRRELVM v);
inline void(*v_sq_pushbool)(HSQUIRRELVM v, SQBool b);
inline void(*v_sq_pushstring)(HSQUIRRELVM v, const SQChar* string, SQInteger len);
inline void(*v_sq_pushinteger)(HSQUIRRELVM v, SQInteger val);
inline void(*v_sq_pushfloat)(HSQUIRRELVM v, SQFloat val);
inline void(*v_sq_newarray)(HSQUIRRELVM v, SQInteger size);
inline void(*v_sq_newtable)(HSQUIRRELVM v);
inline SQRESULT(*v_sq_newslot)(HSQUIRRELVM v, SQInteger idx);
@ -63,6 +132,8 @@ inline SQRESULT(*v_sq_call)(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBo
inline SQRESULT (*v_sq_startconsttable)(HSQUIRRELVM v);
inline SQRESULT (*v_sq_endconsttable)(HSQUIRRELVM v);
inline SQString* (*v_StringTable__Add)(void* a1, const SQChar* str, SQInteger len);
///////////////////////////////////////////////////////////////////////////////
class VSquirrelAPI : public IDetour
{
@ -72,6 +143,7 @@ class VSquirrelAPI : public IDetour
LogFunAdr("sq_pushbool", v_sq_pushbool);
LogFunAdr("sq_pushstring", v_sq_pushstring);
LogFunAdr("sq_pushinteger", v_sq_pushinteger);
LogFunAdr("sq_pushfloat", v_sq_pushfloat);
LogFunAdr("sq_newarray", v_sq_newarray);
LogFunAdr("sq_arrayappend", v_sq_arrayappend);
LogFunAdr("sq_newtable", v_sq_newtable);
@ -82,6 +154,8 @@ class VSquirrelAPI : public IDetour
LogFunAdr("sq_startconsttable", v_sq_startconsttable);
LogFunAdr("sq_endconsttable", v_sq_endconsttable);
LogFunAdr("StringTable::Add", v_StringTable__Add);
}
virtual void GetFun(void) const
{
@ -89,6 +163,7 @@ class VSquirrelAPI : public IDetour
g_GameDll.FindPatternSIMD("48 83 EC 38 33 C0 48 C7 44 24 20 08 ?? ?? 01 48").GetPtr(v_sq_pushbool);
g_GameDll.FindPatternSIMD("40 56 48 83 EC 30 48 8B F1 48 85 D2 0F 84 8F ??").GetPtr(v_sq_pushstring);
g_GameDll.FindPatternSIMD("48 83 EC 38 33 C0 48 C7 44 24 20 02 ?? ?? 05 48").GetPtr(v_sq_pushinteger);
g_GameDll.FindPatternSIMD("48 83 EC 38 8B 51 78 33 C0").GetPtr(v_sq_pushfloat);
g_GameDll.FindPatternSIMD("48 89 5C 24 08 57 48 83 EC 30 48 8B D9 48 C7 44 24 20 40").GetPtr(v_sq_newarray);
g_GameDll.FindPatternSIMD("48 89 5C 24 08 57 48 83 EC 30 48 8B D9 48 C7 44 24 20 20").GetPtr(v_sq_newtable);
g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 44 8B 49 ?? 48 8B D9 41 8B C1").GetPtr(v_sq_newslot);
@ -99,6 +174,8 @@ class VSquirrelAPI : public IDetour
g_GameDll.FindPatternSIMD("8B 51 78 4C 8B 49 60 44 8B C2 49 C1 E0 04 4C 03 81 ?? ?? ?? ?? 8D 42 01 89 41 78 41 F7 81 ?? ?? ?? ?? ?? ?? ?? ?? 74 0A 49 8B 81 ?? ?? ?? ?? FF 40 08 41 F7 00 ?? ?? ?? ?? 41 0F 10 81 ?? ?? ?? ?? 74 15").GetPtr(v_sq_startconsttable);
g_GameDll.FindPatternSIMD("8B 41 78 45 33 C0 FF C8 8B D0 89 41 78 48 C1 E2 04 48 03 91 ?? ?? ?? ?? 8B 02 48 C7 02 ?? ?? ?? ?? 25 ?? ?? ?? ?? 74 15").GetPtr(v_sq_endconsttable);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 41 8D 4D FF").FollowNearCallSelf().GetPtr(v_StringTable__Add);
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }

View File

@ -1,6 +1,7 @@
#pragma once
#include "squirrel.h"
#include "sqstate.h"
#include "sqobject.h"
//-----------------------------------------------------------------------------
//
@ -29,6 +30,13 @@ struct SQVM
return (eDLL_T)GetContext();
}
// push sqobjectptr on to the stack
inline void Push(const SQObjectPtr& o)
{
this->_stack._vals[_top++] = o;
}
// ================================= //
SQVM* _vftable;
_BYTE gap000[16];
SQCONTEXT _contextidx;
@ -40,15 +48,26 @@ struct SQVM
void* _callstack;
int _unk;
int _bottom;
SQInteger _stackbase;
SQInteger unk5c;
SQObjectPtr* _stackbase;
SQSharedState* _sharedstate;
char gap004[16];
int _top;
char gap005[148];
char gap006[30];
SQInteger _nnativecalls;
__int64 gap80;
sqvector<SQObjectPtr> _stack;
char gap_98[24];
SQObjectPtr temp_reg;
char gap_C8[32];
SQObjectPtr _roottable;
SQObjectPtr _lasterror;
char gap_100[48];
int _nnativecalls;
SQBool _suspended;
SQBool _suspended_root;
char gap_13C[8];
int suspended_traps;
};
static_assert(offsetof(SQVM, _top) == 0x78);
static_assert(offsetof(SQVM, _nnativecalls) == 0x130);
/* ==== SQUIRREL ======================================================================================================================================================== */
inline SQRESULT(*v_SQVM_PrintFunc)(HSQUIRRELVM v, SQChar* fmt, ...);

View File

@ -6,8 +6,8 @@
#include "core/stdafx.h"
#include "tier0/tslist.h"
#include "vscript/languages/squirrel_re/include/sqvm.h"
#include "vscript/languages/squirrel_re/include/sqstdaux.h"
#include "sqvm.h"
#include "sqstdaux.h"
bool g_bSQAuxError = false;
bool g_bSQAuxBadLogic = false;

View File

@ -5,43 +5,58 @@
//=============================================================================//
#include "core/stdafx.h"
#include "vscript/languages/squirrel_re/include/squirrel.h"
#include "vscript/languages/squirrel_re/include/sqvm.h"
#include "squirrel.h"
#include "sqvm.h"
#include "sqstring.h"
//---------------------------------------------------------------------------------
SQChar* sq_getstring(HSQUIRRELVM v, SQInteger i)
{
return *reinterpret_cast<SQChar**>(*reinterpret_cast<int64_t*>(&v->_stackbase) + 0x10i64 * i + 0x8) + 0x40;
return v->_stackbase[i]._unVal.pString->_val;
}
//---------------------------------------------------------------------------------
SQInteger sq_getinteger(HSQUIRRELVM v, SQInteger i)
{
return *reinterpret_cast<SQInteger*>(*reinterpret_cast<int64_t*>(&v->_stackbase) + 0x10i64 * i + 0x8);
return v->_stackbase[i]._unVal.nInteger;
}
//---------------------------------------------------------------------------------
SQRESULT sq_pushroottable(HSQUIRRELVM v)
{
return v_sq_pushroottable(v);
v->Push(v->_roottable);
return SQ_OK;
}
//---------------------------------------------------------------------------------
void sq_pushbool(HSQUIRRELVM v, SQBool b)
{
v_sq_pushbool(v, b);
v->Push(b?true:false);
}
//---------------------------------------------------------------------------------
void sq_pushstring(HSQUIRRELVM v, const SQChar* s, SQInteger len)
{
v_sq_pushstring(v, s, len);
if (s)
{
SQString* pString = SQString::Create(v->_sharedstate, s, len);
v->Push(pString);
}
else
v->Push(_null_);
}
//---------------------------------------------------------------------------------
void sq_pushinteger(HSQUIRRELVM v, SQInteger val)
{
v_sq_pushinteger(v, val);
v->Push(val);
}
//---------------------------------------------------------------------------------
void sq_pushfloat(HSQUIRRELVM v, SQFloat n)
{
v->Push(n);
}
//---------------------------------------------------------------------------------
@ -99,9 +114,10 @@ SQRESULT sq_endconsttable(HSQUIRRELVM v)
void VSquirrelAPI::Detour(const bool bAttach) const
{
DetourSetup(&v_sq_pushroottable, &sq_pushroottable, bAttach);
DetourSetup(&v_sq_pushbool, &sq_pushbool, bAttach);
DetourSetup(&v_sq_pushstring, &sq_pushstring, bAttach);
DetourSetup(&v_sq_pushinteger, &sq_pushinteger, bAttach);
//DetourSetup(&v_sq_pushbool, &sq_pushbool, bAttach);
//DetourSetup(&v_sq_pushstring, &sq_pushstring, bAttach);
//DetourSetup(&v_sq_pushinteger, &sq_pushinteger, bAttach);
//DetourSetup(&v_sq_pushfloat, &sq_pushfloat, bAttach);
DetourSetup(&v_sq_newarray, &sq_newarray, bAttach);
DetourSetup(&v_sq_newtable, &sq_newtable, bAttach);
DetourSetup(&v_sq_newslot, &sq_newslot, bAttach);

View File

@ -0,0 +1,3 @@
#include "core/stdafx.h"
#include "sqfuncstate.h"

View File

@ -0,0 +1,21 @@
#include "core/stdafx.h"
#include "sqobject.h"
#include "sqstring.h"
SQRefCounted::~SQRefCounted()
{
if (_weakref) {
_weakref->_type = OT_NULL;
_weakref->_unVal.pRefCounted = NULL;
}
}
const char* SQObjectPtr::GetCString() const
{
//assert(_type == OT_STRING);
if (_type == OT_STRING)
return _unVal.pString->_val;
else
return "(unknown)";
}

View File

@ -0,0 +1,3 @@
#include "core/stdafx.h"
#include "sqstring.h"

View File

@ -15,10 +15,10 @@
#include "vgui/vgui_debugpanel.h"
#include "gameui/IConsole.h"
#endif // !DEDICATED
#include "vscript/languages/squirrel_re/include/squirrel.h"
#include "vscript/languages/squirrel_re/include/sqvm.h"
#include "vscript/languages/squirrel_re/include/sqstate.h"
#include "vscript/languages/squirrel_re/include/sqstdaux.h"
#include "squirrel.h"
#include "sqvm.h"
#include "sqstate.h"
#include "sqstdaux.h"
//---------------------------------------------------------------------------------
// Console variables
@ -36,7 +36,7 @@ SQRESULT SQVM_PrintFunc(HSQUIRRELVM v, SQChar* fmt, ...)
{
eDLL_T remoteContext;
// We use the sqvm pointer as index for SDK usage as the function prototype has to match assembly.
// The compiler 'pointer truncation' warning couldn't be avoided, but it's safe to ignore it.
// The compiler 'pointer truncation' warning couldn't be avoided, but it's safe to ignore it here.
#pragma warning(push)
#pragma warning(disable : 4302 4311)
switch (static_cast<SQCONTEXT>(reinterpret_cast<int>(v)))