Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions TextmodeTF2/TextmodeTF2.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@
<ClCompile Include="src\Hooks\CDebugOverlay_AddBoxOverlay.cpp" />
<ClCompile Include="src\Hooks\CDebugOverlay_AddLineOverlay.cpp" />
<ClCompile Include="src\Hooks\CEngineSoundClient_EmitSoundInternal.cpp" />
<ClCompile Include="src\Hooks\IBaseClientDLL_FrameStageNotify.cpp" />
<ClCompile Include="src\Hooks\IPanel_PaintTraverse.cpp" />
<ClCompile Include="src\Hooks\CModelLoader_GetModelForName.cpp" />
<ClCompile Include="src\Hooks\CModelRender_DrawModelExecute.cpp" />
Expand Down Expand Up @@ -295,4 +294,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>
33 changes: 0 additions & 33 deletions TextmodeTF2/src/BytePatches/BytePatches.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,45 +57,12 @@ class CBytePatches
// We patch the 'jnb' (73) to 'jmp' (EB) to skip the 30fps clamp
BytePatch("engine.dll", "F3 0F 10 40 54 0F 2F 05 ?? ?? ?? ?? 73 ??", 0xC, "EB"),

// SCR_UpdateScreen
BytePatch("engine.dll", "40 55 41 54 41 56 41 57 48 8D 6C 24 ? 48 81 EC 88 00 00 00 48 8B 05 ? ? ? ? 45 33 E4 4C 89 65 ? 45 8B FC", 0x0, "31 C0 C3"),

// CEngineVGui::Simulate
BytePatch("engine.dll", "41 57 48 81 EC A0 00 00 00 4C 8B F9 48 8B 0D ? ? ? ? 48 8B 01 FF 90 20 01 00 00 49 83 BF B8 00 00 00 00", 0x0, "31 C0 C3"),

// CL_DecayLights
BytePatch("engine.dll", "48 83 EC 48 0F 29 74 24 30 48 8D 0D ? ? ? ? 0F 29 7C 24 20 E8 ? ? ? ? 0F 28 F8 0F 57 F6 0F 2F FE 0F 86 ? ? ? ?", 0x0, "C3"),

// _Host_RunFrame -> _Host_RunFrame_Render callsite
BytePatch("engine.dll", "45 84 E4 0F 84 ? ? ? ? E8 ? ? ? ? 48 8B 05 ? ? ? ? 4C 8D 25 ? ? ? ? 4C 89 7D ? 48 8D 15", 0x9, "90 90 90 90 90"),

// _Host_RunFrame_Sound callsite
BytePatch("engine.dll", "83 3D ? ? ? ? 06 F2 0F 11 05 ? ? ? ? 75 09 48 8D 0D ? ? ? ? EB 02 33 C9 E8 ? ? ? ? FF 15 ? ? ? ? F2 0F 10 0D", 0x1C, "90 90 90 90 90"),

// _Host_RunFrame_Client voice gate callsite
BytePatch("engine.dll", "F3 0F 10 05 ? ? ? ? E8 ? ? ? ? E8 ? ? ? ? 84 C0 0F 84 ? ? ? ? 0F 57 C0 C6 44 24 ? 01", 0xD, "31 C0 90 90 90"),

// _Host_RunFrame_Input -> ClientDLL_ProcessInput callsite
BytePatch("engine.dll", "FF 15 ? ? ? ? F2 0F 11 05 ? ? ? ? E8 ? ? ? ? FF 15 ? ? ? ? F2 0F 11 05 ? ? ? ? E8 ? ? ? ?", 0xE, "90 90 90 90 90"),

// _Host_RunFrame non-threaded path -> CL_RunPrediction(PREDICTION_NORMAL)
BytePatch("engine.dll", "48 8B 01 FF 50 18 B9 01 00 00 00 E8 ? ? ? ? E8 ? ? ? ? F3 0F 10 05 ? ? ? ? E8 ? ? ? ? 48 85 F6 74 ? 45 33 C9", 0xB, "90 90 90 90 90"),

