From 29aa1ff3ca57b5daadb4a469f22d7d52fb47988b Mon Sep 17 00:00:00 2001 From: Kenzzer <14257866+kenzzer@users.noreply.github.com> Date: Thu, 30 Oct 2025 22:03:58 +0000 Subject: [PATCH] Add `SDKCall_VirtualAddress` --- extensions/sdktools/vcaller.cpp | 37 +++++++++++++++++++++++++++++++++ extensions/sdktools/vdecoder.h | 1 + plugins/include/sdktools.inc | 5 +++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/extensions/sdktools/vcaller.cpp b/extensions/sdktools/vcaller.cpp index 58b553d7e..60e36a3ee 100644 --- a/extensions/sdktools/vcaller.cpp +++ b/extensions/sdktools/vcaller.cpp @@ -86,6 +86,13 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params) { + auto call_type = (ValveCallType)params[1]; + if (call_type == ValveCall_Raw && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) { + return pContext->ThrowNativeError("SDKCall_Raw is unavailable for plugins that have enabled virtual address."); + } + if (call_type == ValveCall_VirtualAddress && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) != SP_ERROR_NONE) { + return pContext->ThrowNativeError("SDKCall_VirtualAddress is unavailable for plugins that haven't enabled virtual address."); + } s_numparams = 0; s_vtbl_index = -1; s_call_addr = NULL; @@ -412,6 +419,36 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params) startparam++; } break; + case ValveCall_VirtualAddress: + { + //params[startparam] is an address to a pointer to THIS + //params following this are params to the method we will invoke later + if (startparam > numparams) + { + vc->stk_put(ptr); + return pContext->ThrowNativeError("Expected a ThisPtr address, it wasn't found"); + } + + //note: varargs pawn args are passed by-ref + cell_t *cell; + pContext->LocalToPhysAddr(params[startparam], &cell); + void* thisptr = reinterpret_cast(g_pSM->FromPseudoAddress(*cell)); + + if (thisptr == nullptr) + { + vc->stk_put(ptr); + return pContext->ThrowNativeError("ThisPtr address cannot be null"); + } + else if (reinterpret_cast(thisptr) < VALID_MINIMUM_MEMORY_ADDRESS) + { + vc->stk_put(ptr); + return pContext->ThrowNativeError("Invalid ThisPtr address %p is pointing to reserved memory.", thisptr); + } + + *(void **)ptr = thisptr; + startparam++; + } + break; default: { vc->stk_put(ptr); diff --git a/extensions/sdktools/vdecoder.h b/extensions/sdktools/vdecoder.h index c865b8e2e..8f2822401 100644 --- a/extensions/sdktools/vdecoder.h +++ b/extensions/sdktools/vdecoder.h @@ -85,6 +85,7 @@ enum ValveCallType ValveCall_Raw, /**< Thiscall (address explicit first parameter) */ ValveCall_Server, /**< Thiscall (CBaseServer implicit first parameter) */ ValveCall_Engine, /**< Thiscall (CVEngineServer implicit first parameter) */ + ValveCall_VirtualAddress /**< Thiscall (address explicit first parameter) */ }; /** diff --git a/plugins/include/sdktools.inc b/plugins/include/sdktools.inc index 51dcf499c..15d1dfda1 100644 --- a/plugins/include/sdktools.inc +++ b/plugins/include/sdktools.inc @@ -60,9 +60,10 @@ enum SDKCallType SDKCall_Player, /**< CBasePlayer call */ SDKCall_GameRules, /**< CGameRules call */ SDKCall_EntityList, /**< CGlobalEntityList call */ - SDKCall_Raw, /**< |this| pointer with an arbitrary address */ + SDKCall_Raw, /**< |this| pointer with an arbitrary address. This is not available if SM's virtual addresses are enabled */ SDKCall_Server, /**< CBaseServer call */ - SDKCall_Engine /**< CVEngineServer call */ + SDKCall_Engine, /**< CVEngineServer call */ + SDKCall_VirtualAddress /**< |this| pointer with an arbitrary SM virtual address */ }; enum SDKLibrary