From d50273513b75808d4d51463de0ee3cdd1867c49b Mon Sep 17 00:00:00 2001 From: qaate47 Date: Sun, 24 Sep 2023 10:53:00 +0200 Subject: [PATCH] custom gsc builtin functions --- src/bo4-dll/bo4.hpp | 13 +++- src/bo4-dll/custom_gsc_func.cpp | 30 ++++++++ src/bo4-dll/custom_gsc_func.hpp | 23 ++++++ src/bo4-dll/detours.cpp | 120 +++++++++++++++++++++++++++++++- src/bo4-dll/dll_includes.hpp | 1 + 5 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 src/bo4-dll/custom_gsc_func.cpp create mode 100644 src/bo4-dll/custom_gsc_func.hpp diff --git a/src/bo4-dll/bo4.hpp b/src/bo4-dll/bo4.hpp index 2f41031..5d5af8a 100644 --- a/src/bo4-dll/bo4.hpp +++ b/src/bo4-dll/bo4.hpp @@ -4,12 +4,19 @@ namespace bo4 { BYTE* BasePtr(); - + enum offset : uintptr_t { OFFSET_ScrVm_Error = 0x2770330, OFFSET_DB_FindXAssetHeader = 0x2EB75B0, OFFSET_StringTable_GetAsset = 0x28A2660, OFFSET_LogCompilerError = 0x2890470, - OFFSET_Error = 0x3D36CC0 + OFFSET_Error = 0x3D36CC0, + + OFFSET_Scr_GetFunctionReverseLookup = 0x33AF8A0, + OFFSET_CScr_GetFunctionReverseLookup = 0x1F132A0, + OFFSET_Scr_GetFunction = 0x1F13140, + OFFSET_CScr_GetFunction = 0x33AF840, + OFFSET_Scr_GetMethod = 0x33AFC20, + OFFSET_CScr_GetMethod = 0x1F13650, }; -} \ No newline at end of file +} diff --git a/src/bo4-dll/custom_gsc_func.cpp b/src/bo4-dll/custom_gsc_func.cpp new file mode 100644 index 0000000..e778ad2 --- /dev/null +++ b/src/bo4-dll/custom_gsc_func.cpp @@ -0,0 +1,30 @@ +#include + +using namespace custom_gsc_func; +using scriptinstance::ScriptInstance; + +void actshello(ScriptInstance inst) { + LOG_INFO("Hello from vm {}", scriptinstance::Name(inst)); +} + +std::vector custom_gsc_func::custom_functions[2] = { + { // Server functions + { + .name = hash::Hash32("actshello"), + .min_args = 0, + .max_args = 0, + .actionFunc = actshello, + .type = BUILTIN_DEFAULT + } + }, + { // Client functions + { + .name = hash::Hash32("actshello"), + .min_args = 0, + .max_args = 0, + .actionFunc = actshello, + .type = BUILTIN_DEFAULT + } + } +}; + diff --git a/src/bo4-dll/custom_gsc_func.hpp b/src/bo4-dll/custom_gsc_func.hpp new file mode 100644 index 0000000..1916f47 --- /dev/null +++ b/src/bo4-dll/custom_gsc_func.hpp @@ -0,0 +1,23 @@ +#pragma once +#include + +namespace custom_gsc_func { + typedef void (*BuiltinFunction)(scriptinstance::ScriptInstance inst); + + + enum BuiltinType : int { + BUILTIN_DEFAULT = 0, + BUILTIN_DEV = 1 + }; + + struct __declspec(align(8)) Builtin { + UINT32 name; + int min_args; + int max_args; + BuiltinFunction actionFunc; + BuiltinType type; + }; + + extern std::vector custom_functions[2]; + +} \ No newline at end of file diff --git a/src/bo4-dll/detours.cpp b/src/bo4-dll/detours.cpp index d2d7e3e..3638801 100644 --- a/src/bo4-dll/detours.cpp +++ b/src/bo4-dll/detours.cpp @@ -1,5 +1,8 @@ #include "dll_includes.hpp" + +using namespace custom_gsc_func; + // Prototype static void ScrVm_Error(uint64_t code, scriptinstance::ScriptInstance inst, char* unk, bool terminal); static void* DB_FindXAssetHeader(BYTE type, UINT64* name, bool errorIfMissing, int waitTime); @@ -7,6 +10,14 @@ static void* StringTable_GetAsset(char const* name); static void Scr_LogCompilerError(char const* name, ...); static void Error(UINT32 code, const char* empty); +static bool CScr_GetFunctionReverseLookup(byte* func, UINT32* hash, bool* isFunction); +static bool Scr_GetFunctionReverseLookup(byte* func, UINT32* hash, bool* isFunction); +static BuiltinFunction Scr_GetFunction(UINT32 name, BuiltinType* type, int* min_args, int* max_args); +static BuiltinFunction CScr_GetFunction(UINT32 name, BuiltinType* type, int* min_args, int* max_args); +static BuiltinFunction Scr_GetMethod(UINT32 name, BuiltinType* type, int* min_args, int* max_args); +static BuiltinFunction CScr_GetMethod(UINT32 name, BuiltinType* type, int* min_args, int* max_args); + + // Detours static cliconnect::DetourInfo dScrVm_Error{ "ScrVm_Error", bo4::OFFSET_ScrVm_Error, ScrVm_Error }; static cliconnect::DetourInfo dDB_FindXAssetHeader{ "DB_FindXAssetHeader", bo4::OFFSET_DB_FindXAssetHeader, DB_FindXAssetHeader }; @@ -14,6 +25,13 @@ static cliconnect::DetourInfo dStringTable_GetAsset{ "String static cliconnect::DetourInfo dScr_LogCompilerError{ "Scr_LogCompilerError", bo4::OFFSET_LogCompilerError, reinterpret_cast(Scr_LogCompilerError) }; static cliconnect::DetourInfo dError{ "Error", bo4::OFFSET_Error, Error }; +static cliconnect::DetourInfo dCScr_GetFunctionReverseLookup{ "CScr_GetFunctionReverseLookup", bo4::OFFSET_CScr_GetFunctionReverseLookup, CScr_GetFunctionReverseLookup }; +static cliconnect::DetourInfo dScr_GetFunctionReverseLookup{ "Scr_GetFunctionReverseLookup", bo4::OFFSET_Scr_GetFunctionReverseLookup, Scr_GetFunctionReverseLookup }; +static cliconnect::DetourInfo dScr_GetFunction{ "Scr_GetFunction", bo4::OFFSET_Scr_GetFunction, Scr_GetFunction }; +static cliconnect::DetourInfo dCScr_GetFunction{ "CScr_GetFunction", bo4::OFFSET_CScr_GetFunction, CScr_GetFunction }; +static cliconnect::DetourInfo dScr_GetMethod{ "Scr_GetMethod", bo4::OFFSET_Scr_GetMethod, Scr_GetMethod }; +static cliconnect::DetourInfo dCScr_GetMethod{ "CScr_GetMethod", bo4::OFFSET_CScr_GetMethod, CScr_GetMethod }; + // Custom detours static void ScrVm_Error(uint64_t code, scriptinstance::ScriptInstance inst, char* unk, bool terminal) { LOG_ERROR("VM {} Error code={} '{}' terminal={}", scriptinstance::Name(inst), code, unk, terminal ? "true" : "false"); @@ -36,7 +54,7 @@ static void Scr_LogCompilerError(char const* name, ...) { static void Error(UINT32 code, const char* empty) { // hard error - LOG_ERROR("Scr_Error {:x}{}", code, empty); + LOG_ERROR("Scr_Error {}{}", code, empty); dError(code, empty); } @@ -58,3 +76,103 @@ static void* DB_FindXAssetHeader(BYTE type, UINT64* name, bool errorIfMissing, i // for later return dDB_FindXAssetHeader(type, name, errorIfMissing, waitTime); } + +static bool CScr_GetFunctionReverseLookup(BYTE* func, UINT32* hash, bool* isFunction) { + auto res = dCScr_GetFunctionReverseLookup(func, hash, isFunction); + if (res) { + return res; + } + + for (auto& blt : custom_functions[scriptinstance::SI_CLIENT]) { + if (reinterpret_cast(blt.actionFunc) == func) { + *hash = blt.name; + *isFunction = true; + return true; + } + } + + LOG_ERROR("Vm {} Can't reverse lookup API function {:x}", scriptinstance::Name(scriptinstance::SI_CLIENT), reinterpret_cast(func)); + + return false; +} + +static bool Scr_GetFunctionReverseLookup(BYTE* func, UINT32* hash, bool* isFunction) { + auto res = dScr_GetFunctionReverseLookup(func, hash, isFunction); + if (res) { + return res; + } + + for (auto& blt : custom_functions[scriptinstance::SI_SERVER]) { + if (reinterpret_cast(blt.actionFunc) == func) { + *hash = blt.name; + *isFunction = true; + return true; + } + } + + LOG_ERROR("Vm {} Can't reverse lookup API function {:x}", scriptinstance::Name(scriptinstance::SI_SERVER), reinterpret_cast(func)); + + return false; +} + +static BuiltinFunction Scr_GetFunction(UINT32 name, BuiltinType* type, int* min_args, int* max_args) { + auto res = dScr_GetFunction(name, type, min_args, max_args); + // allow dev functions + *type = BUILTIN_DEFAULT; + if (res) { + return res; + } + + for (auto& blt : custom_functions[scriptinstance::SI_SERVER]) { + if (blt.name == name) { + //*type = blt.type; + *min_args = blt.min_args; + *max_args = blt.max_args; + return blt.actionFunc; + } + } + + return NULL; +} + +static BuiltinFunction CScr_GetFunction(UINT32 name, BuiltinType* type, int* min_args, int* max_args) { + auto res = dCScr_GetFunction(name, type, min_args, max_args); + // allow dev functions + *type = BUILTIN_DEFAULT; + if (res) { + return res; + } + + for (auto& blt : custom_functions[scriptinstance::SI_CLIENT]) { + if (blt.name == name) { + //*type = blt.type; + *min_args = blt.min_args; + *max_args = blt.max_args; + return blt.actionFunc; + } + } + + return NULL; +} + +static BuiltinFunction Scr_GetMethod(UINT32 name, BuiltinType* type, int* min_args, int* max_args) { + auto res = dScr_GetMethod(name, type, min_args, max_args); + // allow dev methods + *type = BUILTIN_DEFAULT; + if (res) { + return res; + } + + return NULL; +} + +static BuiltinFunction CScr_GetMethod(UINT32 name, BuiltinType* type, int* min_args, int* max_args) { + auto res = dCScr_GetMethod(name, type, min_args, max_args); + // allow dev methods + *type = BUILTIN_DEFAULT; + if (res) { + return res; + } + + return NULL; +} diff --git a/src/bo4-dll/dll_includes.hpp b/src/bo4-dll/dll_includes.hpp index 2e8238c..49ec610 100644 --- a/src/bo4-dll/dll_includes.hpp +++ b/src/bo4-dll/dll_includes.hpp @@ -5,5 +5,6 @@ #include "bo4.hpp" #include "cli_connect.hpp" +#include "custom_gsc_func.hpp" #define EXPORT extern "C" __declspec(dllexport) \ No newline at end of file