// _Host_RunFrame threaded path -> CL_RunPrediction(PREDICTION_NORMAL)
BytePatch("engine.dll", "B9 01 00 00 00 F3 0F 10 05 ? ? ? ? F3 0F 5E 05 ? ? ? ? F3 0F 11 05 ? ? ? ? E8 ? ? ? ? E8 ? ? ? ? 48 8D 0D ? ? ? ? C6 05", 0x1D, "90 90 90 90 90"),

// _Host_RunFrame non-threaded path -> CL_ExtraMouseUpdate
BytePatch("engine.dll", "F3 0F 10 05 ? ? ? ? E8 ? ? ? ? 48 85 F6 74 ? 45 33 C9 44 89 7C 24 20 45 33 C0 48 8B D3 48 8B CE FF 96 A8 00 00 00", 0x8, "90 90 90 90 90"),

// _Host_RunFrame threaded path -> CL_ExtraMouseUpdate
BytePatch("engine.dll", "E8 ? ? ? ? F3 0F 11 05 ? ? ? ? E8 ? ? ? ? F2 0F 10 05 ? ? ? ? 66 0F 5A C0 44 89 35 ? ? ? ? 89 35 ? ? ? ? F3 0F 11 05", 0xD, "90 90 90 90 90"),

// _Host_RunFrame fallback sleep path
BytePatch("engine.dll", "48 8B 05 ? ? ? ? 8B 48 58 E8 ? ? ? ? 8B 0D ? ? ? ? 85 C9 74 05 E8 ? ? ? ? E8", 0xF, "B9 01 00 00 00 90"),

// _Host_RunFrame tick loop -> toolframework->Think callsite
BytePatch("engine.dll", "40 38 3D ? ? ? ? 75 08 0F B6 CB E8 ? ? ? ? 48 8B 0D ? ? ? ? 0F B6 D3 48 8B 01 FF 90 D8 00 00 00 F2 0F 10 0D ? ? ? ?", 0x1E, "90 90 90 90 90 90"),

// evil cathook's plan b implementation

// Mod_LoadLighting
Expand Down
23 changes: 3 additions & 20 deletions TextmodeTF2/src/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,6 @@ int CCore::LoadClient()
if (!U::BytePatches.Initialize("client"))
return LOAD_WAIT;

// IBaseClientDLL::FrameStageNotify
if (!G::IBaseClientDLL_FrameStageNotifyAddr)
{
if (auto pClient = U::Memory.FindInterface("client.dll", "VClient017"))
G::IBaseClientDLL_FrameStageNotifyAddr = reinterpret_cast<uintptr_t>(U::Memory.GetVFunc(pClient, 35));
}
if (G::IBaseClientDLL_FrameStageNotifyAddr)
U::Hooks.Initialize("IBaseClientDLL_FrameStageNotify");

// IPanel::PaintTraverse
if (!G::IPanel_PaintTraverseAddr)
{
Expand Down Expand Up @@ -391,6 +382,9 @@ void CCore::Load()

int iVPhysics = m_bVPhysicsLoaded ? 1 : LoadVPhysics();
CHECK(iVPhysics, "Failed to load vphysics")

if (!m_bFilesystemLoaded || !m_bEngineLoaded || !m_bMatSysLoaded || !m_bClientLoaded || !m_bGameUILoaded || !m_bParticlesLoaded || !m_bMDLCacheLoaded || !m_bVideoServicesLoaded || !m_bVPhysicsLoaded)
Sleep(10);
}
while (!m_bFilesystemLoaded || !m_bEngineLoaded || !m_bMatSysLoaded || !m_bClientLoaded || !m_bGameUILoaded || !m_bParticlesLoaded || !m_bMDLCacheLoaded || !m_bVideoServicesLoaded || !m_bVPhysicsLoaded);

Expand All @@ -401,17 +395,6 @@ void CCore::Load()

}

void CCore::Loop()
{
while (true)
{
if (m_bUnload)
break;

Sleep(3600000);
}
}

