// g++ -m32 -O2 -fvisibility=hidden -fPIC -shared -Wl,-Bsymbolic -o anomalyhack.so anomalyhack.cpp -ldl // Warning: this a quick'n'dirty hack to renumber uniform locations to prevent // Anomaly: Warzone Earth from segfaulting; not a good libGL wrapping example #include #include #include #pragma GCC visibility push(default) #define GLX_GLXEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #include #pragma GCC visibility pop static std::map, GLint> revmap; GLint glGetUniformLocation(GLuint program, const GLchar *name) { static PFNGLGETUNIFORMLOCATIONPROC realfn = (PFNGLGETUNIFORMLOCATIONPROC) dlsym(RTLD_NEXT, "glGetUniformLocation"); GLint nun, un, origloc = realfn(program, name); if (origloc == -1) return -1; glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &nun); for (un = 0; un < nun; un++) { GLsizei len; GLint size; GLenum type; GLchar uname[256]; glGetActiveUniform(program, un, 256, &len, &size, &type, uname); if (!strcmp(uname, name)) break; } revmap[std::make_pair(program, un)] = origloc; return un; } void glUniform1i(GLint location, GLint v0) { static PFNGLUNIFORM1IPROC realfn = (PFNGLUNIFORM1IPROC) dlsym(RTLD_NEXT, "glUniform1i"); GLuint program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&program); realfn(revmap[std::make_pair(program, location)], v0); } void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) { static PFNGLUNIFORM4FVPROC realfn = (PFNGLUNIFORM4FVPROC) dlsym(RTLD_NEXT, "glUniform4fv"); GLuint program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&program); realfn(revmap[std::make_pair(program, location)], count, value); } void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { static PFNGLUNIFORMMATRIX4FVPROC realfn = (PFNGLUNIFORMMATRIX4FVPROC) dlsym(RTLD_NEXT, "glUniformMatrix4fv"); GLuint program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&program); realfn(revmap[std::make_pair(program, location)], count, transpose, value); } __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procName) { static const char * const redefined_names[] = { "glGetUniformLocation", "glUniform1i", "glUniform4fv", "glUniformMatrix4fv" }; static const __GLXextFuncPtr redefined_fns[] = { (__GLXextFuncPtr) glGetUniformLocation, (__GLXextFuncPtr) glUniform1i, (__GLXextFuncPtr) glUniform4fv, (__GLXextFuncPtr) glUniformMatrix4fv }; enum {n_redefined = sizeof(redefined_fns) / sizeof(redefined_fns[0])}; for (int i = 0; i < n_redefined; i++) if (!strcmp((const char *)procName, redefined_names[i])) return redefined_fns[i]; static PFNGLXGETPROCADDRESSPROC realgpa = (PFNGLXGETPROCADDRESSPROC) dlsym(RTLD_NEXT, "glXGetProcAddressARB"); return realgpa(procName); }