Experimental BSP_LUMP loading hook

The 'CMapLoadHelper' constructor has been rebuild to load lump files too (if they exist). Currently, the game only reads the packed BSP file, or lumps if they exist in the filesystem cache. The newly added logic also reads them from a file. This is currently broken, most likely due to alignment problems. Experimental.
This commit is contained in:
Kawe Mazidjatari 2023-05-20 14:06:36 +02:00
parent e338f0331a
commit 4297cd9ce3
2 changed files with 178 additions and 10 deletions

View File

@ -9,9 +9,71 @@
#include "engine/cmodel_bsp.h"
#include "engine/modelloader.h"
#include "datacache/mdlcache.h"
#ifndef DEDICATED
#include <vgui/vgui_baseui_interface.h>
#endif // !DEDICATED
#include <filesystem/filesystem.h>
model_t* pErrorMDL = nullptr;
//-----------------------------------------------------------------------------
// Purpose: checks if the lump type is valid and used
// Input : lumpType -
//-----------------------------------------------------------------------------
bool IsLumpIdxValid(int lumpType)
{
switch (lumpType)
{
case LUMP_PLANES:
case LUMP_VERTICES:
case LUMP_SHADOW_ENVIRONMENTS:
case LUMP_SURFACE_NAMES:
case LUMP_CONTENTS_MASKS:
case LUMP_SURFACE_PROPERTIES:
case LUMP_BVH_NODES:
case LUMP_BVH_LEAF_DATA:
case LUMP_PACKED_VERTICES:
case LUMP_VERTEX_NORMALS:
case LUMP_UNKNOWN_37:
case LUMP_UNKNOWN_38:
case LUMP_UNKNOWN_39:
case LUMP_VERTEX_UNLIT:
case LUMP_VERTEX_LIT_FLAT:
case LUMP_VERTEX_LIT_BUMP:
case LUMP_VERTEX_UNLIT_TS:
case LUMP_MESH_INDICES:
case LUMP_LIGHTMAP_DATA_SKY:
case LUMP_CSM_AABB_NODES:
case LUMP_CSM_OBJ_REFERENCES:
case LUMP_LIGHTPROBES:
case LUMP_LIGHTPROBE_TREE:
case LUMP_LIGHTPROBE_REFERENCES:
case LUMP_LIGHTMAP_DATA_REAL_TIME_LIGHTS:
case LUMP_CELL_BSP_NODES:
case LUMP_CELLS:
case LUMP_PORTALS:
case LUMP_PORTAL_VERTICES:
case LUMP_PORTAL_EDGES:
case LUMP_PORTAL_VERTEX_EDGES:
case LUMP_PORTAL_VERTEX_REFERENCES:
case LUMP_PORTAL_EDGE_REFERENCES:
case LUMP_PORTAL_EDGE_INTERSECT_AT_EDGE:
case LUMP_PORTAL_EDGE_INTERSECT_AT_VERTEX:
case LUMP_PORTAL_EDGE_INTERSECT_HEADER:
case LUMP_OCCLUSION_MESH_VERTICES:
case LUMP_OCCLUSION_MESH_INDICES:
case LUMP_CELL_AABB_NODES:
case LUMP_OBJ_REFERENCES:
case LUMP_OBJ_REFERENCE_BOUNDS:
case LUMP_SHADOW_MESH_OPAQUE_VERTICES:
case LUMP_SHADOW_MESH_INDICES:
case LUMP_SHADOW_MESHES:
return true;
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *loader -
@ -55,9 +117,97 @@ uint64_t CModelLoader::Map_LoadModelGuts(CModelLoader* loader, model_t* model)
return CModelLoader__Map_LoadModelGuts(loader, model);
}
void CMapLoadHelper::Constructor(CMapLoadHelper* helper, int lumpToLoad)
void CMapLoadHelper::Constructor(CMapLoadHelper* loader, int lumpToLoad)
{
CMapLoadHelper__CMapLoadHelper(helper, lumpToLoad);
#ifndef DEDICATED
g_pEngineVGui->UpdateProgressBar(PROGRESS_DEFAULT);
#endif // !DEDICATED
if (lumpToLoad > HEADER_LUMPS-1)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Can't load lump %i, range is 0 to %i!!!", lumpToLoad, HEADER_LUMPS-1);
loader->m_nLumpID = lumpToLoad;
loader->m_nLumpSize = 0;
loader->m_pData = nullptr;
loader->m_pRawData = nullptr;
loader->m_pUncompressedData = nullptr;
loader->m_nUncompressedLumpSize = 0;
loader->m_bUncompressedDataExternal = 0;
loader->m_bExternal = false;
loader->m_bUnk = false;
loader->m_nLumpOffset = -1;
if (lumpToLoad <= s_MapHeader->lastLump)
{
lump_t* lump = &s_MapHeader->lumps[lumpToLoad];
int lumpOffset = lump->fileofs;
if (!lumpOffset)
return; // Idk if this is correct.
int lumpSize = lump->filelen;
if (lumpSize)
{
loader->m_nLumpSize = lumpSize;
loader->m_nLumpOffset = lump->fileofs;
loader->m_nLumpVersion = lump->version;
FileHandle_t mapFileHandle = *s_MapFileHandle;
if (mapFileHandle == FILESYSTEM_INVALID_HANDLE)
{
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Can't load map from invalid handle!!!");
lumpSize = loader->m_nLumpSize;
}
loader->m_nUncompressedLumpSize = lumpSize;
char pathBuf[MAX_PATH];
FileSystemCache fileCache;
fileCache.pBuffer = nullptr;
if (IsLumpIdxValid(lumpToLoad)
&& (V_snprintf(pathBuf, sizeof(pathBuf), "%s.%.4X.bsp_lump", s_szMapPathName, lumpToLoad), FileSystem()->ReadFromCache(pathBuf, &fileCache)))
{
loader->m_pRawData = nullptr;
loader->m_pData = fileCache.pBuffer->pData;
loader->m_bExternal = true;
loader->m_bUnk = fileCache.pBuffer->nUnk0 == 0;
}
else
{
int bytesToRead = lumpSize ? lumpSize : 1;
loader->m_pRawData = MemAllocSingleton()->Alloc<byte>(bytesToRead);
if (loader->m_nLumpSize)
{
FileHandle_t hLumpFile = FileSystem()->Open(pathBuf, "rb");
if (hLumpFile != FILESYSTEM_INVALID_HANDLE)
{
FileSystem()->ReadEx(loader->m_pRawData, bytesToRead, bytesToRead, hLumpFile);
FileSystem()->Close(hLumpFile);
loader->m_bExternal = true;
}
else // Seek to offset in packed BSP file to load the lump.
{
FileSystem()->Seek(mapFileHandle, loader->m_nLumpOffset, FILESYSTEM_SEEK_HEAD);
FileSystem()->ReadEx(loader->m_pRawData, bytesToRead, bytesToRead, mapFileHandle);
}
loader->m_pData = loader->m_pRawData;
}
}
}
}
else
{
loader->m_nLumpSize = 0;
loader->m_nLumpOffset = 0;
loader->m_nLumpVersion = 0;
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,6 @@
#pragma once
#include "engine/gl_model_private.h"
#include "public/bspfile.h"
//-----------------------------------------------------------------------------
// Purpose:
@ -55,18 +56,17 @@ class CMapLoadHelper
public:
static void Constructor(CMapLoadHelper* helper, int lumpToLoad);
public:
int m_nLumpSize;
int m_nLumpOffset;
int m_nLumpVersion;
unsigned __int8* m_pRawData;
char* m_pData;
unsigned __int8* m_pUncompressedData;
char gap_28[5];
byte* m_pRawData;
byte* m_pData;
byte* m_pUncompressedData;
int m_nUncompressedLumpSize;
bool m_bUncompressedDataExternal;
bool m_bExternal;
bool m_bUnk;
char gap_2F;
int m_nLumpID;
char m_szLumpFilename[260];
};
@ -92,6 +92,9 @@ inline auto CModelLoader__Map_IsValid = p_CModelLoader__Map_IsValid.RCast<bool(*
inline CMemory p_CMapLoadHelper__CMapLoadHelper;
inline auto CMapLoadHelper__CMapLoadHelper = p_CMapLoadHelper__CMapLoadHelper.RCast<void(__fastcall*)(CMapLoadHelper * helper, int lumpToLoad)>();
inline CMemory p_Map_LoadModel;
inline auto v_Map_LoadModel = p_Map_LoadModel.RCast<void(__fastcall*)(void)>();
//inline CMemory p_GetSpriteInfo; // DEDICATED PATCH!
//inline auto GetSpriteInfo = p_GetSpriteInfo.RCast<void* (*)(const char* pName, bool bIsAVI, bool bIsBIK, int& nWidth, int& nHeight, int& nFrameCount, void* a7)>();
@ -99,6 +102,9 @@ inline auto CMapLoadHelper__CMapLoadHelper = p_CMapLoadHelper__CMapLoadHelper.RC
//inline auto BuildSpriteLoadName = p_BuildSpriteLoadName.RCast<void* (*)(const char* pName, char* pOut, int outLen, bool& bIsAVI, bool& bIsBIK)>();
inline CModelLoader* g_pModelLoader;
inline FileHandle_t* s_MapFileHandle;
inline BSPHeader_t* s_MapHeader;
inline const char* s_szMapPathName; /*size = 260*/
///////////////////////////////////////////////////////////////////////////////
class VModelLoader : public IDetour
@ -111,9 +117,14 @@ class VModelLoader : public IDetour
LogFunAdr("CModelLoader::Map_LoadModelGuts", p_CModelLoader__Map_LoadModelGuts.GetPtr());
LogFunAdr("CModelLoader::Map_IsValid", p_CModelLoader__Map_IsValid.GetPtr());
LogFunAdr("CModelLoader::Studio_LoadModel", p_CModelLoader__Studio_LoadModel.GetPtr());
LogFunAdr("CMapLoadHelper::CMapLoadHelper", p_CMapLoadHelper__CMapLoadHelper.GetPtr());
LogFunAdr("Map_LoadModel", p_Map_LoadModel.GetPtr());
//LogFunAdr("GetSpriteInfo", p_GetSpriteInfo.GetPtr());
//LogFunAdr("BuildSpriteLoadName", p_BuildSpriteLoadName.GetPtr());
LogVarAdr("g_pModelLoader", reinterpret_cast<uintptr_t>(g_pModelLoader));
LogVarAdr("s_MapFileHandle", reinterpret_cast<uintptr_t>(s_MapFileHandle));
LogVarAdr("s_MapHeader", reinterpret_cast<uintptr_t>(s_MapHeader));
LogVarAdr("s_szMapPathName", reinterpret_cast<uintptr_t>(s_szMapPathName));
}
virtual void GetFun(void) const
{
@ -137,8 +148,7 @@ class VModelLoader : public IDetour
//p_BuildSpriteLoadName = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC ?? ?? ?? ?? 4D 8B F1 48 8B F2");
p_CMapLoadHelper__CMapLoadHelper = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC 60");
CMapLoadHelper__CMapLoadHelper = p_CMapLoadHelper__CMapLoadHelper.RCast<void(__fastcall*)(CMapLoadHelper*, int)>();
p_Map_LoadModel = g_GameDll.FindPatternSIMD("48 83 EC 28 8B 05 ?? ?? ?? ?? FF C8");
CModelLoader__FindModel = p_CModelLoader__FindModel.RCast<void* (*)(CModelLoader*, const char*)>();
CModelLoader__LoadModel = p_CModelLoader__LoadModel.RCast<void(*)(CModelLoader*, model_t*)>();
@ -146,6 +156,10 @@ class VModelLoader : public IDetour
CModelLoader__Studio_LoadModel = p_CModelLoader__Studio_LoadModel.RCast<void* (*)(CModelLoader*)>();
CModelLoader__Map_LoadModelGuts = p_CModelLoader__Map_LoadModelGuts.RCast<uint64_t(*)(CModelLoader*, model_t* mod)>();
CModelLoader__Map_IsValid = p_CModelLoader__Map_IsValid.RCast<bool(*)(CModelLoader*, const char*)>();
CMapLoadHelper__CMapLoadHelper = p_CMapLoadHelper__CMapLoadHelper.RCast<void(__fastcall*)(CMapLoadHelper*, int)>();
v_Map_LoadModel = p_Map_LoadModel.RCast<void(__fastcall*)(void)>();
//GetSpriteInfo = p_GetSpriteInfo.RCast<void* (*)(const char*, bool, bool, int&, int&, int&, void*)>();
//BuildSpriteLoadName = p_BuildSpriteLoadName.RCast<void* (*)(const char*, char*, int, bool&, bool&)>();
}
@ -153,6 +167,10 @@ class VModelLoader : public IDetour
{
g_pModelLoader = g_GameDll.FindPatternSIMD(
"48 89 4C 24 ?? 53 55 56 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ??").FindPatternSelf("48 ?? 0D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(3, 7).RCast<CModelLoader*>();
s_MapFileHandle = p_Map_LoadModel.FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast<FileHandle_t*>();
s_MapHeader = p_Map_LoadModel.FindPattern("48 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<BSPHeader_t*>();
s_szMapPathName = p_CMapLoadHelper__CMapLoadHelper.FindPattern("4C 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<const char*>();
}
virtual void GetCon(void) const { }
virtual void Attach(void) const;