From fa8cdbd0dfb642f2fa428cefd68743bd89120d77 Mon Sep 17 00:00:00 2001
From: FunkyFr3sh <cc.red.alert.1@googlemail.com>
Date: Fri, 22 Sep 2023 00:38:42 +0200
Subject: [PATCH] move all ini settings to c_config

---
 inc/config.h       |  76 ++++++++++++++-
 inc/dd.h           |  60 ++----------
 inc/hook.h         |   1 -
 src/config.c       | 228 +++++++++++++++------------------------------
 src/dd.c           | 225 ++++++++++++++++++++++++++++++--------------
 src/ddsurface.c    |  23 ++---
 src/directinput.c  |  12 +--
 src/dllmain.c      |   2 +
 src/fps_limiter.c  |   9 +-
 src/hook.c         |  21 ++---
 src/mouse.c        |  11 ++-
 src/render_d3d9.c  |  49 +++++-----
 src/render_gdi.c   |  17 ++--
 src/render_ogl.c   |  54 +++++------
 src/screenshot.c   |   7 +-
 src/utils.c        |  28 +++---
 src/winapi_hooks.c |  88 +++++++++--------
 src/wndproc.c      | 100 ++++++++++----------
 18 files changed, 523 insertions(+), 488 deletions(-)

diff --git a/inc/config.h b/inc/config.h
index 1b40a22..bf2df31 100644
--- a/inc/config.h
+++ b/inc/config.h
@@ -14,7 +14,79 @@ typedef struct CNCDDRAWCONFIG
     char game_path[MAX_PATH];
     char process_file_name[MAX_PATH];
     char process_file_ext[MAX_PATH];
+    
+    /* Optional settings */
+
+    BOOL fullscreen;
+    BOOL windowed;
+    BOOL maintas;
+    BOOL boxing;
+    int maxfps;
+    BOOL vsync;
+    BOOL adjmouse;
+    char shader[MAX_PATH];
+    char renderer[256];
+    BOOL devmode;
+    BOOL border;
     int save_settings;
+    BOOL resizable;
+    int d3d9_filter;
+    BOOL vhack;
+    char screenshot_dir[MAX_PATH];
+    BOOL toggle_borderless;
+
+    /* Compatibility settings */
+
+    BOOL noactivateapp;
+    int maxgameticks;
+    BOOL nonexclusive;
+    BOOL singlecpu;
+    int resolutions;
+    int fixchilds;
+    BOOL hook_peekmessage;
+    int minfps;
+    DWORD minfps_tick_len;
+
+    /* Undocumented settings */
+
+    BOOL releasealt;
+    BOOL fixnotresponding;
+    int hook;
+    int guard_lines;
+    int max_resolutions;
+    BOOL limit_bltfast;
+    BOOL lock_surfaces;
+    BOOL allow_wmactivate;
+    BOOL flipclear;
+    BOOL fixmousehook;
+    BOOL rgb555;
+    BOOL no_dinput_hook;
+    int refresh_rate;
+    int anti_aliased_fonts_min_size;
+    int custom_width;
+    int custom_height;
+    int min_font_size;
+
+    /* Hotkeys */
+
+    struct
+    {
+        int toggle_fullscreen;
+        int toggle_maximize;
+        int unlock_cursor1;
+        int unlock_cursor2;
+        int screenshot;
+    } hotkeys;
+
+    /* Game specific settings */
+
+    BOOL remove_menu;
+    
+    BOOL armadahack;
+    BOOL tshack;
+    BOOL infantryhack;
+    BOOL stronghold_hack;
+    BOOL mgs_hack;
 
 } CNCDDRAWCONFIG;
 
@@ -23,8 +95,4 @@ extern CNCDDRAWCONFIG g_config;
 void cfg_load();
 void cfg_save();
 
-BOOL cfg_get_bool(LPCSTR key, BOOL default_value);
-int cfg_get_int(LPCSTR key, int default_value);
-DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD out_size);
-
 #endif
diff --git a/inc/dd.h b/inc/dd.h
index e4f312c..46a95b1 100644
--- a/inc/dd.h
+++ b/inc/dd.h
@@ -65,13 +65,11 @@ typedef struct CNCDDRAW
     DWORD width;
     DWORD height;
     DWORD bpp;
-    BOOL windowed;
-    BOOL border;
-    BOOL boxing;
+    
     DEVMODE mode;
     struct IDirectDrawSurfaceImpl* primary;
     char title[128];
-    char screenshot_dir[MAX_PATH];
+    
     CRITICAL_SECTION cs;
 
     /* real export from system32\ddraw.dll */
@@ -81,9 +79,6 @@ typedef struct CNCDDRAW
 
     struct
     {
-        int maxfps;
-        int minfps;
-        DWORD minfps_tick_len;
         int width;
         int height;
         int opengl_y_align;
@@ -119,63 +114,20 @@ typedef struct CNCDDRAW
         RECT rc;
     } mouse;
 
-    struct
-    {
-        int toggle_fullscreen;
-        int toggle_maximize;
-        int unlock_cursor1;
-        int unlock_cursor2;
-        int screenshot;
-    } hotkeys;
-
+    DWORD(WINAPI* renderer)(void);
     HWND hwnd;
     WNDPROC wndproc;
     struct { DWORD x; DWORD y; } cursor;
-    BOOL adjmouse;
-    BOOL devmode;
-    BOOL vsync;
-    BOOL vhack;
     int upscale_hack_width;
     int upscale_hack_height;
     BOOL isredalert;
     BOOL iscnc1;
     BOOL iskkndx;
     LONG upscale_hack_active;
-    DWORD(WINAPI* renderer)(void);
-    BOOL fullscreen;
-    BOOL maintas;
-    BOOL noactivateapp;
-    char shader[MAX_PATH];
     BOOL wine;
     HCURSOR old_cursor;
     int show_cursor_count;
-    BOOL allow_wmactivate;
-    BOOL opengl_core;
-    BOOL resizable;
-    BOOL toggle_borderless;
-    BOOL nonexclusive;
-    int fixchilds;
-    BOOL fixnotresponding;
-    BOOL flipclear;
-    BOOL lock_surfaces;
-    int d3d9_filter;
-    BOOL d3d9on12;
-    int guard_lines;
-    int resolutions;
-    int max_resolutions;
-    int refresh_rate;
-    int custom_width;
-    int custom_height;
-    BOOL limit_bltfast;
-    BOOL armadahack;
-    BOOL tshack;
-    BOOL infantryhack;
-    BOOL stronghold_hack;
-    BOOL mgs_hack;
-    BOOL remove_menu;
-    int maxgameticks;
     BOOL alt_key_down;
-    BOOL releasealt;
     BOOL bnet_active;
     BOOL bnet_was_fullscreen;
     BOOL bnet_was_upscaled;
@@ -186,12 +138,12 @@ typedef struct CNCDDRAW
     BOOL child_window_exists;
     BOOL got_child_windows;
     DWORD last_set_window_pos_tick; /* WINE hack */
-    BOOL show_driver_warning;
     SPEEDLIMITER ticks_limiter;
     SPEEDLIMITER flip_limiter;
     DWORD gui_thread_id;
-    BOOL rgb555;
-    BOOL hook_peekmessage;
+    BOOL show_driver_warning;
+    BOOL d3d9on12;
+    BOOL opengl_core;
 
 } CNCDDRAW;
 
diff --git a/inc/hook.h b/inc/hook.h
index 982064f..908c832 100644
--- a/inc/hook.h
+++ b/inc/hook.h
@@ -103,7 +103,6 @@ extern GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA;
 extern COCREATEINSTANCEPROC real_CoCreateInstance;
 extern SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter;
 
-extern int g_hook_method;
 extern BOOL g_hook_active;
 extern HOOKLIST g_hook_hooklist[];
 
diff --git a/src/config.c b/src/config.c
index c8e3bce..9c976cd 100644
--- a/src/config.c
+++ b/src/config.c
@@ -13,6 +13,9 @@
 
 static void cfg_init();
 static void cfg_create_ini();
+static BOOL cfg_get_bool(LPCSTR key, BOOL default_value);
+static int cfg_get_int(LPCSTR key, int default_value);
+static DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD out_size);
 
 CNCDDRAWCONFIG g_config =
     { .window_rect = {.left = -32000, .top = -32000, .right = 0, .bottom = 0 }, .window_state = -1, .borderless_state = -1 };
