#include "core/stdafx.h" #include "vpc/keyvalues.h" #include "rtech/stryder.h" #include "engine/sys_dll2.h" /////////////////////////////////////////////////////////////////////////////// std::vector g_szAllPlaylists = { "none" }; CKeyValuesSystem* g_pKeyValuesSystem = reinterpret_cast(p_KeyValues_Init.FindPatternSelf("48 8D ?? ?? ?? ?? 01", ADDRESS::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr()); #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) KeyValues** g_pPlaylistKeyValues = reinterpret_cast(p_Stryder_StitchRequest.FindPatternSelf("48 8B 2D", ADDRESS::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr()); // Get the KeyValue for the playlist file. #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) KeyValues** g_pPlaylistKeyValues = reinterpret_cast(p_Stryder_StitchRequest.FindPatternSelf("48 8B 0D", ADDRESS::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr()); // Get the KeyValue for the playlist file. #endif //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CKeyValueSystem_InitPlaylist() { while (true) { if ((*g_pPlaylistKeyValues)) { KeyValues* playlists = (*g_pPlaylistKeyValues)->FindKey("Playlists", false); // Find playlists key. 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: //----------------------------------------------------------------------------- bool HKeyValues_LoadPlaylist(const char* playlist) { 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(verifyPlaylistIntegrityFn)(); } return KeyValues_LoadPlaylist(playlist); // Parse playlist. } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const char* KeyValues::GetName() { return g_pKeyValuesSystem->GetStringForSymbol(MAKE_3_BYTES_FROM_1_AND_2(m_iKeyNameCaseSensitive, m_iKeyNameCaseSensitive2)); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CKeyValueSystem_Init() { std::thread t1(CKeyValueSystem_InitPlaylist); // Start thread to grab playlists. t1.detach(); // Detach thread from current one. } /////////////////////////////////////////////////////////////////////////////// void CKeyValueSystem_Attach() { DetourAttach((LPVOID*)&KeyValues_LoadPlaylist, &HKeyValues_LoadPlaylist); } void CKeyValueSystem_Detach() { DetourDetach((LPVOID*)&KeyValues_LoadPlaylist, &HKeyValues_LoadPlaylist); }