From 7d4e4efc5f35de3d0e5aacb56016f964087b6ac9 Mon Sep 17 00:00:00 2001 From: fed <58637860+fedddddd@users.noreply.github.com> Date: Tue, 7 Nov 2023 18:01:59 +0100 Subject: [PATCH] Don't use asmjit for function wrap --- src/component/gsc.cpp | 135 +++++++++++++----------------------------- src/component/gsc.hpp | 73 ++++++++++++++++++----- 2 files changed, 100 insertions(+), 108 deletions(-) diff --git a/src/component/gsc.cpp b/src/component/gsc.cpp index dfdd1a8..7fe7a7b 100644 --- a/src/component/gsc.cpp +++ b/src/component/gsc.cpp @@ -12,17 +12,17 @@ namespace gsc { + std::unordered_map functions; + std::unordered_map methods; + + std::unordered_map function_wraps; + std::unordered_map method_wraps; + namespace { utils::hook::detour get_function_hook; utils::hook::detour get_method_hook; - std::unordered_map functions; - std::unordered_map methods; - - std::unordered_map function_wraps; - std::unordered_map method_wraps; - std::vector get_arguments() { std::vector 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 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(function_wraps[*name]); + return reinterpret_cast(iter->second); } return get_function_hook.invoke(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(method_wraps[*name]); + return reinterpret_cast(iter->second); } return get_method_hook.invoke(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 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); } } diff --git a/src/component/gsc.hpp b/src/component/gsc.hpp index 6ebf3ca..abd5f6b 100644 --- a/src/component/gsc.hpp +++ b/src/component/gsc.hpp @@ -2,12 +2,21 @@ #include "game/scripting/array.hpp" #include "game/scripting/execution.hpp" +#if _HAS_CXX20 namespace gsc { using function_t = std::function; using script_function = void(*)(game::scr_entref_t); - template + extern std::unordered_map functions; + extern std::unordered_map methods; + + extern std::unordered_map function_wraps; + extern std::unordered_map method_wraps; + + // auto = []{} forces template reevaluation + + template auto wrap_function(const std::function& f, std::index_sequence) { return [f]([[maybe_unused]] const scripting::function_arguments& args) @@ -17,7 +26,7 @@ namespace gsc }; } - template + template auto wrap_function(const std::function& f, std::index_sequence) { return [f]([[maybe_unused]] const scripting::function_arguments& args) @@ -26,7 +35,7 @@ namespace gsc }; } - template + template auto wrap_function(const std::function& f, std::index_sequence) { return [f]([[maybe_unused]] const scripting::function_arguments& args) @@ -35,51 +44,85 @@ namespace gsc }; } - template + template auto wrap_function(const std::function& f) { return wrap_function(f, std::index_sequence_for{}); } - template + template 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 + void add_internal(const std::string& name, F function) + { + static auto called = false; + assert(!called); + called = true; - template + 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 void add(const std::string& name, F f) { add_internal(name, wrap_function(f)); } - template + template 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 + void add_internal(const std::string& name, F function) + { + static auto called = false; + assert(!called); + called = true; - template + 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 void add(const std::string& name, F f) { add_internal(name, wrap_function(f)); } - template + template 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