diff --git a/reapi/build.gradle b/reapi/build.gradle index eb3b717..f45943f 100644 --- a/reapi/build.gradle +++ b/reapi/build.gradle @@ -45,7 +45,7 @@ void setupToolchain(NativeBinarySpec b) { pchHeader: 'precompiled.h', pchSourceSet: 'reapi_pch' ) - cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-' + cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-', '/GS-' cfg.singleDefines('_CRT_SECURE_NO_WARNINGS') cfg.extraLibs 'ws2_32.lib' } else if (cfg instanceof GccToolchainConfig) { @@ -61,7 +61,7 @@ void setupToolchain(NativeBinarySpec b) { '_snprintf': 'snprintf' ]) - cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fp-model fast', '-fomit-frame-pointer', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s' + cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fp-model fast=2', '-fomit-frame-pointer', '-inline-forceinline', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s' } ToolchainConfigUtils.apply(project, cfg, b) diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index 237f36e..f17084f 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -361,6 +361,7 @@ true Sync true + StreamingSIMDExtensions2 Windows diff --git a/reapi/src/amxxmodule.h b/reapi/src/amxxmodule.h index 320d44e..bc47e36 100644 --- a/reapi/src/amxxmodule.h +++ b/reapi/src/amxxmodule.h @@ -494,7 +494,7 @@ extern amxxapi_t g_amxxapi; void MF_Log(const char *fmt, ...); void MF_LogError(AMX *amx, int err, const char *fmt, ...); -char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len); +char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len = nullptr); void setAmxString(cell* dest, const char* string, size_t max); inline cell* getAmxAddr(AMX *amx, cell amx_addr) @@ -504,11 +504,16 @@ inline cell* getAmxAddr(AMX *amx, cell amx_addr) struct getAmxString { - getAmxString(cell* src, size_t* len) + getAmxString(cell* src, size_t* len = nullptr) { getAmxStringTemp(src, temp, sizeof temp - 1, len); } + getAmxString(AMX* amx, cell addr, size_t* len = nullptr) + { + getAmxString(getAmxAddr(amx, addr), len); + } + operator char *() { return temp; diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 9194d04..2a3428f 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -246,6 +246,7 @@ void CBasePlayer_ImpulseCommands(IReGameHook_CBasePlayer_ImpulseCommands *chain, { chain->callNext(); }; + callVoidForward(RH_CBasePlayer_ImpulseCommands, original, pthis->entindex()); } diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 263ac40..69b2007 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -39,18 +39,17 @@ inline AType getApiType(float) { return ATYPE_FLOAT; } inline AType getApiType(const char *) { return ATYPE_STRING; } inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; } +#define MAX_ARGS 12u + template -void setupArgTypes(AType args_type[]) +void setupArgTypes(AType args_type[MAX_ARGS]) { - } -#define MAX_ARGS 10u - template void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args) { - args_type[current] = getApiType(arg); + args_type[current] = getApiType(T()); if (sizeof...(args) && current + 1 < MAX_ARGS) setupArgTypes(args_type, args...); } @@ -58,13 +57,19 @@ void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args) struct hookctx_t { template - hookctx_t(size_t count, size_t ptr, t_args... args) + hookctx_t(size_t arg_count, t_args... args) : args_ptr() { - args_count = min(count, MAX_ARGS); - args_ptr = ptr; + args_count = min(arg_count, MAX_ARGS); setupArgTypes(args_type, args...); } + void reset(size_t arg_ptr, AType ret_type = ATYPE_INTEGER) + { + retVal.set = false; + retVal.type = ret_type; + args_ptr = arg_ptr; + } + retval_t retVal; size_t args_count; size_t args_ptr; @@ -73,15 +78,26 @@ struct hookctx_t extern hookctx_t* g_hookCtx; -template -void callVoidForward(int func, original_t original, f_args... args) -{ - hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...); - hookCtx.retVal.set = false; - g_hookCtx = &hookCtx; +#pragma optimize("ts", on) +template +void callVoidForward(size_t func, original_t original, f_args... args) +{ +#ifndef _WIN32 + static +#endif + hookctx_t hookCtx(sizeof...(args), args...); + + g_hookCtx = &hookCtx; + _callVoidForward(g_hookManager.getHook(func), original, args...); + g_hookCtx = nullptr; +} + +template +NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original, volatile f_args... args) +{ + g_hookCtx->reset(size_t(&original) + sizeof(original)); int hc_state = HC_CONTINUE; - auto hook = g_hookManager.getHook(func); for (auto& fwd : hook->pre) { @@ -90,7 +106,6 @@ void callVoidForward(int func, original_t original, f_args... args) auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...); if (ret == HC_BREAK) { - g_hookCtx = nullptr; return; } @@ -112,20 +127,29 @@ void callVoidForward(int func, original_t original, f_args... args) break; } } - - g_hookCtx = nullptr; } template -R callForward(int func, original_t original, f_args... args) +R callForward(size_t func, original_t original, f_args... args) { - hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...); - hookCtx.retVal.set = false; - hookCtx.retVal.type = getApiType(R()); - g_hookCtx = &hookCtx; +#ifndef _WIN32 + static +#endif + hookctx_t hookCtx(sizeof...(args), args...); + g_hookCtx = &hookCtx; + auto ret = _callForward(g_hookManager.getHook(func), original, args...); + g_hookCtx = nullptr; + + return ret; +} + +template +NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, volatile f_args... args) +{ + auto& hookCtx = *g_hookCtx; + hookCtx.reset(size_t(&original) + sizeof(original), getApiType(R())); int hc_state = HC_CONTINUE; - auto hook = g_hookManager.getHook(func); for (auto& fwd : hook->pre) { @@ -136,15 +160,13 @@ R callForward(int func, original_t original, f_args... args) if (ret == HC_CONTINUE) continue; - if (!hookCtx.retVal.set) - { + if (!hookCtx.retVal.set) { g_amxxapi.LogError(fwd->GetAmx(), AMX_ERR_CALLBACK, "%s", "can't suppress original function call without new return value set"); continue; } if (ret == HC_BREAK) { - g_hookCtx = nullptr; - return (R)hookCtx.retVal._interger; + return *(R *)&hookCtx.retVal._interger; } if (ret > hc_state) @@ -169,10 +191,11 @@ R callForward(int func, original_t original, f_args... args) } } - g_hookCtx = nullptr; - return (R)hookCtx.retVal._interger; + return *(R *)&hookCtx.retVal._interger; } +#pragma optimize("", on) + // rehlds functions void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch); void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index cd5000d..8daafba 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -41,7 +41,7 @@ hook_t hooklist_player[] = { DLL(CBasePlayer_Observer_IsValidTarget), }; -hook_t *hooklist_t::operator[](size_t hook) const +/*hook_t *hooklist_t::getHook(size_t hook) { #define CASE(h) case ht_##h: if (index < arraysize(hooklist_##h)) return &hooklist_##h[index]; else break; @@ -55,4 +55,8 @@ hook_t *hooklist_t::operator[](size_t hook) const } return nullptr; -} +}*/ + +const size_t hooklist_engine_size = arraysize(hooklist_engine); +const size_t hooklist_gamedll_size = arraysize(hooklist_gamedll); +const size_t hooklist_player_size = arraysize(hooklist_player); diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 5df7ecf..ed4c191 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -101,9 +101,42 @@ struct hook_t regchain_t unregisterHookchain; // unregister re* API hook }; +extern hook_t hooklist_engine[]; +extern hook_t hooklist_gamedll[]; +extern hook_t hooklist_player[]; +extern const size_t hooklist_engine_size; +extern const size_t hooklist_gamedll_size; +extern const size_t hooklist_player_size; + struct hooklist_t { - hook_t *operator[](size_t hook) const; + hook_t *operator[](size_t hook) const + { +#define CASE(h) case ht_##h: if (index < hooklist_##h##_size) return &hooklist_##h[index]; else break; + + const auto table = hooks_tables_e(hook / MAX_REGION_RANGE); + const auto index = hook & (MAX_REGION_RANGE - 1); + + switch (table) { + CASE(engine) + CASE(gamedll) + CASE(player) + } + + return nullptr; + /*const auto table = hooks_tables_e(hook / MAX_REGION_RANGE); + const auto index = hook & (MAX_REGION_RANGE - 1); + + switch (table) { + case ht_engine: return &hooklist_engine[index]; + case ht_gamedll: return &hooklist_gamedll[index]; + case ht_player: return &hooklist_player[index]; + } + + return nullptr;*/ + } + + //static hook_t *getHook(size_t hook); enum hooks_tables_e { @@ -197,6 +230,3 @@ enum GamedllFunc_CBasePlayer // [...] RH_CBasePlayer_End }; - -extern hook_t hooklist_engine[]; -extern hook_t hooklist_player[]; diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index 798c932..168bc52 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -3,7 +3,7 @@ struct regmember { template - regmember(T &type, size_t maxsize, size_t offset, enum_membertypes member_type) + regmember(T& type, size_t maxsize, size_t offset, enum_membertypes member_type) { member.size = sizeof(T); member.max_size = sizeof(T); diff --git a/reapi/src/natives.cpp b/reapi/src/natives.cpp index b9ac847..5dcf42d 100644 --- a/reapi/src/natives.cpp +++ b/reapi/src/natives.cpp @@ -32,8 +32,8 @@ static cell AMX_NATIVE_CALL RegisterHookChain(AMX *amx, cell *params) return 0; } - int funcid, len; - const char *funcname = g_amxxapi.GetAmxString(amx, params[arg_handler], 0, &len); + int funcid; + const char *funcname = getAmxString(amx, params[arg_handler]); if (g_amxxapi.amx_FindPublic(amx, funcname, &funcid) != AMX_ERR_NONE) { MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: public function \"%s\" not found.", funcname); @@ -69,11 +69,11 @@ static cell AMX_NATIVE_CALL EnableHookChain(AMX *amx, cell *params) if (hook == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "EnableHookChain: invalid HookChain handle."); - return 0; + return FALSE; } hook->m_state = FSTATE_ENABLED; - return 1; + return TRUE; } /* @@ -94,11 +94,11 @@ static cell AMX_NATIVE_CALL DisableHookChain(AMX *amx, cell *params) if (hook == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "DisableHookChain: invalid HookChain handle."); - return 0; + return FALSE; } hook->m_state = FSTATE_STOPPED; - return 1; + return TRUE; } /* @@ -116,7 +116,7 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params) if (!g_hookCtx) { MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set return value without active hook."); - return 0; + return FALSE; } enum args_e { arg_count, arg_type, arg_value }; @@ -125,7 +125,7 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params) if (params[arg_type] != retVal.type) { MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set incompatible return type."); - return 0; + return FALSE; } cell* srcAddr = getAmxAddr(amx, params[arg_value]); @@ -151,11 +151,11 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params) retVal._classptr = CBaseEntity::Instance(INDEXENT(*srcAddr)); break; default: - return 0; + return FALSE; } retVal.set = true; - return 1; + return TRUE; } /* @@ -174,7 +174,7 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params) if (!g_hookCtx) { MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook."); - return 0; + return FALSE; } enum args_e { arg_count, arg_value, arg_maxlen }; @@ -191,7 +191,7 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params) case ATYPE_STRING: { if (params[arg_count] != 2) - return 0; + return FALSE; setAmxString(dstAddr, retVal._string, params[arg_maxlen]); break; @@ -200,10 +200,10 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params) *dstAddr = retVal._classptr->entindex(); break; default: - return 0; + return FALSE; } - return 1; + return TRUE; } /* @@ -223,17 +223,16 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) if (!g_hookCtx) { MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook."); - return 0; + return FALSE; } enum args_e { arg_count, arg_number, arg_type, arg_value }; - size_t number = params[arg_number] - 1; if (number >= g_hookCtx->args_count) { MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: can't set argument %i of hookchain with %i args.", params[arg_number], g_hookCtx->args_count); - return 0; + return FALSE; } AType type = g_hookCtx->args_type[number]; @@ -241,7 +240,7 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) if (params[arg_type] != type) { MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: invalid argument type provided."); - return 0; + return FALSE; } static char temp_strings[MAX_ARGS][1024]; @@ -256,14 +255,14 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) *(cell *)destAddr = *srcAddr; break; case ATYPE_STRING: - *(char **)destAddr = getAmxStringTemp(srcAddr, temp_strings[number], 1023, nullptr); + *(char **)destAddr = getAmxStringTemp(srcAddr, temp_strings[number], 1023); break; case ATYPE_CLASSPTR: *(CBaseEntity **)destAddr = CBaseEntity::Instance(INDEXENT(*srcAddr)); break; } - return 1; + return TRUE; } AMX_NATIVE_INFO Func_Natives[] = diff --git a/reapi/src/natives_member.cpp b/reapi/src/natives_member.cpp index 5052530..3378951 100644 --- a/reapi/src/natives_member.cpp +++ b/reapi/src/natives_member.cpp @@ -8,13 +8,13 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) if (member == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "set_member: unknown member id %i", params[arg_member]); - return 0; + return FALSE; } edict_t *pEdict = INDEXENT(params[arg_index]); if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "set_member: invalid or uninitialized entity", params[arg_member]); - return 0; + return FALSE; } cell* value = getAmxAddr(amx, params[arg_value]); @@ -23,7 +23,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) switch (member->type) { case MEMBER_ENTITY: - return -1; + return FALSE; case MEMBER_CLASSPTR: { // native set_member(_index, any:_member, _value, _elem); @@ -34,7 +34,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) pEntity = CBaseEntity::Instance(pEdictValue); } set_member(pEdict, member->offset, pEntity, element); - return 1; + return TRUE; } case MEMBER_EHANDLE: { @@ -42,23 +42,23 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) EHANDLE& ehandle = get_member(pEdict, member->offset, element); edict_t *pEdictValue = INDEXENT(*value); ehandle.Set(pEdictValue); - return 1; + return TRUE; } case MEMBER_EVARS: - return -1; + return FALSE; case MEMBER_EDICT: { // native set_member(_index, any:_member, _value, _elem); edict_t *pEdictValue = INDEXENT(*value); set_member(pEdict, member->offset, pEdictValue, element); - return 1; + return TRUE; } case MEMBER_VECTOR: { // native set_member(_index, any:_member, Float:_value[3], _elem); Vector *pSource = (Vector *)getAmxAddr(amx, params[arg_value]); set_member(pEdict, member->offset, *pSource, element); - return 1; + return TRUE; } case MEMBER_CHAR_ARRAY: { @@ -68,7 +68,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) char *dest = get_member_direct(pEdict, member->offset); strncpy(dest, source, member->max_size - 1); dest[member->max_size - 1] = '\0'; - return 1; + return TRUE; } case MEMBER_CHAR_POINTER: { @@ -85,51 +85,51 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) strcpy(dest, source); set_member(pEdict, member->offset, dest); - return 1; + return TRUE; } case MEMBER_FLOAT: case MEMBER_INTEGER: { // native set_member(_index, any:_member, any:_value, _elem); set_member(pEdict, member->offset, *value, element); - return 1; + return TRUE; } case MEMBER_SHORT: { // native set_member(_index, any:_member, _value, _elem); set_member(pEdict, member->offset, *value, element); - return 1; + return TRUE; } case MEMBER_BYTE: { // native set_member(_index, any:_member, _value, _elem); set_member(pEdict, member->offset, *value, element); - return 1; + return TRUE; } case MEMBER_BOOL: { // native set_member(_index, any:_member, bool:_value, _elem); set_member(pEdict, member->offset, *value != 0, element); - return 1; + return TRUE; } case MEMBER_SIGNALS: { // native set_member(_index, any:_member, _value); CUnifiedSignals& signal = get_member(pEdict, member->offset, element); signal.Signal(*value); - return 1; + return TRUE; } case MEMBER_DOUBLE: { // native set_member(_index, any:_member, any:_value, _elem); set_member(pEdict, member->offset, *(float *)value, element); - return 1; + return TRUE; } case MEBMER_REBUYSTRUCT: - return -1; + return FALSE; } - return 0; + return FALSE; } // native any:get_member(_index = 0, any:_member, any:...); @@ -140,13 +140,13 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) if (member == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return 0; + return FALSE; } edict_t *pEdict = INDEXENT(params[arg_index]); if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { - return 0; + return FALSE; } size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]); @@ -154,7 +154,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) switch (member->type) { case MEMBER_ENTITY: - return -1; + return FALSE; case MEMBER_CLASSPTR: // native any:get_member(_index, any:_member, element); return get_member(pEdict, member->offset, element)->entindex(); @@ -166,7 +166,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) if (pEntity != nullptr) { return ((CBaseEntity *)ehandle)->entindex(); } - return 0; + return FALSE; } case MEMBER_EVARS: return -1; @@ -178,7 +178,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) return indexOfEdict(pEntity); } - return 0; + return FALSE; } case MEMBER_VECTOR: { @@ -207,7 +207,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) g_amxxapi.SetAmxString(amx, params[3], dest, *g_amxxapi.GetAmxAddr(amx, params[4])); return 1; } - return 0; + return FALSE; } case MEMBER_FLOAT: case MEMBER_INTEGER: @@ -244,7 +244,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) return -1; } - return 0; + return FALSE; } // native set_member_game(any:_member, any:...); @@ -255,7 +255,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) if (member == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return 0; + return FALSE; } size_t value = *g_amxxapi.GetAmxAddr(amx, params[arg_value]); @@ -273,7 +273,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) case MEMBER_BYTE: case MEMBER_SIGNALS: case MEBMER_REBUYSTRUCT: - return -1; + return FALSE; case MEMBER_CLASSPTR: { // native set_member_game(any:_member, _value, _elem); @@ -313,7 +313,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) } } - return 0; + return FALSE; } // native get_member_game(any:_member, any:...); @@ -324,7 +324,7 @@ static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) if (member == nullptr) { MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return 0; + return FALSE; } size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]); @@ -370,7 +370,7 @@ static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) } } - return 0; + return FALSE; } AMX_NATIVE_INFO Member_Natives[] =