about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-03-05 20:47:50 +0100
committerGitHub <noreply@github.com>2023-03-05 20:47:50 +0100
commitb56be08f959557a0a1fd18190ff89f8de83862a1 (patch)
tree479d45d4eec05abd148d5038e9e78807d9400590 /src
parentcabcca2e31207aea12fe0a07c41b3c6b56ce1892 (diff)
parentb1923cadb5fbd4abd3fcba36142266f6ce588f4e (diff)
downloadbox64-b56be08f959557a0a1fd18190ff89f8de83862a1.tar.gz
box64-b56be08f959557a0a1fd18190ff89f8de83862a1.zip
Merge pull request #534 from ptitSeb/steam_chrome
Steamwebhelper compatibility
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c2
-rw-r--r--src/custommem.c334
-rwxr-xr-xsrc/dynarec/arm64/arm64_emitter.h12
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_0f.c14
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_660f.c2
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.c24
-rwxr-xr-xsrc/include/box64context.h6
-rw-r--r--src/include/custommem.h19
-rwxr-xr-xsrc/include/debug.h2
-rw-r--r--src/include/gltools.h12
-rwxr-xr-xsrc/include/library.h4
-rwxr-xr-xsrc/include/myalign.h4
-rwxr-xr-xsrc/librarian/library.c4
-rwxr-xr-xsrc/library_list.h3
-rwxr-xr-xsrc/libtools/signals.c11
-rwxr-xr-xsrc/main.c24
-rw-r--r--src/mallochook.c120
-rwxr-xr-xsrc/tools/gtkclass.c44
-rw-r--r--src/tools/rcfile.c6
-rw-r--r--src/wrapped/generated/functions_list.txt28
-rw-r--r--src/wrapped/generated/wrappedglib2types.h1
-rw-r--r--src/wrapped/generated/wrappedlibglxdefs.h8
-rw-r--r--src/wrapped/generated/wrappedlibglxtypes.h20
-rw-r--r--src/wrapped/generated/wrappedlibglxundefs.h8
-rw-r--r--src/wrapped/generated/wrappedlibibusdefs.h8
-rw-r--r--src/wrapped/generated/wrappedlibibustypes.h33
-rw-r--r--src/wrapped/generated/wrappedlibibusundefs.h8
-rw-r--r--src/wrapped/generated/wrapper.c14
-rw-r--r--src/wrapped/generated/wrapper.h6
-rwxr-xr-xsrc/wrapped/wrappedfontconfig_private.h2
-rwxr-xr-xsrc/wrapped/wrappedgio2_private.h6
-rwxr-xr-xsrc/wrapped/wrappedglib2.c15
-rwxr-xr-xsrc/wrapped/wrappedglib2_private.h6
-rwxr-xr-xsrc/wrapped/wrappedlibc.c29
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h2
-rwxr-xr-xsrc/wrapped/wrappedlibdrm_private.h4
-rwxr-xr-xsrc/wrapped/wrappedlibegl.c65
-rwxr-xr-xsrc/wrapped/wrappedlibgl.c397
-rw-r--r--src/wrapped/wrappedlibglx.c61
-rw-r--r--src/wrapped/wrappedlibglx_private.h48
-rw-r--r--src/wrapped/wrappedlibibus.c123
-rw-r--r--src/wrapped/wrappedlibibus_private.h473
-rwxr-xr-xsrc/wrapped/wrappedsdl1.c48
-rwxr-xr-xsrc/wrapped/wrappedsdl2.c63
44 files changed, 1638 insertions, 485 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 67f7f584..95b4a5bd 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -20,6 +20,7 @@
 #include "x64emu.h"
 #include "signals.h"
 #include "rcfile.h"
+#include "gltools.h"
 
 EXPORTDYN
 void initAllHelpers(box64context_t* context)
@@ -233,6 +234,7 @@ box64context_t *NewBox64Context(int argc)
     return context;
 }
 
+void freeALProcWrapper(box64context_t* context);
 EXPORTDYN
 void FreeBox64Context(box64context_t** context)
 {
diff --git a/src/custommem.c b/src/custommem.c
index 6638af31..633e15fe 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -33,10 +33,11 @@
 
 // init inside dynablocks.c
 static mmaplist_t          *mmaplist = NULL;
-static uintptr_t***        box64_jmptbl3[1<<JMPTABL_SHIFT];
-static uintptr_t**         box64_jmptbldefault2[1<<JMPTABL_SHIFT];
-static uintptr_t*          box64_jmptbldefault1[1<<JMPTABL_SHIFT];
-static uintptr_t           box64_jmptbldefault0[1<<JMPTABL_SHIFT];
+static uint64_t jmptbl_allocated = 0, jmptbl_allocated1 = 0, jmptbl_allocated2 = 0, jmptbl_allocated3 = 0;
+static uintptr_t***        box64_jmptbl3[1<<JMPTABL_SHIFT3];
+static uintptr_t**         box64_jmptbldefault2[1<<JMPTABL_SHIFT2];
+static uintptr_t*          box64_jmptbldefault1[1<<JMPTABL_SHIFT1];
+static uintptr_t           box64_jmptbldefault0[1<<JMPTABL_SHIFT0];
 // lock addresses
 KHASH_SET_INIT_INT64(lockaddress)
 static kh_lockaddress_t    *lockaddress = NULL;
@@ -66,6 +67,9 @@ typedef struct memprot_s
     uint8_t* prot;
     uint8_t* hot;
 } memprot_t;
+#ifdef TRACE_MEMSTAT
+static uint64_t  memprot_allocated = 0, memprot_max_allocated = 0;
+#endif
 static memprot_t memprot[1<<MEMPROT_SIZE0];    // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection]
 static uint8_t   memprot_default[MEMPROT_SIZE];
 static int inited = 0;
@@ -293,6 +297,9 @@ static size_t roundSize(size_t size)
     return size;
 }
 
+#ifdef TRACE_MEMSTAT
+static uint64_t customMalloc_allocated = 0;
+#endif
 void* customMalloc(size_t size)
 {
     size = roundSize(size);
@@ -330,6 +337,9 @@ void* customMalloc(size_t size)
     #else
     void* p = box_calloc(1, allocsize);
     #endif
+#ifdef TRACE_MEMSTAT
+    customMalloc_allocated += allocsize;
+#endif
     p_blocks[i].block = p;
     p_blocks[i].first = p;
     p_blocks[i].size = allocsize;
@@ -451,6 +461,9 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
     return NULL;
 }
 
+#ifdef TRACE_MEMSTAT
+static uint64_t dynarec_allocated = 0;
+#endif
 uintptr_t AllocDynarecMap(size_t size)
 {
     if(!size)
@@ -498,6 +511,9 @@ uintptr_t AllocDynarecMap(size_t size)
                 return 0;
             }
             #endif
+#ifdef TRACE_MEMSTAT
+            dynarec_allocated += allocsize;
+#endif
             setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE | PROT_EXEC);
             list->chunks[i].block = p;
             list->chunks[i].first = p;
@@ -550,7 +566,7 @@ void FreeDynarecMap(uintptr_t addr)
             return;
         }
         ++i;
-        if(i=NCHUNK) {
+        if(i==NCHUNK) {
             i = 0;
             list = list->next;
         }
@@ -559,27 +575,29 @@ void FreeDynarecMap(uintptr_t addr)
 
 static uintptr_t getDBSize(uintptr_t addr, size_t maxsize, dynablock_t** db)
 {
-    const uintptr_t idx3 = (addr>>48)&0xffff;
-    const uintptr_t idx2 = (addr>>32)&0xffff;
-    const uintptr_t idx1 = (addr>>16)&0xffff;
-    uintptr_t idx0 = addr&0xffff;
+    const uintptr_t idx3 = (addr>>JMPTABL_START3)&JMPTABLE_MASK3;
+    const uintptr_t idx2 = (addr>>JMPTABL_START2)&JMPTABLE_MASK2;
+    const uintptr_t idx1 = (addr>>JMPTABL_START1)&JMPTABLE_MASK1;
+    uintptr_t idx0 = addr&JMPTABLE_MASK0;
     *db = *(dynablock_t**)(box64_jmptbl3[idx3][idx2][idx1][idx0]- sizeof(void*));
     if(*db)
-        return 1;
+        return addr+1;
     if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
-        return (addr|0xffffffffffffLL)+1-addr;
+        return ((idx3+1)<<JMPTABL_START3);
     if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
-        return (addr|0xffffffffLL)+1-addr;
+        return (((addr>>JMPTABL_START2)+1)<<JMPTABL_START2);
     uintptr_t* block = box64_jmptbl3[idx3][idx2][idx1];
     if(block == box64_jmptbldefault0)
-        return (addr|0xffffLL)+1-addr;
-    if (maxsize>0x10000)
-        maxsize = 0x10000;
-    while(idx0<maxsize && block[idx0]==(uintptr_t)native_next)
+        return (((addr>>JMPTABL_START1)+1)<<JMPTABL_START1);
+    if (maxsize>JMPTABLE_MASK0)
+        maxsize = JMPTABLE_MASK0;
+    while(block[idx0]==(uintptr_t)native_next) {
         ++idx0;
-    if(idx0<0x10000)
-        *db = *(dynablock_t**)(block[idx0]- sizeof(void*));
-    return idx0+1-(addr&0xffff);
+        if(idx0>maxsize)
+            return (addr&~JMPTABLE_MASK0)+idx0;
+    }
+    *db = *(dynablock_t**)(block[idx0]- sizeof(void*));
+    return (addr&~JMPTABLE_MASK0)+idx0+1;
 }
 
 // each dynmap is 64k of size
@@ -597,7 +615,7 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
     dynablock_t* db = NULL;
     uintptr_t end = addr+size;
     while (start_addr<end) {
-        start_addr += getDBSize(start_addr, end-start_addr, &db);
+        start_addr = getDBSize(start_addr, end-start_addr, &db);
         if(db) {
             if(destroy)
                 FreeRangeDynablock(db, addr, size);
@@ -607,110 +625,112 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
     }
 }
 
-int addJumpTableIfDefault64(void* addr, void* jmp)
+static uintptr_t *create_jmptbl(uintptr_t idx0, uintptr_t idx1, uintptr_t idx2, uintptr_t idx3)
 {
-    uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = (((uintptr_t)addr)>>48)&0xffff;
-    idx2 = (((uintptr_t)addr)>>32)&0xffff;
-    idx1 = (((uintptr_t)addr)>>16)&0xffff;
-    idx0 = (((uintptr_t)addr)    )&0xffff;
     if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
-        uintptr_t*** tbl = (uintptr_t***)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
+        uintptr_t*** tbl = (uintptr_t***)box_malloc((1<<JMPTABL_SHIFT2)*sizeof(uintptr_t**));
+        for(int i=0; i<(1<<JMPTABL_SHIFT2); ++i)
             tbl[i] = box64_jmptbldefault1;
         if(native_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
             box_free(tbl);
+#ifdef TRACE_MEMSTAT
+        else {
+            jmptbl_allocated += (1<<JMPTABL_SHIFT2)*sizeof(uintptr_t**);
+            ++jmptbl_allocated3;
+        }
+#endif
     }
     if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
-        uintptr_t** tbl = (uintptr_t**)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
+        uintptr_t** tbl = (uintptr_t**)box_malloc((1<<JMPTABL_SHIFT1)*sizeof(uintptr_t*));
+        for(int i=0; i<(1<<JMPTABL_SHIFT1); ++i)
             tbl[i] = box64_jmptbldefault0;
         if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
             box_free(tbl);
+#ifdef TRACE_MEMSTAT
+        else {
+            jmptbl_allocated += (1<<JMPTABL_SHIFT1)*sizeof(uintptr_t*);
+            ++jmptbl_allocated2;
+        }
+#endif
     }
     if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
-        uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
+        uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT0)*sizeof(uintptr_t));
+        for(int i=0; i<(1<<JMPTABL_SHIFT0); ++i)
             tbl[i] = (uintptr_t)native_next;
         if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
             box_free(tbl);
+#ifdef TRACE_MEMSTAT
+        else {
+            jmptbl_allocated += (1<<JMPTABL_SHIFT0)*sizeof(uintptr_t);
+            ++jmptbl_allocated1;
+        }
+#endif
     }
+    return &box64_jmptbl3[idx3][idx2][idx1][idx0];
+}
+
+int addJumpTableIfDefault64(void* addr, void* jmp)
+{
+    uintptr_t idx3, idx2, idx1, idx0;
+    idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
+    idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
+    idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
+    idx0 = (((uintptr_t)addr)                )&JMPTABLE_MASK0;
 
-    return (native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, native_next)==jmp)?1:0;
+    return (native_lock_storeifref(create_jmptbl(idx0, idx1, idx2, idx3), jmp, native_next)==jmp)?1:0;
 }
 void setJumpTableDefault64(void* addr)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = (((uintptr_t)addr)>>48)&0xffff;
+    idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
     if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
         return;
-    idx2 = (((uintptr_t)addr)>>32)&0xffff;
+    idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
     if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
         return;
-    idx1 = (((uintptr_t)addr)>>16)&0xffff;
+    idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
     if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
         return;
-    idx0 = (((uintptr_t)addr)    )&0xffff;
+    idx0 = (((uintptr_t)addr)    )&JMPTABLE_MASK0;
     box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)native_next;
 }
 void setJumpTableDefaultRef64(void* addr, void* jmp)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = (((uintptr_t)addr)>>48)&0xffff;
+    idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
     if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
         return;
-    idx2 = (((uintptr_t)addr)>>32)&0xffff;
+    idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
     if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
         return;
-    idx1 = (((uintptr_t)addr)>>16)&0xffff;
+    idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
     if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
         return;
-    idx0 = (((uintptr_t)addr)    )&0xffff;
+    idx0 = (((uintptr_t)addr)    )&JMPTABLE_MASK0;
     native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], native_next, jmp);
 }
 int setJumpTableIfRef64(void* addr, void* jmp, void* ref)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = (((uintptr_t)addr)>>48)&0xffff;
-    idx2 = (((uintptr_t)addr)>>32)&0xffff;
-    idx1 = (((uintptr_t)addr)>>16)&0xffff;
-    idx0 = (((uintptr_t)addr)    )&0xffff;
-    if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
-        uintptr_t*** tbl = (uintptr_t***)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = box64_jmptbldefault1;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
-            box_free(tbl);
-    }
-    if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
-        uintptr_t** tbl = (uintptr_t**)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = box64_jmptbldefault0;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
-            box_free(tbl);
-    }
-    if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
-        uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = (uintptr_t)native_next;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
-            box_free(tbl);
-    }
-    return (native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, ref)==jmp)?1:0;
+    idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
+    idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
+    idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
+    idx0 = (((uintptr_t)addr)    )&JMPTABLE_MASK0;
+    return (native_lock_storeifref(create_jmptbl(idx0, idx1, idx2, idx3), jmp, ref)==jmp)?1:0;
 }
 int isJumpTableDefault64(void* addr)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = (((uintptr_t)addr)>>48)&0xffff;
+    idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
     if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
         return 1;
-    idx2 = (((uintptr_t)addr)>>32)&0xffff;
+    idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
     if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
         return 1;
-    idx1 = (((uintptr_t)addr)>>16)&0xffff;
+    idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
     if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
         return 1;
-    idx0 = (((uintptr_t)addr)    )&0xffff;
+    idx0 = (((uintptr_t)addr)    )&JMPTABLE_MASK0;
     return (box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)native_next)?1:0;
 }
 uintptr_t getJumpTable64()
@@ -721,42 +741,20 @@ uintptr_t getJumpTable64()
 uintptr_t getJumpTableAddress64(uintptr_t addr)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = ((addr)>>48)&0xffff;
