r5sdk/r5dev/vpc/keyvalues.cpp
Kawe Mazidjatari e32cc6ae6a Code overhaul
Moved every pattern to IDetour interface. This allows for debugging patterns scans more easily, and create threads during pattern searching (Operation is now fired in APIENTRY).

Also cleaned up some unused code/extraneous comments.
Slightly increased performance by purging duplicate patterns.
Made variable search less dependent from other results (except if pattern-to-scan results is within the same header)
2022-04-18 03:35:08 +02:00

179 lines
5.7 KiB
C++

//=============================================================================//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "core/stdafx.h"
#include "vpc/keyvalues.h"
#include "vstdlib/keyvaluessystem.h"
#include "rtech/stryder/stryder.h"
#include "engine/sys_dll2.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void KeyValues::Init(void)
{
std::thread t1(KeyValues::InitPlaylist); // Start thread to grab playlists.
t1.detach(); // Detach thread from current one.
}
//-----------------------------------------------------------------------------
// Purpose: Find a keyValue, create it if it is not found.
// Set bCreate to true to create the key if it doesn't already exist
// (which ensures a valid pointer will be returned)
// Input : *pKeyName -
// bCreate -
// Output : *KeyValues
//-----------------------------------------------------------------------------
KeyValues* KeyValues::FindKey(const char* keyName, bool bCreate)
{
static auto func = reinterpret_cast<KeyValues * (__thiscall*)(KeyValues*, const char*, bool)>(KeyValues_FindKey);
return func(this, keyName, bCreate);
}
//-----------------------------------------------------------------------------
// Purpose: Get the name of the current key section
// Output : const char*
//-----------------------------------------------------------------------------
const char* KeyValues::GetName(void) const
{
return g_pKeyValuesSystem->GetStringForSymbol(MAKE_3_BYTES_FROM_1_AND_2(m_iKeyNameCaseSensitive, m_iKeyNameCaseSensitive2));
}
//-----------------------------------------------------------------------------
// Purpose: Get the integer value of a keyName. Default value is returned
// if the keyName can't be found.
// Input : *pKeyName -
// nDefaultValue -
// Output : int
//-----------------------------------------------------------------------------
int KeyValues::GetInt(const char* pKeyName, int nDefaultValue)
{
KeyValues* dat = FindKey(pKeyName, false);
if (!dat)
return nDefaultValue;
switch (dat->m_iDataType)
{
case TYPE_STRING:
return atoi(dat->m_sValue);
case TYPE_FLOAT:
return static_cast<int>(m_flValue());
case TYPE_WSTRING:
return _wtoi(dat->m_wsValue);
case TYPE_UINT64:
return 0;
default:
return dat->m_iValue();
}
return nDefaultValue;
}
//-----------------------------------------------------------------------------
// Purpose: Set the integer value of a keyName.
// Input : *pKeyName -
// iValue -
//-----------------------------------------------------------------------------
void KeyValues::SetInt(const char* pKeyName, int iValue)
{
KeyValues* dat = FindKey(pKeyName, true);
if (dat)
{
dat->m_iValue() = iValue;
dat->m_iDataType = TYPE_INT;
}
}
//-----------------------------------------------------------------------------
// Purpose: Set the float value of a keyName.
// Input : *pKeyName -
// flValue -
//-----------------------------------------------------------------------------
void KeyValues::SetFloat(const char* pKeyName, float flValue)
{
KeyValues* dat = FindKey(pKeyName, true);
if (dat)
{
dat->m_flValue() = flValue;
dat->m_iDataType = TYPE_FLOAT;
}
}
//-----------------------------------------------------------------------------
// Purpose: Initializes the playlist
//-----------------------------------------------------------------------------
void KeyValues::InitPlaylist(void)
{
while (true)
{
if ((*g_pPlaylistKeyValues))
{
KeyValues* playlists = (*g_pPlaylistKeyValues)->FindKey("Playlists", false);
if (playlists)
{
g_szAllPlaylists.clear();
for (KeyValues* dat = playlists->m_pSub; dat != nullptr; dat = dat->m_pPeer) // Parse through all sub keys.
{
g_szAllPlaylists.push_back(dat->GetName()); // Get all playlist names.
}
break; // Break if playlist got filled.
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
//-----------------------------------------------------------------------------
// Purpose: loads the playlist
// Input : *szPlaylist -
//-----------------------------------------------------------------------------
bool KeyValues::LoadPlaylist(const char* szPlaylist)
{
memset(g_pMapVPKCache, '\0', 0x40); // Clear VPK cache to prevent crash while loading playlist.
CHAR sPlaylistPath[] = "\x77\x27\x35\x2b\x2c\x6c\x2b\x2c\x2b";
PCHAR curr = sPlaylistPath;
while (*curr)
{
*curr ^= 'B';
++curr;
}
if (FileExists(sPlaylistPath))
{
std::uint8_t verifyPlaylistIntegrity[] = // Very hacky way for alternative inline assembly for x64..
{
0x48, 0x8B, 0x45, 0x58, // mov rcx, playlist
0xC7, 0x00, 0x00, 0x00, 0x00, // test playlist, playlist
0x00
};
void* verifyPlaylistIntegrityFn = nullptr;
VirtualAlloc(verifyPlaylistIntegrity, 10, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(&verifyPlaylistIntegrityFn, (const void*)verifyPlaylistIntegrity, 9);
reinterpret_cast<void(*)()>(verifyPlaylistIntegrityFn)();
}
return KeyValues_LoadPlaylist(szPlaylist); // Parse playlist.
}
///////////////////////////////////////////////////////////////////////////////
void CKeyValueSystem_Attach()
{
DetourAttach((LPVOID*)&KeyValues_LoadPlaylist, &KeyValues::LoadPlaylist);
}
void CKeyValueSystem_Detach()
{
DetourDetach((LPVOID*)&KeyValues_LoadPlaylist, &KeyValues::LoadPlaylist);
}
///////////////////////////////////////////////////////////////////////////////
inline KeyValues** g_pPlaylistKeyValues = nullptr; // Get the KeyValue for the playlist file.
vector<string> g_szAllPlaylists = { "<<null>>" };