diff --git a/r5dev/appframework/engine_launcher_api.h b/r5dev/appframework/engine_launcher_api.h index c25ed097..1294a84c 100644 --- a/r5dev/appframework/engine_launcher_api.h +++ b/r5dev/appframework/engine_launcher_api.h @@ -12,9 +12,9 @@ struct StartupInfo_t { void* m_pInstance; - const char m_pBaseDirectory[260]; - const char m_pInitialMod[260]; - const char m_pInitialGame[260]; + const char m_szBaseDirectory[260]; + const char m_szInitialMod[260]; + const char m_szInitialGame[260]; uint8_t m_pParentAppSystemGroup[236]; bool m_bTextMode; }; diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index ffd38d4e..941b607a 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -69,6 +69,7 @@ #include "engine/client/cl_main.h" #include "engine/client/client.h" #include "engine/client/clientstate.h" +#include "engine/traceinit.h" #include "engine/common.h" #include "engine/cmodel_bsp.h" #include "engine/host.h" diff --git a/r5dev/engine/common.h b/r5dev/engine/common.h index b8778d55..c60ffce3 100644 --- a/r5dev/engine/common.h +++ b/r5dev/engine/common.h @@ -1,6 +1,9 @@ #pragma once /* ==== COMMON ========================================================================================================================================================== */ +inline CMemory p_COM_InitFilesystem; +inline auto COM_InitFilesystem = p_COM_InitFilesystem.RCast(); + inline CMemory p_COM_ExplainDisconnection; inline auto COM_ExplainDisconnection = p_COM_ExplainDisconnection.RCast(); @@ -9,12 +12,16 @@ class VCommon : public IDetour { virtual void GetAdr(void) const { + spdlog::debug("| FUN: COM_InitFilesystem : {:#18x} |\n", p_COM_InitFilesystem.GetPtr()); spdlog::debug("| FUN: COM_ExplainDisconnection : {:#18x} |\n", p_COM_ExplainDisconnection.GetPtr()); spdlog::debug("+----------------------------------------------------------------+\n"); } virtual void GetFun(void) const { + p_COM_InitFilesystem = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xF9\x48\xC7\x44\x24\x00\x00\x00\x00\x00"), "xxxx?xxxx?xxxx????xxxxxxx?????"); p_COM_ExplainDisconnection = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\xC4\x48\x89\x50\x10\x4C\x89\x40\x18\x4C\x89\x48\x20\x48\x81\xEC\x00\x00\x00\x00"), "xxxxxxxxxxxxxxxxxx????"); + + COM_InitFilesystem = p_COM_InitFilesystem.RCast(); /*48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 48 C7 44 24 ?? ?? ?? ?? ??*/ COM_ExplainDisconnection = p_COM_ExplainDisconnection.RCast(); /*48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 48 81 EC ?? ?? ?? ??*/ } virtual void GetVar(void) const { } diff --git a/r5dev/engine/sys_dll2.cpp b/r5dev/engine/sys_dll2.cpp index 9a2a5973..38423523 100644 --- a/r5dev/engine/sys_dll2.cpp +++ b/r5dev/engine/sys_dll2.cpp @@ -6,14 +6,18 @@ //===========================================================================// #include "core/stdafx.h" +#include "tier0/commandline.h" #include "tier1/cmd.h" #include "tier1/cvar.h" #include "tier1/strtools.h" #include "engine/sys_dll.h" #include "engine/sys_dll2.h" +#include "engine/host_cmd.h" +#include "engine/traceinit.h" #ifndef DEDICATED #include "client/vengineclient_impl.h" #endif // !DEDICATED +#include "filesystem/filesystem.h" //----------------------------------------------------------------------------- // Figure out if we're running a Valve mod or not. @@ -41,7 +45,7 @@ static bool IsRespawnMod(const char* pModName) //----------------------------------------------------------------------------- // Initialization, shutdown of a mod. //----------------------------------------------------------------------------- -bool CEngineAPI::ModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir) +bool CEngineAPI::VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir) { g_pConCommand->InitShipped(); g_pConCommand->PurgeShipped(); @@ -59,13 +63,77 @@ bool CEngineAPI::ModInit(CEngineAPI* pEngineAPI, const char* pModName, const cha return results; } +//----------------------------------------------------------------------------- +// Sets startup info +//----------------------------------------------------------------------------- +void CEngineAPI::VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo) +{ + char szCacheEnableFilePath[280]; // [rsp+20h] [rbp-118h] BYREF + + if (*g_bTextMode) + { + return; + } + + strncpy(&*g_szBaseDir, pStartupInfo->m_szBaseDirectory, 260); + g_pEngineParms->baseDirectory = &*g_szBaseDir; + + void** v4 = &pEngineAPI->m_StartupInfo.m_pInstance; + size_t nInstances = 6; + g_szBaseDir[259] = '\0'; + do + { + v4 += 16; + uint64_t v6 = *(_QWORD*)&pStartupInfo->m_pInstance; + pStartupInfo = (StartupInfo_t*)((char*)pStartupInfo + 128); + *((_QWORD*)v4 - 8) = v6; + *((_QWORD*)v4 - 7) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[132]; + *((_QWORD*)v4 - 6) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[148]; + *((_QWORD*)v4 - 5) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[164]; + *((_QWORD*)v4 - 4) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[180]; + *((_QWORD*)v4 - 3) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[196]; + *((_QWORD*)v4 - 2) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[212]; + *((_QWORD*)v4 - 1) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[228]; + --nInstances; + } while (nInstances); + *(_QWORD*)v4 = *(_QWORD*)&pStartupInfo->m_pInstance; + *((_QWORD*)v4 + 1) = *(_QWORD*)&pStartupInfo->m_szBaseDirectory[8]; + + + char bFixSlashes = FileSystem()->GetCurrentDirectory(szCacheEnableFilePath, 260) ? szCacheEnableFilePath[0] : '\0'; + size_t nCachePathLen = strlen(szCacheEnableFilePath); + size_t nCacheFileLen = 15; // sizeof '/vpk/enable.txt' - 1; + + if ((nCachePathLen + nCacheFileLen) < 0x104 || (nCacheFileLen = 259 - nCachePathLen, nCachePathLen != 259)) + { + strncat(szCacheEnableFilePath, "/vpk/enable.txt", nCacheFileLen)[259] = '\0'; + bFixSlashes = szCacheEnableFilePath[0]; + } + if (bFixSlashes) + { + V_FixSlashes(szCacheEnableFilePath, '/'); + } + if (FileSystem()->FileExists(szCacheEnableFilePath, nullptr)) + { + FileSystem()->SetVPKCacheModeClient(); + FileSystem()->AddSearchPath(".", "MAIN", SearchPathAdd_t::PATH_ADD_TO_TAIL); + FileSystem()->MountVPKFile("vpk/client_frontend.bsp"); + } + v_TRACEINIT(NULL, "COM_InitFilesystem( m_StartupInfo.m_szInitialMod )", "COM_ShutdownFileSystem()"); + COM_InitFilesystem(pEngineAPI->m_StartupInfo.m_szInitialMod); + + *g_bTextMode = true; +} + /////////////////////////////////////////////////////////////////////////////// void SysDll2_Attach() { - DetourAttach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::ModInit); + DetourAttach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::VModInit); + DetourAttach((LPVOID*)&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo); } void SysDll2_Detach() { - DetourDetach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::ModInit); + DetourDetach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::VModInit); + DetourDetach((LPVOID*)&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo); } \ No newline at end of file diff --git a/r5dev/engine/sys_dll2.h b/r5dev/engine/sys_dll2.h index 6d48782d..6a291072 100644 --- a/r5dev/engine/sys_dll2.h +++ b/r5dev/engine/sys_dll2.h @@ -31,8 +31,9 @@ public: virtual void SetMap(const char* pMapName) = 0; - static bool ModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir); -private: + static bool VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir); + static void VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo); +//private: void* m_hEditorHWnd; bool m_bRunningSimulation; StartupInfo_t m_StartupInfo; @@ -47,14 +48,19 @@ inline auto CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast(); -inline CMemory p_PakFile_Init; -inline auto PakFile_Init = p_PakFile_Init.RCast(); +inline CMemory p_CEngineAPI_SetStartupInfo; +inline auto v_CEngineAPI_SetStartupInfo = p_CEngineAPI_SetStartupInfo.RCast(); inline CMemory p_ResetMTVFTaskItem; inline auto v_ResetMTVFTaskItem = p_ResetMTVFTaskItem.RCast(); -inline int64_t* g_pMTVFTaskItem; // struct. -inline char* g_szMTVFItemName; +inline CMemory p_PakFile_Init; +inline auto PakFile_Init = p_PakFile_Init.RCast(); + +inline bool* g_bTextMode = nullptr; +inline char* g_szBaseDir = nullptr; // static size = 260 +inline int64_t* g_pMTVFTaskItem = nullptr; // struct. +inline char* g_szMTVFItemName = nullptr; void SysDll2_Attach(); @@ -67,8 +73,13 @@ class VSys_Dll2 : public IDetour spdlog::debug("| FUN: CEngineAPI::Connect : {:#18x} |\n", p_CEngineAPI_Connect.GetPtr()); spdlog::debug("| FUN: CEngineAPI::ModInit : {:#18x} |\n", p_CEngineAPI_ModInit.GetPtr()); spdlog::debug("| FUN: CEngineAPI::MainLoop : {:#18x} |\n", p_CEngineAPI_MainLoop.GetPtr()); - spdlog::debug("| FUN: PakFile_Init : {:#18x} |\n", p_PakFile_Init.GetPtr()); +#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + spdlog::debug("| FUN: CEngineAPI::SetStartupInfo : {:#18x} |\n", p_CEngineAPI_SetStartupInfo.GetPtr()); +#endif spdlog::debug("| FUN: ResetMTVFTaskItem : {:#18x} |\n", p_ResetMTVFTaskItem.GetPtr()); + spdlog::debug("| FUN: PakFile_Init : {:#18x} |\n", p_PakFile_Init.GetPtr()); + spdlog::debug("| VAR: g_bTextMode : {:#18x} |\n", reinterpret_cast(g_bTextMode)); + spdlog::debug("| VAR: g_szBaseDir : {:#18x} |\n", reinterpret_cast(g_szBaseDir)); spdlog::debug("| VAR: g_pMTVFTaskItem : {:#18x} |\n", reinterpret_cast(g_pMTVFTaskItem)); spdlog::debug("| VAR: g_szMTVFItemName : {:#18x} |\n", reinterpret_cast(g_szMTVFItemName)); spdlog::debug("+----------------------------------------------------------------+\n"); @@ -85,16 +96,21 @@ class VSys_Dll2 : public IDetour p_CEngineAPI_MainLoop = g_GameDll.FindPatternSIMD(reinterpret_cast("\xE8\x00\x00\x00\x00\x48\x8B\x15\x00\x00\x00\x00\x84\xC0\xB9\x00\x00\x00\x00"), "x????xxx????xxx????").FollowNearCallSelf(); p_PakFile_Init = g_GameDll.FindPatternSIMD(reinterpret_cast("\x44\x88\x44\x24\x00\x53\x55\x56\x57"), "xxxx?xxxx"); #endif + p_CEngineAPI_SetStartupInfo = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x48\x8B\xDA"), "xxxx??xxx????xx?????xxx"); p_ResetMTVFTaskItem = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x28\x48\x8B\x15\x00\x00\x00\x00\x48\x85\xD2\x0F\x84\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x33\xC9\xE8\x00\x00\x00\x00\x0F\x28\x05\x00\x00\x00\x00\x0F\x28\x0D\x00\x00\x00\x00\x0F\x11\x05\x00\x00\x00\x00\x0F\x28\x05\x00\x00\x00\x00\x0F\x11\x0D\x00\x00\x00\x00\x0F\x28\x0D\x00\x00\x00\x00\x0F\x11\x05\x00\x00\x00\x00\x0F\x11\x0D\x00\x00\x00\x00\x48\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00"), "xxxxxxx????xxxxx????xxx????xxxxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????????xx????"); - CEngineAPI_Connect = p_CEngineAPI_Connect.RCast(); /*48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15 ?? ?? ?? ??*/ - CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast(); /*48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8*/ - CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast(); /*E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??*/ - PakFile_Init = p_PakFile_Init.RCast(); /*44 88 44 24 ?? 53 55 56 57*/ + CEngineAPI_Connect = p_CEngineAPI_Connect.RCast(); /*48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15 ?? ?? ?? ??*/ + CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast(); /*48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8*/ + CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast(); /*E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??*/ + v_CEngineAPI_SetStartupInfo = p_CEngineAPI_SetStartupInfo.RCast(); /*48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 48 8B DA*/ + PakFile_Init = p_PakFile_Init.RCast(); /*44 88 44 24 ?? 53 55 56 57*/ } virtual void GetVar(void) const { + g_bTextMode = p_CEngineAPI_SetStartupInfo.FindPattern("80 3D", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); + g_szBaseDir = p_CEngineAPI_SetStartupInfo.FindPattern("48 8D", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_pMTVFTaskItem = p_ResetMTVFTaskItem.FindPattern("48 8B", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); g_szMTVFItemName = p_ResetMTVFTaskItem.FindPattern("C6 05", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); } diff --git a/r5dev/engine/traceinit.h b/r5dev/engine/traceinit.h new file mode 100644 index 00000000..82060eae --- /dev/null +++ b/r5dev/engine/traceinit.h @@ -0,0 +1,29 @@ +#ifndef TRACEINIT_H +#define TRACEINIT_H + +inline CMemory p_TRACEINIT; +inline auto v_TRACEINIT = p_TRACEINIT.RCast(); + +/////////////////////////////////////////////////////////////////////////////// +class VTraceInit : public IDetour +{ + virtual void GetAdr(void) const + { + spdlog::debug("| FUN: TRACEINIT : {:#18x} |\n", p_TRACEINIT.GetPtr()); + spdlog::debug("+----------------------------------------------------------------+\n"); + } + virtual void GetFun(void) const + { + p_TRACEINIT = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x00\x49\x8B\xF8\x48\x8B\xF2\x48\x85\xC0"), "xxxx?xxxx?xxxxxxxx????xxxxxxxxx"); + v_TRACEINIT = p_TRACEINIT.RCast(); /*48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B 05 ? ? ? ? 49 8B F8 48 8B F2 48 85 C0*/ + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Attach(void) const { } + virtual void Detach(void) const { } +}; +/////////////////////////////////////////////////////////////////////////////// + +REGISTER(VTraceInit); + +#endif // TRACEINIT_H diff --git a/r5dev/tier1/strtools.cpp b/r5dev/tier1/strtools.cpp index 1d958cd6..034866e9 100644 --- a/r5dev/tier1/strtools.cpp +++ b/r5dev/tier1/strtools.cpp @@ -1,4 +1,5 @@ #include "core/stdafx.h" +#include "tier1/strtools.h" FORCEINLINE unsigned char tolower_fast(unsigned char c) { @@ -85,9 +86,7 @@ int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes) { if (cubDestSizeInBytes > 0) - { pUTF8[0] = 0; - } #ifdef _WIN32 int cchResult = WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL); @@ -98,9 +97,24 @@ int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes #endif if (cubDestSizeInBytes > 0) - { pUTF8[cubDestSizeInBytes - 1] = 0; - } return cchResult; +} + +//----------------------------------------------------------------------------- +// Purpose: Changes all '/' or '\' characters into separator +// Input : *pName - +// cSeparator - +//----------------------------------------------------------------------------- +void V_FixSlashes(char* pName, char cSeperator /* = CORRECT_PATH_SEPARATOR */) +{ + while (*pName) + { + if (*pName == INCORRECT_PATH_SEPARATOR || *pName == CORRECT_PATH_SEPARATOR) + { + *pName = cSeperator; + } + pName++; + } } \ No newline at end of file diff --git a/r5dev/tier1/strtools.h b/r5dev/tier1/strtools.h index 9e040c31..cb8c35c2 100644 --- a/r5dev/tier1/strtools.h +++ b/r5dev/tier1/strtools.h @@ -1,5 +1,13 @@ #pragma once +#ifdef _WIN32 +#define CORRECT_PATH_SEPARATOR '\\' +#define INCORRECT_PATH_SEPARATOR '/' +#elif POSIX +#define CORRECT_PATH_SEPARATOR '/' +#define INCORRECT_PATH_SEPARATOR '\\' +#endif + #define V_snprintf snprintf #define V_strlower _strlwr #define V_strlen strlen @@ -21,4 +29,5 @@ char const* V_stristr(char const* pStr, char const* pSearch); int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes); -int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes); \ No newline at end of file +int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes); +void V_FixSlashes(char* pname, char separator = CORRECT_PATH_SEPARATOR); \ No newline at end of file diff --git a/r5dev/vproj/clientsdk.vcxproj b/r5dev/vproj/clientsdk.vcxproj index ccc2e671..db099985 100644 --- a/r5dev/vproj/clientsdk.vcxproj +++ b/r5dev/vproj/clientsdk.vcxproj @@ -202,6 +202,7 @@ + diff --git a/r5dev/vproj/clientsdk.vcxproj.filters b/r5dev/vproj/clientsdk.vcxproj.filters index 05854ded..6218fe35 100644 --- a/r5dev/vproj/clientsdk.vcxproj.filters +++ b/r5dev/vproj/clientsdk.vcxproj.filters @@ -1796,6 +1796,9 @@ sdk\engine + + sdk\engine + diff --git a/r5dev/vproj/dedicated.vcxproj b/r5dev/vproj/dedicated.vcxproj index 3d7b57d6..b985c68f 100644 --- a/r5dev/vproj/dedicated.vcxproj +++ b/r5dev/vproj/dedicated.vcxproj @@ -170,6 +170,7 @@ + diff --git a/r5dev/vproj/dedicated.vcxproj.filters b/r5dev/vproj/dedicated.vcxproj.filters index f01d1a4a..3d89d5db 100644 --- a/r5dev/vproj/dedicated.vcxproj.filters +++ b/r5dev/vproj/dedicated.vcxproj.filters @@ -1251,6 +1251,9 @@ sdk\public + + sdk\engine + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index ea1a10b2..dd0c3453 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -216,6 +216,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index dd48a04d..cded83a4 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -1892,6 +1892,9 @@ sdk\public + + sdk\engine +