250 lines
6.6 KiB
C++
250 lines
6.6 KiB
C++
#include "pch.h"
|
|
#include "dedicated.h"
|
|
#include "hookutils.h"
|
|
#include "tier0.h"
|
|
#include "gameutils.h"
|
|
|
|
bool IsDedicated()
|
|
{
|
|
return CommandLine()->CheckParm("-dedicated");
|
|
}
|
|
|
|
// CDedidcatedExports defs
|
|
struct CDedicatedExports; // forward declare
|
|
|
|
typedef void (*DedicatedSys_PrintfType)(CDedicatedExports* dedicated, char* msg);
|
|
typedef void (*DedicatedRunServerType)(CDedicatedExports* dedicated);
|
|
|
|
// would've liked to just do this as a class but have not been able to get it to work
|
|
struct CDedicatedExports
|
|
{
|
|
void* vtable; // because it's easier, we just set this to &this, since CDedicatedExports has no props we care about other than funcs
|
|
|
|
char unused[56];
|
|
|
|
DedicatedSys_PrintfType Sys_Printf;
|
|
DedicatedRunServerType RunServer;
|
|
};
|
|
|
|
void Sys_Printf(CDedicatedExports* dedicated, char* msg)
|
|
{
|
|
spdlog::info("[DEDICATED PRINT] {}", msg);
|
|
}
|
|
|
|
typedef bool (*CEngine__FrameType)(void* engineSelf);
|
|
typedef void(*CHostState__InitType)(CHostState* self);
|
|
|
|
void RunServer(CDedicatedExports* dedicated)
|
|
{
|
|
Sys_Printf(dedicated, (char*)"CDedicatedExports::RunServer(): starting");
|
|
|
|
// init hoststate, if we don't do this, we get a crash later on
|
|
CHostState__InitType CHostState__Init = (CHostState__InitType)((char*)GetModuleHandleA("engine.dll") + 0x16E110);
|
|
CHostState__Init(g_pHostState);
|
|
|
|
// set host state to allow us to enter CHostState::FrameUpdate, with the state HS_NEW_GAME
|
|
g_pHostState->m_iNextState = HostState_t::HS_NEW_GAME;
|
|
strncpy(g_pHostState->m_levelName, CommandLine()->ParmValue("+map", "mp_lobby"), sizeof(g_pHostState->m_levelName)); // set map to load into
|
|
|
|
spdlog::info(CommandLine()->GetCmdLine());
|
|
|
|
while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING)
|
|
{
|
|
g_pEngine->Frame();
|
|
|
|
spdlog::info("g_pEngine->Frame() on map {} took {}ms", g_pHostState->m_levelName, g_pEngine->GetFrameTime());
|
|
Sleep(50);
|
|
}
|
|
}
|
|
|
|
void InitialiseDedicated(HMODULE engineAddress)
|
|
{
|
|
if (!IsDedicated())
|
|
return;
|
|
|
|
spdlog::info("InitialiseDedicated");
|
|
|
|
{
|
|
// Host_Init
|
|
// prevent a particle init that relies on client dll
|
|
|
|
char* ptr = (char*)engineAddress + 0x156799;
|
|
TempReadWrite rw(ptr);
|
|
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
}
|
|
|
|
{
|
|
// CModAppSystemGroup::Create
|
|
// force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment
|
|
char* ptr = (char*)engineAddress + 0x1C4EBD;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// cmp => mov
|
|
*(ptr + 1) = (char)0xC6;
|
|
*(ptr + 2) = (char)0x87;
|
|
|
|
// 00 => 01
|
|
*((char*)ptr + 7) = (char)0x01;
|
|
}
|
|
|
|
{
|
|
// Some init that i'm not sure of that crashes
|
|
char* ptr = (char*)engineAddress + 0x156A63;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// nop the call to it
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
}
|
|
|
|
{
|
|
// runframeserver
|
|
char* ptr = (char*)engineAddress + 0x159819;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// nop some access violations
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
*(ptr + 5) = (char)0x90;
|
|
*(ptr + 6) = (char)0x90;
|
|
*(ptr + 7) = (char)0x90;
|
|
*(ptr + 8) = (char)0x90;
|
|
*(ptr + 9) = (char)0x90;
|
|
*(ptr + 10) = (char)0x90;
|
|
*(ptr + 11) = (char)0x90;
|
|
*(ptr + 12) = (char)0x90;
|
|
*(ptr + 13) = (char)0x90;
|
|
*(ptr + 14) = (char)0x90;
|
|
*(ptr + 15) = (char)0x90;
|
|
*(ptr + 16) = (char)0x90;
|
|
}
|
|
|
|
{
|
|
// HostState_State_NewGame
|
|
char* ptr = (char*)engineAddress + 0x156B4C;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// nop some access violations
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
*(ptr + 5) = (char)0x90;
|
|
*(ptr + 6) = (char)0x90;
|
|
*(ptr + 7) = (char)0x90;
|
|
*(ptr + 8) = (char)0x90;
|
|
*(ptr + 9) = (char)0x90;
|
|
*(ptr + 10) = (char)0x90;
|
|
*(ptr + 11) = (char)0x90;
|
|
*(ptr + 12) = (char)0x90;
|
|
*(ptr + 13) = (char)0x90;
|
|
*(ptr + 14) = (char)0x90;
|
|
*(ptr + 15) = (char)0x90;
|
|
*(ptr + 16) = (char)0x90;
|
|
*(ptr + 17) = (char)0x90;
|
|
*(ptr + 18) = (char)0x90;
|
|
*(ptr + 19) = (char)0x90;
|
|
*(ptr + 20) = (char)0x90;
|
|
*(ptr + 21) = (char)0x90;
|
|
}
|
|
|
|
{
|
|
// HostState_State_NewGame
|
|
char* ptr = (char*)engineAddress + 0xB934C;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// nop an access violation
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
*(ptr + 5) = (char)0x90;
|
|
*(ptr + 6) = (char)0x90;
|
|
*(ptr + 7) = (char)0x90;
|
|
*(ptr + 8) = (char)0x90;
|
|
}
|
|
|
|
{
|
|
// CEngineAPI::Connect
|
|
char* ptr = (char*)engineAddress + 0x1C4D7D;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// remove call to Shader_Connect
|
|
*ptr = 0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
*(ptr + 3) = (char)0x90;
|
|
*(ptr + 4) = (char)0x90;
|
|
}
|
|
|
|
// not currently using this because it's for nopping renderthread/gamewindow stuff i.e. very hard
|
|
//{
|
|
// // CEngineAPI::Init
|
|
// char* ptr = (char*)engineAddress + 0x1C60CE;
|
|
// TempReadWrite rw(ptr);
|
|
//
|
|
// // remove call to something or other that reads video settings
|
|
// *ptr = 0x90;
|
|
// *(ptr + 1) = (char)0x90;
|
|
// *(ptr + 2) = (char)0x90;
|
|
// *(ptr + 3) = (char)0x90;
|
|
// *(ptr + 4) = (char)0x90;
|
|
//}
|
|
|
|
{
|
|
// some inputsystem bullshit
|
|
char* ptr = (char*)engineAddress + 0x1CEE28;
|
|
TempReadWrite rw(ptr);
|
|
|
|
// nop an accessviolation: temp because we still create game window atm
|
|
*ptr = (char)0x90;
|
|
*(ptr + 1) = (char)0x90;
|
|
*(ptr + 2) = (char)0x90;
|
|
}
|
|
|
|
CDedicatedExports* dedicatedExports = new CDedicatedExports;
|
|
dedicatedExports->vtable = dedicatedExports;
|
|
dedicatedExports->Sys_Printf = Sys_Printf;
|
|
dedicatedExports->RunServer = RunServer;
|
|
|
|
CDedicatedExports** exports = (CDedicatedExports**)((char*)engineAddress + 0x13F0B668);
|
|
*exports = dedicatedExports;
|
|
|
|
// extra potential patches:
|
|
// nop engine.dll+1c67d1 and +1c67d8 to skip videomode creategamewindow
|
|
// also look into launcher.dll+d381, seems to cause renderthread to get made
|
|
// this crashes HARD if no window which makes sense tbh
|
|
// also look into materialsystem + 5B344 since it seems to be the base of all the renderthread stuff
|
|
|
|
// add cmdline args that are good for dedi
|
|
CommandLine()->AppendParm("-nomenuvid", 0);
|
|
CommandLine()->AppendParm("-nosound", 0);
|
|
CommandLine()->AppendParm("+host_preload_shaders", "0");
|
|
}
|
|
|
|
typedef void(*Tier0_InitOriginType)();
|
|
Tier0_InitOriginType Tier0_InitOrigin;
|
|
void Tier0_InitOriginHook()
|
|
{
|
|
if (!IsDedicated())
|
|
Tier0_InitOrigin();
|
|
}
|
|
|
|
void InitialiseDedicatedOrigin(HMODULE baseAddress)
|
|
{
|
|
HookEnabler hook;
|
|
ENABLER_CREATEHOOK(hook, GetProcAddress(GetModuleHandleA("tier0.dll"), "Tier0_InitOrigin"), &Tier0_InitOriginHook, reinterpret_cast<LPVOID*>(&Tier0_InitOrigin));
|
|
} |