From a4434a4db16c347d5453354c1a15555d168ec7b9 Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Sun, 26 Sep 2021 15:13:45 +0100 Subject: commandline struct change, dedicated refactor --- NorthstarDedicatedTest/dedicated.cpp | 186 +++++++++------------ NorthstarDedicatedTest/dedicated.h | 26 +-- NorthstarDedicatedTest/dedicatedmaterialsystem.cpp | 24 +++ NorthstarDedicatedTest/dllmain.cpp | 11 ++ NorthstarDedicatedTest/gameutils.cpp | 8 +- NorthstarDedicatedTest/gameutils.h | 63 +++++-- NorthstarDedicatedTest/securitypatches.cpp | 5 +- 7 files changed, 178 insertions(+), 145 deletions(-) diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index 01917f50..3dca5032 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -4,48 +4,63 @@ #include "tier0.h" #include "gameutils.h" -#include - bool IsDedicated() { - return CommandLine()->HasParm("-dedicated"); + return CommandLine()->CheckParm("-dedicated"); } -enum EngineState_t +// CDedidcatedExports defs +struct CDedicatedExports; // forward declare + +typedef void (*DedicatedSys_PrintfType)(CDedicatedExports* dedicated, char* msg); +typedef void (*DedicatedRunServerType)(CDedicatedExports* dedicated); + +struct CDedicatedExports { - DLL_INACTIVE = 0, // no dll - DLL_ACTIVE, // engine is focused - DLL_CLOSE, // closing down dll - DLL_RESTART, // engine is shutting down but will restart right away - DLL_PAUSED, // engine is paused, can become active from this state + 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; }; -struct CEngine +void Sys_Printf(CDedicatedExports* dedicated, char* msg) { -public: - void* vtable; - - int m_nQuitting; - EngineState_t m_nDllState; - EngineState_t m_nNextDllState; - double m_flCurrentTime; - float m_flFrameTime; - double m_flPreviousTime; - float m_flFilteredTime; - float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited. -}; + spdlog::info("[DEDICATED PRINT] {}", msg); +} + +typedef bool (*CEngine__FrameType)(void* engineSelf); +typedef void(*CHostState__InitType)(CHostState* self); -enum HostState_t +void RunServer(CDedicatedExports* dedicated) { - HS_NEW_GAME = 0, - HS_LOAD_GAME, - HS_CHANGE_LEVEL_SP, - HS_CHANGE_LEVEL_MP, - HS_RUN, - HS_GAME_SHUTDOWN, - HS_SHUTDOWN, - HS_RESTART, -}; + Sys_Printf(dedicated, (char*)"CDedicatedExports::RunServer(): starting"); + + HMODULE engine = GetModuleHandleA("engine.dll"); + CEngine__FrameType CEngine__Frame = (CEngine__FrameType)((char*)engine + 0x1C8650); + CHostState__InitType CHostState__Init = (CHostState__InitType)((char*)engine + 0x16E110); + + // call once to init + CEngine__Frame(g_pEngine); + + // init hoststate, if we don't do this, we get a crash later on + CHostState__Init(g_pHostState); + + // set up engine and host states to allow us to enter CHostState::FrameUpdate, with the state HS_NEW_GAME + g_pEngine->m_nNextDllState = EngineState_t::DLL_ACTIVE; + 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 + + while (true) + { + CEngine__Frame(g_pEngine); + + //engineApiStartSimulation(nullptr, true); + Sys_Printf(dedicated, (char*)"engine->Frame()"); + Sleep(50); + } +} void InitialiseDedicated(HMODULE engineAddress) { @@ -54,21 +69,6 @@ void InitialiseDedicated(HMODULE engineAddress) spdlog::info("InitialiseDedicated"); - //while (!IsDebuggerPresent()) - // Sleep(100); - - // create binary patches - //{ - // // CEngineAPI::SetStartupInfo - // // prevents englishclient_frontend from loading - // - // char* ptr = (char*)engineAddress + 0x1C7CBE; - // TempReadWrite rw(ptr); - // - // // je => jmp - // *ptr = (char)0xEB; - //} - { // Host_Init // prevent a particle init that relies on client dll @@ -182,6 +182,33 @@ void InitialiseDedicated(HMODULE engineAddress) *(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; @@ -193,24 +220,14 @@ void InitialiseDedicated(HMODULE engineAddress) *(ptr + 2) = (char)0x90; } + CDedicatedExports* dedicatedExports = new CDedicatedExports; + dedicatedExports->vtable = dedicatedExports; + dedicatedExports->Sys_Printf = Sys_Printf; + dedicatedExports->RunServer = RunServer; - // materialsystem later: - // do materialsystem + 5f0f1 je => jmp to make material loading not die - - CDedicatedExports* dedicatedApi = new CDedicatedExports; - dedicatedApi->Sys_Printf = Sys_Printf; - dedicatedApi->RunServer = RunServer; - - // double ptr to dedicatedApi - intptr_t* ptr = (intptr_t*)((char*)engineAddress + 0x13F0B668); + CDedicatedExports** exports = (CDedicatedExports**)((char*)engineAddress + 0x13F0B668); + *exports = dedicatedExports; - // ptr to dedicatedApi - intptr_t* doublePtr = new intptr_t; - *doublePtr = (intptr_t)dedicatedApi; - - // ptr to ptr - *ptr = (intptr_t)doublePtr; - // 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 @@ -219,47 +236,6 @@ void InitialiseDedicated(HMODULE engineAddress) // add cmdline args that are good for dedi CommandLine()->AppendParm("-nomenuvid", 0); - CommandLine()->AppendParm("+host_preload_shaders", 0); CommandLine()->AppendParm("-nosound", 0); -} - -void Sys_Printf(CDedicatedExports* dedicated, char* msg) -{ - spdlog::info("[DEDICATED PRINT] {}", msg); -} - -typedef void(*CHostState__InitType)(CHostState* self); - -void RunServer(CDedicatedExports* dedicated) -{ - while (!IsDebuggerPresent())Sleep(100); - - Sys_Printf(dedicated, (char*)"CDedicatedServerAPI::RunServer(): starting"); - - HMODULE engine = GetModuleHandleA("engine.dll"); - CEngine__Frame engineFrame = (CEngine__Frame)((char*)engine + 0x1C8650); - CEngine* cEnginePtr = (CEngine*)((char*)engine + 0x7D70C8); - CHostState* cHostStatePtr = (CHostState*)((char*)engine + 0x7CF180); - - CHostState__InitType CHostState__Init = (CHostState__InitType)((char*)engine + 0x16E110); - - // call once to init - engineFrame(cEnginePtr); - - // init hoststate, if we don't do this, we get a crash later on - CHostState__Init(cHostStatePtr); - - // set up engine and host states to allow us to enter CHostState::FrameUpdate, with the state HS_NEW_GAME - cEnginePtr->m_nNextDllState = EngineState_t::DLL_ACTIVE; - cHostStatePtr->m_iNextState = HostState_t::HS_NEW_GAME; - strcpy(cHostStatePtr->m_levelName, "mp_lobby"); // set map to load into - - while (true) - { - engineFrame(cEnginePtr); - - //engineApiStartSimulation(nullptr, true); - Sys_Printf(dedicated, (char*)"engine->Frame()"); - Sleep(50); - } + CommandLine()->AppendParm("+host_preload_shaders", "0"); } \ No newline at end of file diff --git a/NorthstarDedicatedTest/dedicated.h b/NorthstarDedicatedTest/dedicated.h index ed2ae09e..96bb96c4 100644 --- a/NorthstarDedicatedTest/dedicated.h +++ b/NorthstarDedicatedTest/dedicated.h @@ -2,28 +2,4 @@ bool IsDedicated(); -struct CDedicatedExports; // forward declare - -// functions for CDedicatedServerAPI -typedef void (*DedicatedSys_Printf)(CDedicatedExports* dedicated, char* msg); -typedef void (*DedicatedRunServer)(CDedicatedExports* dedicated); - -void Sys_Printf(CDedicatedExports* dedicated, char* msg); -void RunServer(CDedicatedExports* dedicated); - -// functions for running dedicated server -typedef bool (*CEngine__Frame)(void* engineSelf); -typedef void (*CEngineAPI__SetMap)(void* engineApiSelf, const char* pMapName); -typedef void (*CEngineAPI__ActivateSimulation)(void* engineApiSelf, bool bActive); - -// struct used internally -struct CDedicatedExports -{ - char unused[64]; - DedicatedSys_Printf Sys_Printf; // base + 64 - DedicatedRunServer RunServer; // base + 72 -}; - -// hooking stuff -extern bool bDedicatedHooksInitialised; -void InitialiseDedicated(HMODULE moduleAddress); +void InitialiseDedicated(HMODULE moduleAddress); \ No newline at end of file diff --git a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp b/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp index 48ade24d..e334e8fe 100644 --- a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp +++ b/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp @@ -8,6 +8,30 @@ void InitialiseDedicatedMaterialSystem(HMODULE baseAddress) { if (!IsDedicated()) return; + + // not using these for now since they're related to nopping renderthread/gamewindow i.e. very hard + //{ + // // function that launches renderthread + // char* ptr = (char*)baseAddress + 0x87047; + // TempReadWrite rw(ptr); + // + // // make it not launch renderthread + // *ptr = (char)0x90; + // *(ptr + 1) = (char)0x90; + // *(ptr + 2) = (char)0x90; + // *(ptr + 3) = (char)0x90; + // *(ptr + 4) = (char)0x90; + // *(ptr + 5) = (char)0x90; + //} + // + //{ + // // some function that waits on renderthread job + // char* ptr = (char*)baseAddress + 0x87d00; + // TempReadWrite rw(ptr); + // + // // return immediately + // *ptr = (char)0xC3; + //} { // CMaterialSystem::FindMaterial diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 3efe38c0..b801b281 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -43,6 +43,16 @@ BOOL APIENTRY DllMain( HMODULE hModule, return TRUE; } +void WaitForDebugger(HMODULE baseAddress) +{ + // earlier waitfordebugger call than is in vanilla, just so we can debug stuff a little easier + if (CommandLine()->CheckParm("-waitfordebugger")) + { + while (!IsDebuggerPresent()) + Sleep(100); + } +} + // in the future this will be called from launcher instead of dllmain void InitialiseNorthstar() { @@ -52,6 +62,7 @@ void InitialiseNorthstar() InstallInitialHooks(); InitialiseInterfaceCreationHooks(); + AddDllLoadCallback("engine.dll", WaitForDebugger); AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions); // dedi patches diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp index bf9ae3e5..1f7870b0 100644 --- a/NorthstarDedicatedTest/gameutils.cpp +++ b/NorthstarDedicatedTest/gameutils.cpp @@ -9,7 +9,10 @@ Cbuf_AddTextType Cbuf_AddText; Cbuf_ExecuteType Cbuf_Execute; // hoststate stuff -CHostState* g_GameCHostStateSingleton; +CHostState* g_pHostState; + +// cengine stuff +CEngine* g_pEngine; // network stuff ConVar* Cvar_hostport; @@ -27,7 +30,8 @@ void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0); Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0); - g_GameCHostStateSingleton = (CHostState*)((char*)baseAddress + 0x7CF180); + g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180); + g_pEngine = (CEngine*)((char*)baseAddress + 0x7D70C8); Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070); diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h index 8db63fd7..cdf9ec3b 100644 --- a/NorthstarDedicatedTest/gameutils.h +++ b/NorthstarDedicatedTest/gameutils.h @@ -62,34 +62,48 @@ extern Cbuf_ExecuteType Cbuf_Execute; class CCommandLine { public: + // based on the defs in the 2013 source sdk, but for some reason has an extra function (may be another CreateCmdLine overload?) + // these seem to line up with what they should be though virtual void CreateCmdLine(const char* commandline) {} virtual void CreateCmdLine(int argc, char** argv) {} + virtual void unknown() {} virtual const char* GetCmdLine(void) const {} - virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const {} - virtual bool HasParm(const char* psz) const {} + virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const {} virtual void RemoveParm() const {} virtual void AppendParm(const char* pszParm, const char* pszValues) {} - virtual int ParmCount() const {} - virtual int FindParm(const char* psz) const {} - virtual const char* GetParm(int nIndex) const {} - virtual const char* ParmValue(const char* psz, const char* pDefaultVal = 0) const {} virtual int ParmValue(const char* psz, int nDefaultVal) const {} virtual float ParmValue(const char* psz, float flDefaultVal) const {} + + virtual int ParmCount() const {} + virtual int FindParm(const char* psz) const {} + virtual const char* GetParm(int nIndex) const {} virtual void SetParm(int nIndex, char const* pParm) {} - virtual const char** GetParms() const {} + //virtual const char** GetParms() const {} }; // hoststate stuff +enum HostState_t +{ + HS_NEW_GAME = 0, + HS_LOAD_GAME, + HS_CHANGE_LEVEL_SP, + HS_CHANGE_LEVEL_MP, + HS_RUN, + HS_GAME_SHUTDOWN, + HS_SHUTDOWN, + HS_RESTART, +}; + struct CHostState { public: - int32_t m_iCurrentState; - int32_t m_iNextState; + HostState_t m_iCurrentState; + HostState_t m_iNextState; float m_vecLocation[3]; float m_angLocation[3]; @@ -97,9 +111,38 @@ public: char m_levelName[32]; // not reversed past this point, struct seems weird + // pretty decent chance m_levelname is bigger, given it was 256 long in normal source +}; + +extern CHostState* g_pHostState; + +// cengine stuff + +enum EngineState_t +{ + DLL_INACTIVE = 0, // no dll + DLL_ACTIVE, // engine is focused + DLL_CLOSE, // closing down dll + DLL_RESTART, // engine is shutting down but will restart right away + DLL_PAUSED, // engine is paused, can become active from this state +}; + +struct CEngine +{ +public: + void* vtable; + + int m_nQuitting; + EngineState_t m_nDllState; + EngineState_t m_nNextDllState; + double m_flCurrentTime; + float m_flFrameTime; + double m_flPreviousTime; + float m_flFilteredTime; + float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited. }; -extern CHostState* g_GameCHostStateSingleton; +extern CEngine* g_pEngine; // network stuff diff --git a/NorthstarDedicatedTest/securitypatches.cpp b/NorthstarDedicatedTest/securitypatches.cpp index f13d778e..cbb5a292 100644 --- a/NorthstarDedicatedTest/securitypatches.cpp +++ b/NorthstarDedicatedTest/securitypatches.cpp @@ -3,6 +3,7 @@ #include "hookutils.h" #include "concommand.h" #include "dedicated.h" +#include "tier0.h" typedef bool(*IsValveModType)(); IsValveModType IsValveMod; @@ -12,9 +13,7 @@ bool IsValveModHook() // basically: by default r2 isn't set as a valve mod, meaning that m_bRestrictServerCommands is false // this is HORRIBLE for security, because it means servers can run arbitrary concommands on clients // especially since we have script commands this could theoretically be awful - - // todo: possibly have a commandline arg to disable this - return true; + return !CommandLine()->CheckParm("-norestrictservercommands"); } void InitialiseClientEngineSecurityPatches(HMODULE baseAddress) -- cgit v1.2.3