Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions src/game/t4/sp/components/gsc.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "pch.h"
#include "gsc.h"
#include "common/gsc_registry.h"
#include <unordered_map>

namespace t4
{
namespace sp
{
static std::unordered_map<const char*, const char*> ReplacedFunctionsSP;
namespace
{
client_t *VM_GetClientForEntRef(scr_entref_t entref)
Expand Down Expand Up @@ -173,6 +175,99 @@ void ScriptEntCmd_CloneBrushModelToScriptModel(scr_entref_t entref)
SV_LinkEntity(scriptEnt);
}

static const char* GetCodePosForParam(int index)
{
const scriptInstance_t inst = SCRIPTINSTANCE_SERVER;
const int numParams = static_cast<int>(Scr_GetNumParam(inst));

if (index < 0 || index >= numParams)
return nullptr;

auto* top = *reinterpret_cast<VariableValue**>(0x84B2F214 + (static_cast<int>(inst) * 0x14));

if (!top)
return nullptr;

auto* value = top - index;

if (value->type != VAR_FUNCTION)
return nullptr;

return value->u.codePosValue;
}
static void GScr_ReplaceFunc()
{
if (Scr_GetNumParam(SCRIPTINSTANCE_SERVER) != 2)
{
Scr_Error("replaceFunc: needs two parameters", SCRIPTINSTANCE_SERVER);
return;
}

const char* what = GetCodePosForParam(0);
const char* with = GetCodePosForParam(1);

if (!what)
{
Scr_Error("replaceFunc: first parameter is not a function", SCRIPTINSTANCE_SERVER);
return;
}

if (!with)
{
Scr_Error("replaceFunc: second parameter is not a function", SCRIPTINSTANCE_SERVER);
return;
}

ReplacedFunctionsSP[what] = with;
}

extern "C" const char* T4SP_GSC_GetReplacedPos(const char* pos)
{
if (!pos)
return pos;

const auto it = ReplacedFunctionsSP.find(pos);

if (it != ReplacedFunctionsSP.end())
return it->second;

return pos;
}

Detour VMExecuteInternal_SP_Detour;

extern "C" __declspec(naked) void VM_Execute_Hook_SP()
{
__asm
{
mr r3, r10
bl T4SP_GSC_GetReplacedPos
mr r10, r3

addi r11, r10, 1
lbz r9, 0(r10)
addi r10, r27, -0x4068
slwi r21, r31, 2

lis r12, 0x8234
ori r12, r12, 0x2EA8
mtctr r12
bctr
}
}

Detour Scr_ShutdownSystem_SP_Detour;

static int Scr_ShutdownSystem_Hook_SP(scriptInstance_t inst, int sys, int bComplete)
{
if (inst == SCRIPTINSTANCE_SERVER && bComplete)
{
ReplacedFunctionsSP.clear();
}

return Scr_ShutdownSystem_SP_Detour.GetOriginal<Scr_ShutdownSystem_t>()(inst, sys, bComplete);
}

static const gsc::Entry<BuiltinMethod> methods[] = {
{"jumpbuttonpressed", PlayerCmd_JumpButtonPressed, BUILTIN_ANY},
{"secondaryoffhandbuttonpressed", PlayerCmd_secondaryOffhandButtonPressed, BUILTIN_ANY},
Expand All @@ -186,6 +281,7 @@ static const gsc::Entry<BuiltinMethod> methods[] = {

static const gsc::Entry<BuiltinFunction> functions[] = {
{"spawncollision", GScr_SpawnCollision, BUILTIN_ANY},
{"replaceFunc", GScr_ReplaceFunc, BUILTIN_ANY},
};
} // namespace

Expand Down Expand Up @@ -230,13 +326,23 @@ GSC::GSC()

Scr_GetMethod_Detour = Detour(Scr_GetMethod, Scr_GetMethod_Hook);
Scr_GetMethod_Detour.Install();

VMExecuteInternal_SP_Detour = Detour(reinterpret_cast<void*>(0x82342E98), reinterpret_cast<const void*>(VM_Execute_Hook_SP));
VMExecuteInternal_SP_Detour.Install();

Scr_ShutdownSystem_SP_Detour = Detour(reinterpret_cast<void*>(0x82341D20), reinterpret_cast<const void*>(Scr_ShutdownSystem_Hook_SP));
Scr_ShutdownSystem_SP_Detour.Install();
}

GSC::~GSC()
{
Scr_GetFunction_Detour.Remove();

Scr_GetMethod_Detour.Remove();

VMExecuteInternal_SP_Detour.Remove();

Scr_ShutdownSystem_SP_Detour.Remove();
}
} // namespace sp
} // namespace t4
32 changes: 32 additions & 0 deletions src/game/t4/sp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -786,5 +786,37 @@ enum connstate_t
CA_MAP_RESTART = 0x9,
CA_ACTIVE = 0xA,
};

enum Vartype_t : __int32
{
VAR_UNDEFINED = 0x0,
VAR_POINTER = 0x1,
VAR_STRING = 0x2,
VAR_ISTRING = 0x3,
VAR_VECTOR = 0x4,
VAR_FLOAT = 0x5,
VAR_INTEGER = 0x6,
VAR_CODEPOS = 0x7,
VAR_PRECODEPOS = 0x8,
VAR_FUNCTION = 0x9,
};

union VariableUnion
{
int intValue;
unsigned int uintValue;
float floatValue;
const char* stringValue;
const char* codePosValue;
unsigned int pointerValue;
};

struct VariableValue
{
VariableUnion u;
Vartype_t type;
};

static_assert(sizeof(VariableValue) == 0x8, "VariableValue size mismatch");
} // namespace sp
} // namespace t4
3 changes: 3 additions & 0 deletions src/game/t4/sp/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,5 +232,8 @@ static auto R_RegisterFont = reinterpret_cast<Font_s *(*)(const char *name, int

static auto va = reinterpret_cast<char *(*)(char *format, ...)>(0x82294218);

typedef int (*Scr_ShutdownSystem_t)(scriptInstance_t inst, int sys, int bComplete);
static auto Scr_ShutdownSystem = reinterpret_cast<Scr_ShutdownSystem_t>(0x82341D20);

} // namespace sp
} // namespace t4
Loading