r5sdk/r5dev/launcher/launcher.cpp
Kawe Mazidjatari a618990937 Detour code refactor
This change was planned for a long time. This moves all REGISTER calls to a single translation unit, this is required as we currently added a very dirty workaround for not registering duplicates by checking if VFTable pointer was already present in the vector... Registering from single translation unit prevents duplicate instances that gets created if header is included by more cpp files.
Reworking this reduced 100kb+ of compiled code. This commit also reworked the way functions/variables/constant gets logged with their addresses; the new code formats them on the fly, and allows for resize at any time. Formatting is no longer required by programmer.

TODO: currently there are some compile errors for dedicated and client dll's. These will be resolved very soon as they need to be properly worked out still (server & client only stuff needs to be properly split). Use the 'main' (stable) branch for the time being if you need to compile these dll's.
2023-01-25 02:26:52 +01:00

189 lines
5.5 KiB
C++

//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines the entry point for the application.
//
// $NoKeywords: $
//===========================================================================//
#include "core/stdafx.h"
#include "tier0/commandline.h"
#include "tier1/strtools.h"
#include "public/utility/crashhandler.h"
#include "launcher/launcher.h"
int HWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// !TODO [AMOS]: 'RemoveSpuriousGameParameters()' is inline with 'LauncherMain()' in S0 and S1,
// and its the only function where we could append our own command line parameters early enough
// programatically (has to be after 'CommandLine()->CreateCmdLine()', but before 'SetPriorityClass()')
// For S0 and S1 we should modify the command line buffer passed to the entry point instead (here).
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
string svCmdLine = lpCmdLine;
if (!strstr(GetCommandLineA(), "-launcher"))
{
svCmdLine = LoadConfigFile(SDK_DEFAULT_CFG);
}
return v_WinMain(hInstance, hPrevInstance, const_cast<LPSTR>(svCmdLine.c_str()), nShowCmd);
#else
return v_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
#endif
}
int LauncherMain(HINSTANCE hInstance)
{
int results = v_LauncherMain(hInstance);
spdlog::info("LauncherMain returned: {:s}\n", ExitCodeToString(results));
return results;
}
#if !defined (GAMEDLL_S0) || !defined (GAMEDLL_S1)
// Remove all but the last -game parameter.
// This is for mods based off something other than Half-Life 2 (like HL2MP mods).
// The Steam UI does 'steam -applaunch 320 -game c:\steam\steamapps\sourcemods\modname', but applaunch inserts
// its own -game parameter, which would supersede the one we really want if we didn't intercede here.
void RemoveSpuriousGameParameters()
{
AppendSDKParametersPreInit();
// Find the last -game parameter.
int nGameArgs = 0;
char lastGameArg[MAX_PATH];
for (int i = 0; i < CommandLine()->ParmCount() - 1; i++)
{
if (Q_stricmp(CommandLine()->GetParm(i), "-game") == 0)
{
Q_snprintf(lastGameArg, sizeof(lastGameArg), "\"%s\"", CommandLine()->GetParm(i + 1));
++nGameArgs;
++i;
}
}
// We only care if > 1 was specified.
if (nGameArgs > 1)
{
CommandLine()->RemoveParm("-game");
CommandLine()->AppendParm("-game", lastGameArg);
}
}
#endif
// Append required command line parameters.
// This avoids having all these in the startup configuration files
// as all there are required to run the game with the game sdk.
void AppendSDKParametersPreInit()
{
#ifdef DEDICATED
CommandLine()->AppendParm("-collate", "");
CommandLine()->AppendParm("-multiple", "");
CommandLine()->AppendParm("-noorigin", "");
CommandLine()->AppendParm("-nodiscord", "");
CommandLine()->AppendParm("-noshaderapi", "");
CommandLine()->AppendParm("-nobakedparticles", "");
CommandLine()->AppendParm("-novid", "");
CommandLine()->AppendParm("-nomenuvid", "");
CommandLine()->AppendParm("-nosound", "");
CommandLine()->AppendParm("-nomouse", "");
CommandLine()->AppendParm("-nojoy", "");
CommandLine()->AppendParm("-nosendtable", "");
#endif
// Assume default configs if the game isn't launched with the SDKLauncher.
if (!CommandLine()->FindParm("-launcher"))
{
string svArguments = LoadConfigFile(SDK_DEFAULT_CFG);
ParseAndApplyConfigFile(svArguments);
}
}
string LoadConfigFile(const string& svConfig)
{
fs::path cfgPath = fs::current_path() /= svConfig; // Get cfg path for default startup.
ifstream cfgFile(cfgPath);
string svArguments;
if (cfgFile.good() && cfgFile)
{
stringstream ss;
ss << cfgFile.rdbuf();
svArguments = ss.str();
}
else
{
spdlog::error("{:s}: '{:s}' does not exist!\n", __FUNCTION__, svConfig);
cfgFile.close();
return "";
}
cfgFile.close();
return svArguments;
}
void ParseAndApplyConfigFile(const string& svConfig)
{
stringstream ss(svConfig);
string svInput;
if (!svConfig.empty())
{
while (std::getline(ss, svInput, '\n'))
{
string::size_type nPos = svInput.find(' ');
if (!svInput.empty()
&& nPos > 0
&& nPos < svInput.size()
&& nPos != svInput.size())
{
string svValue = svInput.substr(nPos + 1);
string svArgument = svInput.erase(svInput.find(' '));
CommandLine()->AppendParm(svArgument.c_str(), svValue.c_str());
}
else
{
CommandLine()->AppendParm(svInput.c_str(), "");
}
}
}
}
const char* ExitCodeToString(int nCode)
{
switch (nCode)
{
case EXIT_SUCCESS:
return "EXIT_SUCCESS";
case EXIT_FAILURE:
return "EXIT_FAILURE";
default:
return "UNKNOWN_EXIT_CODE";
}
}
LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
{
// Don't run the unhandled exception filter from the
// game if we have a valid vectored exception filter.
if (g_CrashHandler && g_CrashHandler->Handled())
{
return NULL;
}
return v_TopLevelExceptionFilter(pExceptionPointers);
}
void VLauncher::Attach(void) const
{
DetourAttach((LPVOID*)&v_WinMain, &HWinMain);
DetourAttach((LPVOID*)&v_LauncherMain, &LauncherMain);
DetourAttach((LPVOID*)&v_TopLevelExceptionFilter, &TopLevelExceptionFilter);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
DetourAttach((LPVOID*)&v_RemoveSpuriousGameParameters, &RemoveSpuriousGameParameters);
#endif
}
void VLauncher::Detach(void) const
{
DetourDetach((LPVOID*)&v_WinMain, &HWinMain);
DetourDetach((LPVOID*)&v_LauncherMain, &LauncherMain);
DetourDetach((LPVOID*)&v_TopLevelExceptionFilter, &TopLevelExceptionFilter);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
DetourDetach((LPVOID*)&v_RemoveSpuriousGameParameters, &RemoveSpuriousGameParameters);
#endif
}