Check this one out: https://github.com/CrumblyLiquid/BakkesLinux
I had to install these packages along the process. I'm on Fedora 36 though, so package names may vary depending on what distro you're on:
protontricks
mingw64-gcc-c++
mingw64-winpthreads-static
Download BakkesMod from the official website.
This installer is only compatible with Windows 10, and proton prefixes are Windows 7 by default. You can get the Windows 7 version of BakkesMod or just change your Windows version like I did:
- Run
protontricks 252950 --gui
. Ignore any warnings about 64bit prefixes, everything's okay. - Select the default wineprefix
- Change settings
- Tick the win10 box
Now you can run the installer like this:
protontricks -c '/home/$USER/Downloads/BakkesModSetup.exe' 252950
This should run the installer in the same wine prefix where Rocket League is installed. 252950 is Rocket League's Steam APPID.
Now you might be tempted to just run BakkesMod with protontricks, but it won't work:
Installing vcredistx64
doesn't fix anything, it still gives that error (trust me, I tried). It's the injector that doesn't play well with Proton for some reason, so we'll have to make our own.
First create a file named inject.cpp
with this content:
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <string>
#define LOG_LINE(x, msg) std::cout << msg << std::endl;
DWORD GetProcessID64(std::wstring processName)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE)
return 0;
Process32First(processesSnapshot, &processInfo);
if (_wcsicmp(processName.c_str(), processInfo.szExeFile) == 0)
{
BOOL iswow64 = FALSE;
// https://stackoverflow.com/questions/14184137/how-can-i-determine-whether-a-process-is-32-or-64-bit
// If IsWow64Process() reports true, the process is 32-bit running on a
// 64-bit OS So we want it to return false (32 bit on 32 bit os, or 64 bit on
// 64 bit OS, since we build x64 the first condition will never satisfy since
// they can't run this exe)
auto hProcess =
OpenProcess(PROCESS_ALL_ACCESS, FALSE, processInfo.th32ProcessID);
if (hProcess == NULL)
{
LOG_LINE(INFO, "Error on OpenProcess to check bitness");
}
else
{
if (IsWow64Process(hProcess, &iswow64))
{
// LOG_LINE(INFO, "Rocket league process ID is " <<
// processInfo.th32ProcessID << " | " << " has the WOW factor: " <<
// iswow64);
if (!iswow64)
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
else
{
LOG_LINE(INFO, "IsWow64Process failed bruv " << GetLastError());
}
CloseHandle(hProcess);
}
}
while (Process32Next(processesSnapshot, &processInfo))
{
if (_wcsicmp(processName.c_str(), processInfo.szExeFile) == 0)
{
BOOL iswow64 = FALSE;
auto hProcess =
OpenProcess(PROCESS_ALL_ACCESS, FALSE, processInfo.th32ProcessID);
if (hProcess == NULL)
{
LOG_LINE(INFO, "Error on OpenProcess to check bitness");
}
else
{
if (IsWow64Process(hProcess, &iswow64))
{
// LOG_LINE(INFO, "Rocket league process ID is " <<
// processInfo.th32ProcessID << " | " << " has the WOW factor: " <<
// iswow64);
if (!iswow64)
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
else
{
LOG_LINE(INFO, "IsWow64Process failed bruv " << GetLastError());
}
CloseHandle(hProcess);
}
}
// CloseHandle(processesSnapshot);
}
CloseHandle(processesSnapshot);
return 0;
}
int wmain(int argc, wchar_t* argv[])
{
DWORD processID;
while (true)
{
processID = GetProcessID64(L"RocketLeague.exe");
if (processID != 0)
break;
Sleep(100);
}
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
if (h)
{
LPVOID LoadLibAddr = (LPVOID)GetProcAddress(
GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
auto ws = L"C:\\users\\steamuser\\Application Data\\bakkesmod\\bakkesmod/dll\\bakkesmod.dll";
auto wslen = (std::wcslen(ws) + 1) * sizeof(WCHAR);
LPVOID dereercomp = VirtualAllocEx(
h, NULL, wslen, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(h, dereercomp, ws, wslen, NULL);
HANDLE asdc = CreateRemoteThread(
h,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadLibAddr,
dereercomp,
0,
NULL);
WaitForSingleObject(asdc, INFINITE);
DWORD res = 0;
GetExitCodeThread(asdc, &res);
LOG_LINE(INFO, "GetExitCodeThread(): " << (int)res);
LOG_LINE(INFO, "Last error: " << GetLastError());
VirtualFreeEx(h, dereercomp, wslen, MEM_RELEASE);
CloseHandle(asdc);
CloseHandle(h);
return res == 0;
}
return 1;
}
Once you have it, compile it with this command:
x86_64-w64-mingw32-g++ inject.cpp -municode -mconsole -lpsapi -std=c++17 -o inject.exe -static
It should spit out a file called inject.exe
. You can test it by starting Rocket League, waiting for the game to load completely and running your shiny new injector:
protontricks -c 'wine ~/inject.exe' 252950
After a few seconds you should be able to hit F2 and see the BakkesMod GUI.
This injector should work in any Proton version, I'm using Proton 6.3-8.
For this trick we're gonna make a shell script that runs Rocket League, waits for it to launch completely and then runs the injector.
Create a file called bakkesinject.sh
with this content:
echo "" > ~/steam-252950.log
eval 'PROTON_LOG=1 "$@"' &
while ! grep "Initializing Engine Completed" ~/steam-252950.log > /dev/null; do
sleep 1
done
protontricks -c 'wine ~/inject.exe' 252950
Make it executable with chmod +x bakkesinject.sh
and add it to the launch parameters of Rocket League like this:
The injector doesn't take care of updating BakkesMod, so whenever a new version comes out, you'll have to run the good old GUI like this:
protontricks -c 'wine "/home/$USER/.steam/steam/steamapps/compatdata/252950/pfx/drive_c/Program Files/BakkesMod/BakkesMod.exe"' 252950
You can make this an alias or another bash script, like I did.
Once it finishes updating you can close it. IMPORTANT: Do not attempt to launch Rocket League while the BakkesMod GUI is running, it won't work. For some reason the game doesn't like when you launch it while something else is running in its prefix (you can run anything after the game has launched though).
Everything is taken from this GitHub issue. The custom injector code comes from this GitHub gist, which is also referenced in the GitHub issue. The launch script is heavily inspired on this comment from the GitHub issue, I just simplified some parts of it.
Thank you for your full answer, I am sure it will help a lot of people.
But I can still not run it. I'am not sure if that is the reason but how did you install bakkesmod in your home folder ?
When I install it, I am only able to install it in the c_drive at that location:
/home/luca/.var/app/com.valvesoftware.Steam/.steam/steam/steamapps/compatdata/252950/pfx/drive_c/Program Files/BakkesMod/BakkesMod.exe
On my side I was able to run BakkesMod without a problem. I just ticked win10 on the protontricks gui.
But It never detects my game.
Are you using the flatpak version of steam ? I am using flatpak, but that is maybe the problem.