read cmdline args from file, disable origin on dedi

This commit is contained in:
BobTheBob 2021-09-27 00:25:36 +01:00
parent da212ca9b7
commit 26d090e4ae
5 changed files with 65 additions and 14 deletions

View File

@ -3,6 +3,7 @@
#include <filesystem>
#include <sstream>
#include <iostream>
#include <fstream>
namespace fs = std::filesystem;
@ -35,7 +36,7 @@ DWORD GetProcessByName(std::wstring processName)
#define PROCESS_NAME L"Titanfall2-unpacked.exe"
#define DLL_NAME L"Northstar.dll"
int main() {
int main(int argc, char* argv[]) {
if (!fs::exists(PROCESS_NAME))
{
MessageBoxA(0, "Titanfall2-unpacked.exe not found! Please launch from your titanfall 2 directory and ensure you have Northstar installed correctly!", "", MB_OK);
@ -48,7 +49,12 @@ int main() {
return 1;
}
if (!GetProcessByName(L"Origin.exe"))
bool isdedi = false;
for (int i = 0; i < argc; i++)
if (!strcmp(argv[i], "-dedicated"))
isdedi = true;
if (!GetProcessByName(L"Origin.exe") && !isdedi)
{
// unpacked exe will crash if origin isn't open on launch, so launch it
// get origin path from registry, code here is reversed from OriginSDK.dll
@ -78,13 +84,36 @@ int main() {
Sleep(200);
}
// get cmdline args from file
std::wstring args;
std::ifstream cmdlineArgFile;
if (!isdedi)
cmdlineArgFile = std::ifstream("ns_startup_args.txt");
else
cmdlineArgFile = std::ifstream("ns_startup_args_dedi.txt");
if (cmdlineArgFile)
{
std::stringstream argBuffer;
argBuffer << cmdlineArgFile.rdbuf();
cmdlineArgFile.close();
std::string str = argBuffer.str();
args.append(std::wstring(str.begin(), str.end()));
}
if (isdedi)
// copy -dedicated into args if we have it in commandline args
args.append(L" -dedicated");
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
memset(&processInfo, 0, sizeof(processInfo));
CreateProcessW(PROCESS_NAME, (wchar_t*)L" -multiple -novid", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo);
CreateProcessW(PROCESS_NAME, (LPWSTR)args.c_str(), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo);
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
LPTHREAD_START_ROUTINE pLoadLibraryW = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW");

View File

@ -15,6 +15,7 @@ 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
@ -37,22 +38,21 @@ void RunServer(CDedicatedExports* dedicated)
{
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);
// 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
while (true)
{
CEngine__Frame(g_pEngine);
spdlog::info(CommandLine()->GetCmdLine());
spdlog::info("CEngine::Frame() on map {} took {}ms", g_pHostState->m_levelName, g_pEngine->m_flFrameTime);
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);
}
}
@ -233,4 +233,18 @@ void InitialiseDedicated(HMODULE engineAddress)
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));
}

View File

@ -2,4 +2,5 @@
bool IsDedicated();
void InitialiseDedicated(HMODULE moduleAddress);
void InitialiseDedicated(HMODULE moduleAddress);
void InitialiseDedicatedOrigin(HMODULE baseAddress);

View File

@ -68,6 +68,7 @@ void InitialiseNorthstar()
// dedi patches
{
AddDllLoadCallback("engine.dll", InitialiseDedicated);
AddDllLoadCallback("launcher.dll", InitialiseDedicatedOrigin);
AddDllLoadCallback("materialsystem_dx11.dll", InitialiseDedicatedMaterialSystem);
}

View File

@ -144,10 +144,16 @@ enum EngineState_t
DLL_PAUSED, // engine is paused, can become active from this state
};
struct CEngine
class CEngine
{
public:
void* vtable;
virtual bool Load(bool dedicated, const char* baseDir) {}
virtual void Unload() {}
virtual void SetNextState(EngineState_t iNextState) {}
virtual EngineState_t GetState() {}
virtual void Frame() {}
virtual float GetFrameTime() {}
virtual float GetCurTime() {}
EngineQuitState m_nQuitting;
EngineState_t m_nDllState;