void CCore::Unload()
{
U::Hooks.Unload();
Expand Down
1 change: 0 additions & 1 deletion TextmodeTF2/src/Core/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class CCore
{
public:
void Load();
void Loop();
void Unload();

void AppendFailText(const char* sMessage, bool bCritical = false);
Expand Down
16 changes: 11 additions & 5 deletions TextmodeTF2/src/DllMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,27 @@ DWORD WINAPI MainThread(LPVOID lpParam)
{
CrashLog::Initialize(lpParam);
U::Core.Load();
U::Core.Loop();
CrashLog::Unload();
U::Core.Unload();

FreeLibraryAndExitThread(static_cast<HMODULE>(lpParam), EXIT_SUCCESS);
if (U::Core.m_bUnload)
{
CrashLog::Unload();
U::Core.Unload();
FreeLibraryAndExitThread(static_cast<HMODULE>(lpParam), EXIT_SUCCESS);
}

return EXIT_SUCCESS;
}


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hinstDLL);

if (const auto hMainThread = CreateThread(nullptr, 0, MainThread, hinstDLL, 0, nullptr))
CloseHandle(hMainThread);
}

return TRUE;
}
}
11 changes: 0 additions & 11 deletions TextmodeTF2/src/Hooks/IBaseClientDLL_FrameStageNotify.cpp

This file was deleted.

3 changes: 1 addition & 2 deletions TextmodeTF2/src/SDK/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ namespace G
inline uintptr_t SVC_GameEvent_ProcessAddr{};
inline uintptr_t SVC_Sounds_ProcessAddr{};
inline uintptr_t SVC_BSPDecal_ProcessAddr{};
inline uintptr_t IBaseClientDLL_FrameStageNotifyAddr{};
inline uintptr_t IPanel_PaintTraverseAddr{};
inline uintptr_t IStudioRender_DrawModelAddr{};
inline uintptr_t IStudioRender_DrawModelStaticPropAddr{};
Expand All @@ -47,4 +46,4 @@ inline uintptr_t SVC_BSPDecal_ProcessAddr{};
inline uintptr_t IStudioRender_AddShadowAddr{};
inline uintptr_t IStudioRender_DrawModelArrayAddr{};
inline IMDLCache* IMDLCache{};
};
};
77 changes: 34 additions & 43 deletions TextmodeTF2/src/SDK/SDK.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "SDK.h"
#include <string_view>
#include <unordered_set>

