Fix EOF read errors and PAKFILE_LUMP not loading correctly when discrete

This commit adds support for loading cubemap lumps from the disk, several patches and hooks had to be implemented to make this work. Since the game was trying to read the pakfile lump from the BSP file (even when absent), it would read EOF (heavily reduces down map loading performance).
This commit is contained in:
Kawe Mazidjatari 2023-05-22 12:32:49 +02:00
parent ceb438b7ca
commit 1fbc3291c7
3 changed files with 87 additions and 1 deletions

View File

@ -3,6 +3,9 @@
#include "filesystem/basefilesystem.h"
#include "filesystem/filesystem.h"
#include "bspfile.h"
#include "engine/modelloader.h"
//---------------------------------------------------------------------------------
// Purpose: prints the output of the filesystem based on the warning level
// Input : *this -
@ -13,7 +16,7 @@ void CBaseFileSystem::Warning(CBaseFileSystem* pFileSystem, FileWarningLevel_t l
{
if (level >= FileWarningLevel_t::FILESYSTEM_WARNING_REPORTALLACCESSES)
{
// Logging reads is very verbose! Explicitly toggle..
// Logging reads are very verbose! Explicitly toggle..
if (!fs_showAllReads->GetBool())
{
return;
@ -101,6 +104,43 @@ bool CBaseFileSystem::VReadFromCache(CBaseFileSystem* pFileSystem, char* pszFile
return result;
}
//---------------------------------------------------------------------------------
// Purpose: mounts a BSP packfile lump as search path
// Input : *this -
// *pPath -
// *pPathID -
// *addType -
//---------------------------------------------------------------------------------
void CBaseFileSystem::VAddMapPackFile(CBaseFileSystem* pFileSystem, const char* pPath, const char* pPathID, SearchPathAdd_t addType)
{
// Since the mounting of the packfile lump is performed before the BSP header
// is loaded and parsed, we have to do it here. The internal 'AddMapPackFile'
// function has been patched to load the fields in the global 's_MapHeader'
// field, instead of the one that is getting initialized (see r5apex.patch).
if (s_MapHeader->ident != IDBSPHEADER || s_MapHeader->version != BSPVERSION)
{
FileHandle_t hBspFile = FileSystem()->Open(pPath, "rb", pPathID);
if (hBspFile != FILESYSTEM_INVALID_HANDLE)
{
memset(s_MapHeader, '\0', sizeof(BSPHeader_t));
FileSystem()->Read(s_MapHeader, sizeof(BSPHeader_t), hBspFile);
}
}
// If a lump exists, replace the path pointer with that of the lump so that
// the internal function loads this instead.
char lumpPathBuf[MAX_PATH];
V_snprintf(lumpPathBuf, sizeof(lumpPathBuf), "%s.%.4X.bsp_lump", pPath, LUMP_PAKFILE);
// TODO[ AMOS ]: Attempt to read from cache first???
if (FileSystem()->FileExists(lumpPathBuf, pPathID))
{
pPath = lumpPathBuf;
}
v_CBaseFileSystem_AddMapPackFile(pFileSystem, pPath, pPathID, addType);
}
//---------------------------------------------------------------------------------
// Purpose: attempts to mount VPK file for filesystem usage
// Input : *this -
@ -173,6 +213,7 @@ void VBaseFileSystem::Attach() const
DetourAttach((LPVOID*)&v_CBaseFileSystem_Warning, &CBaseFileSystem::Warning);
DetourAttach((LPVOID*)&v_CBaseFileSystem_LoadFromVPK, &CBaseFileSystem::VReadFromVPK);
DetourAttach((LPVOID*)&v_CBaseFileSystem_LoadFromCache, &CBaseFileSystem::VReadFromCache);
DetourAttach((LPVOID*)&v_CBaseFileSystem_AddMapPackFile, &CBaseFileSystem::VAddMapPackFile);
DetourAttach((LPVOID*)&v_CBaseFileSystem_MountVPKFile, &CBaseFileSystem::VMountVPKFile);
DetourAttach((LPVOID*)&v_CBaseFileSystem_UnmountVPKFile, &CBaseFileSystem::VUnmountVPKFile);
}
@ -182,6 +223,7 @@ void VBaseFileSystem::Detach() const
DetourDetach((LPVOID*)&v_CBaseFileSystem_Warning, &CBaseFileSystem::Warning);
DetourDetach((LPVOID*)&v_CBaseFileSystem_LoadFromVPK, &CBaseFileSystem::VReadFromVPK);
DetourDetach((LPVOID*)&v_CBaseFileSystem_LoadFromCache, &CBaseFileSystem::VReadFromCache);
DetourDetach((LPVOID*)&v_CBaseFileSystem_AddMapPackFile, &CBaseFileSystem::VAddMapPackFile);
DetourDetach((LPVOID*)&v_CBaseFileSystem_MountVPKFile, &CBaseFileSystem::VMountVPKFile);
DetourDetach((LPVOID*)&v_CBaseFileSystem_UnmountVPKFile, &CBaseFileSystem::VUnmountVPKFile);
}

View File

@ -11,6 +11,7 @@ public:
static bool VCheckDisk(const char* pszFilePath);
static FileHandle_t VReadFromVPK(CBaseFileSystem* pFileSystem, FileHandle_t pResults, char* pszFilePath);
static bool VReadFromCache(CBaseFileSystem* pFileSystem, char* pszFilePath, FileSystemCache* pCache);
static void VAddMapPackFile(CBaseFileSystem* pFileSystem, const char* pPath, const char* pPathID, SearchPathAdd_t addType);
static VPKData_t* VMountVPKFile(CBaseFileSystem* pFileSystem, const char* pszVpkPath);
static const char* VUnmountVPKFile(CBaseFileSystem* pFileSystem, const char* pszVpkPath);
@ -51,6 +52,9 @@ inline auto v_CBaseFileSystem_LoadFromVPK = p_CBaseFileSystem_LoadFromVPK.RCast<
inline CMemory p_CBaseFileSystem_LoadFromCache;
inline auto v_CBaseFileSystem_LoadFromCache = p_CBaseFileSystem_LoadFromCache.RCast<bool(*)(CBaseFileSystem* pFileSystem, const char* pszAssetName, FileSystemCache* pCache)>();
inline CMemory p_CBaseFileSystem_AddMapPackFile;
inline auto v_CBaseFileSystem_AddMapPackFile = p_CBaseFileSystem_AddMapPackFile.RCast<void (*)(CBaseFileSystem* pFileSystem, const char* pPath, const char* pPathID, SearchPathAdd_t addType)>();
inline CMemory p_CBaseFileSystem_MountVPKFile;
inline auto v_CBaseFileSystem_MountVPKFile = p_CBaseFileSystem_MountVPKFile.RCast<VPKData_t* (*)(CBaseFileSystem* pFileSystem, const char* pszVpkPath)>();
@ -70,6 +74,7 @@ class VBaseFileSystem : public IDetour
LogFunAdr("CBaseFileSystem::Warning", p_CBaseFileSystem_Warning.GetPtr());
LogFunAdr("CBaseFileSystem::LoadFromVPK", p_CBaseFileSystem_LoadFromVPK.GetPtr());
LogFunAdr("CBaseFileSystem::LoadFromCache", p_CBaseFileSystem_LoadFromCache.GetPtr());
LogFunAdr("CBaseFileSystem::AddMapPackFile", p_CBaseFileSystem_AddMapPackFile.GetPtr());
LogFunAdr("CBaseFileSystem::MountVPKFile", p_CBaseFileSystem_MountVPKFile.GetPtr());
LogFunAdr("CBaseFileSystem::UnmountVPKFile", p_CBaseFileSystem_UnmountVPKFile.GetPtr());
LogFunAdr("CBaseFileSystem::GetMountedVPKHandle", p_CBaseFileSystem_GetMountedVPKHandle.GetPtr());
@ -80,6 +85,7 @@ class VBaseFileSystem : public IDetour
p_CBaseFileSystem_Warning = g_GameDll.FindPatternSIMD("4C 89 4C 24 20 C3 CC CC CC CC CC CC CC CC CC CC 48");
p_CBaseFileSystem_LoadFromVPK = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 49 8B C0 4C 8D 8C 24 ?? ?? ?? ??");
p_CBaseFileSystem_LoadFromCache = g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 49 8B D8");
p_CBaseFileSystem_AddMapPackFile = g_GameDll.FindPatternSIMD("4C 89 44 24 ?? 48 89 54 24 ?? 55 ?? 41 54 41 55 48 8D AC 24 ?? ?? ?? ??");
p_CBaseFileSystem_MountVPKFile = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 4C 8D 05 ?? ?? ?? ??");
p_CBaseFileSystem_UnmountVPKFile = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 48 8B CB 48 8D 15 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0");
p_CBaseFileSystem_GetMountedVPKHandle = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 4C 8D 05 ?? ?? ?? ??");
@ -87,6 +93,7 @@ class VBaseFileSystem : public IDetour
v_CBaseFileSystem_Warning = p_CBaseFileSystem_Warning.RCast<void(*)(CBaseFileSystem*, FileWarningLevel_t, const char*, ...)>(); /*4C 89 4C 24 20 C3 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 48*/
v_CBaseFileSystem_LoadFromVPK = p_CBaseFileSystem_LoadFromVPK.RCast<FileHandle_t(*)(CBaseFileSystem*, FileHandle_t, const char*)>(); /*48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 49 8B C0 4C 8D 8C 24 ?? ?? ?? ??*/
v_CBaseFileSystem_LoadFromCache = p_CBaseFileSystem_LoadFromCache.RCast<bool(*)(CBaseFileSystem*, const char*, FileSystemCache*)>(); /*40 53 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 49 8B D8*/
v_CBaseFileSystem_AddMapPackFile = p_CBaseFileSystem_AddMapPackFile.RCast<void (*)(CBaseFileSystem*, const char*, const char*, SearchPathAdd_t)>();
v_CBaseFileSystem_MountVPKFile = p_CBaseFileSystem_MountVPKFile.RCast<VPKData_t*(*)(CBaseFileSystem*, const char*)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 4C 8D 05 ?? ?? ?? ??*/
v_CBaseFileSystem_UnmountVPKFile = p_CBaseFileSystem_UnmountVPKFile.RCast<const char*(*)(CBaseFileSystem*, const char*)>(); /*48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 48 8B CB 48 8D 15 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0*/
v_CBaseFileSystem_GetMountedVPKHandle = p_CBaseFileSystem_GetMountedVPKHandle.RCast<int (*)(CBaseFileSystem*, const char*)>(); /*48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 4C 8D 05 ?? ?? ?? ??*/

View File

@ -2,6 +2,43 @@
// Base game executable patch file; this executable
// contains all patches applied directly to the image.
/////////////////////////////
/////////////////////////////
//// Code adjustments ////
/////////////////////////////
/////////////////////////////
// This patch adds support for loading the 'LUMP_PAKFILE' lump as a discrete file.
// The function originally loaded the BSP, and stored the header in a local variable.
// This means that we need to store the BSP header in the lump too, if we want to load
// the packfile lump separately. To avoid this, we hook this function in SDK code,
// and load the BSP header into the static 's_MapHeader' memory. The patch below makes
// the function read the static fields instead, and uses the descritprs in the header to
// read out the lump path passed in. A separate tool sets the 'fileofs' field to 0, so the
// packfile lump can be loaded without any additional patching.
0x382152: "cmp dword ptr ds:[0x00000001666EC6C0], 0x50534272" // s_MapHeader.ident
0x382162: "mov eax, dword ptr ds:[0x00000001666EC6C4]" // s_MapHeader.version
0x382174: "cmp dword ptr ds:[0x00000001666EC954], 0x10" // s_MapHeader.lumps[LUMP_PAKFILE].filelen
0x382181: "movsxd rcx, dword ptr ds:[0x00000001666EC950]" // s_MapHeader.lumps[LUMP_PAKFILE].fileofs
0x382188: "mov rdx, rcx" // Move the operation done at 0x382181 (stored into RCX) into RDX; no need to index into it again.
// Due to the simplification of the operation above, 2 bytes had to be nopped.
0x38218B: "nop"
0x38218C: "nop"
0x38226E: "movsxd r8, dword ptr ds:[0x00000001666EC950]" // s_MapHeader.lumps[LUMP_PAKFILE].fileofs
0x382275: "movsxd rdx, dword ptr ds:[0x00000001666EC954]" // s_MapHeader.lumps[LUMP_PAKFILE].filelen
0x38247B: "cmp dword ptr ds:[0x00000001666EC6C0], 0x50534272" // s_MapHeader.ident
0x38248B: "mov eax, dword ptr ds:[0x00000001666EC6C4]" // s_MapHeader.version
0x38249D: "cmp dword ptr ds:[0x00000001666EC954], 0x10" // s_MapHeader.lumps[LUMP_PAKFILE].filelen
0x3824B6: "movsxd r8, dword ptr ds:[0x00000001666EC950]" // s_MapHeader.lumps[LUMP_PAKFILE].fileofs
0x38257E: movsxd r8, dword ptr ds:[0x00000001666EC950] // s_MapHeader.lumps[LUMP_PAKFILE].fileofs
0x382585: movsxd rdx, dword ptr ds:[0x00000001666EC954] // s_MapHeader.lumps[LUMP_PAKFILE].filelen
/////////////////////////////
/////////////////////////////
//// Code defects ////