Various Preload improvements (down to 600mb per catbot!)

This commit is contained in:
BenCat07 2019-08-22 19:09:56 +02:00
parent dc2ed5aca9
commit b80c983ecf
8 changed files with 98 additions and 14 deletions

View File

@ -96,3 +96,4 @@ extern IFileSystem *g_IFileSystem;
extern IMDLCache *g_IMDLCache;
void CreateInterfaces();
void CreateEarlyInterfaces();

View File

@ -54,5 +54,6 @@ SharedObject &studiorender();
SharedObject &libsdl();
#endif
void LoadEarlyObjects();
void LoadAllSharedObjects();
} // namespace sharedobj

View File

@ -10,9 +10,16 @@
#include <stack>
std::stack<void (*)()> &init_stack();
std::stack<void (*)()> &init_stack_early();
class InitRoutine
{
public:
InitRoutine(void (*func)());
};
class InitRoutineEarly
{
public:
InitRoutineEarly(void (*func)());
};

View File

@ -17,3 +17,14 @@ InitRoutine::InitRoutine(void (*func)())
{
init_stack().push(func);
}
std::stack<void (*)()> &init_stack_early()
{
static std::stack<void (*)()> stack{};
return stack;
}
InitRoutineEarly::InitRoutineEarly(void (*func)())
{
init_stack_early().push(func);
}

View File

@ -84,6 +84,11 @@ template <typename T> T *BruteforceInterface(std::string name, sharedobj::Shared
extern "C" typedef HSteamPipe (*GetHSteamPipe_t)();
extern "C" typedef HSteamUser (*GetHSteamUser_t)();
void CreateEarlyInterfaces()
{
g_IFileSystem = BruteforceInterface<IFileSystem>("VFileSystem", sharedobj::filesystem_stdio());
}
void CreateInterfaces()
{
g_ICvar = BruteforceInterface<ICvar>("VEngineCvar", sharedobj::vstdlib());
@ -141,8 +146,7 @@ void CreateInterfaces()
g_IModelInfo = BruteforceInterface<IVModelInfoClient>("VModelInfoClient", sharedobj::engine());
g_IBaseClientState = *(reinterpret_cast<CBaseClientState **>(gSignatures.GetEngineSignature("C7 04 24 ? ? ? ? E8 ? ? ? ? C7 04 24 ? ? ? ? 89 44 24 04 E8 ? ? ? ? A1 ? ? ? ?") + 3));
logging::Info("BaseClientState: 0x%08x", g_IBaseClientState);
while (!g_IAchievementMgr)
g_IAchievementMgr = g_IEngine->GetAchievementMgr();
g_IAchievementMgr = g_IEngine->GetAchievementMgr();
g_ISteamUserStats = g_ISteamClient->GetISteamUserStats(su, sp, "STEAMUSERSTATS_INTERFACE_VERSION011");
IF_GAME(IsTF2())
{
@ -153,7 +157,6 @@ void CreateInterfaces()
g_pGameRules = *reinterpret_cast<CGameRules **>(g_pGameRules_sig + 8);
}
g_IMaterialSystem = BruteforceInterface<IMaterialSystemFixed>("VMaterialSystem", sharedobj::materialsystem());
g_IFileSystem = BruteforceInterface<IFileSystem>("VFileSystem", sharedobj::filesystem_stdio());
g_IMDLCache = BruteforceInterface<IMDLCache>("MDLCache", sharedobj::datacache());
g_IPanel = BruteforceInterface<vgui::IPanel>("VGUI_Panel", sharedobj::vgui2());

View File

@ -84,19 +84,30 @@ void *SharedObject::CreateInterface(const std::string &interface)
return (void *) (fptr(interface.c_str(), nullptr));
}
void LoadEarlyObjects()
{
try
{
engine().Load();
filesystem_stdio().Load();
tier0().Load();
materialsystem().Load();
}
catch (std::exception &ex)
{
logging::Info("Exception: %s", ex.what());
}
}
void LoadAllSharedObjects()
{
try
{
steamclient().Load();
client().Load();
engine().Load();
steamapi().Load();
vstdlib().Load();
tier0().Load();
inputsystem().Load();
materialsystem().Load();
filesystem_stdio().Load();
datacache().Load();
vgui2().Load();
#if ENABLE_VISUALS

View File

@ -301,10 +301,12 @@ static bool FSHook_Precache(const char *pFileName, const char *pPathID)
static CatCommand debug_invalidate("invalidate_mdl_cache", "Invalidates MDL cache", []() { g_IBaseClient->InvalidateMdlCache(); });
static hooks::VMTHook fs_hook, fs_hook2;
static hooks::VMTHook fs_hook{}, fs_hook2{};
static void ReduceRamUsage()
{
if (fs_hook.IsHooked(reinterpret_cast<void *>(g_IFileSystem)))
return;
/* TO DO: Improves load speeds but doesn't reduce memory usage a lot
* It seems engine still allocates significant parts without them
* being really used
@ -329,7 +331,11 @@ static void ReduceRamUsage()
* spam related to mdl not being able to play sequence that it
* cannot play on error.mdl
*/
static BytePatch playSequence{ gSignatures.GetClientSignature, "55 89 E5 57 56 53 83 EC ? 8B 75 0C 8B 5D 08 85 F6 74 ? 83 BB", 0x00, { 0xC3 } };
if (g_IBaseClient)
{
static BytePatch playSequence{ gSignatures.GetClientSignature, "55 89 E5 57 56 53 83 EC ? 8B 75 0C 8B 5D 08 85 F6 74 ? 83 BB", 0x00, { 0xC3 } };
playSequence.Patch();
}
#if 0
/* Same explanation as above, but spams about certain particles not loaded */
static BytePatch particleCreate{ gSignatures.GetClientSignature,
@ -348,15 +354,28 @@ static void ReduceRamUsage()
particlePrecache.Patch();
particleCreating.Patch();
#endif
playSequence.Patch();
}
static void UnHookFs()
{
fs_hook.Release();
fs_hook2.Release();
g_IBaseClient->InvalidateMdlCache();
if (g_IBaseClient)
g_IBaseClient->InvalidateMdlCache();
}
#if !ENABLE_VISUALS
static InitRoutineEarly nullify_textmode([]() {
ReduceRamUsage();
static auto addr1 = e8call_direct(gSignatures.GetEngineSignature("E8 ? ? ? ? 8B 93 ? ? ? ? 85 D2 0F 84 ? ? ? ?")) + 0x18;
static auto addr2 = sharedobj::materialsystem().Pointer(0x3EC08);
static BytePatch patch1(addr1, { 0x81, 0xC4, 0x6C, 0x20, 0x00, 0x00, 0x5B, 0x5E, 0x5F, 0x5D, 0xC3 });
static BytePatch patch2(addr2, { 0x83, 0xC4, 0x50, 0x5B, 0x5E, 0x5D, 0xC3 });
patch1.Patch();
patch2.Patch();
});
#endif
static void InitRandom()
{
@ -413,15 +432,24 @@ free(logname);*/
#endif /* TEXTMODE */
logging::Info("Initializing...");
InitRandom();
sharedobj::LoadAllSharedObjects();
CreateInterfaces();
CDumper dumper;
sharedobj::LoadEarlyObjects();
CreateEarlyInterfaces();
logging::Info("Clearing Early initializer stack");
null_graphics.installChangeCallback([](settings::VariableBase<bool> &, bool after) {
if (after)
ReduceRamUsage();
else
UnHookFs();
});
while (!init_stack_early().empty())
{
init_stack_early().top()();
init_stack_early().pop();
}
logging::Info("Early Initializer stack done");
sharedobj::LoadAllSharedObjects();
CreateInterfaces();
CDumper dumper;
dumper.SaveDump();
logging::Info("Is TF2? %d", IsTF2());
logging::Info("Is TF2C? %d", IsTF2C());

View File

@ -35,8 +35,20 @@ static settings::Int equip_secondary{ "achievement.equip-secondary", "0" };
static settings::Int equip_melee{ "achievement.equip-melee", "0" };
static settings::Int equip_pda2{ "achievement.equip-pda2", "0" };
bool checkachmngr()
{
if (!g_IAchievementMgr)
{
g_IAchievementMgr = g_IEngine->GetAchievementMgr();
if (!g_IAchievementMgr)
return false;
}
return true;
}
void Lock()
{
if (!checkachmngr())
return;
if (safety)
{
ConColorMsg({ 255, 0, 0, 255 }, "Switch `cat set achievement.safety` to false before using any achievement commands!\n");
@ -53,6 +65,8 @@ void Lock()
void Unlock()
{
if (!checkachmngr())
return;
/*auto Invmng = re::CTFInventoryManager::GTFInventoryManager();
auto Inv = re::CTFPlayerInventory::GTFPlayerInventory();
auto Item = Inv->GetFirstItemOfItemDef(59);
@ -70,6 +84,8 @@ void Unlock()
}
CatCommand dump_achievement("achievement_dump", "Dump achievements to file (development)", []() {
if (!checkachmngr())
return;
std::ofstream out("/tmp/cathook_achievements.txt", std::ios::out);
if (out.bad())
return;
@ -80,6 +96,8 @@ CatCommand dump_achievement("achievement_dump", "Dump achievements to file (deve
out.close();
});
CatCommand unlock_single("achievement_unlock_single", "Unlocks single achievement by ID", [](const CCommand &args) {
if (!checkachmngr())
return;
char *out = nullptr;
int id = strtol(args.Arg(1), &out, 10);
if (out == args.Arg(1))
@ -95,6 +113,8 @@ CatCommand unlock_single("achievement_unlock_single", "Unlocks single achievemen
});
// For some reason it SEGV's when I try to GetAchievementByID();
CatCommand lock_single("achievement_lock_single", "Locks single achievement by INDEX!", [](const CCommand &args) {
if (!checkachmngr())
return;
if (args.ArgC() < 1)
{
logging::Info("Actually provide an index");
@ -143,6 +163,8 @@ std::vector<Autoequip_unlock_list> equip_queue;
void unlock_achievements_and_accept(std::vector<int> items)
{
if (!checkachmngr())
return;
for (auto id : items)
{
IAchievement *ach = reinterpret_cast<IAchievement *>(g_IAchievementMgr->GetAchievementByID(id));