Skip to content

Commit 3734d36

Browse files
committed
fix: linux, use patch class
complete redesign of how the command works lol idk what/how to test this so lmk if i broke it
1 parent d7bd24e commit 3734d36

7 files changed

Lines changed: 50 additions & 49 deletions

File tree

docs/cvars.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@
262262
|sar_hud_ghost_spec|0|Show the name of the ghost you're currently spectating.|
263263
|sar_hud_grounded|0|Draws the state of player being on ground.|
264264
|sar_hud_groundframes|0|Draws the number of ground frames since last landing. Setting it to 2 preserves the value.|
265-
|sar_hud_groundspeed|0|Draw the speed of the player upon leaving the ground.<br>0 = Default,<br>1 = Groundspeed,<br>2 = Groundspeed (Gain)|
265+
|sar_hud_groundspeed|0|Draw the speed of the player upon leaving the ground.<br>0 = Default<br>1 = Groundspeed<br>2 = Groundspeed (Gain)|
266266
|sar_hud_hide_text|cmd|sar_hud_hide_text \<id\|all> - hides the nth text value in the HUD|
267267
|sar_hud_inspection|0|Draws entity inspection data.|
268268
|sar_hud_jump|0|Draws current jump distance.|
@@ -503,6 +503,7 @@
503503
|sar_scrollspeed_y|210|Scroll speed HUD y offset.|
504504
|sar_seamshot_finder|0|Enables or disables seamshot finder overlay.|
505505
|sar_session|cmd|sar_session - prints the current tick of the server since it has loaded|
506+
|sar_set_promo_items_state|cmd|sar_set_promo_items_state \<off\|all\|skins\|helmet\|antenna>... - enables coop promotional items on spawn.|
506507
|sar_show_entinp|0|Print all entity inputs to console.|
507508
|sar_skiptodemo|cmd|sar_skiptodemo \<demoname> - skip demos in demo queue to this demo|
508509
|sar_speedrun_autoreset_clear|cmd|sar_speedrun_autoreset_clear - stop using the autoreset file|

src/Cheats.cpp

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ Variable mm_session_sys_delay_create_host;
6565
Variable hide_gun_when_holding;
6666
Variable r_flashlightbrightness;
6767

