Skip to content

Instantly share code, notes, and snippets.

@Henje
Last active February 28, 2023 23:10
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Henje/eff3fb2cf0bf47910dc9145256a53cfe to your computer and use it in GitHub Desktop.
Save Henje/eff3fb2cf0bf47910dc9145256a53cfe to your computer and use it in GitHub Desktop.
Simple hack to disable joystick scanning and remove stutters from Papers Please.
#include <string>
#include <dlfcn.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
using namespace std::literals;
template<class T>
constexpr T* page_round_down(T* ptr, size_t page_size) {
size_t page = reinterpret_cast<size_t>(ptr) & ~(page_size - 1);
return reinterpret_cast<T*>(page);
}
void patch_function(void* ptr, size_t offset) {
char* func = reinterpret_cast<char*>(ptr);
func += offset;
const long page_size = sysconf(_SC_PAGESIZE);
int result = mprotect(page_round_down(func, page_size), 1, PROT_READ | PROT_WRITE | PROT_EXEC);
if(result) {
fprintf(stderr, "result %d %d\n", result, errno);
return;
}
func[0] = 0xc3;
mprotect(page_round_down(func, page_size), 1, PROT_READ | PROT_EXEC);
}
using dlopen_t = void* (*)(const char*, int);
extern "C"
void* dlopen(const char* filename, int flags) {
static dlopen_t real_dlopen = nullptr;
if(!real_dlopen)
real_dlopen = reinterpret_cast<dlopen_t>(dlsym(RTLD_NEXT, "dlopen"));
void* handle = real_dlopen(filename, flags);
if(!filename || filename != "././lime.ndll"s) {
return handle;
}
char* symbol = getenv("PP_SYMBOL");
if(!symbol) {
fprintf(stderr, "PP_SYMBOL not set\n");
return handle;
}
char* offset = getenv("PP_OFFSET");
if(!offset) {
fprintf(stderr, "PP_OFFSET not set\n");
return handle;
}
void* func = dlsym(handle, symbol);
if(!func) {
fprintf(stderr, "could not find symbol: %s\n", symbol);
return handle;
}
patch_function(func, atoi(offset));
return handle;
}⏎
@tomioe
Copy link

tomioe commented Jan 2, 2022

Very impressive analysis and fix! What arguments are you passing to gcc to compile this? Is there a Makefile?

@jacobsebek
Copy link

jacobsebek commented Jan 2, 2022

Hi. Great and educational article. Although I am not sure if it wouldn't be easier to just create a stub for the global symbol SDL_JoystickInit.

@TibixDev
Copy link

TibixDev commented Jan 3, 2022

Very impressive article, it was an amazing read.

@PabloCastellano
Copy link

Kudos and great write-up!

@santiacq
Copy link

santiacq commented Jan 14, 2022

Great article! It came really handy to me as yesterday I had the same problem

@tomioe here's the commands to compile into a shared library:
g++ -g -ggdb -fPIC -rdynamic -I../static -c papers_please_fix.cpp -o papers_please_fix.o
g++ -g -ggdb -fPIC -rdynamic -shared -o papers_please_fix.so papers_please_fix.o

@xordspar0
Copy link

This was a bug that was fixed in lime. Now you can just download the latest version and replace lime.ndll. See https://www.gog.com/forum/papers_please/terrible_lags_on_linux_with_nvidia_gpu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment