Merge pull request #404 from diamante0018/feature/start-sp
[QuickPatch] Start iw4x-sp
This commit is contained in:
commit
6f0bbe9201
@ -138,6 +138,22 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path FileSystem::GetAppdataPath()
|
||||
{
|
||||
PWSTR path;
|
||||
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &path)))
|
||||
{
|
||||
throw std::runtime_error("Failed to read APPDATA path!");
|
||||
}
|
||||
|
||||
auto _0 = gsl::finally([&path]
|
||||
{
|
||||
CoTaskMemFree(path);
|
||||
});
|
||||
|
||||
return std::filesystem::path(path) / "xlabs";
|
||||
}
|
||||
|
||||
std::vector<std::string> FileSystem::GetFileList(const std::string& path, const std::string& extension)
|
||||
{
|
||||
std::vector<std::string> fileList;
|
||||
|
@ -89,6 +89,7 @@ namespace Components
|
||||
FileSystem();
|
||||
~FileSystem();
|
||||
|
||||
static std::filesystem::path GetAppdataPath();
|
||||
static std::vector<std::string> GetFileList(const std::string& path, const std::string& extension);
|
||||
static std::vector<std::string> GetSysFileList(const std::string& path, const std::string& extension, bool folders = false);
|
||||
static bool DeleteFile(const std::string& folder, const std::string& file);
|
||||
|
@ -78,14 +78,14 @@ namespace Components
|
||||
mov ecx, [eax]
|
||||
|
||||
fireWeapon:
|
||||
push edx
|
||||
push ecx
|
||||
push edi
|
||||
mov eax, 0x4A4D50 // FireWeapon
|
||||
call eax
|
||||
add esp, 0Ch
|
||||
pop edi
|
||||
pop ecx
|
||||
push edx
|
||||
push ecx
|
||||
push edi
|
||||
mov eax, 0x4A4D50 // FireWeapon
|
||||
call eax
|
||||
add esp, 0Ch
|
||||
pop edi
|
||||
pop ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
@ -106,13 +106,13 @@ namespace Components
|
||||
mov edx, [eax]
|
||||
|
||||
fireWeaponMelee:
|
||||
push edx
|
||||
push edi
|
||||
mov eax, 0x4F2470 // FireWeaponMelee
|
||||
call eax
|
||||
add esp, 8
|
||||
pop edi
|
||||
pop ecx
|
||||
push edx
|
||||
push edi
|
||||
mov eax, 0x4F2470 // FireWeaponMelee
|
||||
call eax
|
||||
add esp, 8
|
||||
pop edi
|
||||
pop ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
@ -153,11 +153,11 @@ namespace Components
|
||||
je useCustomRatio;
|
||||
|
||||
// execute switch statement code
|
||||
push 0x005063FC;
|
||||
push 0x5063FC;
|
||||
retn;
|
||||
|
||||
goToDefaultCase:
|
||||
push 0x005064FC;
|
||||
push 0x5064FC;
|
||||
retn;
|
||||
|
||||
useCustomRatio:
|
||||
@ -170,7 +170,7 @@ namespace Components
|
||||
mov eax, 1;
|
||||
|
||||
// continue execution
|
||||
push 0x00506495;
|
||||
push 0x506495;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
@ -240,6 +240,20 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
void QuickPatch::Sys_SpawnQuitProcess_Hk()
|
||||
{
|
||||
if (*Game::sys_exitCmdLine[0] == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto workingDir = std::filesystem::current_path().string();
|
||||
auto dir = FileSystem::GetAppdataPath() / "data" / "iw4x" / *Game::sys_exitCmdLine;
|
||||
|
||||
SetEnvironmentVariableA("XLABS_MW2_INSTALL", workingDir.data());
|
||||
Utils::Library::LaunchProcess(dir.string(), "-singleplayer", workingDir);
|
||||
}
|
||||
|
||||
Game::dvar_t* QuickPatch::Dvar_RegisterConMinicon(const char* dvarName, [[maybe_unused]] bool value, unsigned __int16 flags, const char* description)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@ -274,7 +288,10 @@ namespace Components
|
||||
|
||||
Utils::Hook(0x4FA448, QuickPatch::Dvar_RegisterConMinicon, HOOK_CALL).install()->quick();
|
||||
|
||||
Utils::Hook::Set<void(*)(Game::XAssetHeader, void*)>(0x51FCDD, R_AddImageToList_Hk);
|
||||
Utils::Hook::Set<void(*)(Game::XAssetHeader, void*)>(0x51FCDD, QuickPatch::R_AddImageToList_Hk);
|
||||
|
||||
Utils::Hook::Set<const char*>(0x41DB8C, "iw4x-sp.exe");
|
||||
Utils::Hook(0x4D6989, QuickPatch::Sys_SpawnQuitProcess_Hk, HOOK_CALL).install()->quick();
|
||||
|
||||
// protocol version (workaround for hacks)
|
||||
Utils::Hook::Set<int>(0x4FB501, PROTOCOL);
|
||||
|
@ -30,6 +30,8 @@ namespace Components
|
||||
|
||||
static void R_AddImageToList_Hk(Game::XAssetHeader header, void* data);
|
||||
|
||||
static void Sys_SpawnQuitProcess_Hk();
|
||||
|
||||
static Game::dvar_t* Dvar_RegisterConMinicon(const char* dvarName, bool value, unsigned __int16 flags, const char* description);
|
||||
};
|
||||
}
|
||||
|
@ -631,6 +631,8 @@ namespace Game
|
||||
unsigned int* playerCardUIStringIndex = reinterpret_cast<unsigned int*>(0x62CD7A8);
|
||||
char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38] = reinterpret_cast<char(*)[PLAYER_CARD_UI_STRING_COUNT][38]>(0x62CB4F8);
|
||||
|
||||
char (*sys_exitCmdLine)[1024] = reinterpret_cast<char(*)[1024]>(0x649FB68);
|
||||
|
||||
GamerSettingState* gamerSettings = reinterpret_cast<GamerSettingState*>(0x107D3E8);
|
||||
|
||||
void Sys_LockRead(FastCriticalSection* critSect)
|
||||
|
@ -1303,6 +1303,8 @@ namespace Game
|
||||
extern unsigned int* playerCardUIStringIndex;
|
||||
extern char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38];
|
||||
|
||||
extern char (*sys_exitCmdLine)[1024];
|
||||
|
||||
extern GamerSettingState* gamerSettings;
|
||||
|
||||
void Sys_LockRead(FastCriticalSection* critSect);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <Windows.h>
|
||||
#include <WinSock2.h>
|
||||
#include <ShlObj.h>
|
||||
#include <timeapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <WinInet.h>
|
||||
|
@ -19,20 +19,18 @@ namespace Utils
|
||||
return Library(handle);
|
||||
}
|
||||
|
||||
Library::Library(const std::string& name, bool _freeOnDestroy) : module_(nullptr), freeOnDestroy(_freeOnDestroy)
|
||||
Library::Library(const std::string& name, bool freeOnDestroy) : module_(nullptr), freeOnDestroy_(freeOnDestroy)
|
||||
{
|
||||
this->module_ = LoadLibraryExA(name.data(), nullptr, 0);
|
||||
}
|
||||
|
||||
Library::Library(const HMODULE handle)
|
||||
Library::Library(const HMODULE handle) : module_(handle), freeOnDestroy_(true)
|
||||
{
|
||||
this->module_ = handle;
|
||||
this->freeOnDestroy = true;
|
||||
}
|
||||
|
||||
Library::~Library()
|
||||
{
|
||||
if (this->freeOnDestroy)
|
||||
if (this->freeOnDestroy_)
|
||||
{
|
||||
this->free();
|
||||
}
|
||||
@ -63,6 +61,39 @@ namespace Utils
|
||||
return this->module_;
|
||||
}
|
||||
|
||||
std::string Library::getName() const
|
||||
{
|
||||
if (!this->isValid())
|
||||
return {};
|
||||
|
||||
auto path = this->getPath();
|
||||
const auto pos = path.find_last_of("/\\");
|
||||
if (pos == std::string::npos)
|
||||
return path;
|
||||
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
|
||||
std::string Library::getPath() const
|
||||
{
|
||||
if (!this->isValid())
|
||||
return {};
|
||||
|
||||
char name[MAX_PATH] = {0};
|
||||
GetModuleFileNameA(this->module_, name, sizeof(name));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Library::getFolder() const
|
||||
{
|
||||
if (!this->isValid())
|
||||
return {};
|
||||
|
||||
const auto path = std::filesystem::path(this->getPath());
|
||||
return path.parent_path().generic_string();
|
||||
}
|
||||
|
||||
void Library::free()
|
||||
{
|
||||
if (this->isValid())
|
||||
@ -72,4 +103,23 @@ namespace Utils
|
||||
|
||||
this->module_ = nullptr;
|
||||
}
|
||||
|
||||
void Library::LaunchProcess(const std::string& process, const std::string& commandLine, const std::string& currentDir)
|
||||
{
|
||||
STARTUPINFOA startup_info;
|
||||
PROCESS_INFORMATION process_info;
|
||||
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
ZeroMemory(&process_info, sizeof(process_info));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
|
||||
CreateProcessA(process.data(), const_cast<char*>(commandLine.data()), nullptr,
|
||||
nullptr, false, NULL, nullptr, currentDir.data(),
|
||||
&startup_info, &process_info);
|
||||
|
||||
if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(process_info.hThread);
|
||||
if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(process_info.hProcess);
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,9 @@ namespace Utils
|
||||
static Library Load(const std::filesystem::path& path);
|
||||
static Library GetByAddress(void* address);
|
||||
|
||||
Library() : module_(nullptr), freeOnDestroy(false) {};
|
||||
Library() : module_(nullptr), freeOnDestroy_(false) {}
|
||||
Library(const std::string& name, bool freeOnDestroy);
|
||||
explicit Library(const std::string& name) : module_(GetModuleHandleA(name.data())), freeOnDestroy(true) {};
|
||||
explicit Library(const std::string& name) : module_(GetModuleHandleA(name.data())), freeOnDestroy_(true) {}
|
||||
explicit Library(HMODULE handle);
|
||||
~Library();
|
||||
|
||||
@ -23,6 +23,11 @@ namespace Utils
|
||||
|
||||
bool isValid() const;
|
||||
HMODULE getModule() const;
|
||||
std::string getName() const;
|
||||
std::string getPath() const;
|
||||
std::string getFolder() const;
|
||||
std::uint8_t* getPtr() const;
|
||||
void free();
|
||||
|
||||
template <typename T>
|
||||
T getProc(const std::string& process) const
|
||||
@ -62,10 +67,10 @@ namespace Utils
|
||||
return T();
|
||||
}
|
||||
|
||||
void free();
|
||||
static void LaunchProcess(const std::string& process, const std::string& commandLine, const std::string& currentDir);
|
||||
|
||||
private:
|
||||
HMODULE module_;
|
||||
bool freeOnDestroy;
|
||||
bool freeOnDestroy_;
|
||||
};
|
||||
}
|
||||
|
@ -92,14 +92,14 @@ namespace Utils
|
||||
return elems;
|
||||
}
|
||||
|
||||
void Replace(std::string &string, const std::string& find, const std::string& replace)
|
||||
void Replace(std::string& str, const std::string& from, const std::string& to)
|
||||
{
|
||||
size_t nPos = 0;
|
||||
std::size_t nPos = 0;
|
||||
|
||||
while ((nPos = string.find(find, nPos)) != std::string::npos)
|
||||
while ((nPos = str.find(from, nPos)) != std::string::npos)
|
||||
{
|
||||
string = string.replace(nPos, find.length(), replace);
|
||||
nPos += replace.length();
|
||||
str = str.replace(nPos, from.length(), to);
|
||||
nPos += to.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ namespace Utils
|
||||
std::string ToUpper(std::string text);
|
||||
bool Compare(const std::string& lhs, const std::string& rhs);
|
||||
std::vector<std::string> Split(const std::string& str, char delim);
|
||||
void Replace(std::string& string, const std::string& find, const std::string& replace);
|
||||
void Replace(std::string& str, const std::string& from, const std::string& to);
|
||||
bool StartsWith(const std::string& haystack, const std::string& needle);
|
||||
bool EndsWith(const std::string& haystack, const std::string& needle);
|
||||
bool IsNumber(const std::string& str);
|
||||
|
Loading…
Reference in New Issue
Block a user