diff --git a/ThunkLibs/include/common/X11Manager.h b/ThunkLibs/include/common/X11Manager.h
index 01ad7093a..a0b1f9e8e 100644
--- a/ThunkLibs/include/common/X11Manager.h
+++ b/ThunkLibs/include/common/X11Manager.h
@@ -2,6 +2,7 @@
 
 #include <cstdio>
 #include <cstdlib>
+#include <cstdint>
 #include <dlfcn.h>
 #include <mutex>
 #include <unordered_map>
@@ -9,6 +10,14 @@
 #include <X11/Xlib.h>
 #include <xcb/xcb.h>
 
+#ifdef IS_32BIT_THUNK
+using guest_long = int32_t;
+using guest_size_t = int32_t;
+#else
+using guest_long = long;
+using guest_size_t = size_t;
+#endif
+
 /**
  * Guest X11 displays and xcb connections can't be used by the host, so
  * instead an intermediary object is created and mapped to the original
@@ -47,7 +56,7 @@ struct X11Manager {
     std::unique_lock lock(mutex);
     auto [it, inserted] = displays.emplace(GuestDisplay, nullptr);
     if (inserted) {
-      auto host_display = HostXOpenDisplay(DisplayString(GuestDisplay));
+      auto host_display = HostXOpenDisplay(GuestXDisplayString(GuestDisplay));
       fprintf(stderr, "Opening host-side X11 display: %p -> %p\n", GuestDisplay, host_display);
       if (!host_display) {
         fprintf(stderr, "ERROR: Could not open X display\n");
@@ -104,7 +113,7 @@ struct X11Manager {
 
   // NOTE: Struct pointers are replaced by void* to avoid involving data layout conversion here.
   int (*GuestXSync)(void*, int) = nullptr;
-  void* (*GuestXGetVisualInfo)(void*, long, void*, int*) = nullptr;
+  void* (*GuestXGetVisualInfo)(void*, guest_long, void*, int*) = nullptr;
 
   // XDisplayString internally just reads data from _XDisplay's internal struct definition.
   // This breaks when data layout is different, so allow reading from a guest context instead.
diff --git a/ThunkLibs/libGL/libGL_Guest.cpp b/ThunkLibs/libGL/libGL_Guest.cpp
index 1e264a6fa..120e28607 100644
--- a/ThunkLibs/libGL/libGL_Guest.cpp
+++ b/ThunkLibs/libGL/libGL_Guest.cpp
@@ -16,9 +16,10 @@ $end_info$
 #undef GL_ARB_viewport_array
 #include "glcorearb.h"
 
-#include <stdio.h>
-#include <cstdlib>
 #include <dlfcn.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 #include <functional>
 #include <string_view>
 #include <unordered_map>
diff --git a/ThunkLibs/libGL/libGL_Host.cpp b/ThunkLibs/libGL/libGL_Host.cpp
index cfab36e95..3c76205e5 100644
--- a/ThunkLibs/libGL/libGL_Host.cpp
+++ b/ThunkLibs/libGL/libGL_Host.cpp
@@ -35,7 +35,7 @@ struct host_layout<_XDisplay*> {
 
 static X11Manager x11_manager;
 
-static void* (*GuestMalloc)(size_t) = nullptr;
+static void* (*GuestMalloc)(guest_size_t) = nullptr;
 
 host_layout<_XDisplay*>::host_layout(guest_layout<_XDisplay*>& guest)
   : guest_display(guest.force_get_host_pointer()) {
@@ -136,10 +136,19 @@ auto fexfn_impl_libGL_glXGetProcAddress(const GLubyte* name) -> void (*)() {
     return (VoidFn)fexfn_impl_libGL_glXGetConfig;
   } else if (name_sv == "glXGetVisualFromFBConfig") {
     return (VoidFn)fexfn_impl_libGL_glXGetVisualFromFBConfig;
+#ifdef IS_32BIT_THUNK
+  } else if (name_sv == "glXGetSelectedEvent") {
+    return (VoidFn)fexfn_impl_libGL_glXGetSelectedEvent;
+  } else if (name_sv == "glXGetSelectedEventSGIX") {
+    return (VoidFn)fexfn_impl_libGL_glXGetSelectedEventSGIX;
+#endif
   }
   return (VoidFn)glXGetProcAddress((const GLubyte*)name);
 }
 
+// TODO: unsigned int *glXEnumerateVideoDevicesNV (Display *dpy, int screen, int *nelements);
+
+
 void fexfn_impl_libGL_glCompileShaderIncludeARB(GLuint a_0, GLsizei Count, guest_layout<const GLchar* const*> a_2, const GLint* a_3) {
   // TODO: Only on 32-bit
   auto sources = (const char**)alloca(Count * sizeof(const char*));
@@ -282,7 +291,8 @@ static XVisualInfo* LookupHostVisualInfo(Display* HostDisplay, guest_layout<XVis
   }
 
   int num_matches;
-  auto ret = x11_manager.HostXGetVisualInfo(HostDisplay, VisualScreenMask | VisualIDMask, GuestInfo.force_get_host_pointer(), &num_matches);
+  auto HostInfo = host_layout<XVisualInfo> {*GuestInfo.get_pointer()}.data;
+  auto ret = x11_manager.HostXGetVisualInfo(HostDisplay, uint64_t {VisualScreenMask | VisualIDMask}, &HostInfo, &num_matches);
   if (num_matches != 1) {
     fprintf(stderr, "ERROR: Did not find unique host XVisualInfo\n");
     std::abort();
@@ -296,9 +306,17 @@ static guest_layout<XVisualInfo*> MapToGuestVisualInfo(Display* HostDisplay, XVi
     return guest_layout<XVisualInfo*> {.data = 0};
   }
 
-  int num_matches;
   auto guest_display = x11_manager.HostToGuestDisplay(HostDisplay);
-  auto ret = x11_manager.GuestXGetVisualInfo(guest_display.get_pointer(), VisualScreenMask | VisualIDMask, HostInfo, &num_matches);
+#ifndef IS_32BIT_THUNK
+  int num_matches;
+  auto GuestInfo = to_guest(to_host_layout(*HostInfo));
+#else
+  GuestStackBumpAllocator GuestStack;
+  auto& num_matches = *GuestStack.New<int>();
+  auto& GuestInfo = *GuestStack.New<guest_layout<XVisualInfo>>(to_guest(to_host_layout(*HostInfo)));
+#endif
+  auto ret = x11_manager.GuestXGetVisualInfo(guest_display.get_pointer(), VisualScreenMask | VisualIDMask, &GuestInfo, &num_matches);
+
   if (num_matches != 1) {
     fprintf(stderr, "ERROR: Did not find unique guest XVisualInfo\n");
     std::abort();
@@ -409,6 +427,17 @@ void fexfn_impl_libGL_glVertexArrayVertexBuffers(GLuint a_0, GLuint a_1, GLsizei
   }
   fexldr_ptr_libGL_glVertexArrayVertexBuffers(a_0, a_1, count, a_3, HostOffsets, a_5);
 }
+
+void fexfn_impl_libGL_glXGetSelectedEvent(Display* Display, GLXDrawable Drawable, guest_layout<uint32_t*> Mask) {
+  unsigned long HostMask;
+  fexldr_ptr_libGL_glXGetSelectedEvent(Display, Drawable, &HostMask);
+  *Mask.get_pointer() = HostMask;
+}
+void fexfn_impl_libGL_glXGetSelectedEventSGIX(Display* Display, GLXDrawable Drawable, guest_layout<uint32_t*> Mask) {
+  unsigned long HostMask;
+  fexldr_ptr_libGL_glXGetSelectedEventSGIX(Display, Drawable, &HostMask);
+  *Mask.get_pointer() = HostMask;
+}
 #endif
 
 EXPORTS(libGL)
diff --git a/ThunkLibs/libGL/libGL_interface.cpp b/ThunkLibs/libGL/libGL_interface.cpp
index 17dc3604a..8765c93d2 100644
--- a/ThunkLibs/libGL/libGL_interface.cpp
+++ b/ThunkLibs/libGL/libGL_interface.cpp
@@ -74,7 +74,6 @@ struct fex_gen_config : fexgen::generate_guest_symtable, fexgen::indirect_guest_
 template<auto, int, typename = void>
 struct fex_gen_param {};
 
-#ifndef IS_32BIT_THUNK
 template<>
 struct fex_gen_config<glXQueryCurrentRendererStringMESA> {};
 template<>
@@ -135,8 +134,16 @@ template<>
 struct fex_gen_config<glXDestroyGLXPbufferSGIX> {};
 template<>
 struct fex_gen_config<glXFreeContextEXT> {};
+#ifndef IS_32BIT_THUNK
 template<>
 struct fex_gen_config<glXGetSelectedEventSGIX> {};
+#else
+template<>
+struct fex_gen_config<glXGetSelectedEventSGIX> : fexgen::custom_host_impl {};
+template<>
+struct fex_gen_param<glXGetSelectedEventSGIX, 2, unsigned long*> : fexgen::ptr_passthrough {};
+#endif
+
 template<>
 struct fex_gen_config<glXQueryGLXPbufferSGIX> {};
 template<>
@@ -215,8 +222,15 @@ template<>
 struct fex_gen_config<glXDestroyWindow> {};
 template<>
 struct fex_gen_config<glXFreeMemoryNV> {};
+#ifndef IS_32BIT_THUNK
 template<>
 struct fex_gen_config<glXGetSelectedEvent> {};
+#else
+template<>
+struct fex_gen_config<glXGetSelectedEvent> : fexgen::custom_host_impl {};
+template<>
+struct fex_gen_param<glXGetSelectedEvent, 2, unsigned long*> : fexgen::ptr_passthrough {};
+#endif
 template<>
 struct fex_gen_config<glXQueryDrawable> {};
 template<>
@@ -241,7 +255,6 @@ template<>
 struct fex_gen_config<glXCreateContextAttribsARB> {};
 template<>
 struct fex_gen_config<glXSwapIntervalEXT> {};
-#endif
 
 template<>
 struct fex_gen_config<glColorP3ui> {};
@@ -6352,7 +6365,6 @@ struct fex_gen_config<glGetPathTexGenfvNV> {};
 template<>
 struct fex_gen_config<glBlendEquationSeparateATI> {};
 
-#ifndef IS_32BIT_THUNK
 // glx.h
 template<>
 struct fex_gen_config<glXWaitX> {};
@@ -6428,8 +6440,11 @@ template<>
 struct fex_gen_config<glXResetFrameCountNV> {};
 template<>
 struct fex_gen_config<glXBindVideoCaptureDeviceNV> {};
+#ifndef IS_32BIT_THUNK
+// TODO: 32-bit support
 template<>
 struct fex_gen_config<glXEnumerateVideoCaptureDevicesNV> {};
+#endif
 template<>
 struct fex_gen_config<glXLockVideoCaptureDeviceNV> {};
 template<>
@@ -6444,10 +6459,13 @@ template<>
 struct fex_gen_config<glXBindVideoImageNV> {};
 template<>
 struct fex_gen_config<glXReleaseVideoImageNV> {};
+#ifndef IS_32BIT_THUNK
+// TODO: 32-bit support
 template<>
 struct fex_gen_config<glXSendPbufferToVideoNV> {};
 template<>
 struct fex_gen_config<glXGetVideoInfoNV> {};
+#endif
 template<>
 struct fex_gen_config<glXQueryHyperpipeNetworkSGIX> {};
 template<>
@@ -6482,6 +6500,8 @@ template<>
 struct fex_gen_config<glXChannelRectSyncSGIX> {};
 template<>
 struct fex_gen_config<glXCushionSGI> {};
+#ifndef IS_32BIT_THUNK
+// TODO: 32-bit support
 template<>
 struct fex_gen_config<glXGetTransparentIndexSUN> {};
 #endif