68-
int origPortal2PromoFlagsValue;
69-
int *g_nPortal2PromoFlags = nullptr;
70-
7168
// TSP only
7269
void IN_BhopDown(const CCommand& args) {
7370
if (!client->KeyDown || !client->in_jump) return;
@@ -334,6 +331,7 @@ Memory::Patch *g_floorReportalPatch;
334331
Memory::Patch *g_coopLoadingDotsPatch;
335332
Memory::Patch *g_autoGrabPatchServer;
336333
Memory::Patch *g_autoGrabPatchClient;
334+
Memory::Patch *g_promoFlagsPatch;
337335

338336
void Cheats::Init() {
339337
sv_laser_cube_autoaim = Variable("sv_laser_cube_autoaim");
@@ -402,7 +400,13 @@ void Cheats::Init() {
402400
g_autoGrabPatchClient->Restore();
403401
}
404402

405-
g_nPortal2PromoFlags = *reinterpret_cast<int **>(Memory::Scan(MODULE("server"), Offsets::Portal2PromoFlags_ADDR, 2)); // Note: Has to be active before map loads.
403+
g_promoFlagsPatch = new Memory::Patch();
404+
auto portal2PromoFlags = Memory::Scan(MODULE("server"), Offsets::Portal2PromoFlagsSig, Offsets::Portal2PromoFlagsOff);
405+
if (portal2PromoFlags) {
406+
unsigned char promoFlagsByte = 0x00;
407+
g_promoFlagsPatch->Execute(portal2PromoFlags, &promoFlagsByte, 1); // Note: Has to be active before map loads.
408+
g_promoFlagsPatch->Restore();
409+
}
406410

407411
Variable::RegisterAll();
408412
Command::RegisterAll();
@@ -427,6 +431,8 @@ void Cheats::Shutdown() {
427431
SAFE_DELETE(g_autoGrabPatchServer);
428432
g_autoGrabPatchClient->Restore();
429433
SAFE_DELETE(g_autoGrabPatchClient);
434+
g_promoFlagsPatch->Restore();
435+
SAFE_DELETE(g_promoFlagsPatch);
430436
}
431437

432438

@@ -596,46 +602,35 @@ void Cheats::CheckAutoGrab() {
596602
}
597603

598604
DECL_AUTO_COMMAND_COMPLETION(sar_set_promo_items_state, ({"skins", "helmet", "antenna"})) // TODO: Add support for autofilling multiple args.
599-
CON_COMMAND_F_COMPLETION(sar_set_promo_items_state, "Enables coop promotional items on spawn.", FCVAR_CHEAT, AUTOCOMPLETION_FUNCTION(sar_set_promo_items_state)) {
600-
if (!g_nPortal2PromoFlags) {
601-
console->Print("Could not find PromoFlags global!\n");
602-
return;
605+
CON_COMMAND_F_COMPLETION(sar_set_promo_items_state, "sar_set_promo_items_state <off|all|skins|helmet|antenna>... - enables coop promotional items on spawn.\n", FCVAR_CHEAT, AUTOCOMPLETION_FUNCTION(sar_set_promo_items_state)) {
606+
if (!g_promoFlagsPatch || !g_promoFlagsPatch->IsInit()) {
607+
return console->Print("sar_set_promo_items_state is not available.\n");
603608
}
604-
static bool hasCheckedOriginalValue = false;
605-
if (!hasCheckedOriginalValue) {
606-
origPortal2PromoFlagsValue = *g_nPortal2PromoFlags;
607-
hasCheckedOriginalValue = true;
608-
}
609-
bool bSkin = (_stricmp(args[1], "skins") == 0);
610-
bool bHelmet = (_stricmp(args[1], "helmet") == 0);
611-
bool bAntenna = (_stricmp(args[1], "antenna") == 0);
612-
if (!bSkin && !bHelmet && !bAntenna) {
613-
console->Print("Invalid first argument.\n");
614-
return;
615-
}
616-
bool bAdding = (_stricmp(args[2], "add") == 0);
617-
bool bRemoving = (_stricmp(args[2], "remove") == 0);
618-
if (!bAdding && !bRemoving) {
619-
console->Print("Invalid second argument.\n");
620-
return;
609+
610+
if (args.ArgC() < 2) {
611+
return console->Print(sar_set_promo_items_state.ThisPtr()->m_pszHelpString);
621612
}
622-
if (bSkin) {
623-
if (bAdding) {
624-
*g_nPortal2PromoFlags |= (1 << 0);
625-
} else if (bRemoving) {
626-
*g_nPortal2PromoFlags &= ~(1 << 0);
613+
614+
unsigned char targetFlags = 0;
615+
for (int i = 1; i < args.ArgC(); i++) {
616+
if (strcasecmp(args[i], "off") == 0) {
617+
g_promoFlagsPatch->Restore();
618+
return;
627619
}
628-
} else if (bHelmet) {
629-
if (bAdding) {
630-
*g_nPortal2PromoFlags |= (1 << 1);
631-
} else if (bRemoving) {
632-
*g_nPortal2PromoFlags &= ~(1 << 1);
620+
if (strcasecmp(args[i], "all") == 0) {
621+
targetFlags = 0b111;
622+
break;
633623
}
634-
} else if (bAntenna) {
635-
if (bAdding) {
636-
*g_nPortal2PromoFlags |= (1 << 2);
637-
} else if (bRemoving) {
638-
*g_nPortal2PromoFlags &= ~(1 << 2);
624+
if (strcasecmp(args[i], "skins") == 0) {;
625+
targetFlags |= 0b001;
626+
} else if (strcasecmp(args[i], "helmet") == 0) {
627+
targetFlags |= 0b010;
628+
} else if (strcasecmp(args[i], "antenna") == 0) {
629+
targetFlags |= 0b100;
630+
} else {
631+
return console->Print(sar_set_promo_items_state.ThisPtr()->m_pszHelpString);
639632
}
640633
}
634+
g_promoFlagsPatch->Restore();
635+
g_promoFlagsPatch->Execute(&targetFlags, 1);
641636
}

src/Cheats.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,4 @@ extern Variable r_flashlightbrightness;
5151

5252
extern Command sar_togglewait;
5353

54-
extern int origPortal2PromoFlagsValue;
55-
extern int *g_nPortal2PromoFlags;
54+
extern Memory::Patch *g_promoFlagsPatch;

src/Modules/Server.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,7 @@ DETOUR(Server::PlayerRunCommand, CUserCmd *cmd, void *moveHelper) {
285285

286286
Cheats::AutoStrafe(slot, thisptr, cmd);
287287
Cheats::CheckFloorReportals();
288-
if (!sv_cheats.GetBool() && origPortal2PromoFlagsValue) {
289-
*g_nPortal2PromoFlags = origPortal2PromoFlagsValue; // We only want to check this once per map load, to preserve the intended behavior.
290-
}
288+
if (!sv_cheats.GetBool()) g_promoFlagsPatch->Restore(); // We only want to check this once per map load, to preserve the intended behavior.
291289

292290
inputHud.SetInputInfo(slot, cmd->buttons, {cmd->sidemove, cmd->forwardmove, cmd->upmove});
293291

src/Offsets/Portal 2 9568.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,9 @@ SIGSCAN_DEFAULT(FloorReportalBranch, "75 7D 8B 8E C0 04 00 00",
523523
SIGSCAN_DEFAULT(CPortal_Player__PollForUseEntity_CheckMP, "74 ? ? ? 8B 82 ? ? ? ? FF D0 84 C0 74 ? 8B CE",
524524
"74 ? 8B 10 83 EC 0C 50 FF 92 88 00 00 00 83 C4 10 84 C0 ? ? ? ? ? ? ? ? ? ? ? ? ? 00 00") // "OnJump" xref -> CPortal_Player:PreThink -> CBasePlayer::PreThink -> CBasePlayer::ItemPreFrame -> CBasePlayer::PlayerUse -> CPortal_Player vtable offset -> CPortal_Player::PlayerUse -> Second function call from disassembly -> CPortal_Player::PollForUseEntity -> jz instruction
525525

526-
// TODO:: Linux support.
527-
SIGSCAN_DEFAULT(Portal2PromoFlags_ADDR, "F6 05 ? ? ? ? ? 74 6D",
528-
"") // CPortal_Player::GiveDefaultItems -> portal2 promo flag check
526+
SIGSCAN_DEFAULT(Portal2PromoFlagsSig, "F6 05 ? ? ? ? 02 74 ? 8B CE",
527+
"A1 ? ? ? ? A8 02") // "#P2_WearableType_Flag" xref -> CPortal_Player::GiveDefaultItems -> bitwise & -> portal2 promo flag
528+
OFFSET_DEFAULT(Portal2PromoFlagsOff, 2, 1)
529529

530530
// VPhysics
531531
OFFSET_EMPTY(DestroyEnvironment)

src/Utils/Memory.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ Memory::Patch::~Patch() {
245245
}
246246
bool Memory::Patch::Execute() {
247247
if (this->isPatched) return true; // already executed
248+
if (!this->IsInit()) return false;
248249
unsigned char *tmpPatch = new unsigned char[this->size];
249250
// We create another patch, because this->patch is gonna be deleted
250251
memcpy(tmpPatch, this->patch, this->size);

src/Utils/Memory.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ namespace Memory {
5050
bool Execute(uintptr_t location, unsigned char (&bytes)[size]) {
5151
return Execute(location, bytes, size);
5252
}
53+
bool Execute(unsigned char *bytes, size_t size) {
54+
return Execute(location, bytes, size);
55+
}
56+
template <size_t size>
57+
bool Execute(unsigned char (&bytes)[size]) {
58+
return Execute(location, bytes, size);
59+
}
5360
bool Restore();
5461
bool IsPatched();
5562
bool IsInit();

0 commit comments

Comments
 (0)