Skip to content
Merged
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
4 changes: 2 additions & 2 deletions docs/cvars.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,8 @@
|sar_portalcolor_mp2_1|255 179 31|Portal color for P-Body (orange)'s left portal.|
|sar_portalcolor_mp2_2|57 2 2|Portal color for P-Body (orange)'s right portal.|
|sar_portalcolor_rainbow|0|Rainbow portals!|
|sar_portalcolor_sp_1|64 160 255|Portal color for Chell's left portal.|
|sar_portalcolor_sp_2|255 160 32|Portal color for Chell's right portal.|
|sar_portalcolor_sp_1|64 160 255|Portal color for Chell's left portal. r_portal_fastpath 0 required.|
|sar_portalcolor_sp_2|255 160 32|Portal color for Chell's right portal. r_portal_fastpath 0 required.|
|sar_portalgun_hud|0|Enables the portalgun HUD.|
|sar_portalgun_hud_x|5|The x position of the portalgun HUD.|
|sar_portalgun_hud_y|5|The y position of the portalgun HUD.|
Expand Down
89 changes: 77 additions & 12 deletions src/Modules/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
#include "Features/FovChanger.hpp"
#include "Features/GroundFramesCounter.hpp"
#include "Features/Hud/InputHud.hpp"
#include "Features/Hud/RhythmGame.hpp"
#include "Features/Hud/ScrollSpeed.hpp"
#include "Features/Hud/StrafeHud.hpp"
#include "Features/Hud/RhythmGame.hpp"
#include "Features/Hud/StrafeQuality.hpp"
#include "Features/NetMessage.hpp"
#include "Features/OverlayRender.hpp"
Expand Down Expand Up @@ -84,8 +84,8 @@ Variable sar_patch_minor_angle_decay("sar_patch_minor_angle_decay", "0", "Patche
Variable sar_unlocked_chapters("sar_unlocked_chapters", "-1", "Max unlocked chapter.\n");

Variable sar_portalcolor_enable("sar_portalcolor_enable", "0", "Enable custom portal colors.\n");
Variable sar_portalcolor_sp_1("sar_portalcolor_sp_1", "64 160 255", "Portal color for Chell's left portal.\n");
Variable sar_portalcolor_sp_2("sar_portalcolor_sp_2", "255 160 32", "Portal color for Chell's right portal.\n");
Variable sar_portalcolor_sp_1("sar_portalcolor_sp_1", "64 160 255", "Portal color for Chell's left portal. r_portal_fastpath 0 required.\n");
Variable sar_portalcolor_sp_2("sar_portalcolor_sp_2", "255 160 32", "Portal color for Chell's right portal. r_portal_fastpath 0 required.\n");
Variable sar_portalcolor_mp1_1("sar_portalcolor_mp1_1", "31 127 210", "Portal color for Atlas (blue)'s left portal.\n");
Variable sar_portalcolor_mp1_2("sar_portalcolor_mp1_2", "19 0 210", "Portal color for Atlas (blue)'s right portal.\n");
Variable sar_portalcolor_mp2_1("sar_portalcolor_mp2_1", "255 179 31", "Portal color for P-Body (orange)'s left portal.\n");
Expand Down Expand Up @@ -124,6 +124,7 @@ REDECL(Client::OnCommand);
REDECL(Client::ApplyMouse_Mid);
REDECL(Client::ApplyMouse_Mid_Continue);
#endif
REDECL(Client::DrawPortal);
REDECL(Client::GetChapterProgress);


Expand Down Expand Up @@ -330,12 +331,44 @@ DETOUR_COMMAND(Client::openleaderboard) {
}
}

Memory::Patch *g_drawPortalPatch;
Memory::Patch *g_drawPortalGhostPatch;
// C_Prop_Portal::DrawPortal
extern Hook g_DrawPortalHook;
DETOUR(Client::DrawPortal, void *pRenderContext) {
if (sar_portalcolor_enable.GetBool()) {
g_drawPortalPatch->Execute();
} else {
g_drawPortalPatch->Restore();
}
g_DrawPortalHook.Disable();
auto ret = Client::DrawPortal(thisptr, pRenderContext);
g_DrawPortalHook.Enable();
return ret;
}
Hook g_DrawPortalHook(&Client::DrawPortal_Hook);

