From 8e1953cc8d1b2721175d9df6f2a5b907974213ea Mon Sep 17 00:00:00 2001 From: Amos <48657826+Mauler125@users.noreply.github.com> Date: Wed, 2 Mar 2022 01:16:35 +0100 Subject: [PATCH] Load STBSP file specified in prereq file The game now loads a override STBSP file for the BSP if field 'stbsp' in level prereq settings is populated. --- r5dev/common/opcodes.cpp | 1 + r5dev/core/init.cpp | 11 ++++- r5dev/engine/cmodel_bsp.cpp | 57 +++++++++--------------- r5dev/engine/cmodel_bsp.h | 11 +---- r5dev/engine/gl_matsysiface.h | 20 +++++++++ r5dev/engine/host_cmd.h | 2 +- r5dev/engine/sys_utils.cpp | 2 +- r5dev/materialsystem/materialsystem.cpp | 59 +++++++++++++++++++++++++ r5dev/materialsystem/materialsystem.h | 16 ++++--- r5dev/rtech/rtech_game.cpp | 10 ++++- r5dev/rtech/rtech_game.h | 1 + r5dev/vproj/dedicated.vcxproj | 1 + r5dev/vproj/dedicated.vcxproj.filters | 3 ++ r5dev/vproj/gamesdk.vcxproj | 2 + r5dev/vproj/gamesdk.vcxproj.filters | 6 +++ 15 files changed, 144 insertions(+), 58 deletions(-) create mode 100644 r5dev/engine/gl_matsysiface.h create mode 100644 r5dev/materialsystem/materialsystem.cpp diff --git a/r5dev/common/opcodes.cpp b/r5dev/common/opcodes.cpp index 0b009545..f6b022ef 100644 --- a/r5dev/common/opcodes.cpp +++ b/r5dev/common/opcodes.cpp @@ -9,6 +9,7 @@ #include "engine/cmodel_bsp.h" #include "engine/host_cmd.h" #include "engine/gl_screen.h" +#include "engine/gl_matsysiface.h" #include "engine/modelloader.h" #include "engine/cl_main.h" #include "engine/sv_main.h" diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 21b6234c..fcf184a5 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -58,8 +58,9 @@ #include "engine/sys_engine.h" #include "engine/sys_utils.h" #include "engine/sys_getmodes.h" -#ifndef DEDICATED +#include "engine/gl_matsysiface.h" #include "engine/gl_screen.h" +#ifndef DEDICATED #include "engine/debugoverlay.h" #endif // !DEDICATED #include "game/server/ai_node.h" @@ -107,6 +108,10 @@ void Systems_Init() CBaseClient_Attach(); CBaseFileSystem_Attach(); +#ifndef DEDICATED + CMaterialSystem_Attach(); +#endif // !DEDICATED + QHull_Attach(); //BspLib_Attach(); @@ -192,6 +197,10 @@ void Systems_Shutdown() CBaseClient_Detach(); CBaseFileSystem_Detach(); +#ifndef DEDICATED + CMaterialSystem_Detach(); +#endif // !DEDICATED + QHull_Detach(); //BspLib_Detach(); diff --git a/r5dev/engine/cmodel_bsp.cpp b/r5dev/engine/cmodel_bsp.cpp index 528c382d..913e2357 100644 --- a/r5dev/engine/cmodel_bsp.cpp +++ b/r5dev/engine/cmodel_bsp.cpp @@ -12,21 +12,15 @@ #include "engine/cmodel_bsp.h" #include "rtech/rtech_game.h" -int g_nLoadedPakFileId[256]{}; - //----------------------------------------------------------------------------- -// Purpose: loads required assets for specified level -// Todo : STBSP and VPK loading -// Todo : Unload all assets loaded by this functions using 'nPakId' +// Purpose: loads required pakfile assets for specified BSP //----------------------------------------------------------------------------- -void MOD_LoadDependencies(eBspRes_t resourceType) +void MOD_PreloadPak(void) { std::ostringstream ostream; - ostream << "platform\\scripts\\levels\\" << g_pHostState->m_levelName << ".json"; + ostream << "platform\\scripts\\levels\\settings\\" << g_pHostState->m_levelName << ".json"; std::filesystem::path fsPath = std::filesystem::current_path() /= ostream.str(); - DevMsg(eDLL_T::ENGINE, "Loading level prerequisites file: '%s'\n", fsPath.string().c_str()); - if (FileExists(fsPath.string().c_str())) { nlohmann::json jsIn; @@ -36,47 +30,36 @@ void MOD_LoadDependencies(eBspRes_t resourceType) iPakLoadDefFile >> jsIn; iPakLoadDefFile.close(); - switch (resourceType) + if (!jsIn.is_null()) { - case eBspRes_t::RES_RPAK: - { - if (!jsIn.is_null()) + if (!jsIn["rpak"].is_null()) { - if (!jsIn["rpak"].is_null()) + int iPakIdx{}; + for (auto it = jsIn["rpak"].begin(); it != jsIn["rpak"].end(); ++it) { - int iPakIdx{}; - for (auto it = jsIn["rpak"].begin(); it != jsIn["rpak"].end(); ++it) + if (it.value().is_string()) { - if (it.value().is_string()) - { - std::string svToLoad = it.value().get() + ".rpak"; - unsigned int nPakId = 0; - nPakId = RTech_AsyncLoad((void*)svToLoad.c_str(), g_pMallocPool.GetPtr(), 4, 0); + std::string svToLoad = it.value().get() + ".rpak"; + unsigned int nPakId = 0; + nPakId = RTech_AsyncLoad((void*)svToLoad.c_str(), g_pMallocPool.GetPtr(), 4, 0); - if (nPakId == -1) - { - DevMsg(eDLL_T::RTECH, "RTech AsyncLoad failed read '%s' results '%u'\n", fsPath.string().c_str(), nPakId); - } - else - { - g_nLoadedPakFileId[iPakIdx] = nPakId; - iPakIdx++; - } + if (nPakId == -1) + { + DevMsg(eDLL_T::RTECH, "RTech_AsyncLoad: failed read '%s' results '%u'\n", fsPath.string().c_str(), nPakId); + } + else + { + g_nLoadedPakFileId[iPakIdx] = nPakId; + iPakIdx++; } } } } - break; - } - default: - { - break; - } } } catch (const std::exception& ex) { - DevMsg(eDLL_T::ENGINE, "Error parsing level prerequisites file: '%s'\n", fsPath.string().c_str(), ex.what()); + DevMsg(eDLL_T::RTECH, "Exception while parsing RPak load list: '%s'\n", ex.what()); return; } } diff --git a/r5dev/engine/cmodel_bsp.h b/r5dev/engine/cmodel_bsp.h index 466f4c10..c4287f29 100644 --- a/r5dev/engine/cmodel_bsp.h +++ b/r5dev/engine/cmodel_bsp.h @@ -7,16 +7,7 @@ namespace // 0x140256480 // 48 89 5C 24 ? 48 89 6C 24 ? 57 48 81 EC ? ? ? ? 48 8B F9 33 ED // } -enum class eBspRes_t -{ - RES_RPAK = 0, - RES_VPK, - RES_STBSP -}; - -extern int g_nLoadedPakFileId[256]; - -void MOD_LoadDependencies(eBspRes_t resourceType); +void MOD_PreloadPak(void); /////////////////////////////////////////////////////////////////////////////// class HModel_BSP : public IDetour { diff --git a/r5dev/engine/gl_matsysiface.h b/r5dev/engine/gl_matsysiface.h new file mode 100644 index 00000000..2c3a1157 --- /dev/null +++ b/r5dev/engine/gl_matsysiface.h @@ -0,0 +1,20 @@ +namespace +{ + /* ==== MATSYSIFACE ===================================================================================================================================================== */ + ADDRESS InitMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00", "xxxxxxx????xxx????xxxxx????xxx????xxx????xxxxx????"); // + // 0x14024B390 // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? // + +} + +/////////////////////////////////////////////////////////////////////////////// +class HGL_MatSysIFace : public IDetour +{ + virtual void debugp() + { + std::cout << "| FUN: InitMaterialSystem : 0x" << std::hex << std::uppercase << InitMaterialSystem.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "+----------------------------------------------------------------+" << std::endl; + } +}; +/////////////////////////////////////////////////////////////////////////////// + +REGISTER(HGL_MatSysIFace); diff --git a/r5dev/engine/host_cmd.h b/r5dev/engine/host_cmd.h index 77e407f9..349d825a 100644 --- a/r5dev/engine/host_cmd.h +++ b/r5dev/engine/host_cmd.h @@ -47,7 +47,7 @@ class HHostCmd : public IDetour virtual void debugp() { std::cout << "| FUN: Host_Init : 0x" << std::hex << std::uppercase << p_Host_Init.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: Host_NewGame : 0x" << std::hex << std::uppercase << p_Host_NewGame.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: Host_NewGame : 0x" << std::hex << std::uppercase << p_Host_NewGame.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: malloc_internal : 0x" << std::hex << std::uppercase << p_malloc_internal.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_pEngineParms : 0x" << std::hex << std::uppercase << g_pEngineParmsBuffer.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_pMallocPool : 0x" << std::hex << std::uppercase << g_pMallocPool.GetPtr() << std::setw(npad) << " |" << std::endl; diff --git a/r5dev/engine/sys_utils.cpp b/r5dev/engine/sys_utils.cpp index 0d973dc0..85a1ac2d 100644 --- a/r5dev/engine/sys_utils.cpp +++ b/r5dev/engine/sys_utils.cpp @@ -193,7 +193,7 @@ void* HSys_LoadAssetHelper(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGE bBasePaksLoaded || !strcmp(std::string(lpFileName).erase(0, 11).c_str(), "mp_lobby.rpak")) { // Attempt to load level dependencies if they exist. - MOD_LoadDependencies(eBspRes_t::RES_RPAK); + MOD_PreloadPak(); // By the time mp_lobby.rpak is loaded, all the base paks are loaded as well and we can load anything else. bBasePaksLoaded = true; diff --git a/r5dev/materialsystem/materialsystem.cpp b/r5dev/materialsystem/materialsystem.cpp new file mode 100644 index 00000000..749746c1 --- /dev/null +++ b/r5dev/materialsystem/materialsystem.cpp @@ -0,0 +1,59 @@ +//===========================================================================// +// +// Purpose: +// +//===========================================================================// +#include "core/stdafx.h" +#include "tier0/cvar.h" +#include "engine/sys_utils.h" +#include "materialsystem/materialsystem.h" + +//--------------------------------------------------------------------------------- +// Purpose: loads and processes STBSP files +// (overrides level name if stbsp field has value in prerequisites file) +// Input : *pszStreamDBFile - +//--------------------------------------------------------------------------------- +void HStreamDB_Init(const char* pszStreamDBFile) +{ + std::ostringstream ostream; + ostream << "platform\\scripts\\levels\\settings\\" << pszStreamDBFile << ".json"; + std::filesystem::path fsPath = std::filesystem::current_path() /= ostream.str(); + + if (FileExists(fsPath.string().c_str())) + { + nlohmann::json jsIn; + try + { + std::ifstream iPakLoadDefFile(fsPath, std::ios::binary); // Parse prerequisites file. + iPakLoadDefFile >> jsIn; + iPakLoadDefFile.close(); + + if (!jsIn.is_null()) + { + if (!jsIn["stbsp"].is_null()) + { + std::string svStreamDBFile = jsIn["stbsp"].get(); + DevMsg(eDLL_T::MS, "StreamDB_Init: Loading override STBSP file '%s.stbsp'\n", svStreamDBFile.c_str(), pszStreamDBFile); + StreamDB_Init(svStreamDBFile.c_str()); + return; + } + } + } + catch (const std::exception& ex) + { + DevMsg(eDLL_T::MS, "StreamDB_Init: Exception while parsing STBSP override: '%s'\n", ex.what()); + } + } + StreamDB_Init(pszStreamDBFile); +} + +/////////////////////////////////////////////////////////////////////////////// +void CMaterialSystem_Attach() +{ + DetourAttach((LPVOID*)&StreamDB_Init, &HStreamDB_Init); +} + +void CMaterialSystem_Detach() +{ + DetourDetach((LPVOID*)&StreamDB_Init, &HStreamDB_Init); +} \ No newline at end of file diff --git a/r5dev/materialsystem/materialsystem.h b/r5dev/materialsystem/materialsystem.h index 27f78de1..7a161f63 100644 --- a/r5dev/materialsystem/materialsystem.h +++ b/r5dev/materialsystem/materialsystem.h @@ -1,5 +1,4 @@ #pragma once -#include "engine/debugoverlay.h" namespace { @@ -7,12 +6,14 @@ namespace ADDRESS CMaterialSystem__Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x70\x48\x83\x3D\x00\x00\x00\x00\x00", "xxxx?xxxxxxxxxxxxxxxxxx?????"); // 0x1403BBFD0 // 48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 70 48 83 3D ? ? ? ? ? // - ADDRESS InitMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00", "xxxxxxx????xxx????xxxxx????xxx????xxx????xxxxx????"); // - // 0x14024B390 // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? // - ADDRESS p_DrawStreamOverlay = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x41\x56\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x2B\xE0\xC6\x02\x00", "xxx????x????xxxxxx"); // 41 56 B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 C6 02 00 // const char* (*DrawStreamOverlay)(void* thisptr, std::uint8_t* a2, void* unused, void* a4) = (const char* (*)(void*, std::uint8_t*, void*, void*))p_DrawStreamOverlay.GetPtr(); +#ifndef DEDICATED + ADDRESS p_StreamDB_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x41\x54\x41\x56\x41\x57\x48\x83\xEC\x40\x48\x8B\xE9", "xxxx?xxxx?xxxx?xxxx?xxxxxxxxxxxxx"); + void (*StreamDB_Init)(const char* pszStreamDbFile) = (void (*)(const char* pszStreamDbFile))p_StreamDB_Init.GetPtr(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 54 41 56 41 57 48 83 EC 40 48 8B E9*/ +#endif // !DEDICATED + void* g_pMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x74\x11\x48\x8B\x01\x48\x8D\x15\x00\x00\x00\x00", "xxx????xxxxxxxxxxx????").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); int* total_streaming_tex_memory = p_DrawStreamOverlay.Offset(0x0).FindPatternSelf("48 8B 05", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); @@ -21,19 +22,22 @@ namespace } +void CMaterialSystem_Attach(); +void CMaterialSystem_Detach(); /////////////////////////////////////////////////////////////////////////////// class HMaterialSystem : public IDetour { virtual void debugp() { std::cout << "| FUN: CMaterialSystem::Init : 0x" << std::hex << std::uppercase << CMaterialSystem__Init.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: InitMaterialSystem : 0x" << std::hex << std::uppercase << InitMaterialSystem.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: DrawStreamOverlay : 0x" << std::hex << std::uppercase << p_DrawStreamOverlay.GetPtr() << std::setw(npad) << " |" << std::endl; +#ifndef DEDICATED + std::cout << "| FUN: StreamDB_Init : 0x" << std::hex << std::uppercase << p_StreamDB_Init.GetPtr() << std::setw(npad) << " |" << std::endl; +#endif // !DEDICATED std::cout << "| VAR: g_pMaterialSystem : 0x" << std::hex << std::uppercase << g_pMaterialSystem << std::setw(0) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// -void DebugOverlays_Attach(); REGISTER(HMaterialSystem); diff --git a/r5dev/rtech/rtech_game.cpp b/r5dev/rtech/rtech_game.cpp index 37e101d6..296e28fe 100644 --- a/r5dev/rtech/rtech_game.cpp +++ b/r5dev/rtech/rtech_game.cpp @@ -1,7 +1,13 @@ +//=============================================================================// +// +// Purpose: RTech game utilities +// +//=============================================================================// #include "core/stdafx.h" #include "engine/host_cmd.h" #include "engine/sys_utils.h" #include "rtech/rtech_game.h" +int g_nLoadedPakFileId[256]{}; //----------------------------------------------------------------------------- // Purpose: unloads asset files from the memory pool @@ -39,12 +45,12 @@ void HRtech_AsyncLoad(std::string svPakFileName) if (nPakId == 0xFFFFFFFF) { - DevMsg(eDLL_T::RTECH, "RTech AsyncLoad failed read '%s' results '%u'\n", svPakFileName.c_str(), nPakId); + DevMsg(eDLL_T::RTECH, "RTech_AsyncLoad: Failed read '%s' results '%u'\n", svPakFileName.c_str(), nPakId); } } else { - DevMsg(eDLL_T::RTECH, "RTech AsyncLoad failed. File '%s' doesn't exist\n", svPakFileName.c_str()); + DevMsg(eDLL_T::RTECH, "RTech_AsyncLoad: Failed. File '%s' doesn't exist\n", svPakFileName.c_str()); } } diff --git a/r5dev/rtech/rtech_game.h b/r5dev/rtech/rtech_game.h index 172cc475..7eafa4dc 100644 --- a/r5dev/rtech/rtech_game.h +++ b/r5dev/rtech/rtech_game.h @@ -56,6 +56,7 @@ void HRtech_AsyncLoad(std::string svPakFileName); void RTech_Game_Attach(); void RTech_Game_Detach(); +extern int g_nLoadedPakFileId[256]; /////////////////////////////////////////////////////////////////////////////// class HRTechGame : public IDetour { diff --git a/r5dev/vproj/dedicated.vcxproj b/r5dev/vproj/dedicated.vcxproj index cb37e1d0..8478ff2e 100644 --- a/r5dev/vproj/dedicated.vcxproj +++ b/r5dev/vproj/dedicated.vcxproj @@ -203,6 +203,7 @@ + diff --git a/r5dev/vproj/dedicated.vcxproj.filters b/r5dev/vproj/dedicated.vcxproj.filters index ea45b490..c24a460c 100644 --- a/r5dev/vproj/dedicated.vcxproj.filters +++ b/r5dev/vproj/dedicated.vcxproj.filters @@ -783,6 +783,9 @@ sdk\public\include + + sdk\engine + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index cccc1163..18f83abf 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -56,6 +56,7 @@ + @@ -131,6 +132,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index 147c5ff7..0ea3e491 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -390,6 +390,9 @@ sdk\engine + + sdk\materialsystem + @@ -1124,6 +1127,9 @@ sdk\public\include + + sdk\engine +