@@ -21,171 +24,94 @@ void cfg_load()
 {
     cfg_init();
 
-    /* load settings from ini */
-    g_ddraw->windowed = cfg_get_bool("windowed", FALSE);
-    g_ddraw->fullscreen = cfg_get_bool("fullscreen", FALSE);
-    g_ddraw->border = cfg_get_bool("border", TRUE);
-    g_ddraw->boxing = cfg_get_bool("boxing", FALSE);
-    g_ddraw->maintas = cfg_get_bool("maintas", FALSE);
-    g_ddraw->adjmouse = cfg_get_bool("adjmouse", TRUE) || !cfg_get_bool("handlemouse", TRUE);
-    g_ddraw->devmode = cfg_get_bool("devmode", FALSE);
-    g_ddraw->vsync = cfg_get_bool("vsync", FALSE);
-    g_ddraw->noactivateapp = cfg_get_bool("noactivateapp", FALSE);
-    g_ddraw->vhack = cfg_get_bool("vhack", FALSE);
-    g_ddraw->resizable = cfg_get_bool("resizable", TRUE);
-    g_ddraw->toggle_borderless = cfg_get_bool("toggle_borderless", FALSE);
-    g_ddraw->nonexclusive = cfg_get_bool("nonexclusive", FALSE);
-    g_ddraw->fixchilds = cfg_get_int("fixchilds", FIX_CHILDS_DETECT_PAINT);
-    g_ddraw->flipclear = cfg_get_bool("flipclear", FALSE);
-    g_ddraw->fixnotresponding = cfg_get_bool("fixnotresponding", FALSE);
-    g_ddraw->lock_surfaces = cfg_get_bool("lock_surfaces", FALSE);
-    g_ddraw->releasealt = cfg_get_bool("releasealt", FALSE);
-    g_ddraw->d3d9_filter = cfg_get_int("d3d9_filter", FILTER_CUBIC);
-    g_ddraw->resolutions = cfg_get_int("resolutions", RESLIST_NORMAL);
-    g_ddraw->allow_wmactivate = cfg_get_bool("allow_wmactivate", FALSE);
-    g_ddraw->guard_lines = cfg_get_int("guard_lines", 200);
-    g_ddraw->max_resolutions = cfg_get_int("max_resolutions", 0);
-    g_ddraw->refresh_rate = cfg_get_int("refresh_rate", 0);
-    g_ddraw->custom_width = cfg_get_int("custom_width", 0);
-    g_ddraw->custom_height = cfg_get_int("custom_height", 0);
-    g_ddraw->limit_bltfast = cfg_get_bool("limit_bltfast", FALSE);
-    g_ddraw->rgb555 = cfg_get_bool("rgb555", FALSE);
-    g_ddraw->hook_peekmessage = cfg_get_bool("hook_peekmessage", FALSE);
-    g_ddraw->remove_menu = cfg_get_bool("remove_menu", FALSE);
-    cfg_get_string("screenshotdir", ".\\Screenshots\\", g_ddraw->screenshot_dir, sizeof(g_ddraw->screenshot_dir));
-
-
-    g_ddraw->armadahack = cfg_get_bool("armadahack", FALSE);
-    g_ddraw->tshack = cfg_get_bool("tshack", FALSE);
-    g_ddraw->infantryhack = cfg_get_bool("infantryhack", FALSE);
-    g_ddraw->stronghold_hack = cfg_get_bool("stronghold_hack", FALSE);
-    g_ddraw->mgs_hack = cfg_get_bool("mgs_hack", FALSE);
-
-    if (cfg_get_bool("game_handles_close", FALSE) || g_ddraw->infantryhack)
-    {
-        GameHandlesClose = TRUE;
-    }
-
-    g_ddraw->hotkeys.toggle_fullscreen = cfg_get_int("keytogglefullscreen", VK_RETURN);
-    g_ddraw->hotkeys.toggle_maximize = cfg_get_int("keytogglemaximize", VK_NEXT);
-    g_ddraw->hotkeys.unlock_cursor1 = cfg_get_int("keyunlockcursor1", VK_TAB);
-    g_ddraw->hotkeys.unlock_cursor2 = cfg_get_int("keyunlockcursor2", VK_RCONTROL);
-    g_ddraw->hotkeys.screenshot = cfg_get_int("keyscreenshot", VK_SNAPSHOT);
+    /* Optional settings */
 
     g_config.window_rect.right = cfg_get_int("width", 0);
     g_config.window_rect.bottom = cfg_get_int("height", 0);
+    g_config.fullscreen = cfg_get_bool("fullscreen", FALSE);
+    g_config.windowed = cfg_get_bool("windowed", FALSE);
+    g_config.maintas = cfg_get_bool("maintas", FALSE);
+    g_config.boxing = cfg_get_bool("boxing", FALSE);
+    g_config.maxfps = cfg_get_int("maxfps", -1);
+    g_config.vsync = cfg_get_bool("vsync", FALSE);
+    g_config.adjmouse = cfg_get_bool("adjmouse", TRUE) || !cfg_get_bool("handlemouse", TRUE);
+    cfg_get_string("shader", "Shaders\\cubic\\catmull-rom-bilinear.glsl", g_config.shader, sizeof(g_config.shader));
     g_config.window_rect.left = cfg_get_int("posX", -32000);
     g_config.window_rect.top = cfg_get_int("posY", -32000);
-
+    cfg_get_string("renderer", "auto", g_config.renderer, sizeof(g_config.renderer));
+    g_config.devmode = cfg_get_bool("devmode", FALSE);
+    g_config.border = cfg_get_bool("border", TRUE);
     g_config.save_settings = cfg_get_int("savesettings", 1);
+    g_config.resizable = cfg_get_bool("resizable", TRUE);
+    g_config.d3d9_filter = cfg_get_int("d3d9_filter", FILTER_CUBIC);
+    g_config.vhack = cfg_get_bool("vhack", FALSE);
+    cfg_get_string("screenshotdir", ".\\Screenshots\\", g_config.screenshot_dir, sizeof(g_config.screenshot_dir));
+    g_config.toggle_borderless = cfg_get_bool("toggle_borderless", FALSE);
 
-    g_ddraw->render.maxfps = cfg_get_int("maxfps", -1);
-    g_ddraw->render.minfps = cfg_get_int("minfps", 0);
+    /* Compatibility settings */
 
-    if (g_ddraw->render.minfps > 1000)
+    g_config.noactivateapp = cfg_get_bool("noactivateapp", FALSE);
+    g_config.maxgameticks = cfg_get_int("maxgameticks", 0);
+    g_config.nonexclusive = cfg_get_bool("nonexclusive", FALSE);
+    g_config.singlecpu = cfg_get_bool("singlecpu", TRUE);
+    g_config.resolutions = cfg_get_int("resolutions", RESLIST_NORMAL);
+    g_config.fixchilds = cfg_get_int("fixchilds", FIX_CHILDS_DETECT_PAINT);
+    g_config.hook_peekmessage = cfg_get_bool("hook_peekmessage", FALSE);
+
+    g_config.minfps = cfg_get_int("minfps", 0);
+
+    if (g_config.minfps > 1000)
     {
-        g_ddraw->render.minfps = 1000;
+        g_config.minfps = 1000;
     }
 
-    if (g_ddraw->render.minfps > 0)
+    if (g_config.minfps > 0)
     {
-        g_ddraw->render.minfps_tick_len = (DWORD)(1000.0f / g_ddraw->render.minfps);
+        g_config.minfps_tick_len = (DWORD)(1000.0f / g_config.minfps);
     }
 
-    /* can't fully set it up here due to missing g_ddraw->mode.dmDisplayFrequency  */
-    g_fpsl.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
+    /* Undocumented settings */
 
-    g_ddraw->maxgameticks = cfg_get_int("maxgameticks", 0);
+    g_config.releasealt = cfg_get_bool("releasealt", FALSE);
+    GameHandlesClose = cfg_get_bool("game_handles_close", FALSE);
+    g_config.fixnotresponding = cfg_get_bool("fixnotresponding", FALSE);
+    g_config.hook = cfg_get_int("hook", 4);
+    g_config.guard_lines = cfg_get_int("guard_lines", 200);
+    g_config.max_resolutions = cfg_get_int("max_resolutions", 0);
+    g_config.limit_bltfast = cfg_get_bool("limit_bltfast", FALSE);
+    g_config.lock_surfaces = cfg_get_bool("lock_surfaces", FALSE);
+    g_config.allow_wmactivate = cfg_get_bool("allow_wmactivate", FALSE);
+    g_config.flipclear = cfg_get_bool("flipclear", FALSE);
+    g_config.fixmousehook = cfg_get_bool("fixmousehook", FALSE);
+    g_config.rgb555 = cfg_get_bool("rgb555", FALSE);
+    g_config.no_dinput_hook = cfg_get_bool("no_dinput_hook", FALSE);
+    g_config.refresh_rate = cfg_get_int("refresh_rate", 0);
+    g_config.anti_aliased_fonts_min_size = cfg_get_int("anti_aliased_fonts_min_size", 13);
+    g_config.custom_width = cfg_get_int("custom_width", 0);
+    g_config.custom_height = cfg_get_int("custom_height", 0);
+    g_config.min_font_size = cfg_get_int("min_font_size", 0);
 
-    if (g_ddraw->maxgameticks > 0 && g_ddraw->maxgameticks <= 1000)
+    /* Hotkeys */
+
+    g_config.hotkeys.toggle_fullscreen = cfg_get_int("keytogglefullscreen", VK_RETURN);
+    g_config.hotkeys.toggle_maximize = cfg_get_int("keytogglemaximize", VK_NEXT);
+    g_config.hotkeys.unlock_cursor1 = cfg_get_int("keyunlockcursor1", VK_TAB);
+    g_config.hotkeys.unlock_cursor2 = cfg_get_int("keyunlockcursor2", VK_RCONTROL);
+    g_config.hotkeys.screenshot = cfg_get_int("keyscreenshot", VK_SNAPSHOT);
+
+    /* Game specific settings */
+
+    g_config.remove_menu = cfg_get_bool("remove_menu", FALSE); /* Added for HoMM4 */
+    
+    g_config.armadahack = cfg_get_bool("armadahack", FALSE);
+    g_config.tshack = cfg_get_bool("tshack", FALSE);
+    g_config.infantryhack = cfg_get_bool("infantryhack", FALSE);
+    g_config.stronghold_hack = cfg_get_bool("stronghold_hack", FALSE);
+    g_config.mgs_hack = cfg_get_bool("mgs_hack", FALSE);
+
+    if (g_config.infantryhack)
     {
-        g_ddraw->ticks_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
-
-        float len = 1000.0f / g_ddraw->maxgameticks;
-        g_ddraw->ticks_limiter.tick_length_ns = (LONGLONG)(len * 10000);
-        g_ddraw->ticks_limiter.tick_length = (DWORD)(len + 0.5f);
-    }
-
-    if (g_ddraw->maxgameticks >= 0 || g_ddraw->maxgameticks == -2)
-    {
-        /* always using 60 fps for flip...  */
-        g_ddraw->flip_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
-
-        float flip_len = 1000.0f / 60;
-        g_ddraw->flip_limiter.tick_length_ns = (LONGLONG)(flip_len * 10000);
-        g_ddraw->flip_limiter.tick_length = (DWORD)(flip_len + 0.5f);
-    }
-
-    DWORD system_affinity;
-    DWORD proc_affinity;
-    HANDLE proc = GetCurrentProcess();
-
-    if (cfg_get_bool("singlecpu", TRUE))
-    {
-        SetProcessAffinityMask(proc, 1);
-    }
-    else if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity))
-    {
-        SetProcessAffinityMask(proc, system_affinity);
-    }
-
-    if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity))
-    {
-        TRACE("     proc_affinity=%08X, system_affinity=%08X\n", proc_affinity, system_affinity);
-    }
-
-    /* to do: read .glslp config file instead of the shader and apply the correct settings  */
-    cfg_get_string("shader", "Shaders\\cubic\\catmull-rom-bilinear.glsl", g_ddraw->shader, sizeof(g_ddraw->shader));
-
-    char renderer[256] = {0};
-    cfg_get_string("renderer", "auto", renderer, sizeof(renderer));
-
-    TRACE("     Using %s renderer\n", renderer);
-
-    if (_strcmpi(renderer, "direct3d9on12") == 0)
-    {
-        g_ddraw->d3d9on12 = TRUE;
-    }
-    else if (_strcmpi(renderer, "openglcore") == 0)
-    {
-        g_ddraw->opengl_core = TRUE;
-    }
-
-    if (tolower(renderer[0]) == 'd') /* direct3d9 or direct3d9on12*/
-    {
-        g_ddraw->renderer = d3d9_render_main;
-    }
-    else if (tolower(renderer[0]) == 's' || tolower(renderer[0]) == 'g') /* gdi */
-    {
-        g_ddraw->renderer = gdi_render_main;
-    }
-    else if (tolower(renderer[0]) == 'o') /* opengl or openglcore */
-    {
-        if (oglu_load_dll())
-        {
-            g_ddraw->renderer = ogl_render_main;
-        }
-        else
-        {
-            g_ddraw->show_driver_warning = TRUE;
-            g_ddraw->renderer = gdi_render_main;
-        }
-    }
-    else /* auto */
-    {
-        if (!g_ddraw->wine && d3d9_is_available())
-        {
-            g_ddraw->renderer = d3d9_render_main;
-        }
-        else if (oglu_load_dll())
-        {
-            g_ddraw->renderer = ogl_render_main;
-        }
-        else
-        {
-            g_ddraw->show_driver_warning = TRUE;
-            g_ddraw->renderer = gdi_render_main;
-        }
+        GameHandlesClose = TRUE;
     }
 }
 
@@ -1161,7 +1087,7 @@ static void cfg_init()
     }
 }
 
-DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD out_size)
+static DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD out_size)
 {
     if (!g_config.ini_path[0])
         cfg_init();
@@ -1186,7 +1112,7 @@ DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, DWORD o
     return GetPrivateProfileStringA("ddraw", key, default_value, out_string, out_size, g_config.ini_path);
 }
 
-BOOL cfg_get_bool(LPCSTR key, BOOL default_value)
+static BOOL cfg_get_bool(LPCSTR key, BOOL default_value)
 {
     char value[8];
     cfg_get_string(key, default_value ? "Yes" : "No", value, sizeof(value));
@@ -1194,7 +1120,7 @@ BOOL cfg_get_bool(LPCSTR key, BOOL default_value)
     return (_stricmp(value, "yes") == 0 || _stricmp(value, "true") == 0 || _stricmp(value, "1") == 0);
 }
 
