mirror of
https://github.com/alicealys/t5-gsc-utils.git
synced 2025-04-19 20:42:54 +00:00
Don't use asmjit for function wrap
This commit is contained in:
parent
ddf3edb2ed
commit
7d4e4efc5f
@ -12,17 +12,17 @@
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour get_function_hook;
|
||||
utils::hook::detour get_method_hook;
|
||||
|
||||
std::unordered_map<std::string, function_t> functions;
|
||||
std::unordered_map<std::string, function_t> methods;
|
||||
|
||||
std::unordered_map<std::string, void*> function_wraps;
|
||||
std::unordered_map<std::string, void*> method_wraps;
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour get_function_hook;
|
||||
utils::hook::detour get_method_hook;
|
||||
|
||||
std::vector<scripting::script_value> get_arguments()
|
||||
{
|
||||
std::vector<scripting::script_value> args;
|
||||
@ -46,80 +46,12 @@ namespace gsc
|
||||
scripting::push_value(value);
|
||||
}
|
||||
|
||||
void call_function(const function_t* function)
|
||||
{
|
||||
const auto args = get_arguments();
|
||||
|
||||
try
|
||||
{
|
||||
const auto value = function->operator()(args);
|
||||
return_value(value);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
game::Scr_Error(game::SCRIPTINSTANCE_SERVER, e.what(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void call_method(const function_t* method, const game::scr_entref_t entref)
|
||||
{
|
||||
const auto args = get_arguments();
|
||||
|
||||
try
|
||||
{
|
||||
const scripting::entity entity = game::Scr_GetEntityId(
|
||||
game::SCRIPTINSTANCE_SERVER, entref.entnum, entref.classnum, 0);
|
||||
|
||||
std::vector<scripting::script_value> args_{};
|
||||
args_.push_back(entity);
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
args_.push_back(arg);
|
||||
}
|
||||
|
||||
const auto value = method->operator()(args_);
|
||||
return_value(value);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
game::Scr_Error(game::SCRIPTINSTANCE_SERVER, e.what(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void* wrap_function_call(const function_t* function)
|
||||
{
|
||||
return utils::hook::assemble([&](utils::hook::assembler& a)
|
||||
{
|
||||
a.pushad();
|
||||
a.push(function);
|
||||
a.call(call_function);
|
||||
a.add(esp, 0x4);
|
||||
a.popad();
|
||||
|
||||
a.ret();
|
||||
});
|
||||
}
|
||||
|
||||
void* wrap_method_call(const function_t* method)
|
||||
{
|
||||
return utils::hook::assemble([&](utils::hook::assembler& a)
|
||||
{
|
||||
a.pushad();
|
||||
a.push(dword_ptr(esp, 0x24));
|
||||
a.push(method);
|
||||
a.call(call_method);
|
||||
a.add(esp, 0x8);
|
||||
a.popad();
|
||||
|
||||
a.ret();
|
||||
});
|
||||
}
|
||||
|
||||
script_function get_function_stub(const char** name, int* type)
|
||||
{
|
||||
if (function_wraps.find(*name) != function_wraps.end())
|
||||
const auto iter = function_wraps.find(*name);
|
||||
if (iter != function_wraps.end())
|
||||
{
|
||||
return reinterpret_cast<script_function>(function_wraps[*name]);
|
||||
return reinterpret_cast<script_function>(iter->second);
|
||||
}
|
||||
|
||||
return get_function_hook.invoke<script_function>(name, type);
|
||||
@ -127,9 +59,10 @@ namespace gsc
|
||||
|
||||
script_function get_method_stub(const char** name, int* type)
|
||||
{
|
||||
if (method_wraps.find(*name) != method_wraps.end())
|
||||
const auto iter = method_wraps.find(*name);
|
||||
if (iter != method_wraps.end())
|
||||
{
|
||||
return reinterpret_cast<script_function>(method_wraps[*name]);
|
||||
return reinterpret_cast<script_function>(iter->second);
|
||||
}
|
||||
|
||||
return get_method_hook.invoke<script_function>(name, type);
|
||||
@ -204,27 +137,43 @@ namespace gsc
|
||||
}
|
||||
}
|
||||
|
||||
namespace function
|
||||
void call_function(const function_t* function)
|
||||
{
|
||||
void add_internal(const std::string& name, const function_t& function)
|
||||
const auto args = get_arguments();
|
||||
|
||||
try
|
||||
{
|
||||
const auto lower = utils::string::to_lower(name);
|
||||
const auto [iterator, was_inserted] = functions.insert(std::make_pair(lower, function));
|
||||
const auto function_ptr = &iterator->second;
|
||||
const auto call_wrap = wrap_function_call(function_ptr);
|
||||
function_wraps[lower] = call_wrap;
|
||||
const auto value = function->operator()(args);
|
||||
return_value(value);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
game::Scr_Error(game::SCRIPTINSTANCE_SERVER, e.what(), false);
|
||||
}
|
||||
}
|
||||
|
||||
namespace method
|
||||
void call_method(const function_t* method, const game::scr_entref_t entref)
|
||||
{
|
||||
void add_internal(const std::string& name, const function_t& method)
|
||||
const auto args = get_arguments();
|
||||
|
||||
try
|
||||
{
|
||||
const auto lower = utils::string::to_lower(name);
|
||||
const auto [iterator, was_inserted] = methods.insert(std::make_pair(lower, method));
|
||||
const auto method_ptr = &iterator->second;
|
||||
const auto call_wrap = wrap_method_call(method_ptr);
|
||||
method_wraps[lower] = call_wrap;
|
||||
const scripting::entity entity = game::Scr_GetEntityId(
|
||||
game::SCRIPTINSTANCE_SERVER, entref.entnum, entref.classnum, 0);
|
||||
|
||||
std::vector<scripting::script_value> args_{};
|
||||
args_.push_back(entity);
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
args_.push_back(arg);
|
||||
}
|
||||
|
||||
const auto value = method->operator()(args_);
|
||||
return_value(value);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
game::Scr_Error(game::SCRIPTINSTANCE_SERVER, e.what(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,21 @@
|
||||
#include "game/scripting/array.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
|
||||
#if _HAS_CXX20
|
||||
namespace gsc
|
||||
{
|
||||
using function_t = std::function<scripting::script_value(const scripting::function_arguments& args)>;
|
||||
using script_function = void(*)(game::scr_entref_t);
|
||||
|
||||
template <class... Args, std::size_t... I>
|
||||
extern std::unordered_map<std::string, function_t> functions;
|
||||
extern std::unordered_map<std::string, function_t> methods;
|
||||
|
||||
extern std::unordered_map<std::string, void*> function_wraps;
|
||||
extern std::unordered_map<std::string, void*> method_wraps;
|
||||
|
||||
// auto = []{} forces template reevaluation
|
||||
|
||||
template <class... Args, std::size_t... I, auto = []{}>
|
||||
auto wrap_function(const std::function<void(Args...)>& f, std::index_sequence<I...>)
|
||||
{
|
||||
return [f]([[maybe_unused]] const scripting::function_arguments& args)
|
||||
@ -17,7 +26,7 @@ namespace gsc
|
||||
};
|
||||
}
|
||||
|
||||
template <class... Args, std::size_t... I>
|
||||
template <class... Args, std::size_t... I, auto = []{}>
|
||||
auto wrap_function(const std::function<scripting::script_value(Args...)>& f, std::index_sequence<I...>)
|
||||
{
|
||||
return [f]([[maybe_unused]] const scripting::function_arguments& args)
|
||||
@ -26,7 +35,7 @@ namespace gsc
|
||||
};
|
||||
}
|
||||
|
||||
template <typename R, class... Args, std::size_t... I>
|
||||
template <typename R, class... Args, std::size_t... I, auto = []{}>
|
||||
auto wrap_function(const std::function<R(Args...)>& f, std::index_sequence<I...>)
|
||||
{
|
||||
return [f]([[maybe_unused]] const scripting::function_arguments& args)
|
||||
@ -35,51 +44,85 @@ namespace gsc
|
||||
};
|
||||
}
|
||||
|
||||
template <typename R, class... Args>
|
||||
template <typename R, class... Args, auto = []{}>
|
||||
auto wrap_function(const std::function<R(Args...)>& f)
|
||||
{
|
||||
return wrap_function(f, std::index_sequence_for<Args...>{});
|
||||
}
|
||||
|
||||
template <class F>
|
||||
template <class F, auto = []{}>
|
||||
auto wrap_function(F f)
|
||||
{
|
||||
return wrap_function(std::function(f));
|
||||
}
|
||||
|
||||
void call_function(const function_t* function);
|
||||
void call_method(const function_t* method, const game::scr_entref_t entref);
|
||||
|
||||
namespace function
|
||||
{
|
||||
void add_internal(const std::string& name, const function_t& function);
|
||||
template <typename F, auto = []{}>
|
||||
void add_internal(const std::string& name, F function)
|
||||
{
|
||||
static auto called = false;
|
||||
assert(!called);
|
||||
called = true;
|
||||
|
||||
template <typename F>
|
||||
const auto lower = utils::string::to_lower(name);
|
||||
static const auto [iterator, was_inserted] = functions.insert(std::make_pair(lower, function));
|
||||
static const auto function_ptr = &iterator->second;
|
||||
|
||||
function_wraps[lower] = []()
|
||||
{
|
||||
call_function(function_ptr);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename F, auto = []{}>
|
||||
void add(const std::string& name, F f)
|
||||
{
|
||||
add_internal(name, wrap_function(f));
|
||||
}
|
||||
|
||||
template <typename ...Args, typename F>
|
||||
template <typename ...Args, typename F, auto = []{}>
|
||||
void add_multiple(F f, Args&& ...names)
|
||||
{
|
||||
const auto wrap = wrap_function(f);
|
||||
(add_internal(names, wrap), ...);
|
||||
(add(names, f), ...);
|
||||
}
|
||||
}
|
||||
|
||||
namespace method
|
||||
{
|
||||
void add_internal(const std::string& name, const function_t& function);
|
||||
template <typename F, auto = []{}>
|
||||
void add_internal(const std::string& name, F function)
|
||||
{
|
||||
static auto called = false;
|
||||
assert(!called);
|
||||
called = true;
|
||||
|
||||
template <typename F>
|
||||
const auto lower = utils::string::to_lower(name);
|
||||
static const auto [iterator, was_inserted] = functions.insert(std::make_pair(lower, function));
|
||||
static const auto function_ptr = &iterator->second;
|
||||
|
||||
method_wraps[lower] = [](game::scr_entref_t entref)
|
||||
{
|
||||
call_method(function_ptr, entref);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename F, auto = []{}>
|
||||
void add(const std::string& name, F f)
|
||||
{
|
||||
add_internal(name, wrap_function(f));
|
||||
}
|
||||
|
||||
template <typename ...Args, typename F>
|
||||
template <typename ...Args, typename F, auto = []{}>
|
||||
void add_multiple(F f, Args&& ...names)
|
||||
{
|
||||
const auto wrap = wrap_function(f);
|
||||
(add_internal(names, wrap), ...);
|
||||
(add(names, f), ...);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error pre c++20 is not supported
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user