Fixing a performance issue in Battlefield 6 by holding down ALT
It was recently brought to my attention that Battlefield 6 suffers from occasional dips in performance, and it has to do with how the game’s anti-cheat deals with keyboards. This Reddit post has the details.
Basically, holding down the ALT key gets rid of the performance problems, and people have taken to taping the key down to fix it.
Someone I know plays the game on a controller, however, and the effect of taping down the key is quite problematic for him because of automatic input switching, where the game’s user interface changes based on the type of device the last input came from (eg. pressing a keyboard key changes all the shortcuts to keyboard keys, while pressing a controller button changes them to controller buttons).
When the ALT key is taped down, that means the keyboard is constantly spamming the system with “ALT DOWN” events, and if you’re using a controller at the same time, the UI keeps switching between layouts, which can be quite distracting.
I have run into this problem with AutoPTT as well, and the solution is to simply block the unnecessary keyboard input from the system. But we can’t block all the input; just the repeats.
But then I thought, what if we also blocked the ALT UP? Then you wouldn’t have to tape down the ALT key anymore. Just press it once and it’ll stay down!
Of course, if we block the ALT UP too, then the user can no longer ALT-TAB, so there’s got to be a way to disable that as well. So I wrote a small program that blocks repeated ALT DOWN events and optionally also ALT UP events. The download link is at the top of this post.
All it really took was to install a low level keyboard hook like this:
static LRESULT CALLBACK keyboard_hook(int code, WPARAM w_param, LPARAM l_param) {
if (code != HC_ACTION) {
goto ret;
}
uint32_t message_id = (uint32_t) w_param;
if (message_id != WM_KEYDOWN
and message_id != WM_KEYUP
and message_id != WM_SYSKEYDOWN
and message_id != WM_SYSKEYUP) {
goto ret;
}
KBDLLHOOKSTRUCT *info = (KBDLLHOOKSTRUCT *) l_param;
uint16_t vk_code = info->vkCode;
bool is_down = (info->flags & LLKHF_UP) == 0;
if (vk_code == VK_RCONTROL) {
bool prev_rcontrol_down = self.rcontrol_down;
self.rcontrol_down = is_down;
if (is_down and prev_rcontrol_down != is_down) {
self.block_alt_up = not self.block_alt_up;
if (self.block_alt_up) {
w_log_line("alt up will now be blocked");
}
else {
w_log_line("alt up will now be allowed");
}
}
}
bool is_alt_key =
vk_code == VK_LMENU or
vk_code == VK_RMENU or
vk_code == VK_MENU;
if (not is_alt_key) {
goto ret;
}
if (is_down) {
if (self.alt_down) {
if (self.args.verbose) {
w_log_line("alt down repeat --> block");
}
return 1;
}
else {
w_log_line("alt down --> allow");
self.alt_down = true;
}
}
else if (self.block_alt_up) {
w_log_line("alt up --> block");
}
else {
w_log_line("alt up --> allow");
self.alt_down = false;
}
ret: return CallNextHookEx(0, code, w_param, l_param);
}
AutoPTT