-int cfg_get_int(LPCSTR key, int default_value)
+static int cfg_get_int(LPCSTR key, int default_value)
 {
     char def_value[20];
     _snprintf(def_value, sizeof(def_value), "%d", default_value);
diff --git a/src/dd.c b/src/dd.c
index e49fc00..b6241f8 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -66,13 +66,13 @@ HRESULT dd_EnumDisplayModes(
         max_h = reg_m.dmPelsHeight;
     }
 
-    if (g_ddraw->stronghold_hack && max_w && (max_w % 8))
+    if (g_config.stronghold_hack && max_w && (max_w % 8))
     {
         while (--max_w % 8);
     }
 
-    BOOL rlf = g_ddraw->resolutions == RESLIST_FULL;
-    BOOL rlm = g_ddraw->resolutions == RESLIST_MINI;
+    BOOL rlf = g_config.resolutions == RESLIST_FULL;
+    BOOL rlm = g_config.resolutions == RESLIST_MINI;
 
     SIZE resolutions[] =
     {
@@ -107,7 +107,7 @@ HRESULT dd_EnumDisplayModes(
         { rlf ? 1720 : 0, rlf ? 720 : 0 },
         { rlf ? 2560 : 0, rlf ? 1080 : 0 },
         /* Inject custom resolution */
-        { g_ddraw->custom_width, g_ddraw->custom_height },
+        { g_config.custom_width, g_config.custom_height },
         { max_w, max_h },
     };
     
@@ -120,7 +120,7 @@ HRESULT dd_EnumDisplayModes(
         }
     }
 
-    if ((g_ddraw->bpp && g_ddraw->resolutions == RESLIST_NORMAL) || g_ddraw->resolutions == RESLIST_FULL)
+    if ((g_ddraw->bpp && g_config.resolutions == RESLIST_NORMAL) || g_config.resolutions == RESLIST_FULL)
     {
         TRACE("     g_ddraw->bpp=%u\n", g_ddraw->bpp);
 
@@ -174,15 +174,15 @@ HRESULT dd_EnumDisplayModes(
                 flags == m.dmDisplayFlags &&
                 fixed_output == m.dmDisplayFixedOutput)
             {
-                if (g_ddraw->stronghold_hack && m.dmPelsWidth && (m.dmPelsWidth % 8))
+                if (g_config.stronghold_hack && m.dmPelsWidth && (m.dmPelsWidth % 8))
                 {
                     while (--m.dmPelsWidth % 8);
                 }
 
-                if (i == 0 && g_ddraw->custom_width && g_ddraw->custom_height)
+                if (i == 0 && g_config.custom_width && g_config.custom_height)
                 {
-                    m.dmPelsWidth = g_ddraw->custom_width;
-                    m.dmPelsHeight = g_ddraw->custom_height;
+                    m.dmPelsWidth = g_config.custom_width;
+                    m.dmPelsHeight = g_config.custom_height;
                 }
 
                 TRACE(
@@ -208,9 +208,9 @@ HRESULT dd_EnumDisplayModes(
 
                 if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
                 {
-                    if (g_ddraw->bpp == 8 || g_ddraw->resolutions == RESLIST_FULL)
+                    if (g_ddraw->bpp == 8 || g_config.resolutions == RESLIST_FULL)
                     {
-                        if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                        if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                         {
                             TRACE("     resolution limit reached, stopping\n");
                             return DD_OK;
@@ -233,9 +233,9 @@ HRESULT dd_EnumDisplayModes(
 
                 if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
                 {
-                    if (g_ddraw->bpp == 16 || g_ddraw->resolutions == RESLIST_FULL)
+                    if (g_ddraw->bpp == 16 || g_config.resolutions == RESLIST_FULL)
                     {
-                        if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                        if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                         {
                             TRACE("     resolution limit reached, stopping\n");
                             return DD_OK;
@@ -258,9 +258,9 @@ HRESULT dd_EnumDisplayModes(
 
                 if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
                 {
-                    if (g_ddraw->bpp == 32 || g_ddraw->resolutions == RESLIST_FULL)
+                    if (g_ddraw->bpp == 32 || g_config.resolutions == RESLIST_FULL)
                     {
-                        if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                        if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                         {
                             TRACE("     resolution limit reached, stopping\n");
                             return DD_OK;
@@ -290,14 +290,14 @@ HRESULT dd_EnumDisplayModes(
         }
     }
 
-    if (!g_ddraw->bpp || g_ddraw->resolutions != RESLIST_NORMAL)
+    if (!g_ddraw->bpp || g_config.resolutions != RESLIST_NORMAL)
     {
         for (i = 0; i < sizeof(resolutions) / sizeof(resolutions[0]); i++)
         {
             if (!resolutions[i].cx || !resolutions[i].cy)
                 continue;
 
-            if (!(resolutions[i].cx == g_ddraw->custom_width && resolutions[i].cy == g_ddraw->custom_height) &&
+            if (!(resolutions[i].cx == g_config.custom_width && resolutions[i].cy == g_config.custom_height) &&
                 ((max_w && resolutions[i].cx > max_w) || (max_h && resolutions[i].cy > max_h)))
             {
                 DEVMODE m;
@@ -327,7 +327,7 @@ HRESULT dd_EnumDisplayModes(
 
             if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
             {
-                if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                 {
                     TRACE("     resolution limit reached, stopping\n");
                     return DD_OK;
@@ -349,7 +349,7 @@ HRESULT dd_EnumDisplayModes(
 
             if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
             {
-                if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                 {
                     TRACE("     resolution limit reached, stopping\n");
                     return DD_OK;
@@ -362,7 +362,7 @@ HRESULT dd_EnumDisplayModes(
                 }
             }
 
-            if (g_ddraw->resolutions == RESLIST_MINI)
+            if (g_config.resolutions == RESLIST_MINI)
                 continue;
 
             s.ddpfPixelFormat.dwFlags = DDPF_RGB;
@@ -374,7 +374,7 @@ HRESULT dd_EnumDisplayModes(
 
             if (s.ddpfPixelFormat.dwRGBBitCount == bpp_filter || !bpp_filter)
             {
-                if (g_ddraw->max_resolutions && res_count++ >= g_ddraw->max_resolutions)
+                if (g_config.max_resolutions && res_count++ >= g_config.max_resolutions)
                 {
                     TRACE("     resolution limit reached, stopping\n");
                     return DD_OK;
@@ -531,9 +531,9 @@ HRESULT dd_RestoreDisplayMode()
         }
     }
 
-    if (!g_ddraw->windowed)
+    if (!g_config.windowed)
     {
-        if (g_ddraw->renderer == d3d9_render_main && !g_ddraw->nonexclusive)
+        if (g_ddraw->renderer == d3d9_render_main && !g_config.nonexclusive)
         {
             if (!d3d9_reset(TRUE))
                 d3d9_release();
@@ -552,7 +552,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     if (dwBPP != 8 && dwBPP != 16 && dwBPP != 32)
         return DDERR_INVALIDMODE;
 
-    if (g_ddraw->mgs_hack && dwHeight == 480) dwHeight -= 32; /* Remove black bar in Metal Gear Solid */
+    if (g_config.mgs_hack && dwHeight == 480) dwHeight -= 32; /* Remove black bar in Metal Gear Solid */
 
     if (g_ddraw->render.thread)
     {
@@ -583,7 +583,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
 
             if (!g_ddraw->mode.dmPelsWidth || !g_ddraw->mode.dmPelsHeight)
             {
-                g_ddraw->fullscreen = FALSE;
+                g_config.fullscreen = FALSE;
             }
         }
     }
@@ -592,7 +592,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     g_ddraw->render.height = g_config.window_rect.bottom;
 
     /* temporary fix: center window for games that keep changing their resolution */
-    if ((g_ddraw->width || g_ddraw->infantryhack) &&
+    if ((g_ddraw->width || g_config.infantryhack) &&
         (g_ddraw->width != dwWidth || g_ddraw->height != dwHeight) &&
         (dwWidth > g_config.window_rect.right || dwHeight > g_config.window_rect.bottom))
     {
@@ -607,15 +607,15 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     InterlockedExchange((LONG*)&g_ddraw->cursor.x, dwWidth / 2);
     InterlockedExchange((LONG*)&g_ddraw->cursor.y, dwHeight / 2);
 
-    BOOL border = g_ddraw->border;
+    BOOL border = g_config.border;
     BOOL nonexclusive = FALSE;
 
-    if (g_ddraw->fullscreen)
+    if (g_config.fullscreen)
     {
         g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
         g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
 
-        if (g_ddraw->windowed) /* windowed-fullscreen aka borderless */
+        if (g_config.windowed) /* windowed-fullscreen aka borderless */
         {
             border = FALSE;
 
@@ -645,14 +645,14 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     memset(&g_ddraw->render.mode, 0, sizeof(DEVMODE));
     g_ddraw->render.mode.dmSize = sizeof(DEVMODE);
 
-    if (g_ddraw->refresh_rate)
+    if (g_config.refresh_rate)
     {
         g_ddraw->render.mode.dmFields |= DM_DISPLAYFREQUENCY;
-        g_ddraw->render.mode.dmDisplayFrequency = g_ddraw->refresh_rate;
+        g_ddraw->render.mode.dmDisplayFrequency = g_config.refresh_rate;
 
         if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
         {
-            g_ddraw->refresh_rate = 0;
+            g_config.refresh_rate = 0;
 
             g_ddraw->render.mode.dmFields = 0;
             g_ddraw->render.mode.dmDisplayFrequency = 0;
@@ -663,7 +663,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
     g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
 
-    if (!g_ddraw->windowed)
+    if (!g_config.windowed)
     {
         /* Making sure the chosen resolution is valid */
         if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
@@ -724,7 +724,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
                             g_ddraw->height > g_ddraw->mode.dmPelsHeight)
                         {
                             /* Downscaling requires adjmouse to be enabled */
-                            g_ddraw->adjmouse = TRUE;
+                            g_config.adjmouse = TRUE;
                         }
 
                         /* try current display settings */
@@ -739,8 +739,8 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
                             /* everything failed, use borderless mode instead */
                             ChangeDisplaySettings(NULL, 0);
 
-                            g_ddraw->windowed = TRUE;
-                            g_ddraw->fullscreen = TRUE;
+                            g_config.windowed = TRUE;
+                            g_config.fullscreen = TRUE;
                             border = FALSE;
 
                             /* prevent OpenGL from going automatically into fullscreen exclusive mode */
@@ -755,13 +755,13 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     }
     
     /* Support downscaling in borderless mode */
-    if (g_ddraw->windowed && g_ddraw->fullscreen)
+    if (g_config.windowed && g_config.fullscreen)
     {
         if (g_ddraw->width > g_ddraw->mode.dmPelsWidth ||
             g_ddraw->height > g_ddraw->mode.dmPelsHeight)
         {
             /* Downscaling requires adjmouse to be enabled */
-            g_ddraw->adjmouse = TRUE;
+            g_config.adjmouse = TRUE;
 
             g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
             g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
@@ -776,7 +776,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     g_ddraw->render.viewport.x = 0;
     g_ddraw->render.viewport.y = 0;
 
-    if (g_ddraw->boxing)
+    if (g_config.boxing)
     {
         g_ddraw->render.viewport.width = g_ddraw->width;
         g_ddraw->render.viewport.height = g_ddraw->height;
@@ -794,7 +794,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
         g_ddraw->render.viewport.y = g_ddraw->render.height / 2 - g_ddraw->render.viewport.height / 2;
         g_ddraw->render.viewport.x = g_ddraw->render.width / 2 - g_ddraw->render.viewport.width / 2;
     }
-    else if (g_ddraw->maintas)
+    else if (g_config.maintas)
     {
         g_ddraw->render.viewport.width = g_ddraw->render.width;
         g_ddraw->render.viewport.height =
@@ -830,13 +830,13 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
     g_ddraw->mouse.rc.right = g_ddraw->width + g_ddraw->mouse.x_adjust;
     g_ddraw->mouse.rc.bottom = g_ddraw->height + g_ddraw->mouse.y_adjust;
 
-    if (g_ddraw->adjmouse)
+    if (g_config.adjmouse)
     {
         g_ddraw->mouse.rc.right = g_ddraw->render.viewport.width + g_ddraw->mouse.x_adjust;
         g_ddraw->mouse.rc.bottom = g_ddraw->render.viewport.height + g_ddraw->mouse.y_adjust;
     }
 
-    if (nonexclusive || (g_ddraw->nonexclusive && !g_ddraw->windowed && g_ddraw->renderer == ogl_render_main))
+    if (nonexclusive || (g_config.nonexclusive && !g_config.windowed && g_ddraw->renderer == ogl_render_main))
     {
         g_ddraw->render.height++;
         g_ddraw->render.opengl_y_align = 1;
@@ -846,9 +846,9 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
         g_ddraw->render.opengl_y_align = 0;
     }
 
-    if (g_ddraw->windowed)
+    if (g_config.windowed)
     {
-        if (g_ddraw->remove_menu && GetMenu(g_ddraw->hwnd))
+        if (g_config.remove_menu && GetMenu(g_ddraw->hwnd))
             SetMenu(g_ddraw->hwnd, NULL);
 
         if (!g_ddraw->wine)
@@ -898,7 +898,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
         int x = (g_config.window_rect.left != -32000) ? g_config.window_rect.left : (cy / 2) - (g_ddraw->render.width / 2);
         int y = (g_config.window_rect.top != -32000) ? g_config.window_rect.top : (cx / 2) - (g_ddraw->render.height / 2);
 
-        if (g_ddraw->fullscreen)
+        if (g_config.fullscreen)
         {
             x = y = 0;
         }
@@ -942,7 +942,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
             }
         }
 
-        if (lock_mouse || (g_ddraw->fullscreen && real_GetForegroundWindow() == g_ddraw->hwnd))
+        if (lock_mouse || (g_config.fullscreen && real_GetForegroundWindow() == g_ddraw->hwnd))
             mouse_lock();
     }
     else
@@ -975,7 +975,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
 
         if (g_ddraw->renderer == d3d9_render_main)
         {
-            if (g_ddraw->nonexclusive)
+            if (g_config.nonexclusive)
             {
                 if (util_is_minimized(g_ddraw->hwnd))
                     real_ShowWindow(g_ddraw->hwnd, SW_RESTORE);
@@ -1002,12 +1002,12 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
             }
         }
 
-        if ((!d3d9_active || g_ddraw->nonexclusive) &&
+        if ((!d3d9_active || g_config.nonexclusive) &&
             ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
         {
             g_ddraw->render.run = FALSE;
-            g_ddraw->windowed = TRUE;
-            g_ddraw->fullscreen = TRUE;
+            g_config.windowed = TRUE;
+            g_config.fullscreen = TRUE;
             return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags);
         }
 
@@ -1031,7 +1031,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
             g_ddraw->render.height,
             swp_flags);
 
-        if (d3d9_active && g_ddraw->nonexclusive)
+        if (d3d9_active && g_config.nonexclusive)
             d3d9_reset(TRUE);
 
         g_ddraw->last_set_window_pos_tick = timeGetTime();
@@ -1056,7 +1056,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
         SetThreadPriority(g_ddraw->render.thread, THREAD_PRIORITY_ABOVE_NORMAL);
     }
 
-    if ((dwFlags & SDM_MODE_SET_BY_GAME) && !g_ddraw->infantryhack)
+    if ((dwFlags & SDM_MODE_SET_BY_GAME) && !g_config.infantryhack)
     {
         real_SendMessageA(g_ddraw->hwnd, WM_SIZE_DDRAW, 0, MAKELPARAM(g_ddraw->width, g_ddraw->height));
         real_SendMessageA(g_ddraw->hwnd, WM_MOVE_DDRAW, 0, MAKELPARAM(0, 0));
@@ -1106,7 +1106,7 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
             SetPixelFormat(g_ddraw->render.hdc, ChoosePixelFormat(g_ddraw->render.hdc, &pfd), &pfd);
         }
 
-        if (!g_ddraw->devmode)
+        if (!g_config.devmode)
         {
             HCURSOR cursor = real_SetCursor(LoadCursor(NULL, IDC_ARROW));
 
@@ -1119,13 +1119,13 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
         real_ShowCursor(FALSE);
 
         /* Make sure the cursor is visible in windowed mode initially */
-        if (g_ddraw->windowed && !g_ddraw->fullscreen && !g_ddraw->devmode && cursor_count < 0)
+        if (g_config.windowed && !g_config.fullscreen && !g_config.devmode && cursor_count < 0)
         {
             while (real_ShowCursor(TRUE) < 0);
         }
 
         /* Starcraft locks the cursor before ddraw.dll was loaded */
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             real_ClipCursor(NULL);
         }
@@ -1147,31 +1147,31 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
             g_ddraw->upscale_hack_height = 400;
         }
 
-        if (g_ddraw->vhack && !g_ddraw->isredalert && !g_ddraw->iscnc1 && !g_ddraw->iskkndx)
+        if (g_config.vhack && !g_ddraw->isredalert && !g_ddraw->iscnc1 && !g_ddraw->iskkndx)
         {
-            g_ddraw->vhack = 0;
+            g_config.vhack = 0;
         }
     }
 
     /* Infantry Online Zone List Window */
-    if (g_ddraw->infantryhack)
+    if (g_config.infantryhack)
     {
         static BOOL windowed, fullscreen;
 
         if (dwFlags & DDSCL_FULLSCREEN)
         {
-            g_ddraw->windowed = windowed;
-            g_ddraw->fullscreen = fullscreen;
+            g_config.windowed = windowed;
+            g_config.fullscreen = fullscreen;
         }
         else if (dwFlags & DDSCL_NOWINDOWCHANGES)
         {
-            windowed = g_ddraw->windowed;
-            fullscreen = g_ddraw->fullscreen;
+            windowed = g_config.windowed;
+            fullscreen = g_config.fullscreen;
 
             if (GetMenu(g_ddraw->hwnd) != NULL)
             {
-                g_ddraw->windowed = TRUE;
-                g_ddraw->fullscreen = FALSE;
+                g_config.windowed = TRUE;
+                g_config.fullscreen = FALSE;
             }
 
             dd_SetDisplayMode(640, 480, 16, SDM_MODE_SET_BY_GAME);
@@ -1183,9 +1183,9 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
 
 HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent)
 {
-    if (g_ddraw->maxgameticks == -2)
+    if (g_config.maxgameticks == -2)
     {
-        if (fpsl_dwm_flush() || fpsl_wait_for_vblank(g_ddraw->render.maxfps >= 0 && !g_ddraw->vsync))
+        if (fpsl_dwm_flush() || fpsl_wait_for_vblank(g_config.maxfps >= 0 && !g_config.vsync))
             return DD_OK;
     }
 
@@ -1267,9 +1267,9 @@ ULONG dd_Release()
             }
         }
 
-        if (!g_ddraw->windowed)
+        if (!g_config.windowed)
         {
-            if (g_ddraw->renderer == d3d9_render_main && !g_ddraw->nonexclusive)
+            if (g_ddraw->renderer == d3d9_render_main && !g_config.nonexclusive)
             {
                 if (!d3d9_reset(TRUE))
                     d3d9_release();
@@ -1378,7 +1378,94 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute
         g_ddraw->wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
         g_blt_use_avx = util_is_avx_supported();
 
-        cfg_load();
+        /* can't fully set it up here due to missing g_ddraw->mode.dmDisplayFrequency  */
+        g_fpsl.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
+
+        if (g_config.maxgameticks > 0 && g_config.maxgameticks <= 1000)
+        {
+            g_ddraw->ticks_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
+
+            float len = 1000.0f / g_config.maxgameticks;
+            g_ddraw->ticks_limiter.tick_length_ns = (LONGLONG)(len * 10000);
+            g_ddraw->ticks_limiter.tick_length = (DWORD)(len + 0.5f);
+        }
+
+        if (g_config.maxgameticks >= 0 || g_config.maxgameticks == -2)
+        {
+            /* always using 60 fps for flip...  */
+            g_ddraw->flip_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
+
+            float flip_len = 1000.0f / 60;
+            g_ddraw->flip_limiter.tick_length_ns = (LONGLONG)(flip_len * 10000);
+            g_ddraw->flip_limiter.tick_length = (DWORD)(flip_len + 0.5f);
+        }
+
+
+        DWORD system_affinity;
+        DWORD proc_affinity;
+        HANDLE proc = GetCurrentProcess();
+
+        if (g_config.singlecpu)
+        {
+            SetProcessAffinityMask(proc, 1);
+        }
+        else if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity))
+        {
+            SetProcessAffinityMask(proc, system_affinity);
+        }
+
+        if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity))
+        {
+            TRACE("     proc_affinity=%08X, system_affinity=%08X\n", proc_affinity, system_affinity);
+        }
+
+
+        if (_strcmpi(g_config.renderer, "direct3d9on12") == 0)
+        {
+            g_ddraw->d3d9on12 = TRUE;
+        }
+        else if (_strcmpi(g_config.renderer, "openglcore") == 0)
+        {
+            g_ddraw->opengl_core = TRUE;
+        }
+
+        if (tolower(g_config.renderer[0]) == 'd') /* direct3d9 or direct3d9on12*/
+        {
+            g_ddraw->renderer = d3d9_render_main;
+        }
+        else if (tolower(g_config.renderer[0]) == 's' || tolower(g_config.renderer[0]) == 'g') /* gdi */
+        {
+            g_ddraw->renderer = gdi_render_main;
+        }
+        else if (tolower(g_config.renderer[0]) == 'o') /* opengl or openglcore */
+        {
+            if (oglu_load_dll())
+            {
+                g_ddraw->renderer = ogl_render_main;
+            }
+            else
+            {
+                g_ddraw->show_driver_warning = TRUE;
+                g_ddraw->renderer = gdi_render_main;
+            }
+        }
+        else /* auto */
+        {
+            if (!g_ddraw->wine && d3d9_is_available())
+            {
+                g_ddraw->renderer = d3d9_render_main;
+            }
+            else if (oglu_load_dll())
+            {
+                g_ddraw->renderer = ogl_render_main;
+            }
+            else
+            {
+                g_ddraw->show_driver_warning = TRUE;
+                g_ddraw->renderer = gdi_render_main;
+            }
+        }
+
         g_ddraw->ref--;
     }
 
diff --git a/src/ddsurface.c b/src/ddsurface.c
index dfa059f..3ca910d 100644
--- a/src/ddsurface.c
+++ b/src/ddsurface.c
@@ -10,6 +10,7 @@
 #include "debug.h"
 #include "utils.h"
 #include "blt.h"
+#include "config.h"
 
 
 LONG g_dds_gdi_handles;
@@ -647,7 +648,7 @@ HRESULT dds_BltFast(
         {
             ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
 
-            if (g_ddraw->limit_bltfast && g_ddraw->ticks_limiter.tick_length > 0)
+            if (g_config.limit_bltfast && g_ddraw->ticks_limiter.tick_length > 0)
             {
                 g_ddraw->ticks_limiter.use_blt_or_flip = TRUE;
                 util_limit_game_ticks();
@@ -761,7 +762,7 @@ HRESULT dds_Flip(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurfa
         InterlockedExchangePointer(&backbuffer->hdc, dc);
         InterlockedExchangePointer(&backbuffer->mapping, map);
 
-        if (g_ddraw->flipclear)
+        if (g_config.flipclear)
         {
             blt_clear(buf, 0, backbuffer->size);
         }
@@ -782,7 +783,7 @@ HRESULT dds_Flip(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurfa
         ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
         SwitchToThread();
 
-        if ((g_ddraw->maxgameticks == 0 && (dwFlags & DDFLIP_WAIT)) || g_ddraw->maxgameticks == -2)
+        if ((g_config.maxgameticks == 0 && (dwFlags & DDFLIP_WAIT)) || g_config.maxgameticks == -2)
         {
             dd_WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL);
         }
@@ -949,12 +950,12 @@ HRESULT dds_Lock(
     DWORD dwFlags,
     HANDLE hEvent)
 {
-    if (g_ddraw && g_ddraw->lock_surfaces)
+    if (g_config.lock_surfaces)
         EnterCriticalSection(&This->cs);
 
     dbg_dump_dds_lock_flags(dwFlags);
 
-    if (g_ddraw && g_ddraw->fixnotresponding && !g_ddraw->wine)
+    if (g_ddraw && g_config.fixnotresponding && !g_ddraw->wine)
     {
         MSG msg; /* workaround for "Not Responding" window problem */
         real_PeekMessageA(&msg, g_ddraw->hwnd, 0, 0, PM_NOREMOVE);
@@ -1126,7 +1127,7 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
     }
 
     /* Hack for Star Trek Armada */
-    hwnd = g_ddraw && g_ddraw->armadahack ? FindWindowEx(HWND_DESKTOP, NULL, "#32770", NULL) : NULL;
+    hwnd = g_ddraw && g_config.armadahack ? FindWindowEx(HWND_DESKTOP, NULL, "#32770", NULL) : NULL;
 
     if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE))
     {
@@ -1180,7 +1181,7 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
         }
     }
 
-    if (g_ddraw && g_ddraw->lock_surfaces)
+    if (g_config.lock_surfaces)
         LeaveCriticalSection(&This->cs);
 
     return DD_OK;
@@ -1364,7 +1365,7 @@ HRESULT dd_CreateSurface(
     }
     else
     {
-        if (!(dst_surface->caps & DDSCAPS_SYSTEMMEMORY) || g_ddraw->tshack)
+        if (!(dst_surface->caps & DDSCAPS_SYSTEMMEMORY) || g_config.tshack)
         {
             dst_surface->caps |= DDSCAPS_VIDEOMEMORY;
         }
@@ -1390,12 +1391,12 @@ HRESULT dd_CreateSurface(
         DWORD aligned_width = dst_surface->pitch / dst_surface->bytes_pp;
 
         DWORD bmi_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256;
-        DWORD bmp_size = dst_surface->pitch * (dst_surface->height + g_ddraw->guard_lines);
+        DWORD bmp_size = dst_surface->pitch * (dst_surface->height + g_config.guard_lines);
 
         dst_surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
         dst_surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
         dst_surface->bmi->bmiHeader.biWidth = aligned_width;
-        dst_surface->bmi->bmiHeader.biHeight = -((int)dst_surface->height + g_ddraw->guard_lines);
+        dst_surface->bmi->bmiHeader.biHeight = -((int)dst_surface->height + g_config.guard_lines);
         dst_surface->bmi->bmiHeader.biPlanes = 1;
         dst_surface->bmi->bmiHeader.biBitCount = dst_surface->bpp;
         dst_surface->bmi->bmiHeader.biCompression = dst_surface->bpp == 8 ? BI_RGB : BI_BITFIELDS;
@@ -1420,7 +1421,7 @@ HRESULT dd_CreateSurface(
                 dst_surface->bmi->bmiColors[i].rgbReserved = 0;
             }
         }
-        else if (dst_surface->bpp == 16 && g_ddraw->rgb555)
+        else if (dst_surface->bpp == 16 && g_config.rgb555)
         {
             ((DWORD*)dst_surface->bmi->bmiColors)[0] = 0x7C00;
             ((DWORD*)dst_surface->bmi->bmiColors)[1] = 0x03E0;
diff --git a/src/directinput.c b/src/directinput.c
index c73f7cf..2647d6a 100644
--- a/src/directinput.c
+++ b/src/directinput.c
@@ -47,7 +47,7 @@ static HRESULT WINAPI fake_did_SetCooperativeLevel(IDirectInputDeviceA* This, HW
 
     if (This == g_mouse_device && g_ddraw && (dwFlags & DISCL_EXCLUSIVE))
     {
-        if (g_mouse_locked || g_ddraw->devmode)
+        if (g_mouse_locked || g_config.devmode)
         {
             while (real_ShowCursor(FALSE) >= 0);
         }
@@ -202,7 +202,7 @@ HRESULT WINAPI fake_DirectInputCreateA(
 
     HRESULT result = real_DirectInputCreateA(hinst, dwVersion, lplpDirectInput, punkOuter);
 
-    if (SUCCEEDED(result) && !real_di_CreateDevice && !cfg_get_bool("no_dinput_hook", FALSE))
+    if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
         real_di_CreateDevice =
             (DICREATEDEVICEPROC)hook_func((PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
@@ -238,7 +238,7 @@ HRESULT WINAPI fake_DirectInputCreateW(
 
     HRESULT result = real_DirectInputCreateW(hinst, dwVersion, lplpDirectInput, punkOuter);
 
-    if (SUCCEEDED(result) && !real_di_CreateDevice && !cfg_get_bool("no_dinput_hook", FALSE))
+    if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
         real_di_CreateDevice =
             (DICREATEDEVICEPROC)hook_func((PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
@@ -275,7 +275,7 @@ HRESULT WINAPI fake_DirectInputCreateEx(
 
     HRESULT result = real_DirectInputCreateEx(hinst, dwVersion, riidltf, ppvOut, punkOuter);
 
-    if (SUCCEEDED(result) && !real_di_CreateDevice && !cfg_get_bool("no_dinput_hook", FALSE))
+    if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
         real_di_CreateDevice =
             (DICREATEDEVICEPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
@@ -285,7 +285,7 @@ HRESULT WINAPI fake_DirectInputCreateEx(
         !real_di_CreateDeviceEx &&
         riidltf &&
         (IsEqualGUID(&IID_IDirectInput7A, riidltf) || IsEqualGUID(&IID_IDirectInput7W, riidltf)) 
-        && !cfg_get_bool("no_dinput_hook", FALSE))
+        && !g_config.no_dinput_hook)
     {
         real_di_CreateDeviceEx =
             (DICREATEDEVICEEXPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDeviceEx, (PROC)fake_di_CreateDeviceEx);
@@ -322,7 +322,7 @@ HRESULT WINAPI fake_DirectInput8Create(
 
     HRESULT result = real_DirectInput8Create(hinst, dwVersion, riidltf, ppvOut, punkOuter);
 
-    if (SUCCEEDED(result) && !real_di_CreateDevice && !cfg_get_bool("no_dinput_hook", FALSE))
+    if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
         real_di_CreateDevice =
             (DICREATEDEVICEPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
diff --git a/src/dllmain.c b/src/dllmain.c
index 92e6d2d..c7a042f 100644
--- a/src/dllmain.c
+++ b/src/dllmain.c
@@ -104,6 +104,8 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
                 set_aware();
         }
 
+        cfg_load();
+
         timeBeginPeriod(1);
         hook_init(TRUE);
         break;
diff --git a/src/fps_limiter.c b/src/fps_limiter.c
index ce76f93..094f902 100644
--- a/src/fps_limiter.c
+++ b/src/fps_limiter.c
@@ -3,17 +3,18 @@
 #include "dd.h"
 #include "debug.h"
 #include "hook.h"
+#include "config.h"
 
 FPSLIMITER g_fpsl;
 
 void fpsl_init()
 {
-    int max_fps = g_ddraw->render.maxfps;
+    int max_fps = g_config.maxfps;
 
     g_fpsl.tick_length_ns = 0;
     g_fpsl.tick_length = 0;
 
-    if (max_fps < 0 || g_ddraw->vsync)
+    if (max_fps < 0 || g_config.vsync)
         max_fps = g_ddraw->mode.dmDisplayFrequency;
 
     if (max_fps > 1000)
@@ -124,7 +125,7 @@ void fpsl_frame_start()
 
 void fpsl_frame_end()
 {
-    if (g_ddraw->render.maxfps < 0 || g_ddraw->vsync)
+    if (g_config.maxfps < 0 || g_config.vsync)
     {
         if (fpsl_dwm_flush() || fpsl_wait_for_vblank(TRUE))
             return;
@@ -134,7 +135,7 @@ void fpsl_frame_end()
     {
         if (g_fpsl.htimer)
         {
-            if (g_ddraw->vsync)
+            if (g_config.vsync)
             {
                 WaitForSingleObject(g_fpsl.htimer, g_fpsl.tick_length * 2);
                 LARGE_INTEGER due_time = { .QuadPart = -g_fpsl.tick_length_ns };
diff --git a/src/hook.c b/src/hook.c
index 5f5e7e6..a1e3407 100644
--- a/src/hook.c
+++ b/src/hook.c
@@ -15,7 +15,6 @@
 #endif
 
 BOOL g_hook_active;
-int g_hook_method = 4;
 
 GETCURSORPOSPROC real_GetCursorPos = GetCursorPos;
 CLIPCURSORPROC real_ClipCursor = ClipCursor;
@@ -410,7 +409,7 @@ BOOL hook_got_ddraw_import()
 void hook_create(HOOKLIST* hooks, BOOL initial_hook)
 {
 #ifdef _MSC_VER
-    if ((g_hook_method == 2) && initial_hook)
+    if ((g_config.hook == 2) && initial_hook)
     {
         for (int i = 0; hooks[i].module_name[0]; i++)
         {
@@ -428,7 +427,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
     }
 #endif
 
-    if (g_hook_method == 3 || g_hook_method == 4)
+    if (g_config.hook == 3 || g_config.hook == 4)
     {
         char game_exe_path[MAX_PATH] = { 0 };
         char game_dir[MAX_PATH] = { 0 };
@@ -486,7 +485,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
         }
     }
 
-    if (g_hook_method == 1)
+    if (g_config.hook == 1)
     {
         hook_patch_iat_list(GetModuleHandle(NULL), FALSE, hooks);
     }
@@ -495,7 +494,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
 void hook_revert(HOOKLIST* hooks)
 {
 #ifdef _MSC_VER
-    if (g_hook_method == 2)
+    if (g_config.hook == 2)
     {
         for (int i = 0; hooks[i].module_name[0]; i++)
         {
@@ -513,7 +512,7 @@ void hook_revert(HOOKLIST* hooks)
     }
 #endif
 
-    if (g_hook_method == 3 || g_hook_method == 4)
+    if (g_config.hook == 3 || g_config.hook == 4)
     {
         char game_exe_path[MAX_PATH] = { 0 };
         char game_dir[MAX_PATH] = { 0 };
@@ -560,7 +559,7 @@ void hook_revert(HOOKLIST* hooks)
         }
     }
 
-    if (g_hook_method == 1)
+    if (g_config.hook == 1)
     {
         hook_patch_iat_list(GetModuleHandle(NULL), TRUE, hooks);
     }
@@ -570,16 +569,14 @@ void hook_init(BOOL initial_hook)
 {
     if (initial_hook)
     {
-        g_hook_method = cfg_get_int("hook", 4);
-
-        if (g_hook_method == 4 && hook_got_ddraw_import())
+        if (g_config.hook == 4 && hook_got_ddraw_import())
         {
             /* Switch to 3 if we can be sure that ddraw.dll will not be unloaded from the process */
-            g_hook_method = 3;
+            g_config.hook = 3;
         }
     }
 
-    if (!g_hook_active || g_hook_method == 3 || g_hook_method == 4)
+    if (!g_hook_active || g_config.hook == 3 || g_config.hook == 4)
     {
 #if defined(_DEBUG) && defined(_MSC_VER)
         if (initial_hook)
diff --git a/src/mouse.c b/src/mouse.c
index e709784..504ee92 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -4,6 +4,7 @@
 #include "dd.h"
 #include "hook.h"
 #include "utils.h"
+#include "config.h"
 
 
 BOOL g_mouse_locked;
@@ -12,7 +13,7 @@ HOOKPROC g_mouse_proc;
 
 void mouse_lock()
 {
-    if (g_ddraw->devmode || g_ddraw->bnet_active || !g_ddraw->hwnd)
+    if (g_config.devmode || g_ddraw->bnet_active || !g_ddraw->hwnd)
         return;
 
     if (g_hook_active && !g_mouse_locked && !util_is_minimized(g_ddraw->hwnd))
@@ -41,8 +42,8 @@ void mouse_lock()
         int cur_y = InterlockedExchangeAdd((LONG*)&g_ddraw->cursor.y, 0);
 
         real_SetCursorPos(
-            g_ddraw->adjmouse ? (int)(rc.left + (cur_x * g_ddraw->mouse.scale_x)) : rc.left + cur_x,
-            g_ddraw->adjmouse ? (int)(rc.top + (cur_y * g_ddraw->mouse.scale_y)) : rc.top + cur_y);
+            g_config.adjmouse ? (int)(rc.left + (cur_x * g_ddraw->mouse.scale_x)) : rc.left + cur_x,
+            g_config.adjmouse ? (int)(rc.top + (cur_y * g_ddraw->mouse.scale_y)) : rc.top + cur_y);
 
         CopyRect(&rc, &g_ddraw->mouse.rc);
         real_MapWindowPoints(g_ddraw->hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);
@@ -54,7 +55,7 @@ void mouse_lock()
 
 void mouse_unlock()
 {
-    if (g_ddraw->devmode || !g_hook_active || !g_ddraw->hwnd)
+    if (g_config.devmode || !g_hook_active || !g_ddraw->hwnd)
         return;
 
     if (g_mouse_locked)
@@ -87,7 +88,7 @@ LRESULT CALLBACK mouse_hook_proc(int Code, WPARAM wParam, LPARAM lParam)
     if (!g_ddraw)
         return g_mouse_proc(Code, wParam, lParam);
 
-    if (Code < 0 || (!g_ddraw->devmode && !g_mouse_locked))
+    if (Code < 0 || (!g_config.devmode && !g_mouse_locked))
         return CallNextHookEx(g_mouse_hook, Code, wParam, lParam);
 
     fake_GetCursorPos(&((MOUSEHOOKSTRUCT*)lParam)->pt);
diff --git a/src/render_d3d9.c b/src/render_d3d9.c
index 895f9ab..82b1d64 100644
--- a/src/render_d3d9.c
+++ b/src/render_d3d9.c
@@ -12,6 +12,7 @@
 #include "debug.h"
 #include "D3d9types.h"
 #include "hook.h"
+#include "config.h"
 
 
 static BOOL d3d9_create_resources();
@@ -38,7 +39,7 @@ BOOL d3d9_is_available()
 
 BOOL d3d9_create()
 {
-    if (g_d3d9.hwnd == g_ddraw->hwnd && d3d9_create_resources() && d3d9_reset(g_ddraw->windowed))
+    if (g_d3d9.hwnd == g_ddraw->hwnd && d3d9_create_resources() && d3d9_reset(g_config.windowed))
     {
         return TRUE;
     }
@@ -109,13 +110,13 @@ BOOL d3d9_create()
 
             memset(&g_d3d9.params, 0, sizeof(g_d3d9.params));
 
-            g_d3d9.params.Windowed = g_ddraw->windowed || g_ddraw->nonexclusive;
+            g_d3d9.params.Windowed = g_config.windowed || g_config.nonexclusive;
             g_d3d9.params.SwapEffect = D3DSWAPEFFECT_DISCARD;
             g_d3d9.params.hDeviceWindow = g_ddraw->hwnd;
-            g_d3d9.params.PresentationInterval = g_ddraw->vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
+            g_d3d9.params.PresentationInterval = g_config.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
             g_d3d9.params.BackBufferWidth = g_d3d9.params.Windowed ? 0 : g_ddraw->render.width;
             g_d3d9.params.BackBufferHeight = g_d3d9.params.Windowed ? 0 : g_ddraw->render.height;
-            g_d3d9.params.FullScreen_RefreshRateInHz = g_d3d9.params.Windowed ? 0 : g_ddraw->refresh_rate;
+            g_d3d9.params.FullScreen_RefreshRateInHz = g_d3d9.params.Windowed ? 0 : g_config.refresh_rate;
             g_d3d9.params.BackBufferFormat = g_ddraw->mode.dmBitsPerPel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
             g_d3d9.params.BackBufferCount = 1;
 
@@ -150,7 +151,7 @@ BOOL d3d9_on_device_lost()
 {
     if (g_d3d9.device && IDirect3DDevice9_TestCooperativeLevel(g_d3d9.device) == D3DERR_DEVICENOTRESET)
     {
-        return d3d9_reset(g_ddraw->windowed);
+        return d3d9_reset(g_config.windowed);
     }
 
     return FALSE;
@@ -158,10 +159,10 @@ BOOL d3d9_on_device_lost()
 
 BOOL d3d9_reset(BOOL windowed)
 {
-    g_d3d9.params.Windowed = windowed || g_ddraw->nonexclusive;
+    g_d3d9.params.Windowed = windowed || g_config.nonexclusive;
     g_d3d9.params.BackBufferWidth = g_d3d9.params.Windowed ? 0 : g_ddraw->render.width;
     g_d3d9.params.BackBufferHeight = g_d3d9.params.Windowed ? 0 : g_ddraw->render.height;
-    g_d3d9.params.FullScreen_RefreshRateInHz = g_d3d9.params.Windowed ? 0 : g_ddraw->refresh_rate;
+    g_d3d9.params.FullScreen_RefreshRateInHz = g_d3d9.params.Windowed ? 0 : g_config.refresh_rate;
     g_d3d9.params.BackBufferFormat = g_ddraw->mode.dmBitsPerPel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
 
     if (g_d3d9.device && SUCCEEDED(IDirect3DDevice9_Reset(g_d3d9.device, &g_d3d9.params)))
@@ -281,7 +282,7 @@ static BOOL d3d9_create_resources()
                 g_d3d9.tex_height,
                 1,
                 0,
-                g_ddraw->bpp == 16 ? (g_ddraw->rgb555 ? D3DFMT_X1R5G5B5 : D3DFMT_R5G6B5) : g_ddraw->bpp == 32 ? D3DFMT_X8R8G8B8 : D3DFMT_L8,
+                g_ddraw->bpp == 16 ? (g_config.rgb555 ? D3DFMT_X1R5G5B5 : D3DFMT_R5G6B5) : g_ddraw->bpp == 32 ? D3DFMT_X8R8G8B8 : D3DFMT_L8,
                 D3DPOOL_MANAGED,
                 &g_d3d9.surface_tex[i],
                 0));
@@ -318,7 +319,7 @@ static BOOL d3d9_create_resources()
     }
     else
     {
-        if (g_ddraw->d3d9_filter == FILTER_LANCZOS)
+        if (g_config.d3d9_filter == FILTER_LANCZOS)
         {
             BOOL error = FAILED(
                 IDirect3DDevice9_CreatePixelShader(
@@ -328,11 +329,11 @@ static BOOL d3d9_create_resources()
 
             if (error || !g_d3d9.pixel_shader_upscale)
             {
-                g_ddraw->d3d9_filter = FILTER_CUBIC;
+                g_config.d3d9_filter = FILTER_CUBIC;
             }
         }
 
-        if (g_ddraw->d3d9_filter == FILTER_CUBIC)
+        if (g_config.d3d9_filter == FILTER_CUBIC)
         {
             IDirect3DDevice9_CreatePixelShader(
                 g_d3d9.device,
@@ -357,7 +358,7 @@ static BOOL d3d9_set_states()
         err = err || FAILED(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9*)g_d3d9.palette_tex[0]));
         
         BOOL bilinear =
-            g_ddraw->d3d9_filter &&
+            g_config.d3d9_filter &&
             g_d3d9.pixel_shader_upscale &&
             (g_ddraw->render.viewport.width != g_ddraw->width || g_ddraw->render.viewport.height != g_ddraw->height);
 
@@ -374,9 +375,9 @@ static BOOL d3d9_set_states()
     }
     else
     {
-        if (g_ddraw->d3d9_filter)
+        if (g_config.d3d9_filter)
         {
-            if (g_ddraw->d3d9_filter == FILTER_LANCZOS &&
+            if (g_config.d3d9_filter == FILTER_LANCZOS &&
                 g_d3d9.pixel_shader_upscale &&
                 (g_ddraw->render.viewport.width != g_ddraw->width || 
                     g_ddraw->render.viewport.height != g_ddraw->height) &&
@@ -388,7 +389,7 @@ static BOOL d3d9_set_states()
             else if (
                 SUCCEEDED(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR)) &&
                 SUCCEEDED(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR)) &&
-                g_ddraw->d3d9_filter == FILTER_CUBIC &&
+                g_config.d3d9_filter == FILTER_CUBIC &&
                 g_d3d9.pixel_shader_upscale &&
                 (g_ddraw->render.viewport.width != g_ddraw->width || 
                     g_ddraw->render.viewport.height != g_ddraw->height) &&
@@ -453,10 +454,10 @@ DWORD WINAPI d3d9_render_main(void)
 
     BOOL needs_update = FALSE;
 
-    DWORD timeout = g_ddraw->render.minfps > 0 ? g_ddraw->render.minfps_tick_len : INFINITE;
+    DWORD timeout = g_config.minfps > 0 ? g_config.minfps_tick_len : INFINITE;
 
     while (g_ddraw->render.run &&
-        (g_ddraw->render.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
+        (g_config.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
     {
 #if _DEBUG
         dbg_draw_frame_info_start();
@@ -474,10 +475,10 @@ DWORD WINAPI d3d9_render_main(void)
             g_ddraw->primary->height == g_ddraw->height &&
             (g_ddraw->bpp == 16 || g_ddraw->bpp == 32 || g_ddraw->primary->palette))
         {
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 EnterCriticalSection(&g_ddraw->primary->cs);
 
-            if (g_ddraw->vhack)
+            if (g_config.vhack)
             {
                 if (util_detect_low_res_screen())
                 {
@@ -493,7 +494,7 @@ DWORD WINAPI d3d9_render_main(void)
 
             D3DLOCKED_RECT lock_rc;
 
-            if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE) || g_ddraw->render.minfps == -2)
+            if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE) || g_config.minfps == -2)
             {
                 if (++tex_index >= D3D9_TEXTURE_COUNT)
                     tex_index = 0;
@@ -521,7 +522,7 @@ DWORD WINAPI d3d9_render_main(void)
             }
 
             if (g_ddraw->bpp == 8 &&
-                (InterlockedExchange(&g_ddraw->render.palette_updated, FALSE) || g_ddraw->render.minfps == -2))
+                (InterlockedExchange(&g_ddraw->render.palette_updated, FALSE) || g_config.minfps == -2))
             {
                 if (++pal_index >= D3D9_TEXTURE_COUNT)
                     pal_index = 0;
@@ -537,7 +538,7 @@ DWORD WINAPI d3d9_render_main(void)
                 }
             }
 
-            if (g_ddraw->fixchilds)
+            if (g_config.fixchilds)
             {
                 g_ddraw->child_window_exists = FALSE;
                 EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
@@ -559,7 +560,7 @@ DWORD WINAPI d3d9_render_main(void)
                 }
             }
 
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 LeaveCriticalSection(&g_ddraw->primary->cs);
         }
 
@@ -595,7 +596,7 @@ DWORD WINAPI d3d9_render_main(void)
         fpsl_frame_end();
     }
 
-    if (g_ddraw->vhack)
+    if (g_config.vhack)
         InterlockedExchange(&g_ddraw->upscale_hack_active, FALSE);
 
     return 0;
diff --git a/src/render_gdi.c b/src/render_gdi.c
index f8dfb24..89b0502 100644
--- a/src/render_gdi.c
+++ b/src/render_gdi.c
@@ -8,6 +8,7 @@
 #include "wndproc.h"
 #include "hook.h"
 #include "debug.h"
+#include "config.h"
 
 
 DWORD WINAPI gdi_render_main(void)
@@ -23,7 +24,7 @@ DWORD WINAPI gdi_render_main(void)
 
         warning_end_tick = timeGetTime() + (15 * 1000);
 
-        if (!g_ddraw->windowed)
+        if (!g_config.windowed)
             PostMessage(g_ddraw->hwnd, WM_AUTORENDERER, 0, 0);
 
         _snprintf(
@@ -37,10 +38,10 @@ DWORD WINAPI gdi_render_main(void)
 
     fpsl_init();
 
-    DWORD timeout = g_ddraw->render.minfps > 0 ? g_ddraw->render.minfps_tick_len : INFINITE;
+    DWORD timeout = g_config.minfps > 0 ? g_config.minfps_tick_len : INFINITE;
 
     while (g_ddraw->render.run &&
-        (g_ddraw->render.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
+        (g_config.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
     {
 #if _DEBUG
         dbg_draw_frame_info_start();
@@ -56,7 +57,7 @@ DWORD WINAPI gdi_render_main(void)
             g_ddraw->primary->height == g_ddraw->height &&
             (g_ddraw->bpp == 16 || g_ddraw->bpp == 32 || g_ddraw->primary->palette))
         {
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 EnterCriticalSection(&g_ddraw->primary->cs);
 
             if (warning_end_tick)
@@ -75,12 +76,12 @@ DWORD WINAPI gdi_render_main(void)
                 }
             }
 
-            BOOL upscale_hack = g_ddraw->vhack && util_detect_low_res_screen();
+            BOOL upscale_hack = g_config.vhack && util_detect_low_res_screen();
 
-            if (g_ddraw->vhack)
+            if (g_config.vhack)
                 InterlockedExchange(&g_ddraw->upscale_hack_active, upscale_hack);
 
-            if (g_ddraw->fixchilds)
+            if (g_config.fixchilds)
             {
                 g_ddraw->child_window_exists = FALSE;
                 EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
@@ -154,7 +155,7 @@ DWORD WINAPI gdi_render_main(void)
                     DIB_RGB_COLORS);
             }
 
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 LeaveCriticalSection(&g_ddraw->primary->cs);
         }
 
diff --git a/src/render_ogl.c b/src/render_ogl.c
index 6d4b0ba..7170346 100644
--- a/src/render_ogl.c
+++ b/src/render_ogl.c
@@ -45,7 +45,7 @@ DWORD WINAPI ogl_render_main(void)
         g_ogl.context = ogl_create_core_context(g_ddraw->render.hdc);
 
         if (oglu_ext_exists("WGL_EXT_swap_control", g_ddraw->render.hdc) && wglSwapIntervalEXT)
-            wglSwapIntervalEXT(g_ddraw->vsync ? 1 : 0);
+            wglSwapIntervalEXT(g_config.vsync ? 1 : 0);
 
         fpsl_init();
         ogl_build_programs();
@@ -141,7 +141,7 @@ static void ogl_build_programs()
         {
             g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER, PALETTE_FRAG_SHADER, core_profile);
         }
-        else if (g_ddraw->bpp == 16 && g_ddraw->rgb555)
+        else if (g_ddraw->bpp == 16 && g_config.rgb555)
         {
             g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER, RGB555_FRAG_SHADER, core_profile);
         }
@@ -156,20 +156,20 @@ static void ogl_build_programs()
         {
             char shader_path[MAX_PATH] = { 0 };
 
-            strncpy(shader_path, g_ddraw->shader, sizeof(shader_path) - 1);
+            strncpy(shader_path, g_config.shader, sizeof(shader_path) - 1);
 
             if (GetFileAttributes(shader_path) == INVALID_FILE_ATTRIBUTES)
             {
-                _snprintf(shader_path, sizeof(shader_path) - 1, "%s%s", g_config.game_path, g_ddraw->shader);
+                _snprintf(shader_path, sizeof(shader_path) - 1, "%s%s", g_config.game_path, g_config.shader);
             }
 
             /* detect common upscaling shaders and disable them if no upscaling is required */
 
             BOOL is_upscaler =
-                strstr(g_ddraw->shader, "catmull-rom-bilinear.glsl") != NULL ||
-                strstr(g_ddraw->shader, "lanczos2-sharp.glsl") != NULL ||
-                strstr(g_ddraw->shader, "xbr-lv2-noblend.glsl") != NULL ||
-                strstr(g_ddraw->shader, "xbrz-freescale.glsl") != NULL;
+                strstr(g_config.shader, "catmull-rom-bilinear.glsl") != NULL ||
+                strstr(g_config.shader, "lanczos2-sharp.glsl") != NULL ||
+                strstr(g_config.shader, "xbr-lv2-noblend.glsl") != NULL ||
+                strstr(g_config.shader, "xbrz-freescale.glsl") != NULL;
 
             if (!is_upscaler ||
                 g_ddraw->render.viewport.width != g_ddraw->width ||
@@ -183,19 +183,19 @@ static void ogl_build_programs()
                 {
                     g_ogl.scale_program = 
                         oglu_build_program(
-                            _stricmp(g_ddraw->shader, "xBR-lv2") == 0 ? XBR_LV2_VERT_SHADER :
+                            _stricmp(g_config.shader, "xBR-lv2") == 0 ? XBR_LV2_VERT_SHADER :
                             PASSTHROUGH_VERT_SHADER, 
-                            _stricmp(g_ddraw->shader, "Nearest neighbor") == 0 ? PASSTHROUGH_FRAG_SHADER :
-                            _stricmp(g_ddraw->shader, "Bilinear") == 0 ? PASSTHROUGH_FRAG_SHADER :
-                            _stricmp(g_ddraw->shader, "Lanczos") == 0 ? LANCZOS2_FRAG_SHADER :
-                            _stricmp(g_ddraw->shader, "xBR-lv2") == 0 ? XBR_LV2_FRAG_SHADER :
+                            _stricmp(g_config.shader, "Nearest neighbor") == 0 ? PASSTHROUGH_FRAG_SHADER :
+                            _stricmp(g_config.shader, "Bilinear") == 0 ? PASSTHROUGH_FRAG_SHADER :
+                            _stricmp(g_config.shader, "Lanczos") == 0 ? LANCZOS2_FRAG_SHADER :
+                            _stricmp(g_config.shader, "xBR-lv2") == 0 ? XBR_LV2_FRAG_SHADER :
                             CATMULL_ROM_FRAG_SHADER, 
                             core_profile);
 
                     bilinear =
-                        _stricmp(g_ddraw->shader, "Nearest neighbor") != 0 && 
-                        _stricmp(g_ddraw->shader, "Lanczos") != 0 &&
-                        _stricmp(g_ddraw->shader, "xBR-lv2") != 0;
+                        _stricmp(g_config.shader, "Nearest neighbor") != 0 && 
+                        _stricmp(g_config.shader, "Lanczos") != 0 &&
+                        _stricmp(g_config.shader, "xBR-lv2") != 0;
                 }
             }
         }
@@ -204,7 +204,7 @@ static void ogl_build_programs()
             g_oglu_got_version3 = FALSE;
         }
 
-        g_ogl.filter_bilinear = strstr(g_ddraw->shader, "bilinear.glsl") != NULL || bilinear;
+        g_ogl.filter_bilinear = strstr(g_config.shader, "bilinear.glsl") != NULL || bilinear;
     }
 
     if (g_oglu_got_version2 && !g_ogl.main_program)
@@ -259,7 +259,7 @@ static void ogl_create_textures(int width, int height)
                 g_ogl.surface_type = GL_UNSIGNED_BYTE,
                 0);
         }
-        else if (g_ddraw->bpp == 16 && g_ddraw->rgb555)
+        else if (g_ddraw->bpp == 16 && g_config.rgb555)
         {
             if (g_oglu_got_version3)
             {
@@ -662,10 +662,10 @@ static void ogl_render()
         glEnable(GL_TEXTURE_2D);
     }
 
-    DWORD timeout = g_ddraw->render.minfps > 0 ? g_ddraw->render.minfps_tick_len : INFINITE;
+    DWORD timeout = g_config.minfps > 0 ? g_config.minfps_tick_len : INFINITE;
 
     while (g_ogl.use_opengl && g_ddraw->render.run &&
-        (g_ddraw->render.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
+        (g_config.minfps < 0 || WaitForSingleObject(g_ddraw->render.sem, timeout) != WAIT_FAILED))
     {
 #if _DEBUG
         dbg_draw_frame_info_start();
@@ -688,10 +688,10 @@ static void ogl_render()
             g_ddraw->primary->height == g_ddraw->height &&
             (g_ddraw->bpp == 16 || g_ddraw->bpp == 32 || g_ddraw->primary->palette))
         {
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 EnterCriticalSection(&g_ddraw->primary->cs);
 
-            if (g_ddraw->vhack)
+            if (g_config.vhack)
             {
                 if (util_detect_low_res_screen())
                 {
@@ -709,7 +709,7 @@ static void ogl_render()
             }
 
             if (g_ddraw->bpp == 8 &&
-                (InterlockedExchange(&g_ddraw->render.palette_updated, FALSE) || g_ddraw->render.minfps == -2))
+                (InterlockedExchange(&g_ddraw->render.palette_updated, FALSE) || g_config.minfps == -2))
             {
                 if (++pal_index >= TEXTURE_COUNT)
                     pal_index = 0;
@@ -728,7 +728,7 @@ static void ogl_render()
                     g_ddraw->primary->palette->data_bgr);
             }
 
-            if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE) || g_ddraw->render.minfps == -2)
+            if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE) || g_config.minfps == -2)
             {
                 if (++tex_index >= TEXTURE_COUNT)
                     tex_index = 0;
@@ -767,7 +767,7 @@ static void ogl_render()
                     g_ogl.use_opengl = FALSE;
             }
 
-            if (g_ddraw->fixchilds)
+            if (g_config.fixchilds)
             {
                 g_ddraw->child_window_exists = FALSE;
                 EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
@@ -797,7 +797,7 @@ static void ogl_render()
                 }
             }
 
-            if (g_ddraw->lock_surfaces)
+            if (g_config.lock_surfaces)
                 LeaveCriticalSection(&g_ddraw->primary->cs);
         }
 
@@ -928,7 +928,7 @@ static void ogl_render()
         fpsl_frame_end();
     }
 
-    if (g_ddraw->vhack)
+    if (g_config.vhack)
         InterlockedExchange(&g_ddraw->upscale_hack_active, FALSE);
 }
 
diff --git a/src/screenshot.c b/src/screenshot.c
index d9623c6..4ad3cfc 100644
--- a/src/screenshot.c
+++ b/src/screenshot.c
@@ -7,6 +7,7 @@
 #include "ddsurface.h"
 #include "lodepng.h"
 #include "blt.h"
+#include "config.h"
 
 
 static BOOL ss_screenshot_8bit(char* filename, IDirectDrawSurfaceImpl* src)
@@ -58,7 +59,7 @@ static BOOL ss_screenshot_16bit(char* filename, IDirectDrawSurfaceImpl* src)
 
     if (buf)
     {
-        if (g_ddraw->rgb555)
+        if (g_config.rgb555)
         {
             blt_rgb555_to_rgba8888(
                 buf,
@@ -146,10 +147,10 @@ BOOL ss_take_screenshot(IDirectDrawSurfaceImpl* src)
         }
     }
 
-    CreateDirectoryA(g_ddraw->screenshot_dir, NULL);
+    CreateDirectoryA(g_config.screenshot_dir, NULL);
 
     strftime(str_time, sizeof(str_time), "%Y-%m-%d-%H_%M_%S", localtime(&t));
-    _snprintf(filename, sizeof(filename), "%s%s-%s.png", g_ddraw->screenshot_dir, title, str_time);
+    _snprintf(filename, sizeof(filename), "%s%s-%s.png", g_config.screenshot_dir, title, str_time);
 
     if (src->bpp == 8 && src->palette)
     {
diff --git a/src/utils.c b/src/utils.c
index f556bd6..8477297 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -271,7 +271,7 @@ void util_toggle_maximize()
 
             AdjustWindowRectEx(&dst_rc, style, got_menu, exstyle);
         }
-        else if (g_ddraw->boxing)
+        else if (g_config.boxing)
         {
             dst_rc.left = 0;
             dst_rc.top = 0;
@@ -290,7 +290,7 @@ void util_toggle_maximize()
 
             AdjustWindowRectEx(&dst_rc, style, got_menu, exstyle);
         }
-        else if (g_ddraw->maintas)
+        else if (g_config.maintas)
         {
             util_unadjust_window_rect(&dst_rc, style, got_menu, exstyle);
 
@@ -334,13 +334,13 @@ void util_toggle_fullscreen()
     if (g_ddraw->bnet_active)
         return;
 
-    if (g_ddraw->toggle_borderless && g_ddraw->windowed)
+    if (g_config.toggle_borderless && g_config.windowed)
     {
-        if (!g_ddraw->fullscreen)
+        if (!g_config.fullscreen)
         {
             mouse_unlock();
 
-            g_config.borderless_state = g_ddraw->fullscreen = TRUE;
+            g_config.borderless_state = g_config.fullscreen = TRUE;
             dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp, 0);
 
             mouse_lock();
@@ -349,7 +349,7 @@ void util_toggle_fullscreen()
         {
             mouse_unlock();
 
-            g_config.borderless_state = g_ddraw->fullscreen = FALSE;
+            g_config.borderless_state = g_config.fullscreen = FALSE;
             dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp, 0);
 
             //mouse_lock();
@@ -357,11 +357,11 @@ void util_toggle_fullscreen()
     }
     else 
     {
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             mouse_unlock();
 
-            g_config.window_state = g_ddraw->windowed = FALSE;
+            g_config.window_state = g_config.windowed = FALSE;
             dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp, SDM_LEAVE_WINDOWED);
             util_update_bnet_pos(0, 0);
 
@@ -370,11 +370,11 @@ void util_toggle_fullscreen()
         else
         {
             mouse_unlock();
-            g_config.window_state = g_ddraw->windowed = TRUE;
+            g_config.window_state = g_config.windowed = TRUE;
 
-            if (g_ddraw->renderer == d3d9_render_main && !g_ddraw->nonexclusive)
+            if (g_ddraw->renderer == d3d9_render_main && !g_config.nonexclusive)
             {
-                d3d9_reset(g_ddraw->windowed);
+                d3d9_reset(g_config.windowed);
             }
             else
             {
@@ -418,7 +418,7 @@ BOOL util_unadjust_window_rect(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwEx
 
 void util_set_window_rect(int x, int y, int width, int height, UINT flags)
 {
-    if (g_ddraw->windowed)
+    if (g_config.windowed)
     {
         if (g_ddraw->render.thread)
         {
@@ -470,7 +470,7 @@ BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam)
 
         //TRACE_EXT("     AVIWINDOW class=%s\n", class_name);
 
-        if (g_ddraw->fixchilds == FIX_CHILDS_DETECT_HIDE || 
+        if (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || 
             strcmp(class_name, "VideoRenderer") == 0 ||
             strcmp(class_name, "AVIWnd32") == 0 || 
             strcmp(class_name, "MCIWndClass") == 0)
@@ -496,7 +496,7 @@ BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam)
         {
             g_ddraw->got_child_windows = g_ddraw->child_window_exists = TRUE;
 
-            if (g_ddraw->fixchilds == FIX_CHILDS_DETECT_PAINT)
+            if (g_config.fixchilds == FIX_CHILDS_DETECT_PAINT)
             {
                 HDC dst_dc = GetDC(hwnd);
                 HDC src_dc;
diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c
index 3b0ec4c..f795b27 100644
--- a/src/winapi_hooks.c
+++ b/src/winapi_hooks.c
@@ -31,13 +31,13 @@ BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
     realpt.x = pt.x;
     realpt.y = pt.y;
 
-    if (g_mouse_locked && (!g_ddraw->windowed || real_ScreenToClient(g_ddraw->hwnd, &pt)))
+    if (g_mouse_locked && (!g_config.windowed || real_ScreenToClient(g_ddraw->hwnd, &pt)))
     {
         /* fallback solution for possible ClipCursor failure */
         int diffx = 0, diffy = 0;
 
-        int max_width = g_ddraw->adjmouse ? g_ddraw->render.viewport.width : g_ddraw->width;
-        int max_height = g_ddraw->adjmouse ? g_ddraw->render.viewport.height : g_ddraw->height;
+        int max_width = g_config.adjmouse ? g_ddraw->render.viewport.width : g_ddraw->width;
+        int max_height = g_config.adjmouse ? g_ddraw->render.viewport.height : g_ddraw->height;
 
         pt.x -= g_ddraw->mouse.x_adjust;
         pt.y -= g_ddraw->mouse.y_adjust;
@@ -72,7 +72,7 @@ BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
         int x = 0;
         int y = 0;
 
-        if (g_ddraw->adjmouse)
+        if (g_config.adjmouse)
         {
             x = min((DWORD)(roundf(pt.x * g_ddraw->mouse.unscale_x)), g_ddraw->width - 1);
             y = min((DWORD)(roundf(pt.y * g_ddraw->mouse.unscale_y)), g_ddraw->height - 1);
@@ -83,7 +83,7 @@ BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
             y = min(pt.y, g_ddraw->height - 1);
         }
 
-        if (g_ddraw->vhack && InterlockedExchangeAdd(&g_ddraw->upscale_hack_active, 0))
+        if (g_config.vhack && InterlockedExchangeAdd(&g_ddraw->upscale_hack_active, 0))
         {
             diffx = 0;
             diffy = 0;
@@ -149,7 +149,7 @@ BOOL WINAPI fake_ClipCursor(const RECT* lpRect)
         if (lpRect)
             CopyRect(&dst_rc, lpRect);
 
-        if (g_ddraw->adjmouse)
+        if (g_config.adjmouse)
         {
             dst_rc.left = (LONG)(roundf(dst_rc.left * g_ddraw->render.scale_w));
             dst_rc.top = (LONG)(roundf(dst_rc.top * g_ddraw->render.scale_h));
@@ -157,8 +157,8 @@ BOOL WINAPI fake_ClipCursor(const RECT* lpRect)
             dst_rc.right = (LONG)(roundf(dst_rc.right * g_ddraw->render.scale_w));
         }
 
-        int max_width = g_ddraw->adjmouse ? g_ddraw->render.viewport.width : g_ddraw->width;
-        int max_height = g_ddraw->adjmouse ? g_ddraw->render.viewport.height : g_ddraw->height;
+        int max_width = g_config.adjmouse ? g_ddraw->render.viewport.width : g_ddraw->width;
+        int max_height = g_config.adjmouse ? g_ddraw->render.viewport.height : g_ddraw->height;
 
         dst_rc.bottom = min(dst_rc.bottom, max_height);
         dst_rc.right = min(dst_rc.right, max_width);
@@ -185,7 +185,7 @@ int WINAPI fake_ShowCursor(BOOL bShow)
 {
     if (g_ddraw && g_ddraw->hwnd)
     {
-        if (g_mouse_locked || g_ddraw->devmode)
+        if (g_mouse_locked || g_config.devmode)
         {
             int count = real_ShowCursor(bShow);
             InterlockedExchange((LONG*)&g_ddraw->show_cursor_count, count);
@@ -208,7 +208,7 @@ HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
     {
         HCURSOR cursor = (HCURSOR)InterlockedExchange((LONG*)&g_ddraw->old_cursor, (LONG)hCursor);
 
-        if (!g_mouse_locked && !g_ddraw->devmode)
+        if (!g_mouse_locked && !g_config.devmode)
             return cursor;
     }
 
@@ -220,7 +220,7 @@ BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect)
     if (lpRect &&
         g_ddraw &&
         g_ddraw->hwnd &&
-        (g_hook_method != 2 || g_ddraw->renderer == gdi_render_main))
+        (g_config.hook != 2 || g_ddraw->renderer == gdi_render_main))
     {
         if (g_ddraw->hwnd == hWnd)
         {
@@ -252,7 +252,7 @@ BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect)
     if (lpRect &&
         g_ddraw &&
         g_ddraw->hwnd == hWnd &&
-        (g_hook_method != 2 || g_ddraw->renderer == gdi_render_main))
+        (g_config.hook != 2 || g_ddraw->renderer == gdi_render_main))
     {
         lpRect->bottom = g_ddraw->height;
         lpRect->left = 0;
@@ -292,12 +292,12 @@ BOOL WINAPI fake_SetCursorPos(int X, int Y)
     if (!g_ddraw || !g_ddraw->hwnd || !g_ddraw->width)
         return real_SetCursorPos(X, Y);
 
-    if (!g_mouse_locked && !g_ddraw->devmode)
+    if (!g_mouse_locked && !g_config.devmode)
         return TRUE;
 
     POINT pt = { X, Y };
 
-    if (g_ddraw->adjmouse)
+    if (g_config.adjmouse)
     {
         pt.x = (LONG)(roundf(pt.x * g_ddraw->mouse.scale_x));
         pt.y = (LONG)(roundf(pt.y * g_ddraw->mouse.scale_y));
@@ -426,7 +426,7 @@ LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar
         int x = GET_X_LPARAM(lParam);
         int y = GET_Y_LPARAM(lParam);
 
-        if (g_ddraw->adjmouse)
+        if (g_config.adjmouse)
         {
             x = (int)(roundf(x * g_ddraw->mouse.scale_x));
             y = (int)(roundf(y * g_ddraw->mouse.scale_y));
@@ -435,7 +435,7 @@ LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar
         lParam = MAKELPARAM(x + g_ddraw->mouse.x_adjust, y + g_ddraw->mouse.y_adjust);
     }
 
-    if (g_ddraw->hwnd == hWnd && Msg == WM_SIZE && g_hook_method != 2)
+    if (g_ddraw->hwnd == hWnd && Msg == WM_SIZE && g_config.hook != 2)
     {
         Msg = WM_SIZE_DDRAW;
     }
@@ -538,7 +538,7 @@ BOOL WINAPI fake_ShowWindow(HWND hWnd, int nCmdShow)
         if (nCmdShow == SW_MAXIMIZE)
             nCmdShow = SW_NORMAL;
 
-        if (nCmdShow == SW_MINIMIZE && g_hook_method != 2)
+        if (nCmdShow == SW_MINIMIZE && g_config.hook != 2)
             return TRUE;
     }
 
@@ -547,7 +547,7 @@ BOOL WINAPI fake_ShowWindow(HWND hWnd, int nCmdShow)
 
 HWND WINAPI fake_GetTopWindow(HWND hWnd)
 {
-    if (g_ddraw && g_ddraw->windowed && g_ddraw->hwnd && !hWnd)
+    if (g_ddraw && g_config.windowed && g_ddraw->hwnd && !hWnd)
     {
         return g_ddraw->hwnd;
     }
@@ -557,7 +557,7 @@ HWND WINAPI fake_GetTopWindow(HWND hWnd)
 
 HWND WINAPI fake_GetForegroundWindow()
 {
-    if (g_ddraw && g_ddraw->windowed && g_ddraw->hwnd)
+    if (g_ddraw && g_config.windowed && g_ddraw->hwnd)
     {
         return g_ddraw->hwnd;
     }
@@ -584,7 +584,7 @@ HHOOK WINAPI fake_SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, D
         return NULL;
     }
 
-    if (idHook == WH_MOUSE && lpfn && !hmod && !g_mouse_hook && cfg_get_bool("fixmousehook", FALSE))
+    if (idHook == WH_MOUSE && lpfn && !hmod && !g_mouse_hook && g_config.fixmousehook)
     {
         g_mouse_proc = lpfn;
         return g_mouse_hook = real_SetWindowsHookExA(idHook, mouse_hook_proc, hmod, dwThreadId);
@@ -597,7 +597,7 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w
 {
     BOOL result = real_PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
 
-    if (result && g_ddraw && g_ddraw->width && g_ddraw->hook_peekmessage)
+    if (result && g_ddraw && g_ddraw->width && g_config.hook_peekmessage)
     {
         switch (lpMsg->message)
         {
@@ -605,7 +605,7 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w
         case WM_RBUTTONUP:
         case WM_MBUTTONUP:
         {
-            if (!g_ddraw->devmode && !g_mouse_locked)
+            if (!g_config.devmode && !g_mouse_locked)
             {
                 int x = GET_X_LPARAM(lpMsg->lParam);
                 int y = GET_Y_LPARAM(lpMsg->lParam);
@@ -646,7 +646,7 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w
         case WM_MBUTTONDOWN:
         case WM_MOUSEMOVE:
         {
-            if (!g_ddraw->devmode && !g_mouse_locked)
+            if (!g_config.devmode && !g_mouse_locked)
             {
                 // Does not work with 'New Robinson'
                 //return FALSE;
@@ -655,9 +655,9 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w
             int x = max(GET_X_LPARAM(lpMsg->lParam) - g_ddraw->mouse.x_adjust, 0);
             int y = max(GET_Y_LPARAM(lpMsg->lParam) - g_ddraw->mouse.y_adjust, 0);
 
-            if (g_ddraw->adjmouse)
+            if (g_config.adjmouse)
             {
-                if (g_ddraw->vhack && !g_ddraw->devmode)
+                if (g_config.vhack && !g_config.devmode)
                 {
                     POINT pt = { 0, 0 };
                     fake_GetCursorPos(&pt);
@@ -695,7 +695,7 @@ int WINAPI fake_GetDeviceCaps(HDC hdc, int index)
     if (g_ddraw &&
         g_ddraw->bpp &&
         index == BITSPIXEL &&
-        (g_hook_method != 2 || g_ddraw->renderer == gdi_render_main))
+        (g_config.hook != 2 || g_ddraw->renderer == gdi_render_main))
     {
         return g_ddraw->bpp;
     }
@@ -703,7 +703,7 @@ int WINAPI fake_GetDeviceCaps(HDC hdc, int index)
     if (g_ddraw &&
         g_ddraw->bpp == 8 &&
         index == RASTERCAPS &&
-        (g_hook_method != 2 || g_ddraw->renderer == gdi_render_main))
+        (g_config.hook != 2 || g_ddraw->renderer == gdi_render_main))
     {
         return RC_PALETTE | real_GetDeviceCaps(hdc, index);
     }
@@ -735,8 +735,8 @@ BOOL WINAPI fake_StretchBlt(
 
     if (g_ddraw && g_ddraw->hwnd &&
         (hwnd == g_ddraw->hwnd ||
-            (g_ddraw->fixchilds && IsChild(g_ddraw->hwnd, hwnd) &&
-                (g_ddraw->fixchilds == FIX_CHILDS_DETECT_HIDE ||
+            (g_config.fixchilds && IsChild(g_ddraw->hwnd, hwnd) &&
+                (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE ||
                     strcmp(class_name, "AVIWnd32") == 0 ||
                     strcmp(class_name, "MCIWndClass") == 0))))
     {
@@ -910,15 +910,14 @@ HFONT WINAPI fake_CreateFontIndirectA(CONST LOGFONTA* lplf)
     LOGFONTA lf;
     memcpy(&lf, lplf, sizeof(lf));
 
-    int minFontSize = cfg_get_int("min_font_size", 0);
     if (lf.lfHeight < 0) {
-        lf.lfHeight = min(-minFontSize, lf.lfHeight);
+        lf.lfHeight = min(-g_config.min_font_size, lf.lfHeight);
     }
     else {
-        lf.lfHeight = max(minFontSize, lf.lfHeight);
+        lf.lfHeight = max(g_config.min_font_size, lf.lfHeight);
     }
 
-    if (cfg_get_int("anti_aliased_fonts_min_size", 13) > abs(lf.lfHeight))
+    if (g_config.anti_aliased_fonts_min_size > abs(lf.lfHeight))
         lf.lfQuality = NONANTIALIASED_QUALITY;
 
     return real_CreateFontIndirectA(&lf);
@@ -940,15 +939,14 @@ HFONT WINAPI fake_CreateFontA(
     DWORD fdwPitchAndFamily,
     LPCTSTR lpszFace)
 {
-    int minFontSize = cfg_get_int("min_font_size", 0);
     if (nHeight < 0) {
-        nHeight = min(-minFontSize, nHeight);
+        nHeight = min(-g_config.min_font_size, nHeight);
     }
     else {
-        nHeight = max(minFontSize, nHeight);
+        nHeight = max(g_config.min_font_size, nHeight);
     }
 
-    if (cfg_get_int("anti_aliased_fonts_min_size", 13) > abs(nHeight))
+    if (g_config.anti_aliased_fonts_min_size > abs(nHeight))
         fdwQuality = NONANTIALIASED_QUALITY;
 
     return 
@@ -1077,7 +1075,7 @@ FARPROC WINAPI fake_GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
 
     FARPROC proc = real_GetProcAddress(hModule, lpProcName);
 
-    if (g_hook_method != 3 || !hModule || !HIWORD(lpProcName))
+    if (g_config.hook != 3 || !hModule || !HIWORD(lpProcName))
         return proc;
 
     for (int i = 0; g_hook_hooklist[i].module_name[0]; i++)
@@ -1153,7 +1151,7 @@ BOOL WINAPI fake_DestroyWindow(HWND hWnd)
             SetFocus(g_ddraw->hwnd);
             mouse_lock();
 
-            if (g_ddraw->windowed)
+            if (g_config.windowed)
             {
                 g_ddraw->bnet_pos.x = g_ddraw->bnet_pos.y = 0;
                 real_ClientToScreen(g_ddraw->hwnd, &g_ddraw->bnet_pos);
@@ -1176,11 +1174,11 @@ BOOL WINAPI fake_DestroyWindow(HWND hWnd)
                         flags);
                 }
 
-                g_ddraw->fullscreen = g_ddraw->bnet_was_upscaled;
+                g_config.fullscreen = g_ddraw->bnet_was_upscaled;
 
                 SetTimer(g_ddraw->hwnd, IDT_TIMER_LEAVE_BNET, 1000, (TIMERPROC)NULL);
 
-                g_ddraw->resizable = TRUE;
+                g_config.resizable = TRUE;
             }
         }
     }
@@ -1220,10 +1218,10 @@ HWND WINAPI fake_CreateWindowExA(
     {
         if (!g_ddraw->bnet_active)
         {
-            g_ddraw->bnet_was_upscaled = g_ddraw->fullscreen;
-            g_ddraw->fullscreen = FALSE;
+            g_ddraw->bnet_was_upscaled = g_config.fullscreen;
+            g_config.fullscreen = FALSE;
 
-            if (!g_ddraw->windowed && !g_ddraw->bnet_was_fullscreen)
+            if (!g_config.windowed && !g_ddraw->bnet_was_fullscreen)
             {
                 int ws = g_config.window_state;
                 util_toggle_fullscreen();
@@ -1246,7 +1244,7 @@ HWND WINAPI fake_CreateWindowExA(
             int dst_height = g_config.window_rect.bottom ? g_ddraw->height : 0;
 
             util_set_window_rect(x, y, dst_width, dst_height, flags);
-            g_ddraw->resizable = FALSE;
+            g_config.resizable = FALSE;
 
             g_ddraw->bnet_active = TRUE;
             mouse_unlock();
diff --git a/src/wndproc.c b/src/wndproc.c
index 756e815..96cf44e 100644
--- a/src/wndproc.c
+++ b/src/wndproc.c
@@ -54,7 +54,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     {
         MINMAXINFO* mmi = (MINMAXINFO*)lParam;
 
-        if (g_ddraw->windowed && g_ddraw->width)
+        if (g_config.windowed && g_ddraw->width)
         {
             RECT rc = { 0, 0, g_ddraw->render.width, g_ddraw->render.height };
 
@@ -90,7 +90,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_NCACTIVATE:
     {
-        if (g_ddraw->noactivateapp)
+        if (g_config.noactivateapp)
         {
             return DefWindowProc(hWnd, uMsg, wParam, lParam);
         }
@@ -101,7 +101,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     {
         LRESULT result = DefWindowProc(hWnd, uMsg, wParam, lParam);
 
-        if (!g_ddraw->resizable)
+        if (!g_config.resizable)
         {
             switch (result)
             {
@@ -146,7 +146,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
                 case HTTOPRIGHT:
                     return DefWindowProc(hWnd, uMsg, wParam, lParam);
                 case HTCLIENT:
-                    if (!g_mouse_locked && !g_ddraw->devmode)
+                    if (!g_mouse_locked && !g_config.devmode)
                     {
                         real_SetCursor(LoadCursor(NULL, IDC_ARROW));
                         return TRUE;
@@ -176,11 +176,11 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_D3D9DEVICELOST:
     {
-        if (((!g_ddraw->windowed && !g_ddraw->nonexclusive) || !util_is_minimized(g_ddraw->hwnd)) &&
+        if (((!g_config.windowed && !g_config.nonexclusive) || !util_is_minimized(g_ddraw->hwnd)) &&
             g_ddraw->renderer == d3d9_render_main &&
             d3d9_on_device_lost())
         {
-            if (!g_ddraw->windowed)
+            if (!g_config.windowed)
                 mouse_lock();
         }
         return 0;
@@ -193,7 +193,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         {
             KillTimer(g_ddraw->hwnd, IDT_TIMER_LEAVE_BNET);
 
-            if (!g_ddraw->windowed)
+            if (!g_config.windowed)
                 g_ddraw->bnet_was_fullscreen = FALSE;
 
             if (!g_ddraw->bnet_active)
@@ -229,7 +229,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         */
 
         if (g_ddraw->wine &&
-            !g_ddraw->windowed &&
+            !g_config.windowed &&
             (pos->x > 0 || pos->y > 0) &&
             g_ddraw->last_set_window_pos_tick + 500 < timeGetTime())
         {
@@ -240,7 +240,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_WINEFULLSCREEN:
     {
-        if (!g_ddraw->windowed)
+        if (!g_config.windowed)
         {
             g_ddraw->last_set_window_pos_tick = timeGetTime();
 
@@ -266,7 +266,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_ENTERSIZEMOVE:
     {
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             in_size_move = TRUE;
         }
@@ -274,7 +274,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_EXITSIZEMOVE:
     {
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             in_size_move = FALSE;
 
@@ -287,7 +287,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     {
         RECT* windowrc = (RECT*)lParam;
 
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             if (in_size_move)
             {
@@ -305,7 +305,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
                 RECT clientrc = { 0 };
 
                 /* maintain aspect ratio */
-                if (g_ddraw->maintas &&
+                if (g_config.maintas &&
                     CopyRect(&clientrc, windowrc) &&
                     util_unadjust_window_rect(
                         &clientrc, 
@@ -419,7 +419,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_SIZE:
     {
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             if (wParam == SIZE_RESTORED)
             {
@@ -450,7 +450,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_MOVE:
     {
-        if (g_ddraw->windowed)
+        if (g_config.windowed)
         {
             int x = (int)(short)LOWORD(lParam);
             int y = (int)(short)HIWORD(lParam);
@@ -460,7 +460,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
                 util_update_bnet_pos(x, y);
             }
 
-            if (in_size_move || (g_ddraw->wine && !g_ddraw->fullscreen && g_ddraw->render.thread))
+            if (in_size_move || (g_ddraw->wine && !g_config.fullscreen && g_ddraw->render.thread))
             {
                 if (x != -32000)
                     g_config.window_rect.left = x; /* -32000 = Exit/Minimize */
@@ -502,7 +502,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
 
         if (wParam == SC_MAXIMIZE)
         {
-            if (g_ddraw->resizable)
+            if (g_config.resizable)
             {
                 util_toggle_maximize();
             }
@@ -562,7 +562,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
 
         //if (g_ddraw->windowed || g_ddraw->noactivateapp)
 
-        if (!g_ddraw->allow_wmactivate)
+        if (!g_config.allow_wmactivate)
             return 0;
 
         break;
@@ -571,16 +571,16 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     {
         if (wParam)
         {
-            if (!g_ddraw->windowed)
+            if (!g_config.windowed)
             {
-                if (g_ddraw->renderer != d3d9_render_main || g_ddraw->nonexclusive)
+                if (g_ddraw->renderer != d3d9_render_main || g_config.nonexclusive)
                 {
                     ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN);
                     real_ShowWindow(g_ddraw->hwnd, SW_RESTORE);
                     mouse_lock();
                 }
             }
-            else if (g_ddraw->fullscreen && real_GetForegroundWindow() == g_ddraw->hwnd)
+            else if (g_config.fullscreen && real_GetForegroundWindow() == g_ddraw->hwnd)
             {
                 mouse_lock();
             }
@@ -589,7 +589,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         }
         else
         {
-            if (!g_ddraw->windowed && !g_mouse_locked && g_ddraw->noactivateapp && !g_ddraw->devmode)
+            if (!g_config.windowed && !g_mouse_locked && g_config.noactivateapp && !g_config.devmode)
                 return 0;
 
             mouse_unlock();
@@ -597,9 +597,9 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             if (g_ddraw->wine && g_ddraw->last_set_window_pos_tick + 500 > timeGetTime())
                 return 0;
 
-            if (!g_ddraw->windowed)
+            if (!g_config.windowed)
             {
-                if (g_ddraw->renderer != d3d9_render_main || g_ddraw->nonexclusive)
+                if (g_ddraw->renderer != d3d9_render_main || g_config.nonexclusive)
                 {
                     real_ShowWindow(g_ddraw->hwnd, SW_MINIMIZE);
                     ChangeDisplaySettings(NULL, g_ddraw->bnet_active ? CDS_FULLSCREEN : 0);
@@ -607,7 +607,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             }
         }
 
-        if (wParam && g_ddraw->releasealt)
+        if (wParam && g_config.releasealt)
         {
             INPUT ip;
             memset(&ip, 0, sizeof(ip));
@@ -626,18 +626,18 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             }
         }
 
-        if (g_ddraw->windowed || g_ddraw->noactivateapp)
+        if (g_config.windowed || g_config.noactivateapp)
         {
             /* let it pass through once (tiberian sun) */
             static BOOL one_time;
 
-            if (wParam && !one_time && g_ddraw->tshack)
+            if (wParam && !one_time && g_config.tshack)
             {
                 one_time = TRUE;
                 break;
             }
             
-            if (wParam && g_ddraw->alt_key_down && !g_ddraw->releasealt)
+            if (wParam && g_ddraw->alt_key_down && !g_config.releasealt)
                 PostMessageA(g_ddraw->hwnd, WM_SYSKEYUP, VK_MENU, 0);
 
             return 0;
@@ -654,7 +654,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_NCLBUTTONDBLCLK:
     {
-        if (g_ddraw->resizable)
+        if (g_config.resizable)
         {
             util_toggle_maximize();
         }
@@ -666,9 +666,9 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         BOOL context_code = (lParam & (1 << 29)) != 0;
         BOOL key_state = (lParam & (1 << 30)) != 0;
 
-        if (g_ddraw->hotkeys.toggle_fullscreen &&
-            wParam == g_ddraw->hotkeys.toggle_fullscreen &&
-            (!g_ddraw->fullscreen || (g_ddraw->windowed && g_ddraw->toggle_borderless)) &&
+        if (g_config.hotkeys.toggle_fullscreen &&
+            wParam == g_config.hotkeys.toggle_fullscreen &&
+            (!g_config.fullscreen || (g_config.windowed && g_config.toggle_borderless)) &&
             context_code && 
             !key_state)
         {
@@ -676,11 +676,11 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             return 0;
         }
 
-        if (g_ddraw->hotkeys.toggle_maximize &&
-            wParam == g_ddraw->hotkeys.toggle_maximize &&
-            g_ddraw->resizable && 
-            g_ddraw->windowed && 
-            !g_ddraw->fullscreen)
+        if (g_config.hotkeys.toggle_maximize &&
+            wParam == g_config.hotkeys.toggle_maximize &&
+            g_config.resizable && 
+            g_config.windowed && 
+            !g_config.fullscreen)
         {
             util_toggle_maximize();
             return 0;
@@ -700,7 +700,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             g_ddraw->alt_key_down = FALSE;
         }
 
-        if (wParam == VK_TAB || (g_ddraw->hotkeys.toggle_fullscreen && wParam == g_ddraw->hotkeys.toggle_fullscreen))
+        if (wParam == VK_TAB || (g_config.hotkeys.toggle_fullscreen && wParam == g_config.hotkeys.toggle_fullscreen))
         {
             return DefWindowProc(hWnd, uMsg, wParam, lParam);
         }
@@ -709,20 +709,20 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_KEYDOWN:
     {
-        if (g_ddraw->hotkeys.unlock_cursor1 && 
-            (wParam == VK_CONTROL || wParam == g_ddraw->hotkeys.unlock_cursor1))
+        if (g_config.hotkeys.unlock_cursor1 && 
+            (wParam == VK_CONTROL || wParam == g_config.hotkeys.unlock_cursor1))
         {
-            if (GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(g_ddraw->hotkeys.unlock_cursor1) & 0x8000)
+            if (GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(g_config.hotkeys.unlock_cursor1) & 0x8000)
             {
                 mouse_unlock();
                 return 0;
             }
         }
 
-        if (g_ddraw->hotkeys.unlock_cursor2 && 
-            (wParam == g_ddraw->hotkeys.unlock_cursor2 || wParam == VK_MENU || wParam == VK_CONTROL))
+        if (g_config.hotkeys.unlock_cursor2 && 
+            (wParam == g_config.hotkeys.unlock_cursor2 || wParam == VK_MENU || wParam == VK_CONTROL))
         {
-            if ((GetAsyncKeyState(VK_RMENU) & 0x8000) && GetAsyncKeyState(g_ddraw->hotkeys.unlock_cursor2) & 0x8000)
+            if ((GetAsyncKeyState(VK_RMENU) & 0x8000) && GetAsyncKeyState(g_config.hotkeys.unlock_cursor2) & 0x8000)
             {
                 mouse_unlock();
                 return 0;
@@ -733,7 +733,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     }
     case WM_KEYUP:
     {
-        if (g_ddraw->hotkeys.screenshot && wParam == g_ddraw->hotkeys.screenshot)
+        if (g_config.hotkeys.screenshot && wParam == g_config.hotkeys.screenshot)
             ss_take_screenshot(g_ddraw->primary);
 
         break;
@@ -743,7 +743,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     case WM_RBUTTONUP:
     case WM_MBUTTONUP:
     {
-        if (!g_ddraw->devmode && !g_mouse_locked)
+        if (!g_config.devmode && !g_mouse_locked)
         {
             int x = GET_X_LPARAM(lParam);
             int y = GET_Y_LPARAM(lParam);
@@ -784,7 +784,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     case WM_MBUTTONDOWN:
     case WM_MOUSEMOVE:
     {
-        if (!g_ddraw->devmode && !g_mouse_locked)
+        if (!g_config.devmode && !g_mouse_locked)
         {
             return 0;
         }
@@ -792,9 +792,9 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         int x = max(GET_X_LPARAM(lParam) - g_ddraw->mouse.x_adjust, 0);
         int y = max(GET_Y_LPARAM(lParam) - g_ddraw->mouse.y_adjust, 0);
 
-        if (g_ddraw->adjmouse)
+        if (g_config.adjmouse)
         {
-            if (g_ddraw->vhack && !g_ddraw->devmode)
+            if (g_config.vhack && !g_config.devmode)
             {
                 POINT pt = { 0, 0 };
                 fake_GetCursorPos(&pt);
@@ -831,7 +831,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         case WM_RBUTTONDOWN:
         case WM_XBUTTONDOWN:
         {
-            if (!g_ddraw->devmode && !g_mouse_locked)
+            if (!g_config.devmode && !g_mouse_locked)
             {
                 int x = (DWORD)((GET_X_LPARAM(lParam) - g_ddraw->render.viewport.x) * g_ddraw->mouse.unscale_x);
                 int y = (DWORD)((GET_Y_LPARAM(lParam) - g_ddraw->render.viewport.y) * g_ddraw->mouse.unscale_y);