void SDK::Output(const char* cFunction, const char* cLog, bool bLogFile, int iMessageBox)
{
Expand Down Expand Up @@ -76,106 +78,95 @@ void SDK::OutputFile(const char* cOutputFileName, const char* cMsg)

bool SDK::BlacklistFile(const char* cFileName)
{
const static char* blacklist[] = {
".ani", ".wav", ".mp3", ".vvd", ".vtx", ".vtf", ".vfe", ".cache",
".jpg", ".png", ".tga", ".dds", ".vmt", // Texture and material files
".phy", // Physics
".dem", // Demo and log files
".vcd", // Scene files
".ain", // AI node graph
".lst", // Manifests
".pcf" // Particle systems
};

if (!cFileName)
return false;

if (!std::strncmp(cFileName, "materials/console/", 18))
return false;
using namespace std::literals;

if (!std::strncmp(cFileName, "debug/", 6))
return false;
static const std::unordered_set<std::string_view> blacklist{
".ani"sv, ".wav"sv, ".mp3"sv, ".vvd"sv, ".vtx"sv, ".vtf"sv, ".vfe"sv, ".cache"sv,
".jpg"sv, ".png"sv, ".tga"sv, ".dds"sv, ".vmt"sv,
".phy"sv, ".dem"sv, ".vcd"sv, ".ain"sv, ".lst"sv, ".pcf"sv
};

if (!std::strncmp(cFileName, "sprites/", 8))
return true;
const std::string_view fileName{ cFileName };

std::size_t len = std::strlen(cFileName);
if (len <= 3)
if (fileName.starts_with("materials/console/"sv) || fileName.starts_with("debug/"sv))
return false;

auto ext_p = strrchr(cFileName, '.');
if (!ext_p)
if (fileName.starts_with("sprites/"sv))
return true;

const auto dot = fileName.rfind('.');
if (dot == std::string_view::npos)
return false;
const auto ext = fileName.substr(dot);

// NEVER block .bsp files - they are essential for map loading
if (!std::strcmp(ext_p, ".bsp"))
if (ext == ".bsp"sv)
return false;

// NEVER block .nav files - navengine needs it obviosuly lol
if (!std::strcmp(ext_p, ".nav"))
if (ext == ".nav"sv)
return false;

// Block all particle effects during map load
if (!std::strcmp(ext_p, ".pcf"))
if (ext == ".pcf"sv)
return true;

// Block all soundscapes during map load
if (std::strstr(cFileName, "soundscape") && std::strcmp(ext_p, ".txt"))
if (fileName.find("soundscape"sv) != std::string_view::npos && ext != ".txt"sv)
return true;

// Block detail sprites and props
if (std::strstr(cFileName, "detail") || std::strstr(cFileName, "props_"))
if (fileName.find("detail"sv) != std::string_view::npos || fileName.find("props_"sv) != std::string_view::npos)
return true;

// Block skybox materials during map load
if (std::strstr(cFileName, "skybox"))
if (fileName.find("skybox"sv) != std::string_view::npos)
return true;

// Block all ambient sounds
if (std::strstr(cFileName, "ambient"))
if (fileName.find("ambient"sv) != std::string_view::npos)
return true;

// Block models that aren't players or essential gameplay items
if (!std::strcmp(ext_p, ".mdl"))
if (ext == ".mdl"sv)
{
if (std::strstr(cFileName, "player/") || std::strstr(cFileName, "buildables/") || std::strstr(cFileName, "weapons/") || std::strstr(cFileName, "empty.mdl") || std::strstr(cFileName, "error.mdl"))
if (fileName.find("player/"sv) != std::string_view::npos || fileName.find("buildables/"sv) != std::string_view::npos || fileName.find("weapons/"sv) != std::string_view::npos || fileName.find("empty.mdl"sv) != std::string_view::npos || fileName.find("error.mdl"sv) != std::string_view::npos)
return false;

return true;
}

if (!std::strcmp(ext_p, ".vmt"))
if (ext == ".vmt"sv)
{
// Only allow essential UI materials
if (!std::strstr(cFileName, "hud") && !std::strstr(cFileName, "vgui") && !std::strstr(cFileName, "console"))
if (fileName.find("hud"sv) == std::string_view::npos && fileName.find("vgui"sv) == std::string_view::npos && fileName.find("console"sv) == std::string_view::npos)
return true;

/* Not loading it causes extreme console spam */
if (std::strstr(cFileName, "corner"))
if (fileName.find("corner"sv) != std::string_view::npos)
return false;
/* minor console spam */
if (std::strstr(cFileName, "hud") || std::strstr(cFileName, "vgui"))
if (fileName.find("hud"sv) != std::string_view::npos || fileName.find("vgui"sv) != std::string_view::npos)
return false;

return true;
}

if (std::strstr(cFileName, "sound.cache") || std::strstr(cFileName, "tf2_sound") || std::strstr(cFileName, "game_sounds"))
if (fileName.find("sound.cache"sv) != std::string_view::npos || fileName.find("tf2_sound"sv) != std::string_view::npos || fileName.find("game_sounds"sv) != std::string_view::npos)
return false;
if (!std::strncmp(cFileName, "sound/player/footsteps", 22))
if (fileName.starts_with("sound/player/footsteps"sv))
return false;
if (!std::strncmp(cFileName, "/decal", 6))
if (fileName.starts_with("/decal"sv))
return true;

for (int i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); ++i)
if (!std::strcmp(ext_p, blacklist[i]))
return true;

return false;
return blacklist.contains(ext);
}

double SDK::PlatFloatTime()
{
static auto Plat_FloatTime = U::Memory.GetModuleExport<double(*)()>("tier0.dll", "Plat_FloatTime");
return Plat_FloatTime();
}
}