Skip to content

Commit

Permalink
custom gsc builtin functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ate47 committed Sep 24, 2023
1 parent d1c2bfd commit d502735
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 4 deletions.
13 changes: 10 additions & 3 deletions src/bo4-dll/bo4.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}
}
30 changes: 30 additions & 0 deletions src/bo4-dll/custom_gsc_func.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <dll_includes.hpp>

using namespace custom_gsc_func;
using scriptinstance::ScriptInstance;

void actshello(ScriptInstance inst) {
LOG_INFO("Hello from vm {}", scriptinstance::Name(inst));
}

std::vector<Builtin> 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
}
}
};

23 changes: 23 additions & 0 deletions src/bo4-dll/custom_gsc_func.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once
#include <dll_includes.hpp>

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<Builtin> custom_functions[2];

}
120 changes: 119 additions & 1 deletion src/bo4-dll/detours.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
#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);
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<void, uint64_t, scriptinstance::ScriptInstance, char*, bool> dScrVm_Error{ "ScrVm_Error", bo4::OFFSET_ScrVm_Error, ScrVm_Error };
static cliconnect::DetourInfo<void*, BYTE, UINT64*, bool, int> dDB_FindXAssetHeader{ "DB_FindXAssetHeader", bo4::OFFSET_DB_FindXAssetHeader, DB_FindXAssetHeader };
static cliconnect::DetourInfo<void*, char const*> dStringTable_GetAsset{ "StringTable_GetAsset", bo4::OFFSET_StringTable_GetAsset, StringTable_GetAsset };
static cliconnect::DetourInfo<void> dScr_LogCompilerError{ "Scr_LogCompilerError", bo4::OFFSET_LogCompilerError, reinterpret_cast<void (*)()>(Scr_LogCompilerError) };
static cliconnect::DetourInfo<void, UINT32, const char*> dError{ "Error", bo4::OFFSET_Error, Error };

static cliconnect::DetourInfo<bool, byte*, UINT32*, bool*> dCScr_GetFunctionReverseLookup{ "CScr_GetFunctionReverseLookup", bo4::OFFSET_CScr_GetFunctionReverseLookup, CScr_GetFunctionReverseLookup };
static cliconnect::DetourInfo<bool, byte*, UINT32*, bool*> dScr_GetFunctionReverseLookup{ "Scr_GetFunctionReverseLookup", bo4::OFFSET_Scr_GetFunctionReverseLookup, Scr_GetFunctionReverseLookup };
static cliconnect::DetourInfo<BuiltinFunction, UINT32, BuiltinType*, int*, int*> dScr_GetFunction{ "Scr_GetFunction", bo4::OFFSET_Scr_GetFunction, Scr_GetFunction };
static cliconnect::DetourInfo<BuiltinFunction, UINT32, BuiltinType*, int*, int*> dCScr_GetFunction{ "CScr_GetFunction", bo4::OFFSET_CScr_GetFunction, CScr_GetFunction };
static cliconnect::DetourInfo<BuiltinFunction, UINT32, BuiltinType*, int*, int*> dScr_GetMethod{ "Scr_GetMethod", bo4::OFFSET_Scr_GetMethod, Scr_GetMethod };
static cliconnect::DetourInfo<BuiltinFunction, UINT32, BuiltinType*, int*, int*> 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");
Expand All @@ -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);
}

Expand All @@ -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<BYTE*>(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<uintptr_t>(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<BYTE*>(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<uintptr_t>(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;
}
1 change: 1 addition & 0 deletions src/bo4-dll/dll_includes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@

#include "bo4.hpp"
#include "cli_connect.hpp"
#include "custom_gsc_func.hpp"

#define EXPORT extern "C" __declspec(dllexport)

0 comments on commit d502735

Please sign in to comment.