diff --git a/metamod/src/callback_jit.cpp b/metamod/src/callback_jit.cpp index f8fa792..c1faf79 100644 --- a/metamod/src/callback_jit.cpp +++ b/metamod/src/callback_jit.cpp @@ -69,7 +69,7 @@ void CForwardCallbackJIT::naked_main() }; auto globals = ebx; - auto locals_size = m_jitdata->has_ret ? sizeof(int) * 2 /* orig + over */ : 0; + auto locals_size = m_jitdata->rettype != rt_void ? sizeof(int) * 2 /* orig + over */ : 0; auto framesize = align(locals_size + sizeof(meta_globals_t) + /* for align */m_jitdata->args_count * sizeof(int), xmmreg_size) - m_jitdata->args_count * sizeof(int); if (m_jitdata->has_varargs) { @@ -115,7 +115,7 @@ void CForwardCallbackJIT::naked_main() mov(dword_ptr[globals + mg_esp_save], esp); // setup retval pointers - if (m_jitdata->has_ret) { + if (m_jitdata->rettype != rt_void) { lea(eax, dword_ptr[esp + over_ret]); mov(dword_ptr[globals + mg_orig_ret], esp); mov(dword_ptr[globals + mg_over_ret], eax); @@ -160,7 +160,13 @@ void CForwardCallbackJIT::naked_main() mov(dword_ptr[globals + mg_status], ecx); // save return value if override or supercede - if (m_jitdata->has_ret) { + if (m_jitdata->rettype != rt_void) { + if (m_jitdata->rettype == rt_float) { + sub(esp, sizeof(int)); + fstp(dword_ptr[esp]); + pop(eax); + } + mov(ecx, dword_ptr[esp + over_ret]); cmp(edx, MRES_OVERRIDE); cmovae(ecx, eax); @@ -181,7 +187,7 @@ void CForwardCallbackJIT::naked_main() } // store original return value - if (m_jitdata->has_ret) { + if (m_jitdata->rettype == rt_integer) { if (m_jitdata->pfn_original) mov(dword_ptr[esp + orig_ret], eax); else @@ -189,10 +195,18 @@ void CForwardCallbackJIT::naked_main() jmp("skip_supercede"); } + else if (m_jitdata->rettype == rt_float) { + if (m_jitdata->pfn_original) + fstp(dword_ptr[esp + orig_ret]); + else + mov(dword_ptr[esp + orig_ret], 0); + + jmp("skip_supercede"); + } } L("skip_original"); { - if (m_jitdata->has_ret) { + if (m_jitdata->rettype != rt_void) { // if supercede mov(eax, dword_ptr[esp + over_ret]); mov(dword_ptr[esp + orig_ret], eax); @@ -241,7 +255,13 @@ void CForwardCallbackJIT::naked_main() mov(dword_ptr[globals + mg_status], ecx); // save return value if override or supercede - if (m_jitdata->has_ret) { + if (m_jitdata->rettype != rt_void) { + if (m_jitdata->rettype == rt_float) { + sub(esp, sizeof(int)); + fstp(dword_ptr[esp]); + pop(eax); + } + cmp(edx, MRES_OVERRIDE); mov(ecx, dword_ptr[esp + over_ret]); cmovae(ecx, eax); @@ -264,11 +284,17 @@ void CForwardCallbackJIT::naked_main() movq(qword_ptr[globals + xmmreg_size], xmm1); // setup return value and override it if needed - if (m_jitdata->has_ret) { + if (m_jitdata->rettype == rt_integer) { mov(eax, dword_ptr[esp + orig_ret]); cmp(dword_ptr[globals + mg_status], MRES_OVERRIDE); cmovae(eax, dword_ptr[esp + over_ret]); } + else if (m_jitdata->rettype == rt_float) { + lea(eax, dword_ptr[esp + over_ret]); + cmp(dword_ptr[globals + mg_status], MRES_OVERRIDE); + cmovb(eax, esp); // orig_ret + fld(dword_ptr[eax]); + } // epilogue mov(esp, ebp); @@ -280,7 +306,7 @@ void CForwardCallbackJIT::naked_main() void CForwardCallbackJIT::call_func(Reg32 addr) { const size_t fixed_args_count = m_jitdata->args_count - (m_jitdata->has_varargs ? 1u /* excluding format string */ : 0u); - const size_t strbuf_offset = m_jitdata->has_ret ? sizeof(int) * 2u /* orig + over */ : 0u; + const size_t strbuf_offset = m_jitdata->rettype != rt_void ? sizeof(int) * 2u /* orig + over */ : 0u; // push formatted buf instead of format string if (m_jitdata->has_varargs) { diff --git a/metamod/src/callback_jit.h b/metamod/src/callback_jit.h index 6d104d1..24a7c75 100644 --- a/metamod/src/callback_jit.h +++ b/metamod/src/callback_jit.h @@ -1,13 +1,20 @@ #pragma once -#define CDATA_ENTRY(s, x, p, h) {#x, offsetof(s, x), (uint8)getArgsCount(decltype(s##::##x)()), !is_void(decltype(s##::##x)()), is_varargs(decltype(s##::##x)()), p, h} +#define CDATA_ENTRY(s, x, p, h) {#x, offsetof(s, x), (uint8)getArgsCount(decltype(s##::##x)()), getRetType(decltype(s##::##x)()), is_varargs(decltype(s##::##x)()), p, h} + +enum rettype_t : uint8_t +{ + rt_void, + rt_integer, + rt_float +}; struct jitdata_t { size_t pfn_original; size_t pfn_offset; // from fn table uint8 args_count; - bool has_ret; + rettype_t rettype; bool has_varargs; uint8 mm_hook_time; size_t mm_hook; @@ -26,7 +33,7 @@ struct compile_data_t const char* name; size_t offset; uint8 args_count; - bool has_ret; + rettype_t rettype; bool has_varargs; uint8 mm_hook_time; size_t mm_hook; @@ -45,27 +52,39 @@ size_t getArgsCount(ret_t (*)(t_args..., ...)) } template -bool is_void(void (*)(t_args...)) +rettype_t getRetType(void (*)(t_args..., ...)) { - return true; + return rt_void; } template -bool is_void(void (*)(t_args..., ...)) +rettype_t getRetType(void(*)(t_args...)) { - return true; + return rt_void; +} + +template +rettype_t getRetType(float (*)(t_args...)) +{ + return rt_float; +} + +template +rettype_t getRetType(double (*)(t_args...)) +{ + return rt_float; +} + +template +rettype_t getRetType(long double (*)(t_args...)) +{ + return rt_float; } template -bool is_void(ret_t (*)(t_args..., ...)) +rettype_t getRetType(ret_t (*)(t_args...)) { - return false; -} - -template -bool is_void(ret_t (*)(t_args...)) -{ - return false; + return rt_integer; } template diff --git a/metamod/src/dllapi.cpp b/metamod/src/dllapi.cpp index 864ecbe..711d6dd 100644 --- a/metamod/src/dllapi.cpp +++ b/metamod/src/dllapi.cpp @@ -227,7 +227,7 @@ void compile_dllfunc_callbacks() for (auto& cd : g_dllfunc_cdata) { jitdata.pfn_original = *(size_t *)(size_t(g_GameDLL.funcs.dllapi_table) + cd.offset); jitdata.args_count = cd.args_count; - jitdata.has_ret = cd.has_ret; + jitdata.rettype = cd.rettype; jitdata.has_varargs = cd.has_varargs; jitdata.pfn_offset = cd.offset; jitdata.mm_hook_time = cd.mm_hook_time; @@ -251,7 +251,7 @@ void compile_newdllfunc_callbacks() for (auto& cd : g_newdllfunc_cdata) { jitdata.pfn_original = g_GameDLL.funcs.newapi_table ? *(size_t *)(size_t(g_GameDLL.funcs.newapi_table) + cd.offset) : 0; jitdata.args_count = cd.args_count; - jitdata.has_ret = cd.has_ret; + jitdata.rettype = cd.rettype; jitdata.has_varargs = cd.has_varargs; jitdata.pfn_offset = cd.offset; jitdata.mm_hook_time = cd.mm_hook_time; diff --git a/metamod/src/engine_api.cpp b/metamod/src/engine_api.cpp index 4371a88..24d6a5d 100644 --- a/metamod/src/engine_api.cpp +++ b/metamod/src/engine_api.cpp @@ -202,7 +202,7 @@ void compile_engfuncs_callbacks() for (auto& cd : g_engfuncs_cdata) { jitdata.pfn_original = *(size_t *)(size_t(&g_engfuncs) + cd.offset); jitdata.args_count = cd.args_count; - jitdata.has_ret = cd.has_ret; + jitdata.rettype = cd.rettype; jitdata.has_varargs = cd.has_varargs; jitdata.pfn_offset = cd.offset; jitdata.mm_hook_time = cd.mm_hook_time;