Skip to content

Commit

Permalink
Add autoswitch approach
Browse files Browse the repository at this point in the history
  • Loading branch information
Sainan committed Feb 3, 2024
1 parent 43047a4 commit 45b4604
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
int/
*.exe
*.dll
*.exp
*.lib
2 changes: 2 additions & 0 deletions autoswitch/.sun
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
+*.cpp
require ../../Soup/soup
14 changes: 14 additions & 0 deletions autoswitch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Automatic profile switcher for Wooting keyboards

Automatically switches the profile on your Wooting keyboard based on if a game is focused and what state the game is in.

### Profile Setup

This program is made to "just work" with the factory state of Wooting keyboards:

1. "Digital Profile" - No game active.
2. "Rapid Profile" - Unused by this program.
3. "Racing Profile" - Used for "in vehicle" contexts: W and S are mapped to RT and LT. A and D are mapped to LSTICK LEFT and LSTICK RIGHT. "Gamepad mapping override" is enabled.
4. "Mixed Movement" - Used for most game contexts: WASD is mapped to LSTICK directional inputs. "Gamepad mapping override" is enabled.

However, note that the default state of Wooting keyboards has "Gamepad Mode" set to "No Gamepad", so do be sure to change this so it can be recognised as a controller.
150 changes: 150 additions & 0 deletions autoswitch/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include <iostream>
#include <thread>

#include <DelayedCtor.hpp>
#include <Fiber.hpp>
#include <joaat.hpp>
#include <kbRgbWooting.hpp>
#include <Module.hpp>
#include <Pattern.hpp>
#include <Pointer.hpp>
#include <Process.hpp>
#include <Window.hpp>
#include <wooting_enums.hpp>

using namespace soup;

static DWORD prev_focus_pid = -1;
static UniquePtr<Process> proc;
static std::shared_ptr<Module> mod;
static DelayedCtor<Fiber> fib;
static bool fib_ret;

#define YIELD_VALUE(x) fib_ret = x; Fiber::current()->yield();

[[nodiscard]] static bool isAppropriateGameProcess(const std::string& name)
{
switch (joaat::hash(name))
{
case joaat::hash("Cyberpunk2077.exe"):
case joaat::hash("Warframe.x64.exe"):
return true;
}
return false;
}

[[nodiscard]] static bool isInVehicleContext()
{
if (proc->name == "Cyberpunk2077.exe")
{
if (!fib.isConstructed())
{
fib.construct([](Capture&&)
{
auto func = mod->externalScan(Pattern("48 89 5C 24 10 4C 89 74 24 18 48 89 4C 24 08 55"));
auto player_info = func.add((0x0000000140F886F9 - 0x0000000140F88678) + 3).externalRip(*mod);
while (true)
{
if (Pointer player_ptr = mod->externalRead<void*>(player_info.add(0x10)))
{
if (Pointer player_ped_ptr = mod->externalRead<void*>(player_ptr.add(0x5B0)))
{
if (Pointer vehicle_ptr = mod->externalRead<void*>(player_ped_ptr.add(0x90)))
{
YIELD_VALUE(true);
continue;
}
}
}
YIELD_VALUE(false);
}
});
}
}

if (fib)
{
fib->run();
return fib_ret;
}
return false;
}

[[nodiscard]] static uint8_t getAppropriateProfile()
{
DWORD focus_pid = Window::getFocused().getOwnerPid();
if (focus_pid != prev_focus_pid)
{
prev_focus_pid = focus_pid;
proc = Process::get(focus_pid);
if (isAppropriateGameProcess(proc->name))
{
mod = proc->open();;
std::cout << "Appropriate game process detected: " << proc->name << "\n";
}
else
{
if (mod)
{
mod.reset();
fib.reset();
std::cout << "Game process no longer active/focused\n";
}
}
}

if (mod)
{
if (isInVehicleContext())
{
return 2;
}
return 3;
}
return 0;
}

static void sendProfileSwitchToHardware(uint8_t profile)
{
for (auto& _kbd : kbRgb::getAll(false))
{
if (_kbd->isWooting())
{
auto kbd = _kbd->asWooting();
if (!kbd->isUwu())
{
std::cout << "Sending report to " << kbd->name << "...";
{
Buffer buf(8);
buf.push_back(/* 0 */ 0); // HID report index
buf.push_back(/* 1 */ 0xD0); // Magic word
buf.push_back(/* 2 */ 0xDA); // Magic word
buf.push_back(/* 3 */ (uint8_t)WootingCommand::ActivateProfile);
buf.push_back(/* 4 */ profile);
buf.push_back(/* 5 */ 0);
buf.push_back(/* 6 */ 0);
buf.push_back(/* 7 */ 0);
kbd->hid.sendFeatureReport(std::move(buf));
}
SOUP_UNUSED(kbd->hid.receiveReport());
std::cout << " Success.\n";
}
}
}
}

int main()
{
uint8_t profile = -1;
while (true)
{
auto appropriate_profile = getAppropriateProfile();
if (appropriate_profile != profile)
{
profile = appropriate_profile;
std::cout << "Switching to profile " << (int)(profile + 1) << "\n";
sendProfileSwitchToHardware(profile);
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}

0 comments on commit 45b4604

Please sign in to comment.