-    idx2 = ((addr)>>32)&0xffff;
-    idx1 = ((addr)>>16)&0xffff;
-    idx0 = ((addr)    )&0xffff;
-    if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
-        uintptr_t*** tbl = (uintptr_t***)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = box64_jmptbldefault1;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
-            box_free(tbl);
-    }
-    if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
-        uintptr_t** tbl = (uintptr_t**)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = box64_jmptbldefault0;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
-            box_free(tbl);
-    }
-    if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
-        uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
-            tbl[i] = (uintptr_t)native_next;
-        if(native_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
-            box_free(tbl);
-    }
-
-    return (uintptr_t)&box64_jmptbl3[idx3][idx2][idx1][idx0];
+    idx3 = ((addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
+    idx2 = ((addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
+    idx1 = ((addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
+    idx0 = ((addr)                )&JMPTABLE_MASK0;
+    return (uintptr_t)create_jmptbl(idx0, idx1, idx2, idx3);
 }
 
 dynablock_t* getDB(uintptr_t addr)
 {
     uintptr_t idx3, idx2, idx1, idx0;
-    idx3 = ((addr)>>48)&0xffff;
-    idx2 = ((addr)>>32)&0xffff;
-    idx1 = ((addr)>>16)&0xffff;
-    idx0 = ((addr)    )&0xffff;
+    idx3 = ((addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
+    idx2 = ((addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
+    idx1 = ((addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
+    idx0 = ((addr)                )&JMPTABLE_MASK0;
     /*if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
         return NULL;
     }
@@ -788,18 +786,23 @@ void protectDB(uintptr_t addr, uintptr_t size)
         if(memprot[i].prot==memprot_default) {
             uint8_t* newblock = box_calloc(1<<16, sizeof(uint8_t));
             memprot[i].prot = newblock;
+#ifdef TRACE_MEMSTAT
+            memprot_allocated += (1<<16) * sizeof(uint8_t);
+            if (memprot_allocated > memprot_max_allocated) memprot_max_allocated = memprot_allocated;
+#endif
         }
     for (uintptr_t i=idx; i<=end; ++i) {
         uint32_t prot = memprot[i>>16].prot[i&0xffff];
-        uint32_t dyn = prot&PROT_CUSTOM;
+        uint32_t dyn = prot&PROT_DYN;
+        uint32_t mapped = prot&PROT_MMAP;
         prot&=~PROT_CUSTOM;
         if(!prot)
             prot = PROT_READ | PROT_WRITE | PROT_EXEC;      // comes from malloc & co, so should not be able to execute
         if((prot&PROT_WRITE)) {
             if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
-            memprot[i>>16].prot[i&0xffff] = prot|PROT_DYNAREC;   // need to use atomic exchange?
+            memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC;   // need to use atomic exchange?
         } else 
-            memprot[i>>16].prot[i&0xffff] = prot|PROT_DYNAREC_R;
+            memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC_R;
     }
     mutex_unlock(&mutex_prot);
 }
@@ -816,21 +819,20 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
     if(end<idx) // memory addresses higher than 48bits are not tracked
         return;
     mutex_lock(&mutex_prot);
-    /*for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
-        if(memprot[i].prot==memprot_default) {
-            uint8_t* newblock = box_calloc(1<<16, sizeof(uint8_t));
-            memprot[i].prot = newblock;
-        }*/
     for (uintptr_t i=idx; i<=end; ++i) {
-        uint32_t prot = memprot[i>>16].prot[i&0xffff];
-        if(prot&PROT_DYNAREC) {
-            prot&=~PROT_CUSTOM;
-            if(mark)
-                cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
-            mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
-            memprot[i>>16].prot[i&0xffff] = prot;  // need to use atomic exchange?
-        } else if(prot&PROT_DYNAREC_R)
-            memprot[i>>16].prot[i&0xffff] = prot&~PROT_CUSTOM;
+        if(memprot[i>>16].prot==memprot_default) {
+            i=(((i>>16)+1)<<16)-1;  // next block
+        } else {
+            uint32_t prot = memprot[i>>16].prot[i&0xffff];
+            if(prot&PROT_DYNAREC) {
+                prot&=~PROT_DYN;
+                if(mark)
+                    cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
+                mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
+                memprot[i>>16].prot[i&0xffff] = prot;  // need to use atomic exchange?
+            } else if(prot&PROT_DYNAREC_R)
+                memprot[i>>16].prot[i&0xffff] = prot&~PROT_CUSTOM;
+        }
     }
     mutex_unlock(&mutex_prot);
 }
@@ -848,7 +850,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
     }
     for (uintptr_t i=idx; i<=end; ++i) {
         uint32_t prot = memprot[i>>16].prot[i&0xffff];
-        if(!(prot&(PROT_DYNAREC|PROT_DYNAREC_R))) {
+        if(!(prot&PROT_DYN)) {
             dynarec_log(LOG_DEBUG, "0\n");
             return 0;
         }
@@ -966,16 +968,22 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
         if(memprot[i].prot==memprot_default) {
             uint8_t* newblock = box_calloc(1<<16, sizeof(uint8_t));
             memprot[i].prot = newblock;
+#ifdef TRACE_MEMSTAT
+            memprot_allocated += (1<<16) * sizeof(uint8_t);
+            if (memprot_allocated > memprot_max_allocated) memprot_max_allocated = memprot_allocated;
+#endif
         }
     for (uintptr_t i=idx; i<=end; ++i) {
-        uint32_t dyn=(memprot[i>>16].prot[i&0xffff]&(PROT_DYNAREC | PROT_DYNAREC_R));
+        uint32_t old_prot = memprot[i>>16].prot[i&0xffff];
+        uint32_t dyn=(old_prot&PROT_DYN);
+        uint32_t mapped=(old_prot&PROT_MMAP);
         if(dyn && (prot&PROT_WRITE)) {   // need to remove the write protection from this block
             dyn = PROT_DYNAREC;
             mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
         } else if(dyn && !(prot&PROT_WRITE)) {
             dyn = PROT_DYNAREC_R;
         }
-        memprot[i>>16].prot[i&0xffff] = prot|dyn;
+        memprot[i>>16].prot[i&0xffff] = prot|dyn|mapped;
     }
     mutex_unlock(&mutex_prot);
 }
@@ -992,6 +1000,10 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
         if(memprot[i].prot==memprot_default && prot) {
             uint8_t* newblock = box_calloc(MEMPROT_SIZE, sizeof(uint8_t));
             memprot[i].prot = newblock;
+#ifdef TRACE_MEMSTAT
+            memprot_allocated += (1<<16) * sizeof(uint8_t);
+            if (memprot_allocated > memprot_max_allocated) memprot_max_allocated = memprot_allocated;
+#endif
         }
         if(prot || memprot[i].prot!=memprot_default) {
             uintptr_t bstart = ((i<<16)<idx)?(idx&0xffff):0;
@@ -1003,6 +1015,11 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
     mutex_unlock(&mutex_prot);
 }
 
+void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
+{
+    setProtection(addr, size, prot|PROT_MMAP);
+}
+
 void refreshProtection(uintptr_t addr)
 {
     mutex_lock(&mutex_prot);
@@ -1024,6 +1041,7 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
         end = (1LL<<(48-MEMPROT_SHIFT))-1;
     mutex_lock(&mutex_prot);
     addMapMem(addr, addr+size-1);
+    // don't need to add precise tracking probably
     /*for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
         if(memprot[i].prot==memprot_default) {
             uint8_t* newblock = box_calloc(1<<16, sizeof(uint8_t));
@@ -1094,6 +1112,11 @@ void AddHotPage(uintptr_t addr) {
             uint8_t* newblock = box_calloc(1<<16, sizeof(uint8_t));
             if (native_lock_storeifnull(&memprot[idx].hot, newblock)) {
                 box_free(newblock);
+#ifdef TRACE_MEMSTAT
+            } else {
+                memprot_allocated += (1<<16) * sizeof(uint8_t);
+                if (memprot_allocated > memprot_max_allocated) memprot_max_allocated = memprot_allocated;
+#endif
             }
     }
     native_lock_storeb(&memprot[idx].hot[base], box64_dynarec_hotpage);
@@ -1149,11 +1172,9 @@ void freeProtection(uintptr_t addr, size_t size)
             if(start==0 && finish==MEMPROT_SIZE-1) {
                 memprot[key].prot = memprot_default;
                 box_free(block);
-                if(memprot[key].hot) {
-                    uint8_t *hot = memprot[key].hot;
-                    memprot[key].hot = NULL;
-                    box_free(hot);
-                }
+#ifdef TRACE_MEMSTAT
+                memprot_allocated -= (1<<16) * sizeof(uint8_t);
+#endif
             } else {
                 memset(block+start, 0, (finish-start+1)*sizeof(uint8_t));
                 // blockempty is quite slow, so disable the free of blocks for now
@@ -1163,6 +1184,14 @@ void freeProtection(uintptr_t addr, size_t size)
                 }*/
             }
         }
+        if(memprot[key].hot && start==0 && finish==MEMPROT_SIZE-1) {
+            uint8_t *hot = memprot[key].hot;
+            memprot[key].hot = NULL;
+            box_free(hot);
+#ifdef TRACE_MEMSTAT
+            memprot_allocated -= (1<<16) * sizeof(uint8_t);
+#endif
+        }
         i+=finish-start;    // +1 from the "for" loop
     }
     mutex_unlock(&mutex_prot);
@@ -1176,7 +1205,18 @@ uint32_t getProtection(uintptr_t addr)
     const uintptr_t idx = (addr>>MEMPROT_SHIFT);
     uint32_t ret = memprot[idx>>16].prot[idx&0xffff];
     mutex_unlock(&mutex_prot);
-    return ret;
+    return ret&~PROT_MMAP;
+}
+
+int getMmapped(uintptr_t addr)
+{
+    if(addr>=(1LL<<48))
+        return 0;
+    mutex_lock(&mutex_prot);
+    const uintptr_t idx = (addr>>MEMPROT_SHIFT);
+    uint32_t ret = memprot[idx>>16].prot[idx&0xffff];
+    mutex_unlock(&mutex_prot);
+    return (ret&PROT_MMAP)?1:0;
 }
 
 #define LOWEST (void*)0x10000
@@ -1304,12 +1344,14 @@ void init_custommem_helper(box64context_t* ctx)
     init_mutexes();
 #ifdef DYNAREC
     if(box64_dynarec)
-        for(int i=0; i<(1<<JMPTABL_SHIFT); ++i) {
-            box64_jmptbldefault0[i] = (uintptr_t)native_next;
-            box64_jmptbldefault1[i] = box64_jmptbldefault0;
-            box64_jmptbldefault2[i] = box64_jmptbldefault1;
+        for(int i=0; i<(1<<JMPTABL_SHIFT3); ++i)
             box64_jmptbl3[i] = box64_jmptbldefault2;
-        }
+        for(int i=0; i<(1<<JMPTABL_SHIFT2); ++i)
+            box64_jmptbldefault2[i] = box64_jmptbldefault1;
+        for(int i=0; i<(1<<JMPTABL_SHIFT1); ++i)
+            box64_jmptbldefault1[i] = box64_jmptbldefault0;
+        for(int i=0; i<(1<<JMPTABL_SHIFT0); ++i)
+            box64_jmptbldefault0[i] = (uintptr_t)native_next;
     lockaddress = kh_init(lockaddress);
 #endif
     pthread_atfork(NULL, NULL, atfork_child_custommem);
@@ -1328,6 +1370,26 @@ void init_custommem_helper(box64context_t* ctx)
 void fini_custommem_helper(box64context_t *ctx)
 {
     (void)ctx;
+#ifdef TRACE_MEMSTAT
+    uintptr_t njmps = 0, njmps_in_lv1_max = 0;
+    for (uintptr_t idx3 = 0; idx3 < (1 << JMPTABL_SHIFT3); ++idx3) {
+        if (box64_jmptbl3[idx3] == box64_jmptbldefault2) continue;
+        for (uintptr_t idx2 = 0; idx2 < (1 << JMPTABL_SHIFT3); ++idx2) {
+            if (box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) continue;
+            for (uintptr_t idx1 = 0; idx1 < (1 << JMPTABL_SHIFT1); ++idx1) {
+                if (box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) continue;
+                uintptr_t njmps_in_cur_lv1 = 0;
+                for (uintptr_t idx0 = 0; idx0 < (1 << JMPTABL_SHIFT0); ++idx0) {
+                    if (box64_jmptbl3[idx3][idx2][idx1][idx0] == (uintptr_t)native_next) continue;
+                    ++njmps;
+                    ++njmps_in_cur_lv1;
+                }
+                if (njmps_in_cur_lv1 > njmps_in_lv1_max) njmps_in_lv1_max = njmps_in_cur_lv1;
+            }
+        }
+    }
+    printf_log(LOG_INFO, "Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- memprot: %lld kio (peak at %lld kio)\n- jump table: %lld kio (%lld level 3, %lld level 2, %lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, memprot_allocated / 1024, memprot_max_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated3, jmptbl_allocated2, jmptbl_allocated1, njmps, njmps_in_lv1_max);
+#endif
     if(!inited)
         return;
     inited = 0;
@@ -1351,11 +1413,11 @@ void fini_custommem_helper(box64context_t *ctx)
         }
 
         box_free(mmaplist);
-        for (int i3=0; i3<(1<<DYNAMAP_SHIFT); ++i3)
+        for (int i3=0; i3<(1<<JMPTABL_SHIFT3); ++i3)
             if(box64_jmptbl3[i3]!=box64_jmptbldefault2) {
-                for (int i2=0; i2<(1<<DYNAMAP_SHIFT); ++i2)
+                for (int i2=0; i2<(1<<JMPTABL_SHIFT2); ++i2)
                     if(box64_jmptbl3[i3][i2]!=box64_jmptbldefault1) {
-                        for (int i1=0; i1<(1<<DYNAMAP_SHIFT); ++i1)
+                        for (int i1=0; i1<(1<<JMPTABL_SHIFT1); ++i1)
                             if(box64_jmptbl3[i3][i2][i1]!=box64_jmptbldefault0) {
                                 box_free(box64_jmptbl3[i3][i2][i1]);
                             }
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index b25d490d..5a440520 100755
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -288,23 +288,23 @@
 
 #define LDPx_S7_postindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(1, 1, 0b01, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define LDPw_S7_postindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(0, 1, 0b01, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define LDPxw_S7_postindex(Rt, Rt2, Rn, imm)            EMIT(MEMPAIR_gen(rex.w, 1, 0b01, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define LDPxw_S7_postindex(Rt, Rt2, Rn, imm)            EMIT(MEMPAIR_gen(rex.w, 1, 0b01, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 #define LDPx_S7_preindex(Rt, Rt2, Rn, imm)              EMIT(MEMPAIR_gen(1, 1, 0b11, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define LDPw_S7_preindex(Rt, Rt2, Rn, imm)              EMIT(MEMPAIR_gen(0, 1, 0b11, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define LDPxw_S7_preindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(rex.w, 1, 0b11, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define LDPxw_S7_preindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(rex.w, 1, 0b11, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 #define LDPx_S7_offset(Rt, Rt2, Rn, imm)                EMIT(MEMPAIR_gen(1, 1, 0b10, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define LDPw_S7_offset(Rt, Rt2, Rn, imm)                EMIT(MEMPAIR_gen(0, 1, 0b10, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define LDPxw_S7_offset(Rt, Rt2, Rn, imm)               EMIT(MEMPAIR_gen(rex.w, 1, 0b10, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define LDPxw_S7_offset(Rt, Rt2, Rn, imm)               EMIT(MEMPAIR_gen(rex.w, 1, 0b10, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 
 #define STPx_S7_postindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(1, 0, 0b01, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define STPw_S7_postindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(0, 0, 0b01, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define STPxw_S7_postindex(Rt, Rt2, Rn, imm)            EMIT(MEMPAIR_gen(rex.w, 0, 0b01, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define STPxw_S7_postindex(Rt, Rt2, Rn, imm)            EMIT(MEMPAIR_gen(rex.w, 0, 0b01, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 #define STPx_S7_preindex(Rt, Rt2, Rn, imm)              EMIT(MEMPAIR_gen(1, 0, 0b11, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define STPw_S7_preindex(Rt, Rt2, Rn, imm)              EMIT(MEMPAIR_gen(0, 0, 0b11, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define STPxw_S7_preindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(rex.w, 0, 0b11, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define STPxw_S7_preindex(Rt, Rt2, Rn, imm)             EMIT(MEMPAIR_gen(rex.w, 0, 0b11, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 #define STPx_S7_offset(Rt, Rt2, Rn, imm)                EMIT(MEMPAIR_gen(1, 0, 0b10, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
 #define STPw_S7_offset(Rt, Rt2, Rn, imm)                EMIT(MEMPAIR_gen(0, 0, 0b10, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
-#define STPxw_S7_offset(Rt, Rt2, Rn, imm)               EMIT(MEMPAIR_gen(rex.w, 0, 0b10, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
+#define STPxw_S7_offset(Rt, Rt2, Rn, imm)               EMIT(MEMPAIR_gen(rex.w, 0, 0b10, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
 
 // PUSH / POP helper
 #define POP1(reg)       LDRx_S9_postindex(reg, xRSP, 8)
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index fe039dd7..8a51ab72 100755
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -1642,27 +1642,31 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             GETGX(v0, 1);

             if(!MODREG) {

                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);

-                v1 = 0; // to avoid a warning

+                v1 = -1; // to avoid a warning

             } else

                 v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);

             u8 = F8;

-            if(MODREG && v0==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {

+            if(v0==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {

                 VDUPQ_32(v0, v0, u8&3);

+            } else if(v0==v1 && (u8==0xe0)) {   // easy special case

+                VMOVeS(v0, 1, v0, 0);

+            } else if(v0==v1 && (u8==0xe5)) {   // easy special case

+                VMOVeS(v0, 0, v0, 1);

             } else {

                 d0 = fpu_get_scratch(dyn);

                 // first two elements from Gx

                 for(int i=0; i<2; ++i) {

-                    VMOVeS(d0, i, v0, (u8>>(i*2)&3));

+                    VMOVeS(d0, i, v0, (u8>>(i*2))&3);

                 }

                 // second two from Ex

                 if(MODREG) {

                     for(int i=2; i<4; ++i) {

-                        VMOVeS(d0, i, v1, (u8>>(i*2)&3));

+                        VMOVeS(d0, i, v1, (u8>>(i*2))&3);

                     }

                 } else {

                     SMREAD();

                     for(int i=2; i<4; ++i) {

-                        ADDx_U12(x2, ed, (u8>>(i*2)&3)*4);

+                        ADDx_U12(x2, ed, ((u8>>(i*2))&3)*4);

                         VLD1_32(d0, i, x2);

                     }

                 }

diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c
index 814c2552..01cd736a 100755
--- a/src/dynarec/arm64/dynarec_arm64_660f.c
+++ b/src/dynarec/arm64/dynarec_arm64_660f.c
@@ -1984,7 +1984,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             nextop = F8;

             GETEX(v1, 0, 0);

             GETGX_empty(v0);

-            VFCVTNSQD(v0, v1);  // convert double -> int64

+            VFCVTZSQD(v0, v1);  // convert double -> int64

             SQXTN_32(v0, v0);   // convert int64 -> int32 with saturation in lower part, RaZ high part

             break;

         case 0xE7:

diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index a9af4bf9..569add20 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -405,13 +405,13 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
         uintptr_t tbl = getJumpTable64();
         MAYUSE(tbl);
         TABLE64(x3, tbl);
-        UBFXx(x2, xRIP, 48, JMPTABL_SHIFT);
+        UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
         LDRx_REG_LSL3(x3, x3, x2);
-        UBFXx(x2, xRIP, 32, JMPTABL_SHIFT);
+        UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
         LDRx_REG_LSL3(x3, x3, x2);
-        UBFXx(x2, xRIP, 16, JMPTABL_SHIFT);
+        UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
         LDRx_REG_LSL3(x3, x3, x2);
-        UBFXx(x2, xRIP, 0, JMPTABL_SHIFT);
+        UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
         LDRx_REG_LSL3(x2, x3, x2);
     } else {
         uintptr_t p = getJumpTableAddress64(ip);
@@ -450,13 +450,13 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
     }
     uintptr_t tbl = getJumpTable64();
     MOV64x(x2, tbl);
-    UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
     LDRx_REG_LSL3(x2, x2, x3);
     BLR(x2); // save LR
     CLEARIP();
@@ -487,13 +487,13 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
     }
     uintptr_t tbl = getJumpTable64();
     MOV64x(x2, tbl);
-    UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
     LDRx_REG_LSL3(x2, x2, x3);
-    UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
+    UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
     LDRx_REG_LSL3(x2, x2, x3);
     BLR(x2); // save LR
     CLEARIP();
diff --git a/src/include/box64context.h b/src/include/box64context.h
index c8360017..010521e8 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -33,9 +33,8 @@ typedef struct mmaplist_s       mmaplist_t;
 typedef struct kh_dynablocks_s  kh_dynablocks_t;
 #endif
 #define DYNAMAP_SHIFT 16
-#define JMPTABL_SHIFT 16
 
-typedef void* (*procaddess_t)(const char* name);
+typedef void* (*procaddress_t)(const char* name);
 typedef void* (*vkprocaddess_t)(void* instance, const char* name);
 
 #define MAX_SIGNAL 64
@@ -115,9 +114,6 @@ typedef struct box64context_s {
     uintptr_t           vsyscall;       // vsyscall bridge value
     uintptr_t           vsyscalls[3];   // the 3 x86 VSyscall pseudo bridges (mapped at 0xffffffffff600000+)
     dlprivate_t         *dlprivate;     // dlopen library map
-    kh_symbolmap_t      *glwrappers;    // the map of wrapper for glProcs (for GLX or SDL1/2)
-    kh_symbolmap_t      *glmymap;       // link to the mysymbolmap of libGL
-    procaddess_t        glxprocaddress;
     kh_symbolmap_t      *alwrappers;    // the map of wrapper for alGetProcAddress
     kh_symbolmap_t      *almymap;       // link to the mysymbolmap if libOpenAL
     kh_symbolmap_t      *vkwrappers;    // the map of wrapper for VulkanProcs (TODO: check SDL2)
diff --git a/src/include/custommem.h b/src/include/custommem.h
index f2a4481d..e03db81c 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -34,17 +34,34 @@ int isJumpTableDefault64(void* addr);
 uintptr_t getJumpTable64();
 uintptr_t getJumpTableAddress64(uintptr_t addr);
 uintptr_t getJumpAddress64(uintptr_t addr);
+
+#define JMPTABL_SHIFT3 18
+#define JMPTABL_SHIFT2 18
+#define JMPTABL_SHIFT1 18
+#define JMPTABL_SHIFT0 10
+#define JMPTABL_START3 (JMPTABL_START2+JMPTABL_SHIFT2)
+#define JMPTABL_START2 (JMPTABL_START1+JMPTABL_SHIFT1)
+#define JMPTABL_START1 (JMPTABL_START0+JMPTABL_SHIFT0)
+#define JMPTABL_START0 0
+#define JMPTABLE_MASK3 ((1<<JMPTABL_SHIFT3)-1)
+#define JMPTABLE_MASK2 ((1<<JMPTABL_SHIFT2)-1)
+#define JMPTABLE_MASK1 ((1<<JMPTABL_SHIFT1)-1)
+#define JMPTABLE_MASK0 ((1<<JMPTABL_SHIFT0)-1)
 #endif
 
 #define PROT_DYNAREC    0x80
 #define PROT_DYNAREC_R  0x40
-#define PROT_CUSTOM     (PROT_DYNAREC | PROT_DYNAREC_R)
+#define PROT_MMAP       0x20
+#define PROT_DYN        (PROT_DYNAREC | PROT_DYNAREC_R)
+#define PROT_CUSTOM     (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP)
 
 void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
 void setProtection(uintptr_t addr, size_t size, uint32_t prot);
+void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot);
 void freeProtection(uintptr_t addr, size_t size);
 void refreshProtection(uintptr_t addr);
 uint32_t getProtection(uintptr_t addr);
+int getMmapped(uintptr_t addr);
 void loadProtectionFromMap();
 #ifdef DYNAREC
 void protectDB(uintptr_t addr, size_t size);
diff --git a/src/include/debug.h b/src/include/debug.h
index b9729787..e2e75ee1 100755
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -33,6 +33,7 @@ extern int arm64_crc32;
 extern int arm64_atomics;
 #endif
 #endif
+extern int box64_libcef;
 extern int dlsym_error;    // log dlsym error
 extern int cycle_log;      // if using rolling logs
 #ifdef HAVE_TRACE
@@ -46,6 +47,7 @@ extern char* box64_trace;
 extern uint64_t start_cnt;
 #endif
 extern int box64_nosandbox;
+extern int box64_malloc_hack;
 extern int box64_dummy_crashhandler;
 extern int box64_sse_flushto0;
 extern int box64_x87_no80bits;
diff --git a/src/include/gltools.h b/src/include/gltools.h
new file mode 100644
index 00000000..07bd74f7
--- /dev/null
+++ b/src/include/gltools.h
@@ -0,0 +1,12 @@
+#ifndef __GL_TOOLS_H__
+#define __GL_TOOLS_H__
+
+typedef struct box64context_s box64context_t;
+
+typedef void* (*glprocaddress_t)(const char* name);
+
+void freeGLProcWrapper(box64context_t* context);
+
+void* getGLProcAddress(x64emu_t* emu, glprocaddress_t procaddr, const char* rname);
+
+#endif //__GL_TOOLS_H__
\ No newline at end of file
diff --git a/src/include/library.h b/src/include/library.h
index 48200a9e..afe108e7 100755
--- a/src/include/library.h
+++ b/src/include/library.h
@@ -28,10 +28,6 @@ int IsSameLib(library_t* lib, const char* path);    // check if lib is same (pat
 int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
 int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
 int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
-void fillGLProcWrapper(box64context_t* context);
-void freeGLProcWrapper(box64context_t* context);
-void fillALProcWrapper(box64context_t* context);
-void freeALProcWrapper(box64context_t* context);
 char** GetNeededLibsNames(library_t* lib);
 int GetNeededLibsN(library_t* lib);
 library_t* GetNeededLib(library_t* lib, int idx);
diff --git a/src/include/myalign.h b/src/include/myalign.h
index 4a705afa..cc4922bd 100755
--- a/src/include/myalign.h
+++ b/src/include/myalign.h
@@ -50,7 +50,7 @@ typedef struct {
     memcpy(&p[6], emu->xmm, 8*16);                  \
   }
 
-
+#define PREFER_CONVERT_VAARG
 
 #elif defined(__aarch64__)
 // aarch64: 8 64bits general regs and 8 128bits float regs
@@ -92,6 +92,8 @@ typedef struct  va_list {
     memcpy(&p[6], emu->xmm, 8*16);                                      \
   }
 
+#define PREFER_CONVERT_VAARG
+
 #elif defined(__sw_64__) /* or Alpha */
 /*
 typdef struct {
diff --git a/src/librarian/library.c b/src/librarian/library.c
index 3cfb2bee..48919220 100755
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -306,6 +306,10 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
             box64_dynarec_strongmem = 1;
         }
         #endif
+        if(libname && box64_libcef && strstr(libname, "libcef.so")) {
+            printf_log(LOG_INFO, "libcef detected, using malloc_hack_2\n");
+            box64_malloc_hack = 2;
+        }
         return 1;
     }
     return 0;
diff --git a/src/library_list.h b/src/library_list.h
index fa492fec..9fbb5513 100755
--- a/src/library_list.h
+++ b/src/library_list.h
@@ -11,6 +11,8 @@ GO("libGL.so.1", libgl)
 GO("libGL.so", libgl)
 GO("libOpenGL.so.0", libgl)
 GO("libGLU.so.1", libglu)
+GO("libGLX.so.0", libglx)
+GO("libGLX.so", libglx)
 GO("libX11.so.6", libx11)
 GO("libasound.so.2", libasound)
 GO("libdl.so.2", libdl)
@@ -145,6 +147,7 @@ GO("libpango-1.0.so", pango)
 //GO("libnm.so.0", libnm)
 //GO("libnm-glib.so.4", libnm)
 //GO("libnm-util.so.2", libnm)
+GO("libibus-1.0.so.5", libibus)
 GO("libfontconfig.so.1", fontconfig)
 GO("libfreetype.so.6", freetype)
 GO("libbz2.so.1", bz2)
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index b2da2723..f8aa6cb8 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -847,6 +847,14 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
 #endif
     int Locks = unlockMutex();
     uint32_t prot = getProtection((uintptr_t)addr);
+    #ifdef RK3588
+    // try to see if the si_code makes sense
+    // the RK3588 tend to need a special Kernel that seems to have a weird behaviour sometimes
+    if((sig==SIGSEGV) && (addr) && (info->si_code == 1) && prot&(PROT_READ|PROT_WRITE|PROT_EXEC)) {
+        printf_log(LOG_DEBUG, "Workaround for suspicious si_code for %p / prot=0x%x\n", addr, prot);
+        info->si_code = 2;
+    }
+    #endif
 #ifdef DYNAREC
     if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) {
         relockMutex(Locks);
@@ -984,7 +992,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
         printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr);
 exit(-1);
     } else {
-        if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) {
+        if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_DYN)==5 || (prot&~PROT_DYN)==7)) {
             static uintptr_t old_addr = 0;
         printf_log(/*LOG_DEBUG*/LOG_INFO, "Strange SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x (old_addr=%p)\n", pc, addr, db, prot, (void*)old_addr);
             if(old_addr!=(uintptr_t)addr) {
@@ -1108,7 +1116,6 @@ exit(-1);
                 free(strings);
             } else
                 printf_log(log_minimum, "EmulatedBT: none\n");
-printf_log(log_minimum, "RDI = %p, Prot=0x%02x, ElfName(RDI)=%s\n",(void*)R_RDI, getProtection(R_RDI), ElfName(FindElfAddress(my_context, R_RDI)));
             #define GO(A) R_##A = old_##A
             GO(RAX);
             GO(RBX);
diff --git a/src/main.c b/src/main.c
index 6b5e6dc7..20e5bd35 100755
--- a/src/main.c
+++ b/src/main.c
@@ -45,6 +45,7 @@ int box64_dynarec_log = LOG_NONE;
 uintptr_t box64_pagesize;
 uintptr_t box64_load_addr = 0;
 int box64_nosandbox = 0;
+int box64_malloc_hack = 0;
 #ifdef DYNAREC
 int box64_dynarec = 1;
 int box64_dynarec_dump = 0;
@@ -72,6 +73,7 @@ int arm64_atomics = 0;
 #else   //DYNAREC
 int box64_dynarec = 0;
 #endif
+int box64_libcef = 1;
 int dlsym_error = 0;
 int cycle_log = 0;
 #ifdef HAVE_TRACE
@@ -626,6 +628,15 @@ void LoadLogEnv()
 #endif
 #endif
     // Other BOX64 env. var.
+    p = getenv("BOX64_LIBCEF");
+    if(p) {
+        if(strlen(p)==1) {
+            if(p[0]>='0' && p[0]<='1')
+                box64_libcef = p[0]-'0';
+        }
+        if(!box64_libcef)
+            printf_log(LOG_INFO, "Dynarec will not detect libcef\n");
+    }
     p = getenv("BOX64_LOAD_ADDR");
     if(p) {
         if(sscanf(p, "0x%zx", &box64_load_addr)!=1)
@@ -689,6 +700,19 @@ void LoadLogEnv()
         if(!box64_dummy_crashhandler)
             printf_log(LOG_INFO, "Don't use dummy crashhandler lib\n");
     }
+    p = getenv("BOX64_MALLOC_HACK");
+    if(p) {
+        if(strlen(p)==1) {
+            if(p[0]>='0' && p[0]<='0'+2)
+                box64_malloc_hack = p[0]-'0';
+        }
+        if(!box64_malloc_hack) {
+            if(box64_malloc_hack==1) {
+                printf_log(LOG_INFO, "Malloc hook will not be redirected\n");
+            } else
+                printf_log(LOG_INFO, "Malloc hook will check for mmap/free occurences\n");
+        }
+    }
     p = getenv("BOX64_NOPULSE");
     if(p) {
         if(strlen(p)==1) {
diff --git a/src/mallochook.c b/src/mallochook.c
index 4faa8c08..e502a1a3 100644
--- a/src/mallochook.c
+++ b/src/mallochook.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/param.h>
+#include <sys/mman.h>
 #include <dlfcn.h>
 
 #include "box64context.h"
@@ -11,6 +12,7 @@
 #include "callback.h"
 #include "librarian.h"
 #include "elfs/elfloader_private.h"
+#include "custommem.h"
 
 /*
     This file here is for handling overriding of malloc functions
@@ -139,6 +141,10 @@ void*(*__libc_memalign)(size_t, size_t) = NULL;
 size_t(*box_malloc_usable_size)(void*) = NULL;
 
 int GetTID();
+uint32_t getProtection(uintptr_t addr);
+// malloc_hack "2" handling
+// mmap history
+static int malloc_hack_2 = 0;
 
 char* box_strdup(const char* s) {
     char* ret = box_calloc(1, strlen(s)+1);
@@ -182,6 +188,13 @@ EXPORT void* malloc(size_t l)
 
 EXPORT void free(void* p)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
@@ -192,6 +205,16 @@ EXPORT void* calloc(size_t n, size_t s)
 
 EXPORT void* realloc(void* p, size_t s)
 {
+    if(malloc_hack_2)
+        if(getMmapped((uintptr_t)p)) {
+            // found! Will realloc using regular malloc then copy from old address as much as possible, but need to check size first
+            void* ret = box_malloc(s);
+            printf_log(LOG_DEBUG, "Malloc_Hack_2: hacking realloc(%p, %zu)", p, s);
+            while(s && !(getProtection((uintptr_t)p+s)&PROT_READ)) {if(s>box64_pagesize) s-=box64_pagesize; else s=0;}
+            memcpy(ret, p, s);
+            printf_log(LOG_DEBUG, " -> %p (copied %zu from old)\n", ret, s);
+            return ret;
+        }
     return box_realloc(p, s);
 }
 
@@ -228,6 +251,13 @@ EXPORT void* pvalloc(size_t size)
 
 EXPORT void cfree(void* p)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
@@ -259,26 +289,61 @@ EXPORT void* my__ZnamRKSt9nothrow_t(size_t sz, void* p)   //operator new[](size_
 
 EXPORT void my__ZdaPv(void* p)   //operator delete[](void*)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdaPvm(void* p, size_t sz)   //operator delete[](void*, size_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdaPvmSt11align_val_t(void* p, size_t sz, size_t align)   //operator delete[](void*, unsigned long, std::align_val_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdlPv(void* p)   //operator delete(void*)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdlPvm(void* p, size_t sz)   //operator delete(void*, size_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
@@ -304,36 +369,85 @@ EXPORT void* my__ZnamSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void
 
 EXPORT void my__ZdlPvRKSt9nothrow_t(void* p, void* n)   //operator delete(void*, std::nothrow_t const&)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdaPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n)   //operator delete[](void*, std::align_val_t, std::nothrow_t const&)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdlPvmSt11align_val_t(void* p, size_t sz, size_t align)   //operator delete(void*, unsigned long, std::align_val_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdaPvRKSt9nothrow_t(void* p, void* n)   //operator delete[](void*, std::nothrow_t const&)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdaPvSt11align_val_t(void* p, size_t align)   //operator delete[](void*, std::align_val_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdlPvSt11align_val_t(void* p, size_t align)   //operator delete(void*, std::align_val_t)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
 EXPORT void my__ZdlPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n)   //operator delete(void*, std::align_val_t, std::nothrow_t const&)
 {
+    if(malloc_hack_2 && p) {
+        if(getMmapped((uintptr_t)p)) {
+            printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
+            // Mmaped, do not free...
+            return;
+        }
+    }
     box_free(p);
 }
 
@@ -590,6 +704,8 @@ static void addRelocJmp(void* offs, void* where, size_t size, const char* name)
 void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
 {
     int hooked = 0;
+    if(box64_malloc_hack==1)
+        return;
     for (size_t i=0; i<h->numDynSym && hooked<2; ++i) {
         const char * symname = h->DynStr+h->DynSym[i].st_name;
         int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
@@ -610,7 +726,9 @@ void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
     }
     if(hooked<2)
         return; // only redirect on lib that hooked / redefined the operators
-    printf_log(LOG_INFO, "Redirecting overriden malloc function for %s\n", ElfName(h));
+    if(box64_malloc_hack==2)
+        malloc_hack_2 = 1;
+    printf_log(LOG_INFO, "Redirecting overriden malloc%s function for %s\n", malloc_hack_2?" with hack":"", ElfName(h));
     for (size_t i=0; i<h->numDynSym; ++i) {
         const char * symname = h->DynStr+h->DynSym[i].st_name;
         int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
diff --git a/src/tools/gtkclass.c b/src/tools/gtkclass.c
index 8359294a..881f5000 100755
--- a/src/tools/gtkclass.c
+++ b/src/tools/gtkclass.c
@@ -42,6 +42,13 @@ typedef struct sigoffset_array_s {
 KHASH_MAP_INIT_INT64(sigoffset, sigoffset_array_t)
 static kh_sigoffset_t *my_sigoffset = NULL;
 
+#define ONCE() \
+    static int done = 0;\
+    if(done)            \
+        return;         \
+    done = 1
+
+
 // ---- Defining the multiple functions now -----
 #define SUPER() \
 GO(0)   \
@@ -171,6 +178,7 @@ static void unwrapGObjectClass(my_GObjectClass_t* class)
 // autobridge
 static void bridgeGObjectClass(my_GObjectClass_t* class)
 {
+    ONCE();
     #define GO(A, W) autobridge_##A##_GObject (W, class->A)
     SUPERGO()
     #undef GO
@@ -215,6 +223,7 @@ static void unwrapGInitiallyUnownedClass(my_GInitiallyUnownedClass_t* class)
 // autobridge
 static void bridgeGInitiallyUnownedClass(my_GInitiallyUnownedClass_t* class)
 {
+    ONCE();
     #define GO(A, W) autobridge_##A##_GInitiallyUnowned (W, class->A)
     SUPERGO()
     #undef GO
@@ -250,6 +259,7 @@ static void unwrapGtkObjectClass(my_GtkObjectClass_t* class)
 // autobridge
 static void bridgeGtkObjectClass(my_GtkObjectClass_t* class)
 {
+    ONCE();
     bridgeGObjectClass(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkObject (W, class->A)
     SUPERGO()
@@ -414,6 +424,7 @@ static void unwrapGtkWidget2Class(my_GtkWidget2Class_t* class)
 // autobridge
 static void bridgeGtkWidget2Class(my_GtkWidget2Class_t* class)
 {
+    ONCE();
     bridgeGtkObjectClass(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkWidget2 (W, class->A)
     SUPERGO()
@@ -611,6 +622,7 @@ static void unwrapGtkWidget3Class(my_GtkWidget3Class_t* class)
 // autobridge
 static void bridgeGtkWidget3Class(my_GtkWidget3Class_t* class)
 {
+    ONCE();
     bridgeGInitiallyUnownedClass(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkWidget3 (W, class->A)
     SUPERGO()
@@ -661,6 +673,7 @@ static void unwrapGtkContainer2Class(my_GtkContainer2Class_t* class)
 // autobridge
 static void bridgeGtkContainer2Class(my_GtkContainer2Class_t* class)
 {
+    ONCE();
     bridgeGtkWidget2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkContainer2 (W, class->A)
     SUPERGO()
@@ -713,6 +726,7 @@ static void unwrapGtkContainer3Class(my_GtkContainer3Class_t* class)
 // autobridge
 static void bridgeGtkContainer3Class(my_GtkContainer3Class_t* class)
 {
+    ONCE();
     bridgeGtkWidget3Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkContainer3 (W, class->A)
     SUPERGO()
@@ -757,6 +771,7 @@ static void unwrapGtkActionClass(my_GtkActionClass_t* class)
 // autobridge
 static void bridgeGtkActionClass(my_GtkActionClass_t* class)
 {
+    ONCE();
     bridgeGObjectClass(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkAction (W, class->A)
     SUPERGO()
@@ -779,6 +794,7 @@ static void unwrapGtkMisc2Class(my_GtkMisc2Class_t* class)
 // autobridge
 static void bridgeGtkMisc2Class(my_GtkMisc2Class_t* class)
 {
+    ONCE();
     bridgeGtkWidget2Class(&class->parent_class);
 }
 
@@ -815,6 +831,7 @@ static void unwrapGtkLabel2Class(my_GtkLabel2Class_t* class)
 // autobridge
 static void bridgeGtkLabel2Class(my_GtkLabel2Class_t* class)
 {
+    ONCE();
     bridgeGtkMisc2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkMisc2 (W, class->A)
     SUPERGO()
@@ -878,6 +895,7 @@ static void unwrapGtkTreeView2Class(my_GtkTreeView2Class_t* class)
 // autobridge
 static void bridgeGtkTreeView2Class(my_GtkTreeView2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkTreeView2 (W, class->A)
     SUPERGO()
@@ -901,6 +919,7 @@ static void unwrapGtkBin2Class(my_GtkBin2Class_t* class)
 // autobridge
 static void bridgeGtkBin2Class(my_GtkBin2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
 }
 
@@ -941,6 +960,7 @@ static void unwrapGtkWindow2Class(my_GtkWindow2Class_t* class)
 // autobridge
 static void bridgeGtkWindow2Class(my_GtkWindow2Class_t* class)
 {
+    ONCE();
     bridgeGtkBin2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkWindow2 (W, class->A)
     SUPERGO()
@@ -963,6 +983,7 @@ static void unwrapGtkTable2Class(my_GtkTable2Class_t* class)
 // autobridge
 static void bridgeGtkTable2Class(my_GtkTable2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
 }
 
@@ -981,6 +1002,7 @@ static void unwrapGtkFixed2Class(my_GtkFixed2Class_t* class)
 // autobridge
 static void bridgeGtkFixed2Class(my_GtkFixed2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
 }
 
@@ -999,6 +1021,7 @@ static void unwrapMetaFrames2Class(my_MetaFrames2Class_t* class)
 // autobridge
 static void bridgeMetaFrames2Class(my_MetaFrames2Class_t* class)
 {
+    ONCE();
     bridgeGtkWindow2Class(&class->parent_class);
 }
 
@@ -1031,6 +1054,7 @@ static void unwrapGDBusObjectManagerClientClass(my_GDBusObjectManagerClientClass
 // autobridge
 static void bridgeGDBusObjectManagerClientClass(my_GDBusObjectManagerClientClass_t* class)
 {
+    ONCE();
     bridgeGObjectClass(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GDBusObjectManagerClient (W, class->A)
     SUPERGO()
@@ -1076,6 +1100,7 @@ static void unwrapGtkButton2Class(my_GtkButton2Class_t* class)
 // autobridge
 static void bridgeGtkButton2Class(my_GtkButton2Class_t* class)
 {
+    ONCE();
     bridgeGtkBin2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkButton2 (W, class->A)
     SUPERGO()
@@ -1113,6 +1138,7 @@ static void unwrapGtkComboBox2Class(my_GtkComboBox2Class_t* class)
 // autobridge
 static void bridgeGtkComboBox2Class(my_GtkComboBox2Class_t* class)
 {
+    ONCE();
     bridgeGtkBin2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkComboBox2 (W, class->A)
     SUPERGO()
@@ -1148,6 +1174,7 @@ static void unwrapGtkToggleButton2Class(my_GtkToggleButton2Class_t* class)
 // autobridge
 static void bridgeGtkToggleButton2Class(my_GtkToggleButton2Class_t* class)
 {
+    ONCE();
     bridgeGtkButton2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkToggleButton2 (W, class->A)
     SUPERGO()
@@ -1183,6 +1210,7 @@ static void unwrapGtkCheckButton2Class(my_GtkCheckButton2Class_t* class)
 // autobridge
 static void bridgeGtkCheckButton2Class(my_GtkCheckButton2Class_t* class)
 {
+    ONCE();
     bridgeGtkToggleButton2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkCheckButton2 (W, class->A)
     SUPERGO()
@@ -1237,6 +1265,7 @@ static void unwrapGtkEntry2Class(my_GtkEntry2Class_t* class)
 // autobridge
 static void bridgeGtkEntry2Class(my_GtkEntry2Class_t* class)
 {
+    ONCE();
     bridgeGtkWidget2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkEntry2 (W, class->A)
     SUPERGO()
@@ -1279,6 +1308,7 @@ static void unwrapGtkSpinButton2Class(my_GtkSpinButton2Class_t* class)
 // autobridge
 static void bridgeGtkSpinButton2Class(my_GtkSpinButton2Class_t* class)
 {
+    ONCE();
     bridgeGtkEntry2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkSpinButton2 (W, class->A)
     SUPERGO()
@@ -1317,6 +1347,7 @@ static void unwrapGtkProgress2Class(my_GtkProgress2Class_t* class)
 // autobridge
 static void bridgeGtkProgress2Class(my_GtkProgress2Class_t* class)
 {
+    ONCE();
     bridgeGtkWidget2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkProgress2 (W, class->A)
     SUPERGO()
@@ -1349,6 +1380,7 @@ static void unwrapGtkProgressBar2Class(my_GtkProgressBar2Class_t* class)
 // autobridge
 static void bridgeGtkProgressBar2Class(my_GtkProgressBar2Class_t* class)
 {
+    ONCE();
     bridgeGtkProgress2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkProgressBar2 (W, class->A)
     SUPERGO()
@@ -1383,6 +1415,7 @@ static void unwrapGtkFrame2Class(my_GtkFrame2Class_t* class)
 // autobridge
 static void bridgeGtkFrame2Class(my_GtkFrame2Class_t* class)
 {
+    ONCE();
     bridgeGtkBin2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkFrame2 (W, class->A)
     SUPERGO()
@@ -1433,6 +1466,7 @@ static void unwrapGtkMenuShell2Class(my_GtkMenuShell2Class_t* class)
 // autobridge
 static void bridgeGtkMenuShell2Class(my_GtkMenuShell2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkMenuShell2 (W, class->A)
     SUPERGO()
@@ -1465,6 +1499,7 @@ static void unwrapGtkMenuBar2Class(my_GtkMenuBar2Class_t* class)
 // autobridge
 static void bridgeGtkMenuBar2Class(my_GtkMenuBar2Class_t* class)
 {
+    ONCE();
     bridgeGtkMenuShell2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkMenuBar2 (W, class->A)
     SUPERGO()
@@ -1523,6 +1558,7 @@ static void unwrapGtkTextView2Class(my_GtkTextView2Class_t* class)
 // autobridge
 static void bridgeGtkTextView2Class(my_GtkTextView2Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer2Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkTextView2 (W, class->A)
     SUPERGO()
@@ -1583,6 +1619,7 @@ static void unwrapGtkTextView3Class(my_GtkTextView3Class_t* class)
 // autobridge
 static void bridgeGtkTextView3Class(my_GtkTextView3Class_t* class)
 {
+    ONCE();
     bridgeGtkContainer3Class(&class->parent_class);
     #define GO(A, W) autobridge_##A##_GtkTextView3 (W, class->A)
     SUPERGO()
@@ -1667,6 +1704,7 @@ static void unwrapAtkObjectClass(my_AtkObjectClass_t* class)
 // autobridge
 static void bridgeAtkObjectClass(my_AtkObjectClass_t* class)
 {
+    ONCE();
     bridgeGObjectClass(&class->parent);
     #define GO(A, W) autobridge_##A##_AtkObject (W, class->A)
     SUPERGO()
@@ -1713,6 +1751,7 @@ static void unwrapAtkUtilClass(my_AtkUtilClass_t* class)
 // autobridge
 static void bridgeAtkUtilClass(my_AtkUtilClass_t* class)
 {
+    ONCE();
     bridgeGObjectClass(&class->parent);
     #define GO(A, W) autobridge_##A##_AtkUtil (W, class->A)
     SUPERGO()
@@ -1747,6 +1786,7 @@ static void unwrapGstObjectClass(my_GstObjectClass_t* class)
 // autobridge
 static void bridgeGstObjectClass(my_GstObjectClass_t* class)
 {
+    ONCE();
     bridgeGInitiallyUnownedClass(&class->parent);
     #define GO(A, W) autobridge_##A##_GstObject (W, class->A)
     SUPERGO()
@@ -1783,6 +1823,7 @@ static void unwrapGstAllocatorClass(my_GstAllocatorClass_t* class)
 // autobridge
 static void bridgeGstAllocatorClass(my_GstAllocatorClass_t* class)
 {
+    ONCE();
     bridgeGstObjectClass(&class->parent);
     #define GO(A, W) autobridge_##A##_GstAllocator (W, class->A)
     SUPERGO()
@@ -1925,7 +1966,8 @@ void* wrapCopyGTKClass(void* klass, size_t type)
         return klass;
     }
     memcpy(newklass, klass, sz);
-    wrapGTKClass(newklass, type);
+    //wrapGTKClass(newklass, type);
+    bridgeGTKClass(newklass, type);
     return newklass;
 }
 
diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c
index 60e1a1e5..ff4eb754 100644
--- a/src/tools/rcfile.c
+++ b/src/tools/rcfile.c
@@ -40,7 +40,9 @@ static const char default_rcfile[] =
 "\n"
 "[steamwebhelper]\n"
 "BOX64_NOSANDBOX=1\n"
-"BOX64_EXIT=1\n"
+"BOX64_MALLOC_HACK=2\n"
+"BOX64_LOG=0\n"
+"BOX64_NOGTK=1\n"
 "\n"
 "[steam-runtime-check-requirements]\n"
 "BOX64_EXIT=1\n"
@@ -77,6 +79,8 @@ ENTRYSTRING_(BOX64_BASH, bash)                          \
 ENTRYINT(BOX64_JITGDB, jit_gdb, 0, 2, 2)                \
 ENTRYBOOL(BOX64_NOSANDBOX, box64_nosandbox)             \
 ENTRYBOOL(BOX64_EXIT, want_exit)                        \
+ENTRYBOOL(BOX64_LIBCEF, box64_libcef)                   \
+ENTRYINT(BOX64_MALLOC_HACK, box64_malloc_hack, 0, 2, 2) \
 
 #ifdef HAVE_TRACE
 #define SUPER2()                                        \
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
index 631cbec0..02a8720c 100644
--- a/src/wrapped/generated/functions_list.txt
+++ b/src/wrapped/generated/functions_list.txt
@@ -969,6 +969,7 @@
 #() pFippi
 #() pFippu
 #() pFuiii
+#() pFuuii
 #() pFulli
 #() pFullu
 #() pFffff
@@ -1565,6 +1566,7 @@
 #() iFipuufp
 #() iFipupup
 #() iFipuppp
+#() iFipppLp
 #() iFippppp
 #() iFuppppp
 #() iFdipppL
@@ -1710,6 +1712,7 @@
 #() vFEpiiipp
 #() vFEpipppp
 #() vFEpuipuV
+#() vFEppippp
 #() vFEpppppp
 #() vFiiiiiip
 #() vFiiiiuup
@@ -1928,6 +1931,7 @@
 #() vFEiupippp
 #() vFEipAippp
 #() vFEppipppp
+#() vFEpppippp
 #() vFEpppuipV
 #() vFEpppppuu
 #() vFiiiiuuip
@@ -2061,8 +2065,10 @@
 #() vFEpiiiiipp
 #() vFEpippippV
 #() vFEpippippA
+#() vFEpuuuippp
 #() vFEppiipppp
 #() vFEpppiippp
+#() vFEppppippp
 #() vFiiiiiiiii
 #() vFiiiiiiill
 #() vFiiiiillli
@@ -2710,6 +2716,7 @@ wrappedglib2:
 - vFppV:
   - g_string_append_printf
   - g_string_printf
+  - g_variant_builder_add
   - g_variant_get
 - vFppA:
   - g_string_append_vprintf
@@ -3403,6 +3410,27 @@ wrappedlibglu:
   - gluNurbsCallback
   - gluQuadricCallback
   - gluTessCallback
+wrappedlibglx:
+- pFp:
+  - glXGetProcAddress
+  - glXGetProcAddressARB
+wrappedlibibus:
+- vFpippp:
+  - ibus_bus_current_input_context_async
+  - ibus_bus_get_global_engine_async
+  - ibus_bus_list_active_engines_async
+  - ibus_bus_list_engines_async
+  - ibus_input_context_get_engine_async
+- vFppippp:
+  - ibus_bus_create_input_context_async
+  - ibus_bus_set_global_engine_async
+  - ibus_config_get_values_async
+- vFpppippp:
+  - ibus_config_get_value_async
+- vFpuuuippp:
+  - ibus_input_context_process_key_event_async
+- vFppppippp:
+  - ibus_config_set_value_async
 wrappedlibice:
 wrappedlibm:
 - UFV:
diff --git a/src/wrapped/generated/wrappedglib2types.h b/src/wrapped/generated/wrappedglib2types.h
index 6846a748..c4326be8 100644
--- a/src/wrapped/generated/wrappedglib2types.h
+++ b/src/wrapped/generated/wrappedglib2types.h
@@ -113,6 +113,7 @@ typedef int64_t (*iFpppippppppp_t)(void*, void*, void*, int64_t, void*, void*, v
 	GO(g_static_private_set, vFppp_t) \
 	GO(g_string_append_printf, vFppV_t) \
 	GO(g_string_printf, vFppV_t) \
+	GO(g_variant_builder_add, vFppV_t) \
 	GO(g_variant_get, vFppV_t) \
 	GO(g_string_append_vprintf, vFppA_t) \
 	GO(g_string_vprintf, vFppA_t) \
diff --git a/src/wrapped/generated/wrappedlibglxdefs.h b/src/wrapped/generated/wrappedlibglxdefs.h
new file mode 100644
index 00000000..ec21a1f1
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibglxdefs.h
@@ -0,0 +1,8 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibglxDEFS_H_
+#define __wrappedlibglxDEFS_H_
+
+
+#endif // __wrappedlibglxDEFS_H_
diff --git a/src/wrapped/generated/wrappedlibglxtypes.h b/src/wrapped/generated/wrappedlibglxtypes.h
new file mode 100644
index 00000000..94a5a155
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibglxtypes.h
@@ -0,0 +1,20 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibglxTYPES_H_
+#define __wrappedlibglxTYPES_H_
+
+#ifndef LIBNAME
+#error You should only #include this file inside a wrapped*.c file
+#endif
+#ifndef ADDED_FUNCTIONS
+#define ADDED_FUNCTIONS() 
+#endif
+
+typedef void* (*pFp_t)(void*);
+
+#define SUPER() ADDED_FUNCTIONS() \
+	GO(glXGetProcAddress, pFp_t) \
+	GO(glXGetProcAddressARB, pFp_t)
+
+#endif // __wrappedlibglxTYPES_H_
diff --git a/src/wrapped/generated/wrappedlibglxundefs.h b/src/wrapped/generated/wrappedlibglxundefs.h
new file mode 100644
index 00000000..4113a9f3
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibglxundefs.h
@@ -0,0 +1,8 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibglxUNDEFS_H_
+#define __wrappedlibglxUNDEFS_H_
+
+
+#endif // __wrappedlibglxUNDEFS_H_
diff --git a/src/wrapped/generated/wrappedlibibusdefs.h b/src/wrapped/generated/wrappedlibibusdefs.h
new file mode 100644
index 00000000..ca32b61d
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibibusdefs.h
@@ -0,0 +1,8 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibibusDEFS_H_
+#define __wrappedlibibusDEFS_H_
+
+
+#endif // __wrappedlibibusDEFS_H_
diff --git a/src/wrapped/generated/wrappedlibibustypes.h b/src/wrapped/generated/wrappedlibibustypes.h
new file mode 100644
index 00000000..eddf0fd3
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibibustypes.h
@@ -0,0 +1,33 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibibusTYPES_H_
+#define __wrappedlibibusTYPES_H_
+
+#ifndef LIBNAME
+#error You should only #include this file inside a wrapped*.c file
+#endif
+#ifndef ADDED_FUNCTIONS
+#define ADDED_FUNCTIONS() 
+#endif
+
+typedef void (*vFpippp_t)(void*, int64_t, void*, void*, void*);
+typedef void (*vFppippp_t)(void*, void*, int64_t, void*, void*, void*);
+typedef void (*vFpppippp_t)(void*, void*, void*, int64_t, void*, void*, void*);
+typedef void (*vFpuuuippp_t)(void*, uint64_t, uint64_t, uint64_t, int64_t, void*, void*, void*);
+typedef void (*vFppppippp_t)(void*, void*, void*, void*, int64_t, void*, void*, void*);
+
+#define SUPER() ADDED_FUNCTIONS() \
+	GO(ibus_bus_current_input_context_async, vFpippp_t) \
+	GO(ibus_bus_get_global_engine_async, vFpippp_t) \
+	GO(ibus_bus_list_active_engines_async, vFpippp_t) \
+	GO(ibus_bus_list_engines_async, vFpippp_t) \
+	GO(ibus_input_context_get_engine_async, vFpippp_t) \
+	GO(ibus_bus_create_input_context_async, vFppippp_t) \
+	GO(ibus_bus_set_global_engine_async, vFppippp_t) \
+	GO(ibus_config_get_values_async, vFppippp_t) \
+	GO(ibus_config_get_value_async, vFpppippp_t) \
+	GO(ibus_input_context_process_key_event_async, vFpuuuippp_t) \
+	GO(ibus_config_set_value_async, vFppppippp_t)
+
+#endif // __wrappedlibibusTYPES_H_
diff --git a/src/wrapped/generated/wrappedlibibusundefs.h b/src/wrapped/generated/wrappedlibibusundefs.h
new file mode 100644
index 00000000..be0fd236
--- /dev/null
+++ b/src/wrapped/generated/wrappedlibibusundefs.h
@@ -0,0 +1,8 @@
+/*******************************************************************
+ * File automatically generated by rebuild_wrappers.py (v2.2.0.16) *
+ *******************************************************************/
+#ifndef __wrappedlibibusUNDEFS_H_
+#define __wrappedlibibusUNDEFS_H_
+
+
+#endif // __wrappedlibibusUNDEFS_H_
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 301a4893..e12cd03f 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -1003,6 +1003,7 @@ typedef void* (*pFipip_t)(int64_t, void*, int64_t, void*);
 typedef void* (*pFippi_t)(int64_t, void*, void*, int64_t);
 typedef void* (*pFippu_t)(int64_t, void*, void*, uint64_t);
 typedef void* (*pFuiii_t)(uint64_t, int64_t, int64_t, int64_t);
+typedef void* (*pFuuii_t)(uint64_t, uint64_t, int64_t, int64_t);
 typedef void* (*pFulli_t)(uint64_t, intptr_t, intptr_t, int64_t);
 typedef void* (*pFullu_t)(uint64_t, intptr_t, intptr_t, uint64_t);
 typedef void* (*pFffff_t)(float, float, float, float);
@@ -1599,6 +1600,7 @@ typedef int64_t (*iFipippp_t)(int64_t, void*, int64_t, void*, void*, void*);
 typedef int64_t (*iFipuufp_t)(int64_t, void*, uint64_t, uint64_t, float, void*);
 typedef int64_t (*iFipupup_t)(int64_t, void*, uint64_t, void*, uint64_t, void*);
 typedef int64_t (*iFipuppp_t)(int64_t, void*, uint64_t, void*, void*, void*);
+typedef int64_t (*iFipppLp_t)(int64_t, void*, void*, void*, uintptr_t, void*);
 typedef int64_t (*iFippppp_t)(int64_t, void*, void*, void*, void*, void*);
 typedef int64_t (*iFuppppp_t)(uint64_t, void*, void*, void*, void*, void*);
 typedef int64_t (*iFdipppL_t)(double, int64_t, void*, void*, void*, uintptr_t);
@@ -1744,6 +1746,7 @@ typedef int64_t (*iWpppppu_t)(void*, void*, void*, void*, void*, uint64_t);
 typedef void (*vFEpiiipp_t)(x64emu_t*, void*, int64_t, int64_t, int64_t, void*, void*);
 typedef void (*vFEpipppp_t)(x64emu_t*, void*, int64_t, void*, void*, void*, void*);
 typedef void (*vFEpuipuV_t)(x64emu_t*, void*, uint64_t, int64_t, void*, uint64_t, void*);
+typedef void (*vFEppippp_t)(x64emu_t*, void*, void*, int64_t, void*, void*, void*);
 typedef void (*vFEpppppp_t)(x64emu_t*, void*, void*, void*, void*, void*, void*);
 typedef void (*vFiiiiiip_t)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, void*);
 typedef void (*vFiiiiuup_t)(int64_t, int64_t, int64_t, int64_t, uint64_t, uint64_t, void*);
@@ -1962,6 +1965,7 @@ typedef void (*vFEiippppV_t)(x64emu_t*, int64_t, int64_t, void*, void*, void*, v
 typedef void (*vFEiupippp_t)(x64emu_t*, int64_t, uint64_t, void*, int64_t, void*, void*, void*);
 typedef void (*vFEipAippp_t)(x64emu_t*, int64_t, void*, void*, int64_t, void*, void*, void*);
 typedef void (*vFEppipppp_t)(x64emu_t*, void*, void*, int64_t, void*, void*, void*, void*);
+typedef void (*vFEpppippp_t)(x64emu_t*, void*, void*, void*, int64_t, void*, void*, void*);
 typedef void (*vFEpppuipV_t)(x64emu_t*, void*, void*, void*, uint64_t, int64_t, void*, void*);
 typedef void (*vFEpppppuu_t)(x64emu_t*, void*, void*, void*, void*, void*, uint64_t, uint64_t);
 typedef void (*vFiiiiuuip_t)(int64_t, int64_t, int64_t, int64_t, uint64_t, uint64_t, int64_t, void*);
@@ -2095,8 +2099,10 @@ typedef int64_t (*iWpuipuppp_t)(void*, uint64_t, int64_t, void*, uint64_t, void*
 typedef void (*vFEpiiiiipp_t)(x64emu_t*, void*, int64_t, int64_t, int64_t, int64_t, int64_t, void*, void*);
 typedef void (*vFEpippippV_t)(x64emu_t*, void*, int64_t, void*, void*, int64_t, void*, void*, void*);
 typedef void (*vFEpippippA_t)(x64emu_t*, void*, int64_t, void*, void*, int64_t, void*, void*, void*);
+typedef void (*vFEpuuuippp_t)(x64emu_t*, void*, uint64_t, uint64_t, uint64_t, int64_t, void*, void*, void*);
 typedef void (*vFEppiipppp_t)(x64emu_t*, void*, void*, int64_t, int64_t, void*, void*, void*, void*);
 typedef void (*vFEpppiippp_t)(x64emu_t*, void*, void*, void*, int64_t, int64_t, void*, void*, void*);
+typedef void (*vFEppppippp_t)(x64emu_t*, void*, void*, void*, void*, int64_t, void*, void*, void*);
 typedef void (*vFiiiiiiiii_t)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t);
 typedef void (*vFiiiiiiill_t)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, intptr_t, intptr_t);
 typedef void (*vFiiiiillli_t)(int64_t, int64_t, int64_t, int64_t, int64_t, intptr_t, intptr_t, intptr_t, int64_t);
@@ -3370,6 +3376,7 @@ void pFipip(x64emu_t *emu, uintptr_t fcn) { pFipip_t fn = (pFipip_t)fcn; R_RAX=(
 void pFippi(x64emu_t *emu, uintptr_t fcn) { pFippi_t fn = (pFippi_t)fcn; R_RAX=(uintptr_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX); }
 void pFippu(x64emu_t *emu, uintptr_t fcn) { pFippu_t fn = (pFippu_t)fcn; R_RAX=(uintptr_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX); }
 void pFuiii(x64emu_t *emu, uintptr_t fcn) { pFuiii_t fn = (pFuiii_t)fcn; R_RAX=(uintptr_t)fn((uint64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX); }
+void pFuuii(x64emu_t *emu, uintptr_t fcn) { pFuuii_t fn = (pFuuii_t)fcn; R_RAX=(uintptr_t)fn((uint64_t)R_RDI, (uint64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX); }
 void pFulli(x64emu_t *emu, uintptr_t fcn) { pFulli_t fn = (pFulli_t)fcn; R_RAX=(uintptr_t)fn((uint64_t)R_RDI, (intptr_t)R_RSI, (intptr_t)R_RDX, (int64_t)R_RCX); }
 void pFullu(x64emu_t *emu, uintptr_t fcn) { pFullu_t fn = (pFullu_t)fcn; R_RAX=(uintptr_t)fn((uint64_t)R_RDI, (intptr_t)R_RSI, (intptr_t)R_RDX, (uint64_t)R_RCX); }
 void pFffff(x64emu_t *emu, uintptr_t fcn) { pFffff_t fn = (pFffff_t)fcn; R_RAX=(uintptr_t)fn(emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0], emu->xmm[3].f[0]); }
@@ -3966,6 +3973,7 @@ void iFipippp(x64emu_t *emu, uintptr_t fcn) { iFipippp_t fn = (iFipippp_t)fcn; R
 void iFipuufp(x64emu_t *emu, uintptr_t fcn) { iFipuufp_t fn = (iFipuufp_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (uint64_t)R_RCX, emu->xmm[0].f[0], (void*)R_R8); }
 void iFipupup(x64emu_t *emu, uintptr_t fcn) { iFipupup_t fn = (iFipupup_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (void*)R_RCX, (uint64_t)R_R8, (void*)R_R9); }
 void iFipuppp(x64emu_t *emu, uintptr_t fcn) { iFipuppp_t fn = (iFipuppp_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
+void iFipppLp(x64emu_t *emu, uintptr_t fcn) { iFipppLp_t fn = (iFipppLp_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (void*)R_R9); }
 void iFippppp(x64emu_t *emu, uintptr_t fcn) { iFippppp_t fn = (iFippppp_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
 void iFuppppp(x64emu_t *emu, uintptr_t fcn) { iFuppppp_t fn = (iFuppppp_t)fcn; R_RAX=(int64_t)fn((uint64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
 void iFdipppL(x64emu_t *emu, uintptr_t fcn) { iFdipppL_t fn = (iFdipppL_t)fcn; R_RAX=(int64_t)fn(emu->xmm[0].d[0], (int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8); }
@@ -4111,6 +4119,7 @@ void iWpppppu(x64emu_t *emu, uintptr_t fcn) { iWpppppu_t fn = (iWpppppu_t)fcn; R
 void vFEpiiipp(x64emu_t *emu, uintptr_t fcn) { vFEpiiipp_t fn = (vFEpiiipp_t)fcn; fn(emu, (void*)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9); }
 void vFEpipppp(x64emu_t *emu, uintptr_t fcn) { vFEpipppp_t fn = (vFEpipppp_t)fcn; fn(emu, (void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
 void vFEpuipuV(x64emu_t *emu, uintptr_t fcn) { vFEpuipuV_t fn = (vFEpuipuV_t)fcn; fn(emu, (void*)R_RDI, (uint64_t)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (uint64_t)R_R8, (void*)(R_RSP + 8)); }
+void vFEppippp(x64emu_t *emu, uintptr_t fcn) { vFEppippp_t fn = (vFEppippp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
 void vFEpppppp(x64emu_t *emu, uintptr_t fcn) { vFEpppppp_t fn = (vFEpppppp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); }
 void vFiiiiiip(x64emu_t *emu, uintptr_t fcn) { vFiiiiiip_t fn = (vFiiiiiip_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8)); }
 void vFiiiiuup(x64emu_t *emu, uintptr_t fcn) { vFiiiiuup_t fn = (vFiiiiuup_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (uint64_t)R_R8, (uint64_t)R_R9, *(void**)(R_RSP + 8)); }
@@ -4329,6 +4338,7 @@ void vFEiippppV(x64emu_t *emu, uintptr_t fcn) { vFEiippppV_t fn = (vFEiippppV_t)
 void vFEiupippp(x64emu_t *emu, uintptr_t fcn) { vFEiupippp_t fn = (vFEiupippp_t)fcn; fn(emu, (int64_t)R_RDI, (uint64_t)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
 void vFEipAippp(x64emu_t *emu, uintptr_t fcn) { vFEipAippp_t fn = (vFEipAippp_t)fcn; fn(emu, (int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
 void vFEppipppp(x64emu_t *emu, uintptr_t fcn) { vFEppipppp_t fn = (vFEppipppp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
+void vFEpppippp(x64emu_t *emu, uintptr_t fcn) { vFEpppippp_t fn = (vFEpppippp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
 void vFEpppuipV(x64emu_t *emu, uintptr_t fcn) { vFEpppuipV_t fn = (vFEpppuipV_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX, (int64_t)R_R8, (void*)R_R9, (void*)(R_RSP + 8)); }
 void vFEpppppuu(x64emu_t *emu, uintptr_t fcn) { vFEpppppuu_t fn = (vFEpppppuu_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint64_t)R_R9, *(uint64_t*)(R_RSP + 8)); }
 void vFiiiiuuip(x64emu_t *emu, uintptr_t fcn) { vFiiiiuuip_t fn = (vFiiiiuuip_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (uint64_t)R_R8, (uint64_t)R_R9, *(int64_t*)(R_RSP + 8), *(void**)(R_RSP + 16)); }
@@ -4462,8 +4472,10 @@ void iWpuipuppp(x64emu_t *emu, uintptr_t fcn) { iWpuipuppp_t fn = (iWpuipuppp_t)
 void vFEpiiiiipp(x64emu_t *emu, uintptr_t fcn) { vFEpiiiiipp_t fn = (vFEpiiiiipp_t)fcn; fn(emu, (void*)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
 void vFEpippippV(x64emu_t *emu, uintptr_t fcn) { vFEpippippV_t fn = (vFEpippippV_t)fcn; fn(emu, (void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), (void*)(R_RSP + 16)); }
 void vFEpippippA(x64emu_t *emu, uintptr_t fcn) { vFEpippippA_t fn = (vFEpippippA_t)fcn; fn(emu, (void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
+void vFEpuuuippp(x64emu_t *emu, uintptr_t fcn) { vFEpuuuippp_t fn = (vFEpuuuippp_t)fcn; fn(emu, (void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX, (uint64_t)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
 void vFEppiipppp(x64emu_t *emu, uintptr_t fcn) { vFEppiipppp_t fn = (vFEppiipppp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
 void vFEpppiippp(x64emu_t *emu, uintptr_t fcn) { vFEpppiippp_t fn = (vFEpppiippp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
+void vFEppppippp(x64emu_t *emu, uintptr_t fcn) { vFEppppippp_t fn = (vFEppppippp_t)fcn; fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
 void vFiiiiiiiii(x64emu_t *emu, uintptr_t fcn) { vFiiiiiiiii_t fn = (vFiiiiiiiii_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(int64_t*)(R_RSP + 24)); }
 void vFiiiiiiill(x64emu_t *emu, uintptr_t fcn) { vFiiiiiiill_t fn = (vFiiiiiiill_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(intptr_t*)(R_RSP + 16), *(intptr_t*)(R_RSP + 24)); }
 void vFiiiiillli(x64emu_t *emu, uintptr_t fcn) { vFiiiiillli_t fn = (vFiiiiillli_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (intptr_t)R_R9, *(intptr_t*)(R_RSP + 8), *(intptr_t*)(R_RSP + 16), *(int64_t*)(R_RSP + 24)); }
@@ -5576,6 +5588,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFippi) return 1;
 	if (fun == &pFippu) return 1;
 	if (fun == &pFuiii) return 1;
+	if (fun == &pFuuii) return 1;
 	if (fun == &pFulli) return 1;
 	if (fun == &pFullu) return 1;
 	if (fun == &pFffff) return 5;
@@ -6058,6 +6071,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFipuufp) return 2;
 	if (fun == &iFipupup) return 1;
 	if (fun == &iFipuppp) return 1;
+	if (fun == &iFipppLp) return 1;
 	if (fun == &iFippppp) return 1;
 	if (fun == &iFuppppp) return 1;
 	if (fun == &iFdipppL) return 2;
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
index bd0ea250..90097842 100644
--- a/src/wrapped/generated/wrapper.h
+++ b/src/wrapped/generated/wrapper.h
@@ -1002,6 +1002,7 @@ void pFipip(x64emu_t *emu, uintptr_t fnc);
 void pFippi(x64emu_t *emu, uintptr_t fnc);
 void pFippu(x64emu_t *emu, uintptr_t fnc);
 void pFuiii(x64emu_t *emu, uintptr_t fnc);
+void pFuuii(x64emu_t *emu, uintptr_t fnc);
 void pFulli(x64emu_t *emu, uintptr_t fnc);
 void pFullu(x64emu_t *emu, uintptr_t fnc);
 void pFffff(x64emu_t *emu, uintptr_t fnc);
@@ -1598,6 +1599,7 @@ void iFipippp(x64emu_t *emu, uintptr_t fnc);
 void iFipuufp(x64emu_t *emu, uintptr_t fnc);
 void iFipupup(x64emu_t *emu, uintptr_t fnc);
 void iFipuppp(x64emu_t *emu, uintptr_t fnc);
+void iFipppLp(x64emu_t *emu, uintptr_t fnc);
 void iFippppp(x64emu_t *emu, uintptr_t fnc);
 void iFuppppp(x64emu_t *emu, uintptr_t fnc);
 void iFdipppL(x64emu_t *emu, uintptr_t fnc);
@@ -1743,6 +1745,7 @@ void iWpppppu(x64emu_t *emu, uintptr_t fnc);
 void vFEpiiipp(x64emu_t *emu, uintptr_t fnc);
 void vFEpipppp(x64emu_t *emu, uintptr_t fnc);
 void vFEpuipuV(x64emu_t *emu, uintptr_t fnc);
+void vFEppippp(x64emu_t *emu, uintptr_t fnc);
 void vFEpppppp(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiiip(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiuup(x64emu_t *emu, uintptr_t fnc);
@@ -1961,6 +1964,7 @@ void vFEiippppV(x64emu_t *emu, uintptr_t fnc);
 void vFEiupippp(x64emu_t *emu, uintptr_t fnc);
 void vFEipAippp(x64emu_t *emu, uintptr_t fnc);
 void vFEppipppp(x64emu_t *emu, uintptr_t fnc);
+void vFEpppippp(x64emu_t *emu, uintptr_t fnc);
 void vFEpppuipV(x64emu_t *emu, uintptr_t fnc);
 void vFEpppppuu(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiuuip(x64emu_t *emu, uintptr_t fnc);
@@ -2094,8 +2098,10 @@ void iWpuipuppp(x64emu_t *emu, uintptr_t fnc);
 void vFEpiiiiipp(x64emu_t *emu, uintptr_t fnc);
 void vFEpippippV(x64emu_t *emu, uintptr_t fnc);
 void vFEpippippA(x64emu_t *emu, uintptr_t fnc);
+void vFEpuuuippp(x64emu_t *emu, uintptr_t fnc);
 void vFEppiipppp(x64emu_t *emu, uintptr_t fnc);
 void vFEpppiippp(x64emu_t *emu, uintptr_t fnc);
+void vFEppppippp(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiiiiii(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiiiill(x64emu_t *emu, uintptr_t fnc);
 void vFiiiiillli(x64emu_t *emu, uintptr_t fnc);
diff --git a/src/wrapped/wrappedfontconfig_private.h b/src/wrapped/wrappedfontconfig_private.h
index 28830ff9..bd61dfbd 100755
--- a/src/wrapped/wrappedfontconfig_private.h
+++ b/src/wrapped/wrappedfontconfig_private.h
@@ -42,7 +42,7 @@ GO(FcConfigAppFontAddFile, iFpp)
 GO(FcConfigAppFontClear, vFp)
 //GO(FcConfigBuildFonts, 
 //GO(FcConfigCreate, 
-//GO(FcConfigDestroy, 
+GO(FcConfigDestroy, vFp)
 //GO(FcConfigEnableHome, 
 //GO(FcConfigFilename, 
 GO(FcConfigGetBlanks, pFp)
diff --git a/src/wrapped/wrappedgio2_private.h b/src/wrapped/wrappedgio2_private.h
index f2245ea8..dca16c2d 100755
--- a/src/wrapped/wrappedgio2_private.h
+++ b/src/wrapped/wrappedgio2_private.h
@@ -963,7 +963,7 @@ GOM(g_initable_new_valist, pFEppApp)
 //GO(g_input_stream_skip_finish, 
 //GO(g_io_error_enum_get_type, 
 //GO(g_io_error_from_errno, 
-//GO(g_io_error_quark, 
+GO(g_io_error_quark, uFv)
 //GO(g_io_extension_get_name, 
 //GO(g_io_extension_get_priority, 
 //GO(g_io_extension_get_type, 
@@ -1778,8 +1778,8 @@ GO(g_themed_icon_prepend_name, vFpp)
 //GO(g_unix_credentials_message_new, 
 //GO(g_unix_credentials_message_new_with_credentials, 
 //GO(g_unix_fd_list_append, 
-//GO(g_unix_fd_list_get, 
-//GO(g_unix_fd_list_get_length, 
+GO(g_unix_fd_list_get, iFpip)
+GO(g_unix_fd_list_get_length, iFp)
 GO(g_unix_fd_list_get_type, LFv)
 //GO(g_unix_fd_list_new, 
 //GO(g_unix_fd_list_new_from_array, 
diff --git a/src/wrapped/wrappedglib2.c b/src/wrapped/wrappedglib2.c
index 7b3cccc2..1ddd6cb5 100755
--- a/src/wrapped/wrappedglib2.c
+++ b/src/wrapped/wrappedglib2.c
@@ -30,6 +30,7 @@ typedef void  (*vFppip_t)(void*, void*, int, void*);
     GO(g_variant_get_va, vFpppp_t)              \
     GO(g_build_pathv, pFpp_t)                   \
     GO(g_set_error_literal, vFppip_t)           \
+    GO(g_variant_builder_add_value, vFpp_t)     \
 
 #include "wrappedglib2types.h"
 
@@ -240,7 +241,7 @@ static void* reversePollFct(void* fct)
     #define GO(A) if((uintptr_t)fct == my_poll_fct_##A) return (void*)my_poll_fct_##A;
     SUPER()
     #undef GO
-    return NULL;
+    return (void*)AddCheckBridge(my_lib->w.bridge, iFpui, fct, 0, "GPollFunc");
 }
 
 // GHashFunc ...
@@ -601,7 +602,7 @@ static void* reverseGLogFuncFct(void* fct)
     #define GO(A) if((uintptr_t)fct == my_GLogFunc_fct_##A) return (void*)my_GLogFunc_fct_##A;
     SUPER()
     #undef GO
-    return NULL;
+    return (void*)AddCheckBridge(my_lib->w.bridge, vFpipp, fct, 0, "GLogFunc");
 }
 // GPrintFunc ...
 #define GO(A)   \
@@ -661,7 +662,7 @@ static void* reverseGOptionArgFct(void* fct)
     #define GO(A) if((uintptr_t)fct == my_GOptionArg_fct_##A) return (void*)my_GOptionArg_fct_##A;
     SUPER()
     #undef GO
-    return NULL;
+    return (void*)AddCheckBridge(my_lib->w.bridge, iFpppp, fct, 0, "GOptionArgFunc");
 }
 // GNodeTraverseFunc ...
 #define GO(A)   \
@@ -1058,6 +1059,14 @@ EXPORT void* my_g_variant_new(x64emu_t* emu, char* fmt, uint64_t* V)
     return my->g_variant_new_va(fmt, NULL, &VARARGS);
 }
 
+EXPORT  void my_g_variant_builder_add(x64emu_t* emu, void* builder, void* fmt, uint64_t* V)
+{
+    // equivalent to calling g_variant_new and g_variant_builder_add_value
+    CREATE_VALIST_FROM_VAARG(V, emu->scratch, 2);
+    void* val = my->g_variant_new_va(fmt, NULL, &VARARGS);
+    my->g_variant_builder_add_value(builder, val);
+}
+
 EXPORT void* my_g_completion_new(x64emu_t* emu, void* f)
 {
     return my->g_completion_new(findGCompletionFct(f));
diff --git a/src/wrapped/wrappedglib2_private.h b/src/wrapped/wrappedglib2_private.h
index c11f8fe0..6cbff076 100755
--- a/src/wrapped/wrappedglib2_private.h
+++ b/src/wrapped/wrappedglib2_private.h
@@ -1431,7 +1431,7 @@ GO(g_utf8_to_ucs4_fast, pFplp)
 GO(g_utf8_to_utf16, pFplppp)
 GO(g_utf8_validate, iFplp)
 GO(g_utime, iFpp)
-//GO(g_variant_builder_add, vFppppppppppp)    // vaarg
+GOM(g_variant_builder_add, vFEppV)
 //GO(g_variant_builder_add_parsed, vFppppppppppp) //vaarg
 GO(g_variant_builder_add_value, vFpp)
 GO(g_variant_builder_clear, vFp)
@@ -1504,12 +1504,12 @@ GO(g_variant_is_signature, iFp)
 GO(g_variant_iter_copy, pFp)
 GO(g_variant_iter_free, vFp)
 GO(g_variant_iter_init, uFpp)
-//GO(g_variant_iter_loop, iFpppppppppppp) // vaarg
+GO(g_variant_iter_loop, iFpppppppppppp) // vaarg
 GO(g_variant_iter_n_children, uFp)
 GO(g_variant_iter_new, pFp)
 //GO(g_variant_iter_next, iFpppppppppppp) // vaarg here
 GO(g_variant_iter_next_value, pFp)
-//GO(g_variant_lookup, iFpppppppppppp)    // vaarg
+GO(g_variant_lookup, iFpppppppppppp)    // vaarg
 GO(g_variant_lookup_value, pFppp)
 GO(g_variant_n_children, uFp)
 GOM(g_variant_new, pFEpV)
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 4f4c208d..0f9ae4a5 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -763,8 +763,12 @@ EXPORT void *my_div(void *result, int numerator, int denominator) {
 #endif
 
 EXPORT int my_snprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, uint64_t * b) {
+    #ifdef PREFER_CONVERT_VAARG
+    CREATE_VALIST_FROM_VAARG(b, emu->scratch, 3);
+    #else
     myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
     PREPARE_VALIST;
+    #endif
     int r = vsnprintf(buff, s, fmt, VARARGS);
     return r;
 }
@@ -772,21 +776,33 @@ EXPORT int my___snprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, uint64
 EXPORT int my___snprintf_chk(x64emu_t* emu, void* buff, size_t s, int flags, size_t maxlen, void * fmt, uint64_t * b)
 {
     (void)flags; (void)maxlen;
+    #ifdef PREFER_CONVERT_VAARG
+    CREATE_VALIST_FROM_VAARG(b, emu->scratch, 5);
+    #else
     myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 5);
     PREPARE_VALIST;
+    #endif
     int r = vsnprintf(buff, s, fmt, VARARGS);
     return r;
 }
 
 EXPORT int my_sprintf(x64emu_t* emu, void* buff, void * fmt, void * b) {
+    #ifdef PREFER_CONVERT_VAARG
+    CREATE_VALIST_FROM_VAARG(b, emu->scratch, 2);
+    #else
     myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
     PREPARE_VALIST;
+    #endif
     return vsprintf(buff, (const char*)fmt, VARARGS);
 }
 EXPORT int my___sprintf_chk(x64emu_t* emu, void* buff, int flag, size_t l, void * fmt, void * b) {
     (void)flag; (void)l;
+    #ifdef PREFER_CONVERT_VAARG
+    CREATE_VALIST_FROM_VAARG(b, emu->scratch, 4);
+    #else
     myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 4);
     PREPARE_VALIST;
+    #endif
     return vsprintf(buff, (const char*)fmt, VARARGS);
 }
 
@@ -2425,7 +2441,6 @@ EXPORT int my_readlinkat(x64emu_t* emu, int fd, void* path, void* buf, size_t bu
     return readlinkat(fd, path, buf, bufsize);
 }
 
-
 EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset)
 {
     (void)emu;
@@ -2478,8 +2493,9 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         }
     }
     #endif
-    if(ret!=(void*)-1)
-        setProtection((uintptr_t)ret, length, prot);
+    if(ret!=(void*)-1) {
+        setProtection_mmap((uintptr_t)ret, length, prot);
+    }
     return ret;
 }
 EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset) __attribute__((alias("my_mmap64")));
@@ -2525,7 +2541,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne
                 cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1);
             #endif
         }
-        setProtection((uintptr_t)ret, new_size, prot); // should copy the protection from old block
+        setProtection_mmap((uintptr_t)ret, new_size, prot); // should copy the protection from old block
         #ifdef DYNAREC
         if(box64_dynarec)
             addDBFromAddressRange((uintptr_t)ret, new_size);
@@ -2544,8 +2560,9 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
     }
     #endif
     int ret = munmap(addr, length);
-    if(!ret)
+    if(!ret) {
         freeProtection((uintptr_t)addr, length);
+    }
     return ret;
 }
 
@@ -2557,7 +2574,7 @@ EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot)
         prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on x86_64
     int ret = mprotect(addr, len, prot);
     #ifdef DYNAREC
-    if(box64_dynarec) {
+    if(box64_dynarec && !ret) {
         if(prot& PROT_EXEC)
             addDBFromAddressRange((uintptr_t)addr, len);
         else
diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h
index 6f682431..67a0f6f9 100755
--- a/src/wrapped/wrappedlibc_private.h
+++ b/src/wrapped/wrappedlibc_private.h
@@ -614,7 +614,7 @@ GO(getsecretkey, iFppp)
 GO(getservbyname, pFpp)
 //GO(getservbyname_r, iFpp!pL!)
 GO(getservbyport, pFip)
-//GO(getservbyport_r, iFip!pL!)
+GO(getservbyport_r, iFipppLp)
 GO(getservent, pFv)
 //GO(getservent_r, iF!pL!)
 //GO(getsgent, 
diff --git a/src/wrapped/wrappedlibdrm_private.h b/src/wrapped/wrappedlibdrm_private.h
index 83774033..8116d2ae 100755
--- a/src/wrapped/wrappedlibdrm_private.h
+++ b/src/wrapped/wrappedlibdrm_private.h
@@ -49,7 +49,7 @@ GO(drmAuthMagic, iFiu)
 //GO(drmFreeBufs, 
 //GO(drmFreeBusid, 
 //GO(drmFreeDevice, 
-//GO(drmFreeDevices, 
+GO(drmFreeDevices, vFpi)
 //GO(drmFreeReservedContextList, 
 GO(drmFreeVersion, vFp)
 //GO(drmGetBufInfo, 
@@ -63,7 +63,7 @@ GO(drmFreeVersion, vFp)
 //GO(drmGetDevice2, 
 GO(drmGetDeviceNameFromFd, pFi)
 //GO(drmGetDeviceNameFromFd2, 
-//GO(drmGetDevices, 
+GO(drmGetDevices, iFpi)
 //GO(drmGetDevices2, 
 //GO(drmGetEntry, 
 //GO(drmGetHashTable, 
diff --git a/src/wrapped/wrappedlibegl.c b/src/wrapped/wrappedlibegl.c
index 7f8e7cb9..2a19ed94 100755
--- a/src/wrapped/wrappedlibegl.c
+++ b/src/wrapped/wrappedlibegl.c
@@ -15,6 +15,7 @@
 #include "box64context.h"
 #include "librarian.h"
 #include "callback.h"
+#include "gltools.h"
 
 const char* libeglName = "libEGL.so.1";
 #define LIBNAME libegl
@@ -23,75 +24,15 @@ const char* libeglName = "libEGL.so.1";
 
 #include "wrappercallback.h"
 
-// FIXME: old wrapped* type of file, cannot use generated/wrappedlibgltypes.h
-
-void fillGLProcWrapper(box64context_t*);
-void freeProcWrapper(kh_symbolmap_t** symbolmap);
-
 EXPORT void* my_eglGetProcAddress(x64emu_t* emu, void* name) 
 {
     khint_t k;
     const char* rname = (const char*)name;
-    if(dlsym_error && box64_log<LOG_DEBUG) printf_log(LOG_NONE, "Calling eglGetProcAddress(\"%s\") => ", rname);
-    if(!emu->context->glwrappers)
-        fillGLProcWrapper(emu->context);
-    // check if glxprocaddress is filled, and search for lib and fill it if needed
-    // get proc adress using actual glXGetProcAddress
-    k = kh_get(symbolmap, emu->context->glmymap, rname);
-    int is_my = (k==kh_end(emu->context->glmymap))?0:1;
-    void* symbol;
-    if(is_my) {
-        // try again, by using custom "my_" now...
-        char tmp[200];
-        strcpy(tmp, "my_");
-        strcat(tmp, rname);
-        symbol = dlsym(emu->context->box64lib, tmp);
-    } else 
-        symbol = my->eglGetProcAddress((void*)rname);
-    if(!symbol) {
-        if(dlsym_error && box64_log<LOG_DEBUG) printf_log(LOG_NONE, "%p\n", NULL);
-        return NULL;    // easy
-    }
-    // check if alread bridged
-    uintptr_t ret = CheckBridged(emu->context->system, symbol);
-    if(ret) {
-        if(dlsym_error && box64_log<LOG_DEBUG) printf_log(LOG_NONE, "%p\n", (void*)ret);
-        return (void*)ret; // already bridged
-    }
-    // get wrapper    
-    k = kh_get(symbolmap, emu->context->glwrappers, rname);
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "ARB")==NULL) {
-        // try again, adding ARB at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "ARB");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "EXT")==NULL) {
-        // try again, adding EXT at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "EXT");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers)) {
-        if(dlsym_error && box64_log<LOG_DEBUG) printf_log(LOG_NONE, "%p\n", NULL);
-        if(dlsym_error && box64_log<LOG_INFO) printf_log(LOG_NONE, "Warning, no wrapper for %s\n", rname);
-        return NULL;
-    }
-    const char* constname = kh_key(emu->context->glwrappers, k);
-    AddOffsetSymbol(emu->context->maplib, symbol, rname);
-    ret = AddBridge(emu->context->system, kh_value(emu->context->glwrappers, k), symbol, 0, constname);
-    if(dlsym_error && box64_log<LOG_DEBUG) printf_log(LOG_NONE, "%p\n", (void*)ret);
-    return (void*)ret;
-
+    return getGLProcAddress(emu, (glprocaddress_t)my->eglGetProcAddress, name);
 }
 
-
 #define CUSTOM_INIT                 \
-    getMy(lib);                     \
-    if (!box64->glxprocaddress)     \
-        box64->glxprocaddress = (procaddess_t)my->eglGetProcAddress;
+    getMy(lib);
 
 #define CUSTOM_FINI \
     freeMy();
diff --git a/src/wrapped/wrappedlibgl.c b/src/wrapped/wrappedlibgl.c
index 9875847c..f210a255 100755
--- a/src/wrapped/wrappedlibgl.c
+++ b/src/wrapped/wrappedlibgl.c
@@ -15,72 +15,19 @@
 #include "box64context.h"
 #include "librarian.h"
 #include "callback.h"
+#include "gltools.h"
 
 const char* libglName = "libGL.so.1";
 #define LIBNAME libgl
+static library_t* my_lib = NULL;
 
 // FIXME: old wrapped* type of file, cannot use generated/wrappedlibgltypes.h
 
-void fillGLProcWrapper(box64context_t*);
-void freeProcWrapper(kh_symbolmap_t** symbolmap);
-
 EXPORT void* my_glXGetProcAddress(x64emu_t* emu, void* name) 
 {
     khint_t k;
     const char* rname = (const char*)name;
-    printf_dlsym(LOG_DEBUG, "Calling glXGetProcAddress(\"%s\") => ", rname);
-    if(!emu->context->glwrappers)
-        fillGLProcWrapper(emu->context);
-    // check if glxprocaddress is filled, and search for lib and fill it if needed
-    // get proc adress using actual glXGetProcAddress
-    k = kh_get(symbolmap, emu->context->glmymap, rname);
-    int is_my = (k==kh_end(emu->context->glmymap))?0:1;
-    void* symbol;
-    if(is_my) {
-        // try again, by using custom "my_" now...
-        char tmp[200];
-        strcpy(tmp, "my_");
-        strcat(tmp, rname);
-        symbol = dlsym(emu->context->box64lib, tmp);
-    } else 
-        symbol = emu->context->glxprocaddress(rname);
-    if(!symbol) {
-        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
-        return NULL;    // easy
-    }
-    // check if alread bridged
-    uintptr_t ret = CheckBridged(emu->context->system, symbol);
-    if(ret) {
-        printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
-        return (void*)ret; // already bridged
-    }
-    // get wrapper    
-    k = kh_get(symbolmap, emu->context->glwrappers, rname);
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "ARB")==NULL) {
-        // try again, adding ARB at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "ARB");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "EXT")==NULL) {
-        // try again, adding EXT at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "EXT");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers)) {
-        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
-        printf_dlsym(LOG_INFO, "Warning, no wrapper for %s\n", rname);
-        return NULL;
-    }
-    const char* constname = kh_key(emu->context->glwrappers, k);
-    AddOffsetSymbol(emu->context->maplib, symbol, rname);
-    ret = AddBridge(emu->context->system, kh_value(emu->context->glwrappers, k), symbol, 0, constname);
-    printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
-    return (void*)ret;
-
+    return getGLProcAddress(emu, my_lib->w.priv, rname);
 }
 EXPORT void* my_glXGetProcAddressARB(x64emu_t* emu, void* name) __attribute__((alias("my_glXGetProcAddress")));
 
@@ -89,6 +36,16 @@ typedef void (*vFpp_t)(void*, void*);
 typedef void*(*pFp_t)(void*);
 typedef void (*debugProc_t)(int32_t, int32_t, uint32_t, int32_t, int32_t, void*, void*);
 
+typedef struct gl_wrappers_s {
+    glprocaddress_t      procaddress;
+    kh_symbolmap_t      *glwrappers;    // the map of wrapper for glProcs (for GLX or SDL1/2)
+    kh_symbolmap_t      *glmymap;       // link to the mysymbolmap of libGL
+} gl_wrappers_t;
+
+KHASH_MAP_INIT_INT64(gl_wrappers, gl_wrappers_t*)
+
+static kh_gl_wrappers_t *gl_wrappers = NULL;
+
 #define SUPER() \
 GO(0)   \
 GO(1)   \
@@ -140,106 +97,304 @@ static void* find_program_callback_Fct(void* fct)
     printf_log(LOG_NONE, "Warning, no more slot for libGL program_callback callback\n");
     return NULL;
 }
-#undef SUPER
 
-EXPORT void my_glDebugMessageCallback(x64emu_t* emu, void* prod, void* param)
+// glDebugMessageCallback ...
+#define GO(A)                                                                       \
+static vFpp_t my_glDebugMessageCallback_fct_##A = NULL;                             \
+static void my_glDebugMessageCallback_##A(x64emu_t* emu, void* prod, void* param)   \
+{                                                                                   \
+    if(!my_glDebugMessageCallback_fct_##A)                                          \
+        return;                                                                     \
+    my_glDebugMessageCallback_fct_##A(find_debug_callback_Fct(prod), param);        \
+}
+SUPER()
+#undef GO
+static void* find_glDebugMessageCallback_Fct(void* fct)
 {
-    static vFpp_t DebugMessageCallback = NULL;
-    static int init = 1;
-    if(init) {
-        DebugMessageCallback = emu->context->glxprocaddress("glDebugMessageCallback");
-        init = 0;
-    }
-    if(!DebugMessageCallback)
-        return;
-    DebugMessageCallback(find_debug_callback_Fct(prod), param);
+    if(!fct) return fct;
+    #define GO(A) if(my_glDebugMessageCallback_fct_##A == (vFpp_t)fct) return my_glDebugMessageCallback_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glDebugMessageCallback_fct_##A == 0) {my_glDebugMessageCallback_fct_##A = (vFpp_t)fct; return my_glDebugMessageCallback_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glDebugMessageCallback callback\n");
+    return NULL;
 }
-EXPORT void my_glDebugMessageCallbackARB(x64emu_t* emu, void* prod, void* param) __attribute__((alias("my_glDebugMessageCallback")));
-EXPORT void my_glDebugMessageCallbackAMD(x64emu_t* emu, void* prod, void* param) __attribute__((alias("my_glDebugMessageCallback")));
-EXPORT void my_glDebugMessageCallbackKHR(x64emu_t* emu, void* prod, void* param) __attribute__((alias("my_glDebugMessageCallback")));
-
-EXPORT int my_glXSwapIntervalMESA(int interval)
+// glDebugMessageCallbackARB ...
+#define GO(A)                                                                       \
+static vFpp_t my_glDebugMessageCallbackARB_fct_##A = NULL;                             \
+static void my_glDebugMessageCallbackARB_##A(x64emu_t* emu, void* prod, void* param)   \
+{                                                                                   \
+    if(!my_glDebugMessageCallbackARB_fct_##A)                                          \
+        return;                                                                     \
+    my_glDebugMessageCallbackARB_fct_##A(find_debug_callback_Fct(prod), param);        \
+}
+SUPER()
+#undef GO
+static void* find_glDebugMessageCallbackARB_Fct(void* fct)
 {
-    static iFi_t SwapIntervalMESA = NULL;
-    static int init = 1;
-    if(init) {
-        SwapIntervalMESA = my_context->glxprocaddress("glXSwapIntervalMESA");
-        init = 0;
-    }
-    if(!SwapIntervalMESA)
-        return 0;
-    return SwapIntervalMESA(interval);
+    if(!fct) return fct;
+    #define GO(A) if(my_glDebugMessageCallbackARB_fct_##A == (vFpp_t)fct) return my_glDebugMessageCallbackARB_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glDebugMessageCallbackARB_fct_##A == 0) {my_glDebugMessageCallbackARB_fct_##A = (vFpp_t)fct; return my_glDebugMessageCallbackARB_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glDebugMessageCallbackARB callback\n");
+    return NULL;
 }
-
-EXPORT void my_glProgramCallbackMESA(x64emu_t* emu, void* f, void* data)
+// glDebugMessageCallbackAMD ...
+#define GO(A)                                                                       \
+static vFpp_t my_glDebugMessageCallbackAMD_fct_##A = NULL;                             \
+static void my_glDebugMessageCallbackAMD_##A(x64emu_t* emu, void* prod, void* param)   \
+{                                                                                   \
+    if(!my_glDebugMessageCallbackAMD_fct_##A)                                          \
+        return;                                                                     \
+    my_glDebugMessageCallbackAMD_fct_##A(find_debug_callback_Fct(prod), param);        \
+}
+SUPER()
+#undef GO
+static void* find_glDebugMessageCallbackAMD_Fct(void* fct)
 {
-    static vFpp_t ProgramCallbackMESA = NULL;
-    static int init = 1;
-    if(init) {
-        ProgramCallbackMESA = my_context->glxprocaddress("glProgramCallbackMESA");
-        init = 0;
-    }
-    if(!ProgramCallbackMESA)
-        return;
-    ProgramCallbackMESA(find_program_callback_Fct(f), data);
+    if(!fct) return fct;
+    #define GO(A) if(my_glDebugMessageCallbackAMD_fct_##A == (vFpp_t)fct) return my_glDebugMessageCallbackAMD_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glDebugMessageCallbackAMD_fct_##A == 0) {my_glDebugMessageCallbackAMD_fct_##A = (vFpp_t)fct; return my_glDebugMessageCallbackAMD_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glDebugMessageCallbackAMD callback\n");
+    return NULL;
+}
+// glDebugMessageCallbackKHR ...
+#define GO(A)                                                                       \
+static vFpp_t my_glDebugMessageCallbackKHR_fct_##A = NULL;                             \
+static void my_glDebugMessageCallbackKHR_##A(x64emu_t* emu, void* prod, void* param)   \
+{                                                                                   \
+    if(!my_glDebugMessageCallbackKHR_fct_##A)                                          \
+        return;                                                                     \
+    my_glDebugMessageCallbackKHR_fct_##A(find_debug_callback_Fct(prod), param);        \
+}
+SUPER()
+#undef GO
+static void* find_glDebugMessageCallbackKHR_Fct(void* fct)
+{
+    if(!fct) return fct;
+    #define GO(A) if(my_glDebugMessageCallbackKHR_fct_##A == (vFpp_t)fct) return my_glDebugMessageCallbackKHR_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glDebugMessageCallbackKHR_fct_##A == 0) {my_glDebugMessageCallbackKHR_fct_##A = (vFpp_t)fct; return my_glDebugMessageCallbackKHR_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glDebugMessageCallbackKHR callback\n");
+    return NULL;
+}
+// glXSwapIntervalMESA ...
+#define GO(A)                                           \
+static iFi_t my_glXSwapIntervalMESA_fct_##A = NULL;     \
+static int my_glXSwapIntervalMESA_##A(int interval)     \
+{                                                       \
+    if(!my_glXSwapIntervalMESA_fct_##A)                 \
+        return 0;                                       \
+    return my_glXSwapIntervalMESA_fct_##A(interval);    \
+}
+SUPER()
+#undef GO
+static void* find_glXSwapIntervalMESA_Fct(void* fct)
+{
+    if(!fct) return fct;
+    #define GO(A) if(my_glXSwapIntervalMESA_fct_##A == (iFi_t)fct) return my_glXSwapIntervalMESA_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glXSwapIntervalMESA_fct_##A == 0) {my_glXSwapIntervalMESA_fct_##A = (iFi_t)fct; return my_glXSwapIntervalMESA_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glXSwapIntervalMESA callback\n");
+    return NULL;
+}
+// glProgramCallbackMESA ...
+#define GO(A)                                                               \
+static vFpp_t my_glProgramCallbackMESA_fct_##A = NULL;                      \
+static void my_glProgramCallbackMESA_##A(x64emu_t* emu, void* f, void* data)\
+{                                                                           \
+    if(!my_glProgramCallbackMESA_fct_##A)                                   \
+        return;                                                             \
+    my_glProgramCallbackMESA_fct_##A(find_program_callback_Fct(f), data);   \
+}
+SUPER()
+#undef GO
+static void* find_glProgramCallbackMESA_Fct(void* fct)
+{
+    if(!fct) return fct;
+    #define GO(A) if(my_glProgramCallbackMESA_fct_##A == (vFpp_t)fct) return my_glProgramCallbackMESA_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glProgramCallbackMESA_fct_##A == 0) {my_glProgramCallbackMESA_fct_##A = (vFpp_t)fct; return my_glProgramCallbackMESA_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glProgramCallbackMESA callback\n");
+    return NULL;
 }
-
 void* my_GetVkProcAddr(x64emu_t* emu, void* name, void*(*getaddr)(void*));  // defined in wrappedvulkan.c
-EXPORT void* my_glGetVkProcAddrNV(x64emu_t* emu, void* name)
+// glGetVkProcAddrNV ...
+#define GO(A)                                                           \
+static pFp_t my_glGetVkProcAddrNV_fct_##A = NULL;                       \
+static void* my_glGetVkProcAddrNV_##A(x64emu_t* emu, void* name)        \
+{                                                                       \
+    if(!my_glGetVkProcAddrNV_fct_##A)                                   \
+        return NULL;                                                    \
+    return my_GetVkProcAddr(emu, name, my_glGetVkProcAddrNV_fct_##A);   \
+}
+SUPER()
+#undef GO
+static void* find_glGetVkProcAddrNV_Fct(void* fct)
 {
-    static pFp_t GetVkProcAddrNV = NULL;
-    static int init = 1;
-    if(init) {
-        GetVkProcAddrNV = my_context->glxprocaddress("glGetVkProcAddrNV");
-        init = 0;
-    }
-    return my_GetVkProcAddr(emu, name, GetVkProcAddrNV);
+    if(!fct) return fct;
+    #define GO(A) if(my_glGetVkProcAddrNV_fct_##A == (pFp_t)fct) return my_glGetVkProcAddrNV_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_glGetVkProcAddrNV_fct_##A == 0) {my_glGetVkProcAddrNV_fct_##A = (pFp_t)fct; return my_glGetVkProcAddrNV_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libGL glGetVkProcAddrNV callback\n");
+    return NULL;
 }
+#undef SUPER
 
 #define PRE_INIT if(box64_libGL) {lib->w.lib = dlopen(box64_libGL, RTLD_LAZY | RTLD_GLOBAL); lib->path = strdup(box64_libGL);} else
 #define CUSTOM_INIT \
+    my_lib = lib;   \
     lib->w.priv = dlsym(lib->w.lib, "glXGetProcAddress"); \
-    if (!box64->glxprocaddress) \
-        box64->glxprocaddress = lib->w.priv;
-
 
 #include "wrappedlib_init.h"
 
-void fillGLProcWrapper(box64context_t* context)
+#define SUPER()                         \
+ GO(vFpp_t, glDebugMessageCallback)     \
+ GO(vFpp_t, glDebugMessageCallbackARB)  \
+ GO(vFpp_t, glDebugMessageCallbackAMD)  \
+ GO(vFpp_t, glDebugMessageCallbackKHR)  \
+ GO(iFi_t, glXSwapIntervalMESA)         \
+ GO(vFpp_t, glProgramCallbackMESA)      \
+ GO(pFp_t, glGetVkProcAddrNV)           \
+
+
+gl_wrappers_t* getGLProcWrapper(box64context_t* context, glprocaddress_t procaddress)
 {
     int cnt, ret;
     khint_t k;
-    kh_symbolmap_t * symbolmap = kh_init(symbolmap);
+    if(!gl_wrappers) {
+        gl_wrappers = kh_init(gl_wrappers);
+    }
+    k = kh_put(gl_wrappers, gl_wrappers, (uintptr_t)procaddress, &ret);
+    if(!ret)
+        return kh_value(gl_wrappers, k);
+    gl_wrappers_t* wrappers = kh_value(gl_wrappers, k) = (gl_wrappers_t*)calloc(1, sizeof(gl_wrappers_t));
+
+    wrappers->procaddress = procaddress;
+    wrappers->glwrappers = kh_init(symbolmap);
     // populates maps...
     cnt = sizeof(libglsymbolmap)/sizeof(map_onesymbol_t);
     for (int i=0; i<cnt; ++i) {
-        k = kh_put(symbolmap, symbolmap, libglsymbolmap[i].name, &ret);
-        kh_value(symbolmap, k) = libglsymbolmap[i].w;
+        k = kh_put(symbolmap, wrappers->glwrappers, libglsymbolmap[i].name, &ret);
+        kh_value(wrappers->glwrappers, k) = libglsymbolmap[i].w;
     }
     // and the my_ symbols map
     cnt = sizeof(MAPNAME(mysymbolmap))/sizeof(map_onesymbol_t);
     for (int i=0; i<cnt; ++i) {
-        k = kh_put(symbolmap, symbolmap, libglmysymbolmap[i].name, &ret);
-        kh_value(symbolmap, k) = libglmysymbolmap[i].w;
+        k = kh_put(symbolmap, wrappers->glwrappers, libglmysymbolmap[i].name, &ret);
+        kh_value(wrappers->glwrappers, k) = libglmysymbolmap[i].w;
     }
-    context->glwrappers = symbolmap;
     // my_* map
-    symbolmap = kh_init(symbolmap);
+    wrappers->glmymap = kh_init(symbolmap);
     cnt = sizeof(MAPNAME(mysymbolmap))/sizeof(map_onesymbol_t);
     for (int i=0; i<cnt; ++i) {
-        k = kh_put(symbolmap, symbolmap, libglmysymbolmap[i].name, &ret);
-        kh_value(symbolmap, k) = libglmysymbolmap[i].w;
+        k = kh_put(symbolmap, wrappers->glmymap, libglmysymbolmap[i].name, &ret);
+        kh_value(wrappers->glmymap, k) = libglmysymbolmap[i].w;
     }
-    context->glmymap = symbolmap;
+    return wrappers;
 }
 void freeGLProcWrapper(box64context_t* context)
 {
     if(!context)
         return;
-    if(context->glwrappers)
-        kh_destroy(symbolmap, context->glwrappers);
-    if(context->glmymap)
-        kh_destroy(symbolmap, context->glmymap);
-    context->glwrappers = NULL;
-    context->glmymap = NULL;
+    if(!gl_wrappers)
+        return;
+    gl_wrappers_t* wrappers;
+    kh_foreach_value(gl_wrappers, wrappers,
+        if(wrappers->glwrappers)
+            kh_destroy(symbolmap, wrappers->glwrappers);
+        if(wrappers->glmymap)
+            kh_destroy(symbolmap, wrappers->glmymap);
+        wrappers->glwrappers = NULL;
+        wrappers->glmymap = NULL;
+    );
+    kh_destroy(gl_wrappers, gl_wrappers);
+    gl_wrappers = NULL;
 }
+
+void* getGLProcAddress(x64emu_t* emu, glprocaddress_t procaddr, const char* rname)
+{
+    khint_t k;
+    printf_dlsym(LOG_DEBUG, "Calling getGLProcAddress[%p](\"%s\") => ", procaddr, rname);
+    gl_wrappers_t* wrappers = getGLProcWrapper(emu->context, procaddr);
+    // check if glxprocaddress is filled, and search for lib and fill it if needed
+    // get proc adress using actual glXGetProcAddress
+    k = kh_get(symbolmap, wrappers->glmymap, rname);
+    int is_my = (k==kh_end(wrappers->glmymap))?0:1;
+    void* symbol;
+    if(is_my) {
+        // try again, by using custom "my_" now...
+        #define GO(A, B) else if(!strcmp(rname, #B)) symbol = find_##B##_Fct(procaddr(rname));
+        if(0) {}
+        SUPER()
+        else {
+            if(strcmp(rname, "glXGetProcAddress") && strcmp(rname, "glXGetProcAddressARB")) {
+                printf_log(LOG_NONE, "Warning, %s defined as GOM, but find_%s_Fct not defined\n", rname, rname);
+            }
+            char tmp[200];
+            strcpy(tmp, "my_");
+            strcat(tmp, rname);
+            symbol = dlsym(emu->context->box64lib, tmp);
+        }
+        #undef GO
+        #undef SUPER
+    } else 
+        symbol = procaddr(rname);
+    if(!symbol) {
+        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
+        return NULL;    // easy
+    }
+    // check if alread bridged
+    uintptr_t ret = CheckBridged(emu->context->system, symbol);
+    if(ret) {
+        printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
+        return (void*)ret; // already bridged
+    }
+    // get wrapper    
+    k = kh_get(symbolmap, wrappers->glwrappers, rname);
+    if(k==kh_end(wrappers->glwrappers) && strstr(rname, "ARB")==NULL) {
+        // try again, adding ARB at the end if not present
+        char tmp[200];
+        strcpy(tmp, rname);
+        strcat(tmp, "ARB");
+        k = kh_get(symbolmap, wrappers->glwrappers, tmp);
+    }
+    if(k==kh_end(wrappers->glwrappers) && strstr(rname, "EXT")==NULL) {
+        // try again, adding EXT at the end if not present
+        char tmp[200];
+        strcpy(tmp, rname);
+        strcat(tmp, "EXT");
+        k = kh_get(symbolmap, wrappers->glwrappers, tmp);
+    }
+    if(k==kh_end(wrappers->glwrappers)) {
+        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
+        printf_dlsym(LOG_INFO, "Warning, no wrapper for %s\n", rname);
+        return NULL;
+    }
+    const char* constname = kh_key(wrappers->glwrappers, k);
+    AddOffsetSymbol(emu->context->maplib, symbol, rname);
+    ret = AddBridge(emu->context->system, kh_value(wrappers->glwrappers, k), symbol, 0, constname);
+    printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
+    return (void*)ret;
+}
\ No newline at end of file
diff --git a/src/wrapped/wrappedlibglx.c b/src/wrapped/wrappedlibglx.c
new file mode 100644
index 00000000..52bae55d
--- /dev/null
+++ b/src/wrapped/wrappedlibglx.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <dlfcn.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "x64emu.h"
+#include "emu/x64emu_private.h"
+#include "callback.h"
+#include "librarian.h"
+#include "box64context.h"
+#include "emu/x64emu_private.h"
+#include "myalign.h"
+#include "gltools.h"
+
+const char* libglxName = "libGLX.so.0";
+#define LIBNAME libglx
+
+#include "generated/wrappedlibglxtypes.h"
+
+#include "wrappercallback.h"
+
+#define SUPER() \
+GO(0)   \
+GO(1)   \
+GO(2)   \
+GO(3)   \
+
+
+#undef SUPER
+
+EXPORT void* myx_glXGetProcAddress(x64emu_t* emu, void* name) 
+{
+    khint_t k;
+    const char* rname = (const char*)name;
+    return getGLProcAddress(emu, (glprocaddress_t)my->glXGetProcAddress, rname);
+}
+
+EXPORT void* myx_glXGetProcAddressARB(x64emu_t* emu, void* name) 
+{
+    khint_t k;
+    const char* rname = (const char*)name;
+    return getGLProcAddress(emu, (glprocaddress_t)my->glXGetProcAddressARB, rname);
+}
+
+
+
+#define CUSTOM_INIT     \
+    getMy(lib);         \
+    SETALT(myx_);       \
+
+#define CUSTOM_FINI     \
+    freeMy();
+
+#include "wrappedlib_init.h"
diff --git a/src/wrapped/wrappedlibglx_private.h b/src/wrapped/wrappedlibglx_private.h
new file mode 100644
index 00000000..aab119d6
--- /dev/null
+++ b/src/wrapped/wrappedlibglx_private.h
@@ -0,0 +1,48 @@
+#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
+#error meh!
+#endif
+
+// __glXGLLoadGLXFunction
+GO(glXChooseFBConfig, pFpipp)
+GO(glXChooseVisual, pFpip)
+GO(glXCopyContext,vFppp)
+GO(glXCreateContext,pFpppi)
+GO(glXCreateGLXPixmap,pFppp)
+GO(glXCreateNewContext,pFppipi)
+GO(glXCreatePbuffer,pFppp)
+GO(glXCreatePixmap,pFppp)
+GO(glXCreateWindow,pFpppp)
+GO(glXDestroyContext,vFpp)
+GO(glXDestroyGLXPixmap,vFpp)
+GO(glXDestroyPbuffer,vFpp)
+GO(glXDestroyPixmap,vFpp)
+GO(glXDestroyWindow,vFpp)
+GO(glXGetClientString, pFpi)
+GO(glXGetConfig, iFppip)
+GO(glXGetCurrentContext, pFv)
+GO(glXGetCurrentDisplay, pFv)
+GO(glXGetCurrentDrawable, pFv)
+GO(glXGetCurrentReadDrawable, pFv)
+GO(glXGetFBConfigAttrib, iFppip)
+GO(glXGetFBConfigs,pFpip)
+GOM(glXGetProcAddress, pFEp)
+GOM(glXGetProcAddressARB, pFEp)
+GO(glXGetSelectedEvent, vFppp)
+GO(glXGetVisualFromFBConfig, pFpp)
+GO(glXIsDirect,iFpp)
+GO(glXMakeContextCurrent,iFpppp)
+GO(glXMakeCurrent,iFppp)
+GO(glXQueryContext,iFppip)
+GO(glXQueryDrawable, iFppip)
+GO(glXQueryExtension, iFppp)
+GO(glXQueryExtensionsString,pFpi)
+GO(glXQueryServerString,pFpii)
+GO(glXQueryVersion,iFppp)
+GO(glXSelectEvent, vFppu)
+GO(glXSwapBuffers,vFpp)
+GO(glXUseXFont,vFpiii)
+GO(glXWaitGL,vFv)
+GO(glXWaitX,vFv)
+
+
+
diff --git a/src/wrapped/wrappedlibibus.c b/src/wrapped/wrappedlibibus.c
new file mode 100644
index 00000000..95ea0f81
--- /dev/null
+++ b/src/wrapped/wrappedlibibus.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <dlfcn.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "x64emu.h"
+#include "emu/x64emu_private.h"
+#include "callback.h"
+#include "librarian.h"
+#include "box64context.h"
+#include "emu/x64emu_private.h"
+#include "myalign.h"
+
+const char* libibusName = "libibus-1.0.so.5";
+#define LIBNAME libibus
+
+#define ADDED_FUNCTIONS() \
+
+#include "wrappedlibibustypes.h"
+
+#include "wrappercallback.h"
+
+#define SUPER() \
+GO(0)   \
+GO(1)   \
+GO(2)   \
+GO(3)
+
+// GAsyncReadyCallback
+#define GO(A)   \
+static uintptr_t my_GAsyncReadyCallback_fct_##A = 0;   \
+static void my_GAsyncReadyCallback_##A(void* source, void* res, void* data)     \
+{                                       \
+    RunFunction(my_context, my_GAsyncReadyCallback_fct_##A, 3, source, res, data);\
+}
+SUPER()
+#undef GO
+static void* findGAsyncReadyCallbackFct(void* fct)
+{
+    if(!fct) return fct;
+    if(GetNativeFnc((uintptr_t)fct))  return GetNativeFnc((uintptr_t)fct);
+    #define GO(A) if(my_GAsyncReadyCallback_fct_##A == (uintptr_t)fct) return my_GAsyncReadyCallback_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_GAsyncReadyCallback_fct_##A == 0) {my_GAsyncReadyCallback_fct_##A = (uintptr_t)fct; return my_GAsyncReadyCallback_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libibus GAsyncReadyCallback callback\n");
+    return NULL;
+}
+
+#undef SUPER
+
+EXPORT void my_ibus_bus_create_input_context_async(x64emu_t* emu, void* bus, void* name, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_create_input_context_async(bus, name, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_bus_current_input_context_async(x64emu_t* emu, void* bus, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_current_input_context_async(bus, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_bus_get_global_engine_async(x64emu_t* emu, void* bus, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_get_global_engine_async(bus, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_bus_list_active_engines_async(x64emu_t* emu, void* bus, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_list_active_engines_async(bus, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_bus_list_engines_async(x64emu_t* emu, void* bus, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_list_engines_async(bus, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_bus_set_global_engine_async(x64emu_t* emu, void* bus, void* engine, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_bus_set_global_engine_async(bus, engine, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_config_get_value_async(x64emu_t* emu, void* bus, void* section, void* name, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_config_get_value_async(bus, section, name, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_config_get_values_async(x64emu_t* emu, void* bus, void* section, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_config_get_values_async(bus, section, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_config_set_value_async(x64emu_t* emu, void* bus, void* section, void* name, void* value, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_config_set_value_async(bus, section, name, value, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_input_context_get_engine_async(x64emu_t* emu, void* bus, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_input_context_get_engine_async(bus, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+EXPORT void my_ibus_input_context_process_key_event_async(x64emu_t* emu, void* bus, uint32_t keyval, uint32_t keycode, uint32_t state, int timeout, void* cancel, void* f, void* data)
+{
+    my->ibus_input_context_process_key_event_async(bus, keyval, keycode, state, timeout, cancel, findGAsyncReadyCallbackFct(f), data);
+}
+
+#define PRE_INIT    \
+    if(box64_nogtk) \
+        return -1;
+
+#define CUSTOM_INIT \
+    setNeededLibs(lib, 3, "libgio-2.0.so.0", "libgobject-2.0.so.0", "libglib-2.0.so.0");
+
+#include "wrappedlib_init.h"
diff --git a/src/wrapped/wrappedlibibus_private.h b/src/wrapped/wrappedlibibus_private.h
new file mode 100644
index 00000000..35a53927
--- /dev/null
+++ b/src/wrapped/wrappedlibibus_private.h
@@ -0,0 +1,473 @@
+#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
+#error meh!
+#endif
+
+//GO(ibus_accelerator_name, 
+//GO(ibus_accelerator_parse, 
+//GO(ibus_accelerator_valid, 
+//GO(ibus_attr_background_new, 
+//GO(ibus_attr_foreground_new, 
+//GO(ibus_attribute_get_attr_type, 
+//GO(ibus_attribute_get_end_index, 
+//GO(ibus_attribute_get_start_index, 
+//GO(ibus_attribute_get_type, 
+//GO(ibus_attribute_get_value, 
+//GO(ibus_attribute_new, 
+//GO(ibus_attr_list_append, 
+//GO(ibus_attr_list_get, 
+//GO(ibus_attr_list_get_type, 
+//GO(ibus_attr_list_new, 
+GO(ibus_attr_type_get_type, LFv)
+GO(ibus_attr_underline_get_type, LFv)
+//GO(ibus_attr_underline_new, 
+//GO(ibus_bus_add_match, 
+//GO(ibus_bus_add_match_async, 
+//GO(ibus_bus_add_match_async_finish, 
+//GO(ibus_bus_create_input_context, 
+GOM(ibus_bus_create_input_context_async, vFEppippp)
+GO(ibus_bus_create_input_context_async_finish, pFppp)
+//GO(ibus_bus_current_input_context, 
+GOM(ibus_bus_current_input_context_async, vFEpippp)
+GO(ibus_bus_current_input_context_async_finish, pFppp)
+//GO(ibus_bus_exit, 
+//GO(ibus_bus_exit_async, 
+//GO(ibus_bus_exit_async_finish, 
+GO(ibus_bus_get_config, pFp)
+//GO(ibus_bus_get_connection, 
+GO(ibus_bus_get_engines_by_names, pFpp)
+//GO(ibus_bus_get_global_engine, 
+GOM(ibus_bus_get_global_engine_async, vFEpippp)
+GO(ibus_bus_get_global_engine_async_finish, pFppp)
+//GO(ibus_bus_get_ibus_property, 
+//GO(ibus_bus_get_ibus_property_async, 
+//GO(ibus_bus_get_ibus_property_async_finish, 
+//GO(ibus_bus_get_name_owner, 
+//GO(ibus_bus_get_name_owner_async, 
+//GO(ibus_bus_get_name_owner_async_finish, 
+//GO(ibus_bus_get_service_name, 
+//GO(ibus_bus_get_type, 
+//GO(ibus_bus_get_use_global_engine, 
+//GO(ibus_bus_get_use_global_engine_async, 
+//GO(ibus_bus_get_use_global_engine_async_finish, 
+//GO(ibus_bus_get_use_sys_layout, 
+//GO(ibus_bus_get_use_sys_layout_async, 
+//GO(ibus_bus_get_use_sys_layout_async_finish, 
+GO(ibus_bus_hello, pFp)
+GO(ibus_bus_is_connected, iFp)
+//GO(ibus_bus_is_global_engine_enabled, 
+//GO(ibus_bus_is_global_engine_enabled_async, 
+//GO(ibus_bus_is_global_engine_enabled_async_finish, 
+//GO(ibus_bus_list_active_engines, 
+GOM(ibus_bus_list_active_engines_async, vFEpippp)
+GO(ibus_bus_list_active_engines_async_finish, pFppp)
+//GO(ibus_bus_list_engines, 
+GOM(ibus_bus_list_engines_async, vFEpippp)
+GO(ibus_bus_list_engines_async_finish, pFppp)
+//GO(ibus_bus_list_names, 
+//GO(ibus_bus_list_queued_owners, 
+GO(ibus_bus_name_flag_get_type, LFv)
+//GO(ibus_bus_name_has_owner, 
+//GO(ibus_bus_name_has_owner_async, 
+//GO(ibus_bus_name_has_owner_async_finish, 
+GO(ibus_bus_new, pFv)
+//GO(ibus_bus_new_async, 
+//GO(ibus_bus_new_async_client, 
+//GO(ibus_bus_preload_engines, 
+//GO(ibus_bus_preload_engines_async, 
+//GO(ibus_bus_preload_engines_async_finish, 
+//GO(ibus_bus_register_component, 
+//GO(ibus_bus_register_component_async, 
+//GO(ibus_bus_register_component_async_finish, 
+//GO(ibus_bus_release_name, 
+//GO(ibus_bus_release_name_async, 
+//GO(ibus_bus_release_name_async_finish, 
+//GO(ibus_bus_remove_match, 
+//GO(ibus_bus_remove_match_async, 
+//GO(ibus_bus_remove_match_async_finish, 
+//GO(ibus_bus_request_name, 
+//GO(ibus_bus_request_name_async, 
+//GO(ibus_bus_request_name_async_finish, 
+GO(ibus_bus_request_name_reply_get_type, LFv)
+//GO(ibus_bus_set_global_engine, 
+GOM(ibus_bus_set_global_engine_async, vFEppippp)
+GO(ibus_bus_set_global_engine_async_finish, pFppp)
+//GO(ibus_bus_set_ibus_property, 
+//GO(ibus_bus_set_ibus_property_async, 
+//GO(ibus_bus_set_ibus_property_async_finish, 
+GO(ibus_bus_set_watch_dbus_signal, vFpi)
+GO(ibus_bus_set_watch_ibus_signal, vFpi)
+GO(ibus_bus_start_service_by_name_reply_get_type, LFv)
+GO(ibus_capabilite_get_type, LFv)
+//GO(ibus_check_algorithmically, 
+//GO(ibus_component_add_engine, 
+//GO(ibus_component_add_observed_path, 
+//GO(ibus_component_check_modification, 
+//GO(ibus_component_get_author, 
+//GO(ibus_component_get_description, 
+//GO(ibus_component_get_engines, 
+//GO(ibus_component_get_exec, 
+//GO(ibus_component_get_homepage, 
+//GO(ibus_component_get_license, 
+//GO(ibus_component_get_name, 
+//GO(ibus_component_get_observed_paths, 
+//GO(ibus_component_get_textdomain, 
+//GO(ibus_component_get_type, 
+//GO(ibus_component_get_version, 
+//GO(ibus_component_new, 
+//GO(ibus_component_new_from_file, 
+//GO(ibus_component_new_from_xml_node, 
+//GO(ibus_component_new_varargs, 
+//GO(ibus_component_output, 
+//GO(ibus_component_output_engines, 
+//GO(ibus_compose_table_check, 
+//DATA(ibus_compose_table_compact, 
+//DATA(ibus_compose_table_compact_32bit, 
+//DATA(ibus_compose_table_compact_32bit_priv, 
+//GO(ibus_compose_table_compact_check, 
+//GO(ibus_compose_table_list_add_array, 
+//GO(ibus_compose_table_list_add_file, 
+//GO(ibus_compose_table_load_cache, 
+//GO(ibus_compose_table_new_with_file, 
+//GO(ibus_compose_table_save_cache, 
+//GO(ibus_config_get_type, 
+//GO(ibus_config_get_value, 
+GOM(ibus_config_get_value_async, vFEpppippp)
+GO(ibus_config_get_value_async_finish, pFppp)
+//GO(ibus_config_get_values, 
+GOM(ibus_config_get_values_async, vFEppippp)
+GO(ibus_config_get_values_async_finish, pFppp)
+//GO(ibus_config_new, 
+//GO(ibus_config_new_async, 
+//GO(ibus_config_new_async_finish, 
+//GO(ibus_config_service_get_type, 
+//GO(ibus_config_service_new, 
+//GO(ibus_config_service_value_changed, 
+//GO(ibus_config_set_value, 
+GOM(ibus_config_set_value_async, vFEppppippp)
+GO(ibus_config_set_value_async_finish, pFppp)
+GO(ibus_config_unset, iFppp)
+GO(ibus_config_unwatch, iFppp)
+GO(ibus_config_watch, iFppp)
+//GO(ibus_emoji_data_get_annotations, 
+//GO(ibus_emoji_data_get_category, 
+//GO(ibus_emoji_data_get_description, 
+//GO(ibus_emoji_data_get_emoji, 
+//GO(ibus_emoji_data_get_type, 
+//GO(ibus_emoji_data_load, 
+//GO(ibus_emoji_data_new, 
+//GO(ibus_emoji_data_save, 
+//GO(ibus_emoji_data_set_annotations, 
+//GO(ibus_emoji_data_set_description, 
+//GO(ibus_emoji_dict_load, 
+//GO(ibus_emoji_dict_lookup, 
+//GO(ibus_emoji_dict_save, 
+//GO(ibus_engine_commit_text, 
+//GO(ibus_engine_delete_surrounding_text, 
+GO(ibus_engine_desc_get_author, pFp)
+GO(ibus_engine_desc_get_description, pFp)
+GO(ibus_engine_desc_get_hotkeys, pFp)
+GO(ibus_engine_desc_get_icon, pFp)
+GO(ibus_engine_desc_get_icon_prop_key, pFp)
+GO(ibus_engine_desc_get_language, pFp)
+GO(ibus_engine_desc_get_layout, pFp)
+GO(ibus_engine_desc_get_layout_option, pFp)
+GO(ibus_engine_desc_get_layout_variant, pFp)
+GO(ibus_engine_desc_get_license, pFp)
+GO(ibus_engine_desc_get_longname, pFp)
+GO(ibus_engine_desc_get_name, pFp)
+GO(ibus_engine_desc_get_rank, iFp)
+GO(ibus_engine_desc_get_setup, pFp)
+GO(ibus_engine_desc_get_symbol, pFp)
+GO(ibus_engine_desc_get_textdomain, pFp)
+GO(ibus_engine_desc_get_type, pFp)
+GO(ibus_engine_desc_get_version, pFp)
+//GO(ibus_engine_desc_new, 
+//GO(ibus_engine_desc_new_from_xml_node, 
+//GO(ibus_engine_desc_new_varargs, 
+//GO(ibus_engine_desc_output, 
+//GO(ibus_engine_forward_key_event, 
+//GO(ibus_engine_get_content_type, 
+//GO(ibus_engine_get_name, 
+//GO(ibus_engine_get_surrounding_text, 
+//GO(ibus_engine_get_type, 
+//GO(ibus_engine_hide_auxiliary_text, 
+//GO(ibus_engine_hide_lookup_table, 
+//GO(ibus_engine_hide_preedit_text, 
+//GO(ibus_engine_new, 
+//GO(ibus_engine_new_with_type, 
+//GO(ibus_engine_register_properties, 
+//GO(ibus_engine_show_auxiliary_text, 
+//GO(ibus_engine_show_lookup_table, 
+//GO(ibus_engine_show_preedit_text, 
+//GO(ibus_engine_simple_add_compose_file, 
+//GO(ibus_engine_simple_add_table, 
+//GO(ibus_engine_simple_add_table_by_locale, 
+//GO(ibus_engine_simple_get_type, 
+//GO(ibus_engine_update_auxiliary_text, 
+//GO(ibus_engine_update_lookup_table, 
+//GO(ibus_engine_update_lookup_table_fast, 
+//GO(ibus_engine_update_preedit_text, 
+//GO(ibus_engine_update_preedit_text_with_mode, 
+//GO(ibus_engine_update_property, 
+GO(ibus_error_get_type, LFv)
+//GO(ibus_error_quark, 
+//GO(ibus_extension_event_get_name, 
+//GO(ibus_extension_event_get_params, 
+//GO(ibus_extension_event_get_type, 
+//GO(ibus_extension_event_get_version, 
+//GO(ibus_extension_event_is_enabled, 
+//GO(ibus_extension_event_is_extension, 
+//GO(ibus_extension_event_new, 
+//GO(ibus_factory_add_engine, 
+//GO(ibus_factory_create_engine, 
+//GO(ibus_factory_get_type, 
+//GO(ibus_factory_new, 
+//GO(ibus_free_strv, 
+//GO(ibus_get_address, 
+//GO(ibus_get_daemon_uid, 
+//GO(ibus_get_language_name, 
+//GO(ibus_get_local_machine_id, 
+//GO(ibus_get_session_id, 
+//GO(ibus_get_socket_path, 
+//GO(ibus_get_timeout, 
+//GO(ibus_get_untranslated_language_name, 
+//GO(ibus_get_user_name, 
+//GO(ibus_hotkey_get_type, 
+//GO(ibus_hotkey_profile_add_hotkey, 
+//GO(ibus_hotkey_profile_add_hotkey_from_string, 
+//GO(ibus_hotkey_profile_filter_key_event, 
+//GO(ibus_hotkey_profile_get_type, 
+//GO(ibus_hotkey_profile_lookup_hotkey, 
+//GO(ibus_hotkey_profile_new, 
+//GO(ibus_hotkey_profile_remove_hotkey, 
+//GO(ibus_hotkey_profile_remove_hotkey_by_event, 
+GO(ibus_init, vFv)
+//GO(ibus_input_context_cancel_hand_writing, 
+//GO(ibus_input_context_cursor_down, 
+//GO(ibus_input_context_cursor_up, 
+GO(ibus_input_context_focus_in, vFp)
+GO(ibus_input_context_focus_out, vFp)
+//GO(ibus_input_context_get_engine, 
+GOM(ibus_input_context_get_engine_async, vFEpippp)
+GO(ibus_input_context_get_engine_async_finish, pFppp)
+//GO(ibus_input_context_get_input_context, 
+//GO(ibus_input_context_get_input_context_async, 
+//GO(ibus_input_context_get_input_context_async_finish, 
+//GO(ibus_input_context_get_type, 
+GO(ibus_input_context_needs_surrounding_text, iFp)
+//GO(ibus_input_context_new, 
+//GO(ibus_input_context_new_async, 
+//GO(ibus_input_context_new_async_finish, 
+//GO(ibus_input_context_page_down, 
+//GO(ibus_input_context_page_up, 
+//GO(ibus_input_context_process_hand_writing_event, 
+//GO(ibus_input_context_process_key_event, 
+GOM(ibus_input_context_process_key_event_async, vFEpuuuippp)
+GO(ibus_input_context_process_key_event_async_finish, pFppp)
+GO(ibus_input_context_property_activate, vFppu)
+//GO(ibus_input_context_property_hide, 
+//GO(ibus_input_context_property_show, 
+GO(ibus_input_context_reset, vFp)
+GO(ibus_input_context_set_capabilities, vFpu)
+//GO(ibus_input_context_set_client_commit_preedit, 
+GO(ibus_input_context_set_content_type, vFpuu)
+GO(ibus_input_context_set_cursor_location, vFpuuuu)
+//GO(ibus_input_context_set_cursor_location_relative, 
+GO(ibus_input_context_set_engine, vFpp)
+GO(ibus_input_context_set_surrounding_text, vFppuu)
+GO(ibus_input_hints_get_type, LFv)
+GO(ibus_input_purpose_get_type, LFv)
+//GO(ibus_key_event_from_string, 
+//GO(ibus_key_event_to_string, 
+//GO(ibus_keymap_fill, 
+GO(ibus_keymap_get, pFp)
+GO(ibus_keymap_get_type, LFv)
+GO(ibus_keymap_lookup_keysym, uFpWu)
+//GO(ibus_keymap_new, 
+//GO(ibus_keysym_to_unicode, 
+//GO(ibus_keyval_convert_case, 
+GO(ibus_keyval_from_name, uFp)
+GO(ibus_keyval_name, pFu)
+//GO(ibus_keyval_to_lower, 
+GO(ibus_keyval_to_unicode, uFu)
+//GO(ibus_keyval_to_upper, 
+GO(ibus_lookup_table_append_candidate, vFpp)
+GO(ibus_lookup_table_append_label, vFpp)
+GO(ibus_lookup_table_clear, vFp)
+//GO(ibus_lookup_table_cursor_down, 
+//GO(ibus_lookup_table_cursor_up, 
+GO(ibus_lookup_table_get_candidate, pFpu)
+GO(ibus_lookup_table_get_cursor_in_page, uFp)
+GO(ibus_lookup_table_get_cursor_pos, uFp)
+GO(ibus_lookup_table_get_label, pFpu)
+GO(ibus_lookup_table_get_number_of_candidates, uFp)
+GO(ibus_lookup_table_get_orientation, iFp)
+GO(ibus_lookup_table_get_page_size, uFp)
+//GO(ibus_lookup_table_get_type, 
+GO(ibus_lookup_table_is_cursor_visible, iFp)
+GO(ibus_lookup_table_is_round, iFp)
+GO(ibus_lookup_table_new, pFuuii)
+//GO(ibus_lookup_table_page_down, 
+//GO(ibus_lookup_table_page_up, 
+GO(ibus_lookup_table_set_cursor_pos, vFpu)
+GO(ibus_lookup_table_set_cursor_visible, vFpi)
+GO(ibus_lookup_table_set_label, vFpup)
+GO(ibus_lookup_table_set_orientation, vFpi)
+GO(ibus_lookup_table_set_page_size, vFpu)
+GO(ibus_lookup_table_set_round, vFpi)
+//GO(ibus_main, 
+GO(ibus_modifier_type_get_type, LFv)
+//GO(ibus_object_destroy, 
+GO(ibus_object_flags_get_type, LFv)
+GO(ibus_object_get_type, LFv)
+//GO(ibus_object_new, 
+//GO(ibus_observed_path_check_modification, 
+//GO(ibus_observed_path_get_type, 
+//GO(ibus_observed_path_new, 
+//GO(ibus_observed_path_new_from_xml_node, 
+//GO(ibus_observed_path_output, 
+//GO(ibus_observed_path_traverse, 
+GO(ibus_orientation_get_type, LFv)
+//GO(ibus_panel_service_candidate_clicked, 
+//GO(ibus_panel_service_commit_text, 
+//GO(ibus_panel_service_cursor_down, 
+//GO(ibus_panel_service_cursor_up, 
+//GO(ibus_panel_service_get_type, 
+//GO(ibus_panel_service_new, 
+//GO(ibus_panel_service_page_down, 
+//GO(ibus_panel_service_page_up, 
+//GO(ibus_panel_service_panel_extension, 
+//GO(ibus_panel_service_panel_extension_register_keys, 
+//GO(ibus_panel_service_property_activate, 
+//GO(ibus_panel_service_property_hide, 
+//GO(ibus_panel_service_property_show, 
+//GO(ibus_panel_service_update_auxiliary_text_received, 
+//GO(ibus_panel_service_update_lookup_table_received, 
+//GO(ibus_panel_service_update_preedit_text_received, 
+GO(ibus_preedit_focus_mode_get_type, LFv)
+GO(ibus_property_get_icon, pFp)
+GO(ibus_property_get_key, pFp)
+GO(ibus_property_get_label, pFp)
+GO(ibus_property_get_prop_type, iFp)
+GO(ibus_property_get_sensitive, iFp)
+GO(ibus_property_get_state, iFp)
+GO(ibus_property_get_sub_props, pFp)
+GO(ibus_property_get_symbol, pFp)
+GO(ibus_property_get_tooltip, pFp)
+GO(ibus_property_get_type, LFv)
+GO(ibus_property_get_visible, iFp)
+//GO(ibus_property_new, 
+//GO(ibus_property_new_varargs, 
+GO(ibus_property_set_icon, vFpp)
+GO(ibus_property_set_label, vFpp)
+GO(ibus_property_set_sensitive, vFpi)
+GO(ibus_property_set_state, vFpi)
+//GO(ibus_property_set_sub_props, 
+GO(ibus_property_set_symbol, vFpp)
+GO(ibus_property_set_tooltip, vFpp)
+GO(ibus_property_set_visible, vFpi)
+//GO(ibus_property_update, 
+//GO(ibus_prop_list_append, 
+GO(ibus_prop_list_get, pFpu)
+GO(ibus_prop_list_get_type, LFv)
+//GO(ibus_prop_list_new, 
+//GO(ibus_prop_list_update_property, 
+GO(ibus_prop_state_get_type, LFv)
+GO(ibus_prop_type_get_type, LFv)
+//GO(ibus_proxy_destroy, 
+//GO(ibus_proxy_get_type, 
+//GO(ibus_quit, 
+//GO(ibus_registry_check_modification, 
+//GO(ibus_registry_get_components, 
+//GO(ibus_registry_get_observed_paths, 
+//GO(ibus_registry_get_type, 
+//GO(ibus_registry_load, 
+//GO(ibus_registry_load_cache, 
+//GO(ibus_registry_load_cache_file, 
+//GO(ibus_registry_load_in_dir, 
+//GO(ibus_registry_new, 
+//GO(ibus_registry_output, 
+//GO(ibus_registry_save_cache, 
+//GO(ibus_registry_save_cache_file, 
+//GO(ibus_registry_start_monitor_changes, 
+//GO(ibus_serializable_copy, 
+//GO(ibus_serializable_deserialize_object, 
+//GO(ibus_serializable_get_qattachment, 
+//GO(ibus_serializable_get_type, 
+//GO(ibus_serializable_new, 
+//GO(ibus_serializable_remove_qattachment, 
+//GO(ibus_serializable_serialize_object, 
+//GO(ibus_serializable_set_qattachment, 
+//GO(ibus_service_class_add_interfaces, 
+//GO(ibus_service_emit_signal, 
+//GO(ibus_service_get_connection, 
+//GO(ibus_service_get_object_path, 
+//GO(ibus_service_get_type, 
+//GO(ibus_service_new, 
+//GO(ibus_service_register, 
+//GO(ibus_service_unregister, 
+//GO(ibus_set_display, 
+//GO(ibus_set_log_handler, 
+//GO(ibus_text_append_attribute, 
+//GO(ibus_text_get_attributes, 
+//GO(ibus_text_get_is_static, 
+//GO(ibus_text_get_length, 
+GO(ibus_text_get_text, pFp)
+GO(ibus_text_get_type, LFv)
+//GO(ibus_text_new_from_printf, 
+//GO(ibus_text_new_from_static_string, 
+GO(ibus_text_new_from_string, pFp)
+//GO(ibus_text_new_from_ucs4, 
+//GO(ibus_text_new_from_unichar, 
+//GO(ibus_text_set_attributes, 
+//GO(ibus_unicode_block_get_end, 
+//GO(ibus_unicode_block_get_name, 
+//GO(ibus_unicode_block_get_start, 
+//GO(ibus_unicode_block_get_type, 
+//GO(ibus_unicode_block_load, 
+//GO(ibus_unicode_block_new, 
+//GO(ibus_unicode_block_save, 
+//GO(ibus_unicode_data_get_alias, 
+//GO(ibus_unicode_data_get_block_name, 
+//GO(ibus_unicode_data_get_code, 
+//GO(ibus_unicode_data_get_name, 
+//GO(ibus_unicode_data_get_type, 
+//GO(ibus_unicode_data_load, 
+//GO(ibus_unicode_data_load_async, 
+//GO(ibus_unicode_data_new, 
+//GO(ibus_unicode_data_save, 
+//GO(ibus_unicode_data_set_block_name, 
+GO(ibus_unicode_to_keyval, uFu)
+//GO(ibus_unset_log_handler, 
+//GO(ibus_write_address, 
+//GO(ibus_x_event_get_event_type, 
+//GO(ibus_x_event_get_group, 
+//GO(ibus_x_event_get_hardware_keycode, 
+//GO(ibus_x_event_get_is_modifier, 
+//GO(ibus_x_event_get_keyval, 
+//GO(ibus_x_event_get_length, 
+//GO(ibus_x_event_get_purpose, 
+//GO(ibus_x_event_get_root, 
+//GO(ibus_x_event_get_same_screen, 
+//GO(ibus_x_event_get_send_event, 
+//GO(ibus_x_event_get_serial, 
+//GO(ibus_x_event_get_state, 
+//GO(ibus_x_event_get_string, 
+//GO(ibus_x_event_get_subwindow, 
+//GO(ibus_x_event_get_time, 
+//GO(ibus_x_event_get_type, 
+//GO(ibus_x_event_get_version, 
+//GO(ibus_x_event_get_window, 
+//GO(ibus_x_event_get_x, 
+//GO(ibus_x_event_get_x_root, 
+//GO(ibus_x_event_get_y, 
+//GO(ibus_x_event_get_y_root, 
+//GO(ibus_x_event_new, 
+//GO(ibus_xevent_type_get_type, 
+//GO(ibus_xml_copy, 
+//GO(ibus_xml_free, 
+//GO(ibus_xml_get_type, 
+//GO(ibus_xml_output, 
+//GO(ibus_xml_parse_buffer, 
+//GO(ibus_xml_parse_file, 
+
diff --git a/src/wrapped/wrappedsdl1.c b/src/wrapped/wrappedsdl1.c
index 97353568..4ebfb31e 100755
--- a/src/wrapped/wrappedsdl1.c
+++ b/src/wrapped/wrappedsdl1.c
@@ -16,6 +16,7 @@
 #include "emu/x64emu_private.h"
 #include "box64context.h"
 #include "sdl1rwops.h"
+#include "gltools.h"
 
 #include "x64trace.h"
 #include "threads.h"
@@ -349,56 +350,11 @@ EXPORT void my_SDL_KillThread(x64emu_t* emu, void* p)
     my->SDL_KillThread(p);
 }
 
-void fillGLProcWrapper(box64context_t* context);
 EXPORT void* my_SDL_GL_GetProcAddress(x64emu_t* emu, void* name) 
 {
     khint_t k;
     const char* rname = (const char*)name;
-    printf_log(LOG_DEBUG, "Calling SDL_GL_GetProcAddress(%s)\n", rname);
-    // check if glxprocaddress is filled, and search for lib and fill it if needed
-    if(!emu->context->glwrappers)
-        fillGLProcWrapper(emu->context);
-    // get proc adress using actual glXGetProcAddress
-    k = kh_get(symbolmap, emu->context->glmymap, rname);
-    int is_my = (k==kh_end(emu->context->glmymap))?0:1;
-    void* symbol;
-    if(is_my) {
-        // try again, by using custom "my_" now...
-        char tmp[200];
-        strcpy(tmp, "my_");
-        strcat(tmp, rname);
-        symbol = dlsym(emu->context->box64lib, tmp);
-    } else 
-        symbol = my->SDL_GL_GetProcAddress(name);
-    if(!symbol)
-        return NULL;    // easy
-    // check if alread bridged
-    uintptr_t ret = CheckBridged(emu->context->system, symbol);
-    if(ret)
-        return (void*)ret; // already bridged
-    // get wrapper    
-    k = kh_get(symbolmap, emu->context->glwrappers, rname);
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "ARB")==NULL) {
-        // try again, adding ARB at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "ARB");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "EXT")==NULL) {
-        // try again, adding EXT at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "EXT");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers)) {
-        printf_log(LOG_INFO, "Warning, no wrapper for %s\n", rname);
-        return NULL;
-    }
-    AddOffsetSymbol(emu->context->maplib, symbol, rname);
-    const char* constname = kh_key(emu->context->glwrappers, k);
-    return (void*)AddBridge(emu->context->system, kh_value(emu->context->glwrappers, k), symbol, 0, constname);
+    return getGLProcAddress(emu, (glprocaddress_t)my->SDL_GL_GetProcAddress, rname);
 }
 
 // DL functions from wrappedlibdl.c
diff --git a/src/wrapped/wrappedsdl2.c b/src/wrapped/wrappedsdl2.c
index d68ca1a9..40b39edf 100755
--- a/src/wrapped/wrappedsdl2.c
+++ b/src/wrapped/wrappedsdl2.c
@@ -18,6 +18,7 @@
 #include "sdl2rwops.h"
 #include "myalign.h"
 #include "threads.h"
+#include "gltools.h"
 
 #include "generated/wrappedsdl2defs.h"
 
@@ -645,71 +646,11 @@ EXPORT void my2_SDL_Log(x64emu_t* emu, void* fmt, void *b) {
     my->SDL_LogMessageV(0, 3, fmt, VARARGS);
 }
 
-void fillGLProcWrapper(box64context_t*);
 EXPORT void* my2_SDL_GL_GetProcAddress(x64emu_t* emu, void* name) 
 {
     khint_t k;
     const char* rname = (const char*)name;
-    printf_dlsym(LOG_DEBUG, "Calling SDL_GL_GetProcAddress(%s) => ", rname);
-    // check if glxprocaddress is filled, and search for lib and fill it if needed
-    if(!emu->context->glxprocaddress)
-        emu->context->glxprocaddress = (procaddess_t)my->SDL_GL_GetProcAddress;
-    if(!emu->context->glwrappers) {
-        fillGLProcWrapper(emu->context);
-        // check if libGL is loaded, load it if not (helps DeadCells)
-        if(!my_glhandle && !GetLibInternal(box64_libGL?box64_libGL:"libGL.so.1")) {
-            // use a my_dlopen to actually open that lib, like SDL2 is doing...
-            my_glhandle = my_dlopen(emu, box64_libGL?box64_libGL:"libGL.so.1", RTLD_LAZY|RTLD_GLOBAL);
-        }
-    }
-    // get proc adress using actual glXGetProcAddress
-    k = kh_get(symbolmap, emu->context->glmymap, rname);
-    int is_my = (k==kh_end(emu->context->glmymap))?0:1;
-    void* symbol;
-    if(is_my) {
-        // try again, by using custom "my_" now...
-        char tmp[200];
-        strcpy(tmp, "my_");
-        strcat(tmp, rname);
-        symbol = dlsym(emu->context->box64lib, tmp);
-    } else 
-        symbol = my->SDL_GL_GetProcAddress(name);
-    if(!symbol) {
-        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
-        return NULL;    // easy
-    }
-    // check if alread bridged
-    uintptr_t ret = CheckBridged(emu->context->system, symbol);
-    if(ret) {
-        printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
-        return (void*)ret; // already bridged
-    }
-    // get wrapper    
-    k = kh_get(symbolmap, emu->context->glwrappers, rname);
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "ARB")==NULL) {
-        // try again, adding ARB at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "ARB");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers) && strstr(rname, "EXT")==NULL) {
-        // try again, adding EXT at the end if not present
-        char tmp[200];
-        strcpy(tmp, rname);
-        strcat(tmp, "EXT");
-        k = kh_get(symbolmap, emu->context->glwrappers, tmp);
-    }
-    if(k==kh_end(emu->context->glwrappers)) {
-        printf_dlsym(LOG_DEBUG, "%p\n", NULL);
-        printf_log(LOG_INFO, "Warning, no wrapper for %s\n", rname);
-        return NULL;
-    }
-    AddOffsetSymbol(emu->context->maplib, symbol, rname);
-    const char* constname = kh_key(emu->context->glwrappers, k);
-    ret = AddBridge(emu->context->system, kh_value(emu->context->glwrappers, k), symbol, 0, constname);
-    printf_dlsym(LOG_DEBUG, "%p\n", (void*)ret);
-    return (void*)ret;
+    return getGLProcAddress(emu, (glprocaddress_t)my->SDL_GL_GetProcAddress, rname);
 }
 
 #define nb_once	16