mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
This is currently the most robust way to perform this. However it might fail still as the locks don't seem valid for the second loads (we currently load more paks from the same queue..). We need to push the strings to the queue list and let the engine load these too so a new lock is acquired for that job.
364 lines
11 KiB
C++
364 lines
11 KiB
C++
//=============================================================================//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "core/stdafx.h"
|
|
#include "tier0/jobthread.h"
|
|
#include "engine/host_cmd.h"
|
|
#include "engine/sys_utils.h"
|
|
#include "engine/cmodel_bsp.h"
|
|
#include "rtech/rtech_utils.h"
|
|
#include "rtech/rtech_game.h"
|
|
#include "datacache/mdlcache.h"
|
|
|
|
string g_svLevelName;
|
|
bool s_bLevelResourceInitialized = false;
|
|
bool s_bBasePaksInitialized = false;
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: checks if level has changed
|
|
// Input : &svLevelName -
|
|
// Output : true if level name deviates from previous level
|
|
//-----------------------------------------------------------------------------
|
|
bool MOD_LevelHasChanged(const string& svLevelName)
|
|
{
|
|
return (strcmp(svLevelName.c_str(), g_svLevelName.c_str()) != 0);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: gets the queued pak handles
|
|
// Input : *a1 -
|
|
// *a2 -
|
|
// a3 -
|
|
// Output : __int64
|
|
//-----------------------------------------------------------------------------
|
|
__int64 __fastcall MOD_GetQueuedPakHandle(char* a1, char* a2, __int64 a3)
|
|
{
|
|
char v3; // al
|
|
signed int v4; // er11
|
|
__int64 v5; // r10
|
|
char* v6; // r9
|
|
signed __int64 v7; // rdx
|
|
char v8; // al
|
|
char* v10; // r8
|
|
char* v11; // r8
|
|
|
|
v3 = *a2;
|
|
v4 = 0;
|
|
*a1 = *a2;
|
|
v5 = 0i64;
|
|
if (v3)
|
|
{
|
|
v6 = a1;
|
|
v7 = a2 - a1;
|
|
while (1)
|
|
{
|
|
++v5;
|
|
++v6;
|
|
if (v5 == a3)
|
|
break;
|
|
v8 = v6[v7];
|
|
*v6 = v8;
|
|
if (!v8)
|
|
return v5;
|
|
}
|
|
*(v6 - 1) = 0;
|
|
if (--v5)
|
|
{
|
|
v10 = &a1[v5 - 1];
|
|
if ((*v10 & 0xC0) == 0x80)
|
|
{
|
|
do
|
|
++v4;
|
|
while ((v10[-v4] & 0xC0) == 0x80);
|
|
}
|
|
v11 = &v10[-v4];
|
|
if (v4 != ((0xE5000000 >> (((unsigned __int8)*v11 >> 3) & 0x1E)) & 3))
|
|
{
|
|
*v11 = 0;
|
|
v5 -= v4;
|
|
}
|
|
}
|
|
}
|
|
return v5;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: processes queued pak files
|
|
//-----------------------------------------------------------------------------
|
|
void MOD_ProcessPakQueue()
|
|
{
|
|
char v0; // bl
|
|
char** v1; // r10
|
|
int i; // er9
|
|
char* v3; // rcx
|
|
signed __int64 v4; // r8
|
|
int v5; // eax
|
|
int v6; // edx
|
|
int v7; // eax
|
|
__int64 v8; // rbp
|
|
__int64 v9; // rsi
|
|
char* v10; // rbx
|
|
unsigned int v11; // ecx
|
|
__int64 v12; // rax
|
|
int v13; // edi
|
|
char v14; // al
|
|
char* v15; // rbx
|
|
int v16; // edi
|
|
char* v17; // rsi
|
|
char* v18; // rax
|
|
int v19; // ecx
|
|
int v20; // er8
|
|
int v21; // ecx
|
|
__int64 v22; // rdx
|
|
__int64 v23; // rbx
|
|
__int64 v24{}; // rdx
|
|
__int64 v25{}; // rcx
|
|
|
|
v0 = 0;
|
|
if (*(float*)&*dword_14B383420 == 1.0 && *qword_167ED7BB8 && *((int*)&*qword_14180A098/* + 36*/) < 2)
|
|
{
|
|
*byte_16709DDDF = 0;
|
|
v0 = 1;
|
|
}
|
|
else if (*byte_16709DDDF)
|
|
{
|
|
return;
|
|
}
|
|
if ((*(unsigned __int8(__fastcall**)(__int64))(*(_QWORD*)*g_FileSystem + 696i64))(*g_FileSystem) && !*dword_1634F445C)
|
|
{
|
|
v1 = &*off_141874660;
|
|
for (i = 0; i < 5; ++i)
|
|
{
|
|
if (*((_BYTE*)v1 - 268))
|
|
break;
|
|
v3 = (char*)&*unk_141874555 + 280 * i;
|
|
v4 = *v1 - v3;
|
|
do
|
|
{
|
|
v5 = (unsigned __int8)v3[v4];
|
|
v6 = (unsigned __int8)*v3 - v5;
|
|
if (v6)
|
|
break;
|
|
++v3;
|
|
} while (v5);
|
|
if (v6)
|
|
break;
|
|
v1 += 35;
|
|
}
|
|
v7 = 0;
|
|
if (!v0)
|
|
v7 = i;
|
|
v8 = v7;
|
|
if (v7 <= 4i64)
|
|
{
|
|
v9 = 4i64;
|
|
v10 = (char*)&*unk_1418749B0;
|
|
do
|
|
{
|
|
if (v10[5])
|
|
{
|
|
v11 = *(_DWORD*)v10;
|
|
v12 = *(_DWORD*)v10 & 0x1FF;
|
|
v10[4] = 1;
|
|
if (*((_DWORD*)&*unk_167D40B70 + 46 * v12) == v11)
|
|
{
|
|
v13 = *((_DWORD*)&*unk_167D40B70 + 46 * v12 + 1);
|
|
v14 = v10[4];
|
|
}
|
|
else
|
|
{
|
|
v13 = 14;
|
|
v14 = 1;
|
|
}
|
|
if (!v14 || v13 == 9)
|
|
{
|
|
g_pakLoadApi->Unload(*(_DWORD*)v10);
|
|
MOD_UnloadPakFile();
|
|
}
|
|
if (v13 && (unsigned int)(v13 - 13) > 1)
|
|
return;
|
|
*((_WORD*)v10 + 2) = 0;
|
|
*(_DWORD*)v10 = -1;
|
|
}
|
|
--v9;
|
|
v10 -= 280;
|
|
} while (v9 >= v8);
|
|
}
|
|
*byte_16709DDDF = 1;
|
|
v15 = (char*)&*unk_141874550;
|
|
v16 = 0;
|
|
while (1)
|
|
{
|
|
v17 = (char*)&*unk_141874550 + 280 * v16 + 5;
|
|
v18 = v17;
|
|
do
|
|
{
|
|
v19 = (unsigned __int8)v18[*((_QWORD*)v15 + 34) - (_QWORD)v17];
|
|
v20 = (unsigned __int8)*v18 - v19;
|
|
if (v20)
|
|
break;
|
|
++v18;
|
|
} while (v19);
|
|
if (!v20)
|
|
goto LABEL_37;
|
|
sub_1401F9C10(v17, *((char**)v15 + 34), 260i64);
|
|
if (v15[5])
|
|
break;
|
|
*(_DWORD*)v15 = -1;
|
|
LABEL_40:
|
|
++v16;
|
|
v15 += 280;
|
|
if (v16 >= 5)
|
|
{
|
|
if (*byte_16709DDDF)
|
|
{
|
|
v23 = *qword_1671061C8;
|
|
if (*qword_1671061C8)
|
|
{
|
|
if (!*(_BYTE*)(*qword_1671061C8 + 4))
|
|
{
|
|
if (*qword_167ED7BC0 || WORD2(*qword_167ED7C68) != HIWORD(*qword_167ED7C68))
|
|
{
|
|
if (!JT_AcquireFifoLock((JobFifoLock_s*)&*qword_167ED7BE0)
|
|
&& !(unsigned __int8)sub_14045BAC0((__int64(__fastcall*)(__int64, _DWORD*, __int64, _QWORD*))qword_14045C070, (__int64)&*qword_167ED7BE0, -1i64, 0i64))
|
|
{
|
|
sub_14045A1D0((unsigned __int8(__fastcall*)(_QWORD))qword_14045C070, (__int64)&*qword_167ED7BE0, -1i64, 0i64, 0i64, 1);
|
|
}
|
|
|
|
sub_140441220(v25, v24);
|
|
if (GetCurrentThreadId() == *dword_1641E443C)
|
|
{
|
|
if (*byte_167208B0C)
|
|
{
|
|
*byte_167208B0C = 0;
|
|
JT_ReleaseFifoLock((JobFifoLock_s*)&*qword_167ED7BE0);
|
|
}
|
|
}
|
|
JT_ReleaseFifoLock((JobFifoLock_s*)&*qword_167ED7BE0);
|
|
v23 = *qword_1671061C8;
|
|
}
|
|
(*(void(__fastcall**)(__int64, __int64))(*(_QWORD*)*g_FileSystem + 656i64))(*g_FileSystem, 256i64);
|
|
(*(void(__fastcall**)(__int64, __int64))(*(_QWORD*)*g_FileSystem + 648i64))(*g_FileSystem, v23);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (strcmp(v17, "mp_lobby.rpak") == 0)
|
|
s_bBasePaksInitialized = true;
|
|
|
|
if (s_bBasePaksInitialized && !s_bLevelResourceInitialized)
|
|
{
|
|
s_bLevelResourceInitialized = true;
|
|
MOD_PreloadPakFile(g_svLevelName);
|
|
}
|
|
|
|
*(_DWORD*)v15 = g_pakLoadApi->AsyncLoad(v17, g_pMallocPool.GetPtr(), 4, 0);
|
|
|
|
LABEL_37:
|
|
v21 = *(_DWORD*)v15;
|
|
if (*(_DWORD*)v15 != -1)
|
|
{
|
|
v22 = 184i64 * (v21 & 0x1FF);
|
|
if (*(_DWORD*)((char*)&*unk_167D40B70 + v22) != v21 || ((*(_DWORD*)((char*)&*unk_167D40B70 + v22 + 4) - 9) & 0xFFFFFFFB) != 0)
|
|
{
|
|
*byte_16709DDDF = 0; return;
|
|
}
|
|
}
|
|
goto LABEL_40;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: load assets for level with fifolock (still not reliable enough).
|
|
// Input : *szLevelName -
|
|
// Output : true on success, false on failure
|
|
//-----------------------------------------------------------------------------
|
|
bool MOD_LoadPakForMap(const char* szLevelName)
|
|
{
|
|
if (MOD_LevelHasChanged(szLevelName))
|
|
s_bLevelResourceInitialized = false;
|
|
|
|
g_svLevelName = szLevelName;
|
|
return v_MOD_LoadPakForMap(szLevelName);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: loads required pakfile assets for specified BSP
|
|
// Input : &svSetFile -
|
|
//-----------------------------------------------------------------------------
|
|
void MOD_PreloadPakFile(const string& svLevelName)
|
|
{
|
|
ostringstream ostream;
|
|
ostream << "platform\\scripts\\levels\\settings\\" << svLevelName << ".json";
|
|
|
|
fs::path fsPath = std::filesystem::current_path() /= ostream.str();
|
|
if (FileExists(fsPath.string().c_str()))
|
|
{
|
|
nlohmann::json jsIn;
|
|
try
|
|
{
|
|
ifstream iPakLoadDefFile(fsPath.string().c_str(), std::ios::binary); // Load prerequisites file.
|
|
|
|
jsIn = nlohmann::json::parse(iPakLoadDefFile);
|
|
iPakLoadDefFile.close();
|
|
|
|
if (!jsIn.is_null())
|
|
{
|
|
if (!jsIn["rpak"].is_null())
|
|
{
|
|
for (auto& it : jsIn["rpak"])
|
|
{
|
|
if (it.is_string())
|
|
{
|
|
string svToLoad = it.get<string>() + ".rpak";
|
|
RPakHandle_t nPakId = g_pakLoadApi->AsyncLoad(svToLoad.c_str(), g_pMallocPool.GetPtr(), 4, 0);
|
|
|
|
if (nPakId == -1)
|
|
Error(eDLL_T::ENGINE, "%s: unable to load pak '%s' results '%d'\n", __FUNCTION__, svToLoad.c_str(), nPakId);
|
|
else
|
|
g_LoadedPakHandle.push_back(nPakId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (const std::exception& ex)
|
|
{
|
|
Warning(eDLL_T::RTECH, "Exception while parsing RPak load list: '%s'\n", ex.what());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: unloads all pakfiles loaded by the SDK
|
|
//-----------------------------------------------------------------------------
|
|
void MOD_UnloadPakFile(void)
|
|
{
|
|
for (auto& it : g_LoadedPakHandle)
|
|
{
|
|
if (it >= 0)
|
|
{
|
|
g_pakLoadApi->Unload(it);
|
|
}
|
|
}
|
|
g_LoadedPakHandle.clear();
|
|
g_BadMDLHandles.clear();
|
|
}
|
|
|
|
void CModelBsp_Attach()
|
|
{
|
|
DetourAttach((LPVOID*)&v_MOD_LoadPakForMap, &MOD_LoadPakForMap);
|
|
DetourAttach((LPVOID*)&v_MOD_ProcessPakQueue, &MOD_ProcessPakQueue);
|
|
}
|
|
|
|
void CModelBsp_Detach()
|
|
{
|
|
DetourDetach((LPVOID*)&v_MOD_LoadPakForMap, &MOD_LoadPakForMap);
|
|
DetourDetach((LPVOID*)&v_MOD_ProcessPakQueue, &MOD_ProcessPakQueue);
|
|
} |