2022-03-02 01:16:35 +01:00
|
|
|
//===========================================================================//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
//===========================================================================//
|
|
|
|
#include "core/stdafx.h"
|
2023-01-31 22:13:40 +01:00
|
|
|
#include "tier0/crashhandler.h"
|
2022-04-09 16:16:40 +02:00
|
|
|
#include "tier1/cvar.h"
|
2022-11-24 11:10:46 +01:00
|
|
|
#include "vpc/keyvalues.h"
|
2022-08-18 02:15:23 +02:00
|
|
|
#include "rtech/rtech_utils.h"
|
2022-11-24 11:10:46 +01:00
|
|
|
#include "engine/cmodel_bsp.h"
|
2022-12-27 23:10:51 +01:00
|
|
|
#include "bsplib/bsplib.h"
|
2022-10-05 01:59:22 +02:00
|
|
|
#include "materialsystem/cmaterialglue.h"
|
2022-03-26 01:04:20 +01:00
|
|
|
#include "materialsystem/cmaterialsystem.h"
|
2022-03-02 01:16:35 +01:00
|
|
|
|
2022-10-05 02:11:13 +02:00
|
|
|
#ifndef DEDICATED
|
2022-03-02 01:16:35 +01:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: loads and processes STBSP files
|
|
|
|
// (overrides level name if stbsp field has value in prerequisites file)
|
2022-06-23 20:08:07 +02:00
|
|
|
// Input : *pszLevelName -
|
2022-03-02 01:16:35 +01:00
|
|
|
//---------------------------------------------------------------------------------
|
2022-06-23 20:08:07 +02:00
|
|
|
void StreamDB_Init(const char* pszLevelName)
|
2022-03-02 01:16:35 +01:00
|
|
|
{
|
2022-11-24 11:58:32 +01:00
|
|
|
KeyValues* pSettingsKV = Mod_GetLevelSettings(pszLevelName);
|
2022-03-02 01:16:35 +01:00
|
|
|
|
2022-11-24 11:10:46 +01:00
|
|
|
if (pSettingsKV)
|
2022-03-02 01:16:35 +01:00
|
|
|
{
|
2022-11-24 11:10:46 +01:00
|
|
|
KeyValues* pStreamKV = pSettingsKV->FindKey("StreamDB");
|
2022-08-31 03:01:45 +02:00
|
|
|
|
2022-11-24 11:10:46 +01:00
|
|
|
if (pStreamKV)
|
2022-03-02 01:16:35 +01:00
|
|
|
{
|
2022-11-24 11:10:46 +01:00
|
|
|
const char* pszColumnName = pStreamKV->GetString();
|
2023-04-01 13:10:22 +02:00
|
|
|
DevMsg(eDLL_T::MS, "StreamDB_Init: Loading override STBSP file '%s.stbsp'\n", pszColumnName);
|
2022-08-31 03:01:45 +02:00
|
|
|
|
2022-11-24 11:10:46 +01:00
|
|
|
v_StreamDB_Init(pszColumnName);
|
|
|
|
return;
|
2022-03-02 01:16:35 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-31 03:01:45 +02:00
|
|
|
|
2023-04-01 13:10:22 +02:00
|
|
|
DevMsg(eDLL_T::MS, "StreamDB_Init: Loading STBSP file '%s.stbsp'\n", pszLevelName);
|
2022-06-23 20:08:07 +02:00
|
|
|
v_StreamDB_Init(pszLevelName);
|
2022-03-02 01:16:35 +01:00
|
|
|
}
|
|
|
|
|
2022-04-30 20:35:08 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: draw frame
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
2022-05-18 01:22:59 +02:00
|
|
|
void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, char a5, int a6, uint8_t a7, int64_t a8, uint32_t a9, uint32_t a10, __m128* a11, int a12)
|
2022-04-30 20:35:08 +02:00
|
|
|
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
|
|
|
void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64_t a5, int a6, uint8_t a7, int64_t a8, uint32_t a9, uint32_t a10, int a11, __m128* a12, int a13, int64_t a14)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// This only happens when the BSP is in a horrible condition (bad depth buffer draw calls!)
|
|
|
|
// but allows you to load BSP's with virtually all missing shaders/materials and models
|
|
|
|
// being replaced with 'material_for_aspect/error.rpak' and 'mdl/error.rmdl'.
|
|
|
|
if (!s_pRenderContext.GetValue<void*>())
|
|
|
|
return nullptr;
|
|
|
|
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
|
|
|
return v_DispatchDrawCall(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
|
|
|
|
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
|
|
|
return v_DispatchDrawCall(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
|
|
|
|
#endif
|
|
|
|
}
|
2022-10-05 02:11:13 +02:00
|
|
|
#endif // !DEDICATED
|
2022-04-30 20:35:08 +02:00
|
|
|
|
2022-10-03 01:15:02 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: checks if ptr is valid, and checks for equality against CMaterial vftable
|
|
|
|
// Input : **pCandidate -
|
|
|
|
// Output : true if valid and material, false otherwise
|
|
|
|
//-----------------------------------------------------------------------------
|
2023-02-17 23:56:56 +01:00
|
|
|
FORCENOINLINE bool CMaterialSystem::IsMaterialInternal(void** pCandidate)
|
2022-10-03 01:15:02 +02:00
|
|
|
{
|
|
|
|
// NOTE: this is a dirty fix, but for running technically broken BSP's, this is the only fix
|
|
|
|
// besides going bare metal inline assembly (which on its own isn't directly the problem, but
|
|
|
|
// portability wise it will be a problem as the majority of the code in r5apex.exe is declared inline).
|
|
|
|
// In the future, do not fix anything like this unless there is absolutely no other choice!
|
|
|
|
// The context of the problem is that we fix the missing models defined in the game_lump of a
|
|
|
|
// BSP by swapping missing models out for existing models, which will in many cases, end up with
|
|
|
|
// 2 or more model name duplicates within a single BSP's game_lump, which is illegal and causes
|
|
|
|
// unpredictable behavior, which in this case causes a register to be assigned to an invalid CMaterial
|
|
|
|
// address. The pointer can still be dereferenced in many cases, which is why we do an equality test.
|
|
|
|
// The first member of the CMaterial data structure should be its VFTable pointer, anything else is invalid.
|
|
|
|
__try
|
|
|
|
{
|
2022-10-05 01:59:22 +02:00
|
|
|
if (*pCandidate == g_pMaterialVFTable ||
|
|
|
|
*pCandidate == g_pMaterialGlueVFTable)
|
2022-10-03 01:15:02 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2022-10-05 01:59:22 +02:00
|
|
|
return false;
|
2022-10-03 01:15:02 +02:00
|
|
|
}
|
|
|
|
|
2022-10-13 02:41:09 +02:00
|
|
|
#ifndef DEDICATED
|
2022-10-13 02:22:50 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: finds a material
|
|
|
|
// Input : *pMatSys -
|
|
|
|
// *pMaterialName -
|
|
|
|
// nMaterialType -
|
|
|
|
// nUnk -
|
|
|
|
// bComplain -
|
|
|
|
// Output : pointer to material
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CMaterialGlue* CMaterialSystem::FindMaterialEx(CMaterialSystem* pMatSys, const char* pMaterialName, uint8_t nMaterialType, int nUnk, bool bComplain)
|
|
|
|
{
|
|
|
|
CMaterialGlue* pMaterial = CMaterialSystem__FindMaterialEx(pMatSys, pMaterialName, nMaterialType, nUnk, bComplain);
|
2022-10-21 21:49:10 +02:00
|
|
|
|
|
|
|
if ((bComplain || mat_alwaysComplain->GetBool()) && pMaterial->IsErrorMaterial())
|
2022-10-13 02:22:50 +02:00
|
|
|
{
|
|
|
|
Error(eDLL_T::MS, NO_ERROR, "Material \"%s\" not found; replacing with \"%s\".\n", pMaterialName, pMaterial->GetName());
|
|
|
|
}
|
|
|
|
return pMaterial;
|
|
|
|
}
|
2022-10-23 01:20:49 +02:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: get screen size
|
|
|
|
// Input : *pMatSys -
|
|
|
|
// Output : Vector2D screen size
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
Vector2D CMaterialSystem::GetScreenSize(CMaterialSystem* pMatSys)
|
|
|
|
{
|
|
|
|
Vector2D vecScreenSize;
|
|
|
|
|
|
|
|
CMaterialSystem_GetScreenSize(pMatSys, &vecScreenSize.x, &vecScreenSize.y);
|
|
|
|
|
|
|
|
return vecScreenSize;
|
|
|
|
}
|
2022-10-13 02:41:09 +02:00
|
|
|
#endif // !DEDICATED
|
2022-10-13 02:22:50 +02:00
|
|
|
|
2022-03-02 01:16:35 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-01-25 02:26:52 +01:00
|
|
|
void VMaterialSystem::Attach() const
|
2022-03-02 01:16:35 +01:00
|
|
|
{
|
2022-12-27 23:10:51 +01:00
|
|
|
// TODO: This has to be removed!!!
|
|
|
|
#ifndef _DEBUG
|
2023-02-17 23:56:56 +01:00
|
|
|
vector<CMemory> find_IMI_ref = CMemory(CMaterialSystem::IsMaterialInternal).FindAllCallReferences(reinterpret_cast<uintptr_t>(BuildPropStaticFrustumCullMap), 1000);
|
2022-12-27 23:10:51 +01:00
|
|
|
if (!find_IMI_ref.empty())
|
|
|
|
{
|
|
|
|
void* imiRetAddr = find_IMI_ref.at(0).Offset(0x5).RCast<void*>();
|
2022-12-28 15:38:34 +01:00
|
|
|
g_CrashHandler->AddWhitelist(imiRetAddr);
|
2022-12-27 23:10:51 +01:00
|
|
|
}
|
|
|
|
#endif // !_DEBUG
|
|
|
|
|
2022-10-05 02:11:13 +02:00
|
|
|
#ifndef DEDICATED
|
2022-05-27 22:31:52 +02:00
|
|
|
DetourAttach((LPVOID*)&v_StreamDB_Init, &StreamDB_Init);
|
2022-04-30 20:35:08 +02:00
|
|
|
DetourAttach((LPVOID*)&v_DispatchDrawCall, &DispatchDrawCall);
|
2022-10-13 02:22:50 +02:00
|
|
|
DetourAttach((LPVOID*)&CMaterialSystem__FindMaterialEx, &CMaterialSystem::FindMaterialEx);
|
2022-10-05 02:11:13 +02:00
|
|
|
#endif // !DEDICATED
|
2022-03-02 01:16:35 +01:00
|
|
|
}
|
|
|
|
|
2023-01-25 02:26:52 +01:00
|
|
|
void VMaterialSystem::Detach() const
|
2022-03-02 01:16:35 +01:00
|
|
|
{
|
2022-10-05 02:11:13 +02:00
|
|
|
#ifndef DEDICATED
|
2022-05-27 22:31:52 +02:00
|
|
|
DetourDetach((LPVOID*)&v_StreamDB_Init, &StreamDB_Init);
|
2022-04-30 20:35:08 +02:00
|
|
|
DetourDetach((LPVOID*)&v_DispatchDrawCall, &DispatchDrawCall);
|
2022-10-13 02:22:50 +02:00
|
|
|
DetourDetach((LPVOID*)&CMaterialSystem__FindMaterialEx, &CMaterialSystem::FindMaterialEx);
|
2022-10-05 02:11:13 +02:00
|
|
|
#endif // !DEDICATED
|
2022-03-02 01:16:35 +01:00
|
|
|
}
|