static void (*g_DrawPortalGhost)(void *pRenderContext);

// C_Prop_Portal::DrawPortalGhostLocations
extern Hook g_DrawPortalGhostHook;
static void DrawPortalGhost_Hook(void *pRenderContext) {
if (sar_portalcolor_enable.GetBool()) {
g_drawPortalGhostPatch->Execute();
} else {
g_drawPortalGhostPatch->Restore();
}
g_DrawPortalGhostHook.Disable();
g_DrawPortalGhost(pRenderContext);
g_DrawPortalGhostHook.Enable();
return;
}
Hook g_DrawPortalGhostHook(&DrawPortalGhost_Hook);


static SourceColor (*UTIL_Portal_Color)(int iPortal, int iTeamNumber);
extern Hook UTIL_Portal_Color_Hook;
static SourceColor UTIL_Portal_Color_Detour(int iPortal, int iTeamNumber) {
// FIXME: SP portal rendering does not use this but rather the
// texture's color itself. This does however work on the color
// of the SP *crosshair* and particles.
UTIL_Portal_Color_Hook.Disable();
SourceColor ret = UTIL_Portal_Color(iPortal, iTeamNumber);
UTIL_Portal_Color_Hook.Enable();
Expand Down Expand Up @@ -992,13 +1025,45 @@ bool Client::Init() {

#ifdef _WIN32
auto ApplyMouse_Mid_addr = (uintptr_t)(Client::ApplyMouse) + Offsets::ApplyMouse_Mid;
g_ApplyMouseMidHook.SetFunc(ApplyMouse_Mid_addr);
g_ApplyMouseMidHook.Disable();
g_ApplyMouseMidHook.SetFunc(ApplyMouse_Mid_addr, false);
Client::ApplyMouse_Mid_Continue = ApplyMouse_Mid_addr + 0x5;
#endif
MatrixBuildRotationAboutAxis = (decltype(MatrixBuildRotationAboutAxis))Memory::Scan(client->Name(), Offsets::MatrixBuildRotationAboutAxis);
MatrixBuildRotationAboutAxisHook.SetFunc(MatrixBuildRotationAboutAxis);
MatrixBuildRotationAboutAxisHook.Disable(); // only during ApplyMouse
MatrixBuildRotationAboutAxisHook.SetFunc(MatrixBuildRotationAboutAxis, false); // only during ApplyMouse

auto drawPortalSpBranch = Memory::Scan(client->Name(), Offsets::DrawPortalSpBranch);
auto drawPortalGhostSpBranch = Memory::Scan(client->Name(), Offsets::DrawPortalGhostSpBranch);

Client::DrawPortal = (decltype(Client::DrawPortal))Memory::Scan(client->Name(), Offsets::DrawPortal);
g_DrawPortalGhost = (decltype(g_DrawPortalGhost))Memory::Scan(client->Name(), Offsets::DrawPortalGhost);

g_DrawPortalHook.SetFunc(Client::DrawPortal);
g_DrawPortalGhostHook.SetFunc(g_DrawPortalGhost);

g_drawPortalPatch = new Memory::Patch();
g_drawPortalGhostPatch = new Memory::Patch();

unsigned char drawPortalGhostByte = 0x80;
if (drawPortalSpBranch && drawPortalGhostSpBranch) {
#ifndef _WIN32
unsigned char drawPortalBytes[5];

*(int32_t *)(drawPortalBytes + 1) = *(int32_t *)(drawPortalSpBranch + 2) + Offsets::DrawPortalSpBranchOff;
drawPortalBytes[0] = 0x81;

g_drawPortalPatch->Execute(drawPortalSpBranch + 1, drawPortalBytes, 5);
g_drawPortalGhostPatch->Execute(drawPortalGhostSpBranch + 1, &drawPortalGhostByte, 1);

#else
unsigned char drawPortalBytes[2];

drawPortalBytes[0] = 0xEB;
drawPortalBytes[1] = Offsets::DrawPortalSpBranchOff;

g_drawPortalPatch->Execute(drawPortalSpBranch, drawPortalBytes, 2);
g_drawPortalGhostPatch->Execute(drawPortalGhostSpBranch + 1, &drawPortalGhostByte, 1);
#endif
}

in_forceuser = Variable("in_forceuser");
if (!!in_forceuser && this->g_Input) {
Expand Down Expand Up @@ -1057,8 +1122,8 @@ bool Client::Init() {

g_AddShadowToReceiverHook.SetFunc(Client::AddShadowToReceiver);

UTIL_Portal_Color = (decltype (UTIL_Portal_Color))Memory::Scan(client->Name(), Offsets::UTIL_Portal_Color);
UTIL_Portal_Color_Particles = (decltype (UTIL_Portal_Color_Particles))Memory::Scan(client->Name(), Offsets::UTIL_Portal_Color_Particles);
UTIL_Portal_Color = (decltype(UTIL_Portal_Color))Memory::Scan(client->Name(), Offsets::UTIL_Portal_Color);
UTIL_Portal_Color_Particles = (decltype(UTIL_Portal_Color_Particles))Memory::Scan(client->Name(), Offsets::UTIL_Portal_Color_Particles);
UTIL_Portal_Color_Hook.SetFunc(UTIL_Portal_Color);
UTIL_Portal_Color_Particles_Hook.SetFunc(UTIL_Portal_Color_Particles);

Expand Down
3 changes: 3 additions & 0 deletions src/Modules/Client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ class Client : public Module {
DECL_DETOUR_MID_MH(ApplyMouse_Mid);
#endif

// C_Prop_Portal::DrawPortal
DECL_DETOUR(DrawPortal, void *pRenderContext);

bool Init() override;
void Shutdown() override;
const char *Name() override {
Expand Down
1 change: 1 addition & 0 deletions src/Offsets/INFRA 6905.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ SIGSCAN_WINDOWS(SND_RecordBuffer, "55 8B EC 80 3D ? ? ? ? 00 56")

// Client
SIGSCAN_WINDOWS(DrawTranslucentRenderables, "55 8B EC 81 EC 80 00 00 00 53 56 8B F1")
SIGSCAN_WINDOWS(DrawPortalGhost, "")
SIGSCAN_WINDOWS(DrawOpaqueRenderables, "55 8B EC 83 EC 54 A1 ? ? ? ? 83 7D ? 00")
SIGSCAN_WINDOWS(GetHudSig, "55 8B EC 8B 45 ? 83 F8 FF 75 ? 8B 0D ? ? ? ? 8B 01 8B 90 ? ? ? ? FF D2 69 C0 84 00 00 00") // usage of FindElement -> probably previous function call
SIGSCAN_WINDOWS(FindElementSig, "55 8B EC 53 8B 5D ? 56 57 8B F1 33 FF") // "[%d] Could not find Hud Element: %s\n" xref
Expand Down
8 changes: 8 additions & 0 deletions src/Offsets/Portal 2 5723.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ OFFSET_LINUX(snd_linear_count, 33)
OFFSET_LINUX(snd_p, 72)
OFFSET_LINUX(snd_vol, 80)

// Pathmatch
SIGSCAN_LINUX(PathMatch, "55 89 E5 57 56 53 83 EC ? 0F B6 45 ? 80 3D")

// Client
SIGSCAN_LINUX(DrawPortal, "55 89 E5 83 EC 58 A1 ? ? ? ? 89 5D ? 89 75 ? 8B 5D ? 89 7D ? 8B 75 ? 8B 10")
SIGSCAN_LINUX(DrawPortalSpBranch, "0F 85 ? ? ? ? 0F B6 83 ? ? ? ? 8B 3C 85 ? ? ? ? A1 ? ? ? ? 89 04 24 E8 ? ? ? ? 84 C0 74")
OFFSET_LINUX(DrawPortalSpBranchOff, 0x15)
SIGSCAN_LINUX(DrawPortalGhost, "55 89 E5 57 56 53 83 EC 5C A1 ? ? ? ? 8B 40")
SIGSCAN_LINUX(DrawPortalGhostSpBranch, "0F 84 ? ? ? ? FF 90 ? ? ? ? 80 BB ? ? ? ? 01")
SIGSCAN_LINUX(GetChapterProgress, "55 89 E5 57 56 53 83 EC 2C 8B 7D 08 E8 ? ? ? ? 8B 10 C7")
5 changes: 5 additions & 0 deletions src/Offsets/Portal 2 8151.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ SIGSCAN_LINUX(SND_RecordBuffer, "55 89 E5 57 56 53 83 EC 3C 65 A1 ? ? ? ? 89 45
// Client
SIGSCAN_LINUX(MatrixBuildRotationAboutAxis, "55 89 E5 56 53 8D 45 ? 8D 55 ? 83 EC 20")
SIGSCAN_LINUX(DrawTranslucentRenderables, "55 89 E5 57 56 53 81 EC DC 00 00 00 8B 45 08 8B 5D 0C 89 C7 89 45 84 8B 45 10 89 85 4C FF FF FF")
SIGSCAN_LINUX(DrawPortal, "55 89 E5 57 56 53 83 EC 3C A1 ? ? ? ? 8B 5D ? 8B 10 89 04 24 FF 52 ? A8 02")
SIGSCAN_LINUX(DrawPortalSpBranch, "0F 85 ? ? ? ? 0F B6 83 ? ? ? ? 8B 34 85")
OFFSET_LINUX(DrawPortalSpBranchOff, 0x15)
SIGSCAN_LINUX(DrawPortalGhost, "A1 ? ? ? ? 8B 40 ? 85 C0 74 ? 55 89 E5 57 56 53 83 EC 4C")
SIGSCAN_LINUX(DrawPortalGhostSpBranch, "0F 84 ? ? ? ? 8B 03 89 1C 24 FF 90 ? ? ? ? 80 BB ? ? ? ? 01")
SIGSCAN_LINUX(DrawOpaqueRenderables, "55 89 E5 57 56 53 81 EC 8C 00 00 00 8B 45 0C 8B 5D 08 89 45 8C 8B 45 14 89 45 90 65 A1 14 00 00 00")
SIGSCAN_LINUX(AddShadowToReceiver, "55 89 E5 57 56 53 83 EC ? 8B 45 ? 8B 4D ? 8B 7D ? 89 45 ? 0F B7 C0")
SIGSCAN_LINUX(UTIL_Portal_Color, "55 89 E5 56 53 83 EC 10 8B 75 ? 8B 5D ? 85 F6 0F 84")
Expand Down
13 changes: 11 additions & 2 deletions src/Offsets/Portal 2 8491.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,15 @@ SIGSCAN_DEFAULT(MatrixBuildRotationAboutAxis, "55 8B EC 51 F3 0F 10 45 ? 0F 5A C
"56 66 0F EF C0 53 83 EC 14 8B 5C 24 ? 8D 44 24")
SIGSCAN_DEFAULT(DrawTranslucentRenderables, "55 8B EC 81 EC 80 00 00 00 53 56 8B F1 8B 0D ? ? ? ? 8B 01 8B 90 C4 01 00 00 57 89 75 F0 FF D2 8B F8",
"55 89 E5 57 56 53 81 EC B8 00 00 00 8B 45 10 8B 5D 0C 89 85 60 FF FF FF 88 45 A7 A1 ? ? ? ?")
SIGSCAN_DEFAULT(DrawPortal, "55 8B EC 83 EC 14 53 8B D9 8B 0D ? ? ? ? 8B 01",
"55 57 56 53 83 EC 2C A1 ? ? ? ? 8B 5C 24 ? 8B 74 24 ? 8B 10") // "$PortalColorGradientLight" xref[0] -> C_Prop_Portal::DrawPortal
SIGSCAN_DEFAULT(DrawPortalSpBranch, "8B 15 ? ? ? ? 33 C0 32 C9",
"0F 85 ? ? ? ? 0F B6 83 ? ? ? ? 8B 2C 85")
OFFSET_DEFAULT(DrawPortalSpBranchOff, -14, 0x19)
SIGSCAN_DEFAULT(DrawPortalGhost, "55 8B EC A1 ? ? ? ? 83 EC 24 83 78 ? ? 0F 84 1E 02 00 00 A1 ? ? ? ?",
"A1 ? ? ? ? 8B 40 ? 85 C0 0F 84 ? ? ? ? 55 57") // "Portal Ghosts" xref[1] -> next function call has sig (int *) -> C_Prop_Portal::DrawPortalGhostLocations
SIGSCAN_DEFAULT(DrawPortalGhostSpBranch, "0F 84 ? ? ? ? 8B 90 ? ? ? ? FF D2 50 33 C0 38 86 ? ? ? ? 8D 4D ? 0F 95 C0",
"0F 84 ? ? ? ? 8B 03 83 EC 0C 53 FF 90 ? ? ? ? 83 C4 10 80 BB ? ? ? ? 01")
SIGSCAN_DEFAULT(DrawOpaqueRenderables, "55 8B EC 83 EC 54 83 7D 0C 00 A1 ? ? ? ? 53 56 0F 9F 45 EC 83 78 30 00 57 8B F1 0F 84 BA 03 00 00",
"55 89 E5 57 56 53 83 EC 7C A1 ? ? ? ? 8B 5D 08 89 45 90 85 C0 0F 85 34 04 00 00 A1 ? ? ? ? 8B 40 30 85 C0")
SIGSCAN_DEFAULT(MsgPreSkipToNextLevel, "57 8B F9 E8 ? ? ? ? 8B C8 E8 ? ? ? ? 0B C2",
Expand All @@ -403,9 +412,9 @@ SIGSCAN_DEFAULT(CalcViewModelLag, "53 8B DC 83 EC 08 83 E4 F0 83 C4 04 55 8B 6B
SIGSCAN_DEFAULT(AddShadowToReceiver, "55 8B EC 51 53 56 57 0F B7 7D 08",
"55 89 E5 57 56 53 83 EC 44 8B 45 0C 8B 5D 08 8B 55 14 8B 75 10")
SIGSCAN_DEFAULT(UTIL_Portal_Color, "55 8B EC 56 8B 75 ? 85 F6 0F 84 ? ? ? ? 0F 8E",
"56 53 83 EC 04 8B 44 24 ? 8B 74 24 ? 85 C0 74 ? 8D 58")
"56 53 83 EC 04 8B 44 24 ? 8B 74 24 ? 85 C0 74 ? 8D 58")
SIGSCAN_DEFAULT(UTIL_Portal_Color_Particles, "55 8B EC 51 8B 0D ? ? ? ? 8B 01 8B 90 ? ? ? ? FF D2 84 C0",
"53 83 EC 14 A1 ? ? ? ? 8B 5C 24 ? 8B 10 50 FF 92 ? ? ? ? 83 C4 10 84 C0 75")
"53 83 EC 14 A1 ? ? ? ? 8B 5C 24 ? 8B 10 50 FF 92 ? ? ? ? 83 C4 10 84 C0 75")
SIGSCAN_DEFAULT(GetNumChapters, "55 8B EC 80 7D 08 00 57 74 0C",
"55 89 E5 56 80 7D")
SIGSCAN_DEFAULT(CPortalLeaderboardPanel_OnThink, "55 8B EC A1 ? ? ? ? 81 EC ? ? ? ? 53 56 32 DB",
Expand Down
71 changes: 61 additions & 10 deletions src/Utils/Memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,19 +231,49 @@ std::vector<std::vector<uintptr_t>> Memory::MultiScan(const char *moduleName, co
return results;
}

#ifdef _WIN32
Memory::Patch::~Patch() {
if (this->original) {
this->Restore();
delete this->original;
delete[] this->original;
this->original = nullptr;
}
if (this->patch) {
delete[] this->patch;
this->patch = nullptr;
}
this->isPatched = false;
}
bool Memory::Patch::Execute() {
if (this->isPatched) return true; // already executed
unsigned char *tmpPatch = new unsigned char[this->size];
// We create another patch, because this->patch is gonna be deleted
memcpy(tmpPatch, this->patch, this->size);
auto ret = this->Execute(this->location, tmpPatch, this->size);
delete[] tmpPatch;
return ret;
}

bool Memory::Patch::Execute(uintptr_t location, unsigned char *bytes, size_t size) {
if (this->isPatched) return true; // already executed
this->location = location;
this->size = size;
if (this->original) {
delete[] this->original;
this->original = nullptr;
}
this->original = new unsigned char[this->size];

if (!bytes) {
return false;
}
if (this->patch) {
delete[] this->patch;
this->patch = nullptr;
}
this->patch = new unsigned char[this->size];
memcpy(this->patch, bytes, size);

#ifdef _WIN32
for (size_t i = 0; i < this->size; ++i) {
if (!ReadProcessMemory(GetCurrentProcess(), reinterpret_cast<LPVOID>(this->location + i), &this->original[i], 1, 0)) {
return false;
Expand All @@ -255,17 +285,38 @@ bool Memory::Patch::Execute(uintptr_t location, unsigned char *bytes, size_t siz
return false;
}
}
#else
Memory::UnProtect(reinterpret_cast<void *>(this->location), this->size);
for (size_t i = 0; i < this->size; ++i) {
this->original[i] = *(uint8_t *)(this->location + i);
*(uint8_t *)(this->location + i) = bytes[i];
}
#endif
this->isPatched = true;
return true;
}
bool Memory::Patch::Restore() {
if (this->location && this->original) {
for (size_t i = 0; i < this->size; ++i) {
if (!WriteProcessMemory(GetCurrentProcess(), reinterpret_cast<LPVOID>(this->location + i), &this->original[i], 1, 0)) {
return false;
}
if (!this->location || !this->original) {
return false;
}
if (!this->isPatched) return true; // already restored
#ifdef _WIN32
for (size_t i = 0; i < this->size; ++i) {
if (!WriteProcessMemory(GetCurrentProcess(), reinterpret_cast<LPVOID>(this->location + i), &this->original[i], 1, 0)) {
return false;
}
return true;
}
return false;
}
#else
// Should be already unprotected, but just in case
Memory::UnProtect(reinterpret_cast<void *>(this->location), this->size);
for (size_t i = 0; i < this->size; ++i) {
*(uint8_t *)(this->location + i) = this->original[i];
}
#endif
this->isPatched = false;
return true;
}

bool Memory::Patch::IsPatched() {
return this->isPatched;
}
6 changes: 4 additions & 2 deletions src/Utils/Memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,25 @@ namespace Memory {
uintptr_t Scan(const char *moduleName, const char *pattern, int offset = 0);
std::vector<uintptr_t> MultiScan(const char *moduleName, const char *pattern, int offset = 0);

#ifdef _WIN32
class Patch {
private:
uintptr_t location;
unsigned char *original;
unsigned char *patch;
size_t size;
bool isPatched;

public:
~Patch();
bool Execute();
bool Execute(uintptr_t location, unsigned char *bytes, size_t size);
template <size_t size>
bool Execute(uintptr_t location, unsigned char (&bytes)[size]) {
return Execute(location, bytes, size);
}
bool Restore();
bool IsPatched();
};
#endif

struct Pattern {
const char *signature;
Expand Down