调用 PluginBase / Call
查看 MarkdownCall / CallDyn / Method / VMT 选型与基址
shared/PluginBase.h · 命名空间 plugin
优先顺序:已有 C++ 封装 → Command → Call → 最后才 patch。
| 场景 | 选用 |
|---|---|
| 编译期已知地址、cdecl | Call / CallAndReturn |
| thiscall | CallMethod / CallMethodAndReturn |
| 运行时才有地址(Pattern / 重定位) | CallDyn* |
| 地址已是绝对、不要再加基址 | *DynGlobal |
| 虚表槽 | CallVirtualMethod* |
编译期地址 → Call*
运行时地址 → CallDyn*(多数配合 GetGlobalAddress / Pattern)
*DynGlobal 不做重定位
不要在这些时机 Call 游戏逻辑
静态构造 / DllMain / 对象池尚未建立 / 设备 Lost 之后继续画或调渲染相关逻辑。
无返回的 cdecl 调用。address 按 void(__cdecl*)(Args...) 解释。调用约定错误会破坏栈。固定 RVA 换游戏版本通常要更新,或改用 Pattern + CallDyn。
template <uintptr_t address, typename... Args>
void Call(Args... args);Ret 写在模板参数最前。
template <typename Ret, uintptr_t address, typename... Args>
Ret CallAndReturn(Args... args);游戏内多数并不是 stdcall,确认约定后再用。
template <uintptr_t address, typename... Args>
void CallStd(Args... args);
template <typename Ret, uintptr_t address, typename... Args>
Ret CallStdAndReturn(Args... args);第一个参数是 this,必须有效。
template <uintptr_t address, typename C, typename... Args>
void CallMethod(C _this, Args... args);
template <typename Ret, uintptr_t address, typename C, typename... Args>
Ret CallMethodAndReturn(C _this, Args... args);模板参数是虚表 下标,不是函数地址。下标错误几乎必崩。
template <uintptr_t tableIndex, typename C, typename... Args>
void CallVirtualMethod(C _this, Args... args);
template <typename Ret, uintptr_t tableIndex, typename C, typename... Args>
Ret CallVirtualMethodAndReturn(C _this, Args... args);内部会做重定位。地址为 0 时不要调用。
template <typename... Args>
void CallDyn(uintptr_t address, Args... args);
template <typename Ret, typename... Args>
Ret CallAndReturnDyn(uintptr_t address, Args... args);template <typename... Args>
void CallStdDyn(uintptr_t address, Args... args);
template <typename Ret, typename... Args>
Ret CallStdAndReturnDyn(uintptr_t address, Args... args);template <typename C, typename... Args>
void CallMethodDyn(uintptr_t address, C _this, Args... args);
template <typename Ret, typename C, typename... Args>
Ret CallMethodAndReturnDyn(uintptr_t address, C _this, Args... args);template <typename... Args>
void CallDynGlobal(uintptr_t address, Args... args);
template <typename Ret, typename... Args>
Ret CallAndReturnDynGlobal(uintptr_t address, Args... args);template <typename C, typename... Args>
void CallMethodDynGlobal(uintptr_t address, C _this, Args... args);
template <typename Ret, typename C, typename... Args>
Ret CallMethodAndReturnDynGlobal(uintptr_t address, C _this, Args... args);取虚表指针,或某一槽位。
inline void** GetVMT(const void* self);
inline void* GetVMT(const void* self, size_t index);模块基址;RVA → 绝对地址。
uintptr_t GetBaseAddress();
uintptr_t GetGlobalAddress(uintptr_t address);等价于 new / delete,必须成对使用。
template <typename ClassType, typename... ArgTypes>
ClassType* operator_new(ArgTypes... args);
template <typename ClassType>
ClassType* operator_new_array(size_t size);
template <typename ClassType>
void operator_delete(ClassType* data);
template <typename ClassType>
void operator_delete_array(ClassType* data);template <typename T>
struct stack_object {
template <typename... ArgTypes>
stack_object(ArgTypes... args);
T* operator->();
T& get_object();
};namespace Core {
PLUGIN_API unsigned int GetVersion();
}按当前工程宏取三端之一。
BY_GAME(iii_val, vc_val, sa_val)
评论