mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-12 16:30:53 +01:00
177 lines
4.5 KiB
C++
177 lines
4.5 KiB
C++
|
|
#include <TiltedReverse/Code/reverse/include/Debug.hpp>
|
|
#include "TargetConfig.h"
|
|
#include "launcher.h"
|
|
|
|
#include "loader/ExeLoader.h"
|
|
#include "loader/PathRerouting.h"
|
|
|
|
#include "Utils/Error.h"
|
|
#include "Utils/FileVersion.inl"
|
|
|
|
#include "oobe/PathSelection.h"
|
|
#include "oobe/PathArgument.h"
|
|
#include "oobe/SupportChecks.h"
|
|
#include "steam/SteamLoader.h"
|
|
|
|
#include "base/dialogues/win/TaskDialog.h"
|
|
#include "utils/Registry.h"
|
|
|
|
#include <BranchInfo.h>
|
|
|
|
// These symbols are defined within the client code skyrimtogetherclient
|
|
extern void InstallStartHook();
|
|
extern void RunTiltedApp();
|
|
extern void RunTiltedInit(const std::filesystem::path& acGamePath, const TiltedPhoques::String& aExeVersion);
|
|
|
|
// Defined in EarlyLoad.dll
|
|
bool __declspec(dllimport) EarlyInstallSucceeded();
|
|
|
|
HICON g_SharedWindowIcon = nullptr;
|
|
|
|
namespace launcher
|
|
{
|
|
static LaunchContext* g_context = nullptr;
|
|
|
|
LaunchContext* GetLaunchContext()
|
|
{
|
|
#if 0
|
|
if (!g_context)
|
|
__debugbreak();
|
|
#endif
|
|
return g_context;
|
|
}
|
|
|
|
// Everything is nothing, life is worth living, just look to the stars
|
|
#define DIE_NOW(err) \
|
|
{ \
|
|
Die(err); \
|
|
return false; \
|
|
}
|
|
|
|
void SetMaxstdio()
|
|
{
|
|
const auto handle = GetModuleHandleW(L"API-MS-WIN-CRT-STDIO-L1-1-0.DLL");
|
|
if (!handle)
|
|
return;
|
|
|
|
const auto setmaxstdioFunc = reinterpret_cast<decltype(&_setmaxstdio)>(GetProcAddress(handle, "_setmaxstdio"));
|
|
|
|
if (!setmaxstdioFunc)
|
|
return;
|
|
|
|
setmaxstdioFunc(8192);
|
|
}
|
|
|
|
int StartUp(int argc, char** argv)
|
|
{
|
|
bool askSelect = (GetAsyncKeyState(VK_SPACE) & 0x8000);
|
|
if (!HandleArguments(argc, argv, askSelect))
|
|
return -1;
|
|
|
|
// TODO(Force): Make some InitSharedResources func.
|
|
g_SharedWindowIcon = LoadIconW(GetModuleHandleW(nullptr), MAKEINTRESOURCEW(102));
|
|
|
|
#if (!IS_MASTER)
|
|
TiltedPhoques::Debug::CreateConsole();
|
|
#endif
|
|
|
|
SetMaxstdio();
|
|
|
|
if (!EarlyInstallSucceeded())
|
|
DIE_NOW(L"Early load install failed. Tell Force about this.");
|
|
|
|
auto LC = std::make_unique<LaunchContext>();
|
|
g_context = LC.get();
|
|
|
|
{
|
|
const wchar_t* ec = nullptr;
|
|
const auto status = oobe::ReportModCompatabilityStatus();
|
|
switch (status)
|
|
{
|
|
case oobe::CompatabilityStatus::kDX11Unsupported: ec = L"Device does not support DirectX 11"; break;
|
|
case oobe::CompatabilityStatus::kOldOS: ec = L"Operating system unsupported. Please upgrade to Windows 8.1 or greater"; break;
|
|
}
|
|
|
|
if (ec)
|
|
DIE_NOW(ec);
|
|
}
|
|
|
|
if (!oobe::SelectInstall(askSelect))
|
|
DIE_NOW(L"Failed to select game install.");
|
|
|
|
// Bind path environment.
|
|
loader::InstallPathRouting(LC->gamePath);
|
|
steam::Load(LC->gamePath);
|
|
|
|
if (!LoadProgram(*LC))
|
|
return 3;
|
|
|
|
InstallStartHook();
|
|
// Initialize all hooks before calling game init
|
|
// TiltedPhoques::Initializer::RunAll();
|
|
RunTiltedInit(LC->gamePath, LC->Version);
|
|
|
|
// This shouldn't return until the game is killed
|
|
LC->gameMain();
|
|
return 0;
|
|
}
|
|
|
|
bool LoadProgram(LaunchContext& LC)
|
|
{
|
|
auto content = TiltedPhoques::LoadFile(LC.exePath);
|
|
if (content.empty())
|
|
DIE_NOW(L"Failed to mount game executable");
|
|
|
|
LC.Version = QueryFileVersion(LC.exePath.c_str());
|
|
if (LC.Version.empty())
|
|
DIE_NOW(L"Failed to query game version");
|
|
|
|
ExeLoader loader(CurrentTarget.exeLoadSz);
|
|
if (!loader.Load(reinterpret_cast<uint8_t*>(content.data())))
|
|
DIE_NOW(L"Fatal error while mapping executable");
|
|
|
|
LC.gameMain = loader.GetEntryPoint();
|
|
return true;
|
|
}
|
|
|
|
void InitClient()
|
|
{
|
|
// Jump into client code.
|
|
RunTiltedApp();
|
|
}
|
|
|
|
bool HandleArguments(int aArgc, char** aArgv, bool& aAskSelect)
|
|
{
|
|
for (int i = 1; i < aArgc; i++)
|
|
{
|
|
if (std::strcmp(aArgv[i], "-r") == 0)
|
|
aAskSelect = true;
|
|
else if (std::strcmp(aArgv[i], "--exePath") == 0)
|
|
{
|
|
if (i + 1 >= aArgc)
|
|
{
|
|
SetLastError(ERROR_BAD_PATHNAME);
|
|
Die(L"No exe path specified", true);
|
|
return false;
|
|
}
|
|
|
|
if (!oobe::PathArgument(aArgv[i + 1]))
|
|
{
|
|
SetLastError(ERROR_BAD_ARGUMENTS);
|
|
Die(L"Failed to parse path argument", true);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} // namespace launcher
|
|
|
|
// CreateProcess in suspended mode.
|
|
// Inject usvfs_64.dll -> invoke InitHooks
|
|
// (https://github.com/ModOrganizer2/usvfs/blob/f8051c179dee114b7e06c5dab2482977c285d611/src/usvfs_dll/usvfs.cpp#L352)
|
|
// Resume proc
|
|
|
|
// InjectDLLRemoteThread ->SkipInit
|