diff --git a/Makefile.common b/Makefile.common
index e3e3d219ae..2bf94f9dba 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -441,8 +441,11 @@ ifeq ($(HAVE_NEON),1)
 endif
 
 ifneq ($(findstring Win32,$(OS)),)
-HAVE_VULKAN=1
-DEFINES += -DHAVE_VULKAN
+   # if user explicitly sets --disable-vulkan on Windows, then disable it
+   ifneq ($(HAVE_NO_VULKAN),1)
+      HAVE_VULKAN=1
+      DEFINES += -DHAVE_VULKAN
+   endif
 endif
 
 HW_CONTEXT_MENU_DRIVERS=$(HAVE_RGUI)
@@ -1161,6 +1164,13 @@ ifneq ($(findstring Win32,$(OS)),)
           input/drivers_keyboard/keyboard_event_win32.o \
           gfx/common/win32_common.o \
           frontend/drivers/platform_win32.o
+
+   OBJ += gfx/drivers/gdi_gfx.o \
+          gfx/drivers_context/gdi_ctx.o \
+          gfx/drivers_font/gdi_font.o \
+          menu/drivers_display/menu_display_gdi.o
+
+   LIBS += -lmsimg32
 endif
 
 ifeq ($(HAVE_AVFOUNDATION), 1)
diff --git a/audio/drivers/coreaudio.c b/audio/drivers/coreaudio.c
index d9e73a1251..a17ead090f 100644
--- a/audio/drivers/coreaudio.c
+++ b/audio/drivers/coreaudio.c
@@ -139,7 +139,7 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
    AudioObjectPropertyAddress propaddr =
    { 
       kAudioHardwarePropertyDevices, 
-      kAudioObjectPropertyScopeGlobal, 
+      kAudioObjectPropertyScopeOutput,
       kAudioObjectPropertyElementMaster 
    };
    UInt32 size = 0;
@@ -155,14 +155,13 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
             &propaddr, 0, 0, &size, devices) != noErr)
       goto done;
 
-   propaddr.mScope    = kAudioDevicePropertyScopeOutput;
    propaddr.mSelector = kAudioDevicePropertyDeviceName;
-   size               = 1024;
 
    for (i = 0; i < deviceCount; i ++)
    {
       char device_name[1024];
       device_name[0] = 0;
+      size           = 1024;
 
       if (AudioObjectGetPropertyData(devices[i],
                &propaddr, 0, 0, &size, device_name) == noErr 
diff --git a/audio/drivers/xaudio.cpp b/audio/drivers/xaudio.cpp
index 36de2720ed..c47cb07fd4 100644
--- a/audio/drivers/xaudio.cpp
+++ b/audio/drivers/xaudio.cpp
@@ -29,6 +29,11 @@
 #include <compat/msvc.h>
 #include <retro_miscellaneous.h>
 
+#if defined(_MSC_VER) && (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
+/* needed for CoInitializeEx */
+#define _WIN32_DCOM
+#endif
+
 #include "xaudio.h"
 
 #include "../audio_driver.h"
diff --git a/command.c b/command.c
index c5ec6d3e7a..5a419fd7da 100644
--- a/command.c
+++ b/command.c
@@ -2259,7 +2259,7 @@ bool command_event(enum event_command cmd, void *data)
          {
             int flags = DRIVER_AUDIO_MASK;
             driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);
-            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
+            drivers_init(flags);
          }
          break;
       case CMD_EVENT_RESET_CONTEXT:
@@ -2278,7 +2278,7 @@ bool command_event(enum event_command cmd, void *data)
             memcpy(hwr, &hwr_copy, sizeof(*hwr));
             video_driver_set_context_negotiation_interface(iface);
 
-            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
+            drivers_init(flags);
          }
          break;
       case CMD_EVENT_SHUTDOWN:
diff --git a/config.def.h b/config.def.h
index dc5b14d610..28ed46adef 100644
--- a/config.def.h
+++ b/config.def.h
@@ -51,6 +51,8 @@ enum video_driver_enum
    VIDEO_EXYNOS,
    VIDEO_SUNXI,
    VIDEO_DISPMANX,
+   VIDEO_CACA,
+   VIDEO_GDI,
    VIDEO_NULL
 };
 
@@ -209,6 +211,8 @@ enum record_driver_enum
 #define VIDEO_DEFAULT_DRIVER VIDEO_SDL
 #elif defined(HAVE_SDL2)
 #define VIDEO_DEFAULT_DRIVER VIDEO_SDL2
+#elif defined(_WIN32) && !defined(_XBOX)
+#define VIDEO_DEFAULT_DRIVER VIDEO_GDI
 #elif defined(HAVE_DYLIB) && !defined(ANDROID)
 #define VIDEO_DEFAULT_DRIVER VIDEO_EXT
 #else
diff --git a/configuration.c b/configuration.c
index 00edc333da..76d2271c77 100644
--- a/configuration.c
+++ b/configuration.c
@@ -310,6 +310,10 @@ const char *config_get_default_video(void)
          return "dispmanx";
       case VIDEO_SUNXI:
          return "sunxi";
+      case VIDEO_CACA:
+         return "caca";
+      case VIDEO_GDI:
+         return "gdi";
       case VIDEO_NULL:
          break;
    }
diff --git a/dist-scripts/wiiu-cores.sh b/dist-scripts/wiiu-cores.sh
index e3a5d53fc2..b1a384e555 100755
--- a/dist-scripts/wiiu-cores.sh
+++ b/dist-scripts/wiiu-cores.sh
@@ -117,7 +117,6 @@ for f in `ls -v *_${platform}.${EXT}`; do
       fi
    fi
    rm -rf ${name}_meta.xml
-   rm -rf $name.png
 
 done
 
diff --git a/driver.c b/driver.c
index 5de24cb3de..b0f1aacfd5 100644
--- a/driver.c
+++ b/driver.c
@@ -287,13 +287,13 @@ static bool driver_update_system_av_info(const struct retro_system_av_info *info
 }
 
 /**
- * init_drivers:
+ * drivers_init:
  * @flags              : Bitmask of drivers to initialize.
  *
  * Initializes drivers.
  * @flags determines which drivers get initialized.
  **/
-static void init_drivers(int flags)
+void drivers_init(int flags)
 {
    if (flags & DRIVER_VIDEO_MASK)
       video_driver_unset_own_driver();
@@ -453,19 +453,6 @@ bool driver_ctl(enum driver_ctl_state state, void *data)
             int flags = DRIVERS_CMD_ALL;
             return driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);
          }
-      case RARCH_DRIVER_CTL_INIT:
-         {
-            int *flags = (int*)data;
-            if (!flags)
-               return false;
-            init_drivers(*flags);
-         }
-         break;
-      case RARCH_DRIVER_CTL_INIT_ALL:
-         {
-            int flags = DRIVERS_CMD_ALL;
-            return driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
-         }
       case RARCH_DRIVER_CTL_INIT_PRE:
          audio_driver_find_driver();
          video_driver_find_driver();
diff --git a/driver.h b/driver.h
index 475564058b..34633736e6 100644
--- a/driver.h
+++ b/driver.h
@@ -72,13 +72,6 @@ enum driver_ctl_state
 
    RARCH_DRIVER_CTL_UNINIT_ALL,
 
-   /* Initializes drivers.
-    * @data is a bitmask which determines 
-    * which drivers get initialized. */
-   RARCH_DRIVER_CTL_INIT,
-
-   RARCH_DRIVER_CTL_INIT_ALL,
-
    /* Attempts to find a default driver for 
     * all driver types.
     *
@@ -122,6 +115,8 @@ typedef struct driver_ctx_info
 
 bool driver_ctl(enum driver_ctl_state state, void *data);
 
+void drivers_init(int flags);
+
 RETRO_END_DECLS
 
 #endif
diff --git a/file_path_special.c b/file_path_special.c
index 2957c0d444..fb96d87d21 100644
--- a/file_path_special.c
+++ b/file_path_special.c
@@ -285,7 +285,7 @@ void fill_pathname_application_path(char *s, size_t len)
 #endif
 
 #ifdef HAVE_XMB
-const char *xmb_theme_ident(void);
+const char* xmb_theme_ident(void);
 #endif
 
 void fill_pathname_application_special(char *s, size_t len, enum application_special_type type)
diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c
index fcfc4e68ca..29e903ca8b 100644
--- a/frontend/drivers/platform_wiiu.c
+++ b/frontend/drivers/platform_wiiu.c
@@ -49,6 +49,7 @@
 #include <proc_ui/procui.h>
 #include <vpad/input.h>
 #include <sysapp/launch.h>
+#include <padscore.h>
 
 #include <fat.h>
 #include <iosuhax.h>
@@ -279,6 +280,9 @@ int main(int argc, char **argv)
    devoptab_list[STD_ERR] = &dotab_stdout;
 #endif
    VPADInit();
+   WPADEnableURCC(true);
+   WPADEnableWiiRemote(true);
+   KPADInit();
 
    verbosity_enable();
    DEBUG_VAR(argc);
diff --git a/frontend/drivers/platform_win32.c b/frontend/drivers/platform_win32.c
index b7da98da6d..03e79a1054 100644
--- a/frontend/drivers/platform_win32.c
+++ b/frontend/drivers/platform_win32.c
@@ -328,7 +328,7 @@ static uint64_t frontend_win32_get_mem_used(void)
 static void frontend_win32_attach_console(void)
 {
 #ifdef _WIN32
-#if(_WIN32_WINNT >= 0x0500)
+#ifdef _WIN32_WINNT_WINXP
    if (!AttachConsole(ATTACH_PARENT_PROCESS))
    {
       AllocConsole();
@@ -343,7 +343,7 @@ static void frontend_win32_attach_console(void)
 static void frontend_win32_detach_console(void)
 {
 #if defined(_WIN32) && !defined(_XBOX)
-#if(_WIN32_WINNT >= 0x0500)
+#ifdef _WIN32_WINNT_WINXP
    if (!AttachConsole(ATTACH_PARENT_PROCESS))
    {
       HWND wnd = GetConsoleWindow();
diff --git a/gfx/common/gdi_common.h b/gfx/common/gdi_common.h
new file mode 100644
index 0000000000..b4acb0afb5
--- /dev/null
+++ b/gfx/common/gdi_common.h
@@ -0,0 +1,26 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ *  copyright (c) 2011-2015 - Daniel De Matteis
+ *  copyright (c) 2016 - Brad Parker
+ *
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDI_COMMON_H
+#define __GDI_COMMON_H
+
+typedef struct gdi
+{
+   WNDCLASSEX wndclass;
+} gdi_t;
+
+#endif
diff --git a/gfx/common/win32_common.cpp b/gfx/common/win32_common.cpp
index 2179dd7d17..beb959cc6f 100644
--- a/gfx/common/win32_common.cpp
+++ b/gfx/common/win32_common.cpp
@@ -43,6 +43,11 @@
 #include "../../retroarch.h"
 #include "../video_thread_wrapper.h"
 #include <shellapi.h>
+
+#ifdef HAVE_MENU
+#include "../../menu/menu_driver.h"
+#endif
+
 #ifndef _MSC_VER
 extern "C" {
 #endif
@@ -55,10 +60,13 @@ LRESULT win32_menu_loop(HWND owner, WPARAM wparam);
 }
 #endif
 
+#ifdef HAVE_D3D9
 extern "C" bool dinput_handle_message(void *dinput, UINT message,
       WPARAM wParam, LPARAM lParam);
+extern void *dinput_gdi;
 extern void *dinput_wgl;
 extern void *dinput;
+#endif
 
 unsigned g_resize_width             = 0;
 unsigned g_resize_height            = 0;
@@ -106,7 +114,9 @@ typedef enum _POWER_REQUEST_TYPE
 #define POWER_REQUEST_CONTEXT_DETAILED_STRING 2
 #endif
 
+#ifdef _WIN32_WINNT_WIN7
 typedef REASON_CONTEXT POWER_REQUEST_CONTEXT, *PPOWER_REQUEST_CONTEXT, *LPPOWER_REQUEST_CONTEXT;
+#endif
 
 #ifndef MAX_MONITORS
 #define MAX_MONITORS 9
@@ -118,10 +128,10 @@ static unsigned win32_monitor_count              = 0;
 
 extern "C"
 {
-	bool doubleclick_on_titlebar_pressed(void)
-	{
-		return doubleclick_on_titlebar;
-	}
+   bool doubleclick_on_titlebar_pressed(void)
+   {
+      return doubleclick_on_titlebar;
+   }
 
    void unset_doubleclick_on_titlebar(void)
    {
@@ -277,8 +287,8 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam)
 
       core_info_get_list(&core_info_list);
 
-	  if (!core_info_list)
-		  return 0;
+     if (!core_info_list)
+        return 0;
 
       core_info_list_get_supported_cores(core_info_list,
             (const char*)szFilename, &core_info, &list_size);
@@ -407,7 +417,7 @@ static LRESULT CALLBACK WndProcCommon(bool *quit, HWND hwnd, UINT message,
          }
          *quit = true;
          break;
-	  case WM_COMMAND:
+     case WM_COMMAND:
          {
             settings_t *settings     = config_get_ptr();
             if (settings->ui.menubar_enable)
@@ -420,6 +430,7 @@ static LRESULT CALLBACK WndProcCommon(bool *quit, HWND hwnd, UINT message,
 
 extern void ui_window_win32_set_droppable(void *data, bool droppable);
 
+#ifdef HAVE_D3D9
 LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
       WPARAM wparam, LPARAM lparam)
 {
@@ -464,7 +475,9 @@ LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
       return 0;
    return DefWindowProc(hwnd, message, wparam, lparam);
 }
+#endif
 
+#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
 LRESULT CALLBACK WndProcGL(HWND hwnd, UINT message,
       WPARAM wparam, LPARAM lparam)
 {
@@ -504,8 +517,94 @@ LRESULT CALLBACK WndProcGL(HWND hwnd, UINT message,
          return 0;
    }
 
+#ifdef HAVE_D3D9
    if (dinput_wgl && dinput_handle_message(dinput_wgl, message, wparam, lparam))
       return 0;
+#endif
+   return DefWindowProc(hwnd, message, wparam, lparam);
+}
+#endif
+
+LRESULT CALLBACK WndProcGDI(HWND hwnd, UINT message,
+      WPARAM wparam, LPARAM lparam)
+{
+   LRESULT ret;
+   bool quit = false;
+
+   if (message == WM_NCLBUTTONDBLCLK)
+      doubleclick_on_titlebar = true;
+
+   switch (message)
+   {
+      case WM_PAINT:
+      {
+         PAINTSTRUCT ps;
+         HDC hdc = BeginPaint(hwnd, &ps);
+
+#ifdef HAVE_MENU
+         if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL) && !gdi_has_menu_frame())
+         {
+            RECT rect;
+            GetClientRect(hwnd, &rect);
+
+            TRIVERTEX vertex[2];
+            vertex[0].x     = rect.left;
+            vertex[0].y     = rect.top;
+            vertex[0].Red   = 1 << 8;
+            vertex[0].Green = 81 << 8;
+            vertex[0].Blue  = 127 << 8;
+            vertex[0].Alpha = 0;
+
+            vertex[1].x     = rect.right;
+            vertex[1].y     = rect.bottom;
+            vertex[1].Red   = 0;
+            vertex[1].Green = 1 << 8;
+            vertex[1].Blue  = 33 << 8;
+            vertex[1].Alpha = 0;
+
+            GRADIENT_RECT gRect;
+            gRect.LowerRight = 0;
+            gRect.UpperLeft  = 1;
+
+            GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
+         }
+#endif
+
+         EndPaint(hwnd, &ps);
+         break;
+      }
+      case WM_DROPFILES:
+      case WM_SYSCOMMAND:
+      case WM_CHAR:
+      case WM_KEYDOWN:
+      case WM_KEYUP:
+      case WM_SYSKEYUP:
+      case WM_SYSKEYDOWN:
+      case WM_CLOSE:
+      case WM_DESTROY:
+      case WM_QUIT:
+      case WM_SIZE:
+      case WM_COMMAND:
+         ret = WndProcCommon(&quit, hwnd, message, wparam, lparam);
+         if (quit)
+            return ret;
+         break;
+      case WM_CREATE:
+         {
+            ui_window_win32_t win32_window;
+            win32_window.hwnd = hwnd;
+
+            create_gdi_context(hwnd, &g_quit);
+
+            ui_window_win32_set_droppable(&win32_window, true);
+         }
+         return 0;
+   }
+
+#ifdef HAVE_D3D9
+   if (dinput_gdi && dinput_handle_message(dinput_gdi, message, wparam, lparam))
+      return 0;
+#endif
    return DefWindowProc(hwnd, message, wparam, lparam);
 }
 
@@ -532,7 +631,7 @@ bool win32_window_create(void *data, unsigned style,
 #endif
 
 bool win32_get_metrics(void *data,
-	enum display_metric_types type, float *value)
+   enum display_metric_types type, float *value)
 {
 #ifdef _XBOX
    return false;
@@ -647,6 +746,7 @@ bool win32_suppress_screensaver(void *data, bool enable)
 
       if (major*100+minor >= 601)
       {
+#ifdef _WIN32_WINNT_WIN7
          /* Windows 7, 8, 10 codepath */
          typedef HANDLE (WINAPI * PowerCreateRequestPtr)(REASON_CONTEXT *context);
          typedef BOOL   (WINAPI * PowerSetRequestPtr)(HANDLE PowerRequest,
@@ -671,6 +771,7 @@ bool win32_suppress_screensaver(void *data, bool enable)
             powerSetRequest( Request, PowerRequestDisplayRequired);
             return true;
          }
+#endif
       }
       else
       {
@@ -686,8 +787,8 @@ bool win32_suppress_screensaver(void *data, bool enable)
 
 /* FIXME: It should not be necessary to add the W after MONITORINFOEX, but linking fails without it. */
 void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
-	unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
-	RECT *rect, RECT *mon_rect, DWORD *style)
+   unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
+   RECT *rect, RECT *mon_rect, DWORD *style)
 {
 #ifndef _XBOX
    settings_t *settings = config_get_ptr();
@@ -714,7 +815,7 @@ void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
 
          if (!win32_monitor_set_fullscreen(*width, *height,
                   refresh, current_mon->szDevice))
-			 {}
+          {}
 
          /* Display settings might have changed, get new coordinates. */
          GetMonitorInfo(*hm_to_use, (MONITORINFOEX*)current_mon);
@@ -780,6 +881,7 @@ bool win32_set_video_mode(void *data,
    RECT rect             = {0};
    HMONITOR hm_to_use    = NULL;
    settings_t *settings  = config_get_ptr();
+   int res               = 0;
 
    win32_monitor_info(&current_mon, &hm_to_use, &mon_id);
 
@@ -797,11 +899,20 @@ bool win32_set_video_mode(void *data,
    
    win32_set_window(&width, &height, fullscreen, windowed_full, &rect);
 
-   /* Wait until context is created (or failed to do so ...) */
-   while (!g_inited && !g_quit && GetMessage(&msg, main_window.hwnd, 0, 0))
+   /* Wait until context is created (or failed to do so ...).
+    * Please don't remove the (res = ) as GetMessage can return -1. */
+   while (!g_inited && !g_quit && (res = GetMessage(&msg, main_window.hwnd, 0, 0)) != 0)
    {
-      TranslateMessage(&msg);
-      DispatchMessage(&msg);
+      if (res == -1)
+      {
+         RARCH_ERR("GetMessage error code %d\n", GetLastError());
+         break;
+      }
+      else
+      {
+         TranslateMessage(&msg);
+         DispatchMessage(&msg);
+      }
    }
 
    if (g_quit)
diff --git a/gfx/common/win32_common.h b/gfx/common/win32_common.h
index 6e41231600..61aa2849b7 100644
--- a/gfx/common/win32_common.h
+++ b/gfx/common/win32_common.h
@@ -52,6 +52,16 @@ void win32_monitor_info(void *data, void *hm_data, unsigned *mon_id);
 
 void create_graphics_context(HWND hwnd, bool *quit);
 
+void create_gdi_context(HWND hwnd, bool *quit);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+bool gdi_has_menu_frame(void);
+#ifdef __cplusplus
+}
+#endif
+
 bool win32_shader_dlg_init(void);
 void shader_dlg_show(HWND parent_hwnd);
 void shader_dlg_params_reload(void);
@@ -84,7 +94,13 @@ bool win32_get_metrics(void *data,
 
 void win32_show_cursor(bool state);
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 HWND win32_get_window(void);
+#ifdef __cplusplus
+}
+#endif
 
 bool win32_has_focus(void);
 
@@ -95,7 +111,6 @@ void win32_set_window(unsigned *width, unsigned *height,
       bool fullscreen, bool windowed_full, void *rect_data);
 
 #ifndef _XBOX
-/* FIXME: It should not be necessary to add the W after MONITORINFOEX, but linking fails without it. */
 void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
 	unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
 	RECT *rect, RECT *mon_rect, DWORD *style);
@@ -105,11 +120,18 @@ void win32_window_reset(void);
 
 void win32_destroy_window(void);
 
+#ifdef HAVE_D3D9
 LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
       WPARAM wparam, LPARAM lparam);
+#endif
 
+#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
 LRESULT CALLBACK WndProcGL(HWND hwnd, UINT message,
       WPARAM wparam, LPARAM lparam);
+#endif
+
+LRESULT CALLBACK WndProcGDI(HWND hwnd, UINT message,
+      WPARAM wparam, LPARAM lparam);
 
 #ifdef _XBOX
 BOOL IsIconic(HWND hwnd);
diff --git a/gfx/drivers/d3d.cpp b/gfx/drivers/d3d.cpp
index 9503a0cdf3..46e706e675 100644
--- a/gfx/drivers/d3d.cpp
+++ b/gfx/drivers/d3d.cpp
@@ -259,18 +259,18 @@ static bool d3d_init_multipass(d3d_video_t *d3d)
    }
 
    memset(&d3d->shader, 0, sizeof(d3d->shader));
-
+#ifdef HAVE_SHADERPIPELINE
    if (!video_shader_read_conf_cgp(conf, &d3d->shader))
    {
       config_file_free(conf);
       RARCH_ERR("Failed to parse CGP file.\n");
       return false;
    }
-
+#endif
    config_file_free(conf);
-
+#ifdef HAVE_SHADERPIPELINE
    video_shader_resolve_relative(&d3d->shader, d3d->shader_path.c_str());
-
+#endif
    RARCH_LOG("[D3D9 Meta-Cg] Found %u shaders.\n", d3d->shader.passes);
 
    for (i = 0; i < d3d->shader.passes; i++)
diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c
new file mode 100644
index 0000000000..5100759dee
--- /dev/null
+++ b/gfx/drivers/gdi_gfx.c
@@ -0,0 +1,499 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ *  Copyright (C) 2011-2016 - Daniel De Matteis
+ *  Copyright (C) 2016 - Brad Parker
+ *
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <retro_miscellaneous.h>
+
+#include "../../driver.h"
+#include "../../configuration.h"
+#include "../../verbosity.h"
+#include "../../menu/menu_driver.h"
+#include "../common/gdi_common.h"
+
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../common/win32_common.h"
+#endif
+
+static unsigned char *gdi_menu_frame = NULL;
+static unsigned gdi_menu_width = 0;
+static unsigned gdi_menu_height = 0;
+static unsigned gdi_menu_pitch = 0;
+static unsigned gdi_video_width = 0;
+static unsigned gdi_video_height = 0;
+static unsigned gdi_video_pitch = 0;
+static unsigned gdi_video_bits = 0;
+static unsigned gdi_menu_bits = 0;
+static bool gdi_rgb32 = false;
+static bool gdi_menu_rgb32 = false;
+
+static void gdi_gfx_free(void *data);
+
+static void gdi_gfx_create()
+{
+}
+
+static void *gdi_gfx_init(const video_info_t *video,
+      const input_driver_t **input, void **input_data)
+{
+   unsigned full_x, full_y;
+   settings_t *settings = config_get_ptr();
+   gdi_t *gdi = (gdi_t*)calloc(1, sizeof(*gdi));
+   const gfx_ctx_driver_t *ctx_driver = NULL;
+   gfx_ctx_input_t inp;
+   gfx_ctx_mode_t mode;
+   unsigned win_width = 0, win_height = 0;
+   unsigned temp_width = 0, temp_height = 0;
+
+   *input = NULL;
+   *input_data = NULL;
+
+   gdi_video_width = video->width;
+   gdi_video_height = video->height;
+   gdi_rgb32 = video->rgb32;
+
+   gdi_video_bits = video->rgb32 ? 32 : 16;
+
+   if (video->rgb32)
+      gdi_video_pitch = video->width * 4;
+   else
+      gdi_video_pitch = video->width * 2;
+
+   gdi_gfx_create();
+
+   ctx_driver = video_context_driver_init_first(gdi,
+         settings->video.context_driver,
+         GFX_CTX_GDI_API, 1, 0, false);
+   if (!ctx_driver)
+      goto error;
+
+   video_context_driver_set((const gfx_ctx_driver_t*)ctx_driver);
+
+   RARCH_LOG("Found GDI context: %s\n", ctx_driver->ident);
+
+   video_context_driver_get_video_size(&mode);
+
+   full_x  = mode.width;
+   full_y  = mode.height;
+   mode.width  = 0;
+   mode.height = 0;
+
+   RARCH_LOG("Detecting screen resolution %ux%u.\n", full_x, full_y);
+
+   win_width  = video->width;
+   win_height = video->height;
+
+   if (video->fullscreen && (win_width == 0) && (win_height == 0))
+   {
+      win_width  = full_x;
+      win_height = full_y;
+   }
+
+   mode.width      = win_width;
+   mode.height     = win_height;
+   mode.fullscreen = video->fullscreen;
+
+   if (!video_context_driver_set_video_mode(&mode))
+      goto error;
+
+   mode.width     = 0;
+   mode.height    = 0;
+
+   video_context_driver_get_video_size(&mode);
+
+   temp_width     = mode.width;
+   temp_height    = mode.height;
+   mode.width     = 0;
+   mode.height    = 0;
+
+   /* Get real known video size, which might have been altered by context. */
+
+   if (temp_width != 0 && temp_height != 0)
+      video_driver_set_size(&temp_width, &temp_height);
+
+   video_driver_get_size(&temp_width, &temp_height);
+
+   RARCH_LOG("GDI: Using resolution %ux%u\n", temp_width, temp_height);
+
+   inp.input      = input;
+   inp.input_data = input_data;
+
+   video_context_driver_input_driver(&inp);
+
+   if (settings->video.font_enable)
+      font_driver_init_osd(NULL, false, FONT_DRIVER_RENDER_GDI);
+
+   RARCH_LOG("[GDI]: Init complete.\n");
+
+   return gdi;
+
+error:
+   video_context_driver_destroy();
+   if (gdi)
+      free(gdi);
+   return NULL;
+}
+
+static bool gdi_gfx_frame(void *data, const void *frame,
+      unsigned frame_width, unsigned frame_height, uint64_t frame_count,
+      unsigned pitch, const char *msg, video_frame_info_t video_info)
+{
+   const void *frame_to_copy = frame;
+   unsigned width = 0;
+   unsigned height = 0;
+   unsigned bits = gdi_video_bits;
+   bool draw = true;
+   gdi_t *gdi = (gdi_t*)data;
+   gfx_ctx_mode_t mode;
+   HWND hwnd = win32_get_window();
+   RECT rect;
+
+   if (!frame || !frame_width || !frame_height)
+      return true;
+
+#ifdef HAVE_MENU
+   menu_driver_ctl(RARCH_MENU_CTL_FRAME, NULL);
+#endif
+
+   if (gdi_video_width != frame_width || gdi_video_height != frame_height || gdi_video_pitch != pitch)
+   {
+      if (frame_width > 4 && frame_height > 4)
+      {
+         gdi_video_width = frame_width;
+         gdi_video_height = frame_height;
+         gdi_video_pitch = pitch;
+      }
+   }
+
+   if (gdi_menu_frame && menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
+   {
+      frame_to_copy = gdi_menu_frame;
+      width = gdi_menu_width;
+      height = gdi_menu_height;
+      pitch = gdi_menu_pitch;
+      bits = gdi_menu_bits;
+   }
+   else
+   {
+      width = gdi_video_width;
+      height = gdi_video_height;
+      pitch = gdi_video_pitch;
+
+      if (frame_width == 4 && frame_height == 4 && (frame_width < width && frame_height < height))
+         draw = false;
+
+      if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
+         draw = false;
+   }
+
+   GetClientRect(hwnd, &rect);
+   video_context_driver_get_video_size(&mode);
+
+   if (draw)
+   {
+      HDC winDC = GetDC(hwnd);
+      HDC memDC = CreateCompatibleDC(winDC);
+      HBITMAP bmp = CreateCompatibleBitmap(winDC, width, height);
+      HBITMAP bmp_old;
+      BITMAPINFO *info = (BITMAPINFO*)calloc(1, sizeof(*info) + (3 * sizeof(RGBQUAD)));
+
+      bmp_old = (HBITMAP)SelectObject(memDC, bmp);
+
+      info->bmiHeader.biBitCount = bits;
+      info->bmiHeader.biWidth = pitch / (bits / 8);
+      info->bmiHeader.biHeight = -height;
+      info->bmiHeader.biPlanes = 1;
+      info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + (3 * sizeof(RGBQUAD));
+      info->bmiHeader.biSizeImage = 0;
+
+      if (bits == 16)
+      {
+         unsigned *masks = (unsigned*)info->bmiColors;
+
+         info->bmiHeader.biCompression = BI_BITFIELDS;
+
+         /* map RGB565 color bits, default is 555 */
+         masks[0] = 0xF800;
+         masks[1] = 0x07E0;
+         masks[2] = 0x1F;
+      }
+      else
+         info->bmiHeader.biCompression = BI_RGB;
+
+      StretchDIBits(memDC, 0, 0, width, height, 0, 0, width, height,
+            frame_to_copy, info, DIB_RGB_COLORS, SRCCOPY);
+
+      StretchBlt(winDC,
+            0, 0,
+            mode.width, mode.height,
+            memDC, 0, 0, width, height, SRCCOPY);
+
+      SelectObject(memDC, bmp_old);
+
+      DeleteObject(bmp);
+      DeleteDC(memDC);
+      ReleaseDC(hwnd, winDC);
+
+      free(info);
+   }
+
+   if (msg)
+      font_driver_render_msg(NULL, msg, NULL);
+
+   InvalidateRect(hwnd, NULL, false);
+
+   video_context_driver_update_window_title(video_info);
+
+   return true;
+}
+
+static void gdi_gfx_set_nonblock_state(void *data, bool toggle)
+{
+   (void)data;
+   (void)toggle;
+}
+
+static bool gdi_gfx_alive(void *data)
+{
+   gfx_ctx_size_t size_data;
+   unsigned temp_width  = 0;
+   unsigned temp_height = 0;
+   bool quit = false;
+   bool resize = false;
+ 
+   /* Needed because some context drivers don't track their sizes */
+   video_driver_get_size(&temp_width, &temp_height);
+
+   size_data.quit       = &quit;
+   size_data.resize     = &resize;
+   size_data.width      = &temp_width;
+   size_data.height     = &temp_height;
+
+   video_context_driver_check_window(&size_data);
+
+   if (temp_width != 0 && temp_height != 0)
+      video_driver_set_size(&temp_width, &temp_height);
+
+   return true;
+}
+
+static bool gdi_gfx_focus(void *data)
+{
+   (void)data;
+   return true;
+}
+
+static bool gdi_gfx_suppress_screensaver(void *data, bool enable)
+{
+   (void)data;
+   (void)enable;
+   return false;
+}
+
+static bool gdi_gfx_has_windowed(void *data)
+{
+   (void)data;
+   return true;
+}
+
+static void gdi_gfx_free(void *data)
+{
+   gdi_t *gdi = (gdi_t*)data;
+
+   if (gdi_menu_frame)
+   {
+      free(gdi_menu_frame);
+      gdi_menu_frame = NULL;
+   }
+
+   if (!gdi)
+      return;
+
+   font_driver_free_osd();
+   video_context_driver_free();
+   free(gdi);
+}
+
+static bool gdi_gfx_set_shader(void *data,
+      enum rarch_shader_type type, const char *path)
+{
+   (void)data;
+   (void)type;
+   (void)path;
+
+   return false;
+}
+
+static void gdi_gfx_set_rotation(void *data,
+      unsigned rotation)
+{
+   (void)data;
+   (void)rotation;
+}
+
+static void gdi_gfx_viewport_info(void *data,
+      struct video_viewport *vp)
+{
+   (void)data;
+   (void)vp;
+}
+
+static bool gdi_gfx_read_viewport(void *data, uint8_t *buffer)
+{
+   (void)data;
+   (void)buffer;
+
+   return true;
+}
+
+static void gdi_set_texture_frame(void *data,
+      const void *frame, bool rgb32, unsigned width, unsigned height,
+      float alpha)
+{
+   unsigned pitch = width * 2;
+
+   if (rgb32)
+      pitch = width * 4;
+
+   if (gdi_menu_frame)
+   {
+      free(gdi_menu_frame);
+      gdi_menu_frame = NULL;
+   }
+
+   if (!gdi_menu_frame || gdi_menu_width != width || gdi_menu_height != height || gdi_menu_pitch != pitch)
+      if (pitch && height)
+         gdi_menu_frame = (unsigned char*)malloc(pitch * height);
+
+   if (gdi_menu_frame && frame && pitch && height)
+   {
+      memcpy(gdi_menu_frame, frame, pitch * height);
+      gdi_menu_width = width;
+      gdi_menu_height = height;
+      gdi_menu_pitch = pitch;
+      gdi_menu_bits = rgb32 ? 32 : 16;
+   }
+}
+
+static void gdi_set_osd_msg(void *data, const char *msg,
+      const struct font_params *params, void *font)
+{
+   font_driver_render_msg(font, msg, params);
+}
+
+static void gdi_get_video_output_size(void *data,
+      unsigned *width, unsigned *height)
+{
+   gfx_ctx_size_t size_data;
+   size_data.width  = width;
+   size_data.height = height;
+   video_context_driver_get_video_output_size(&size_data);
+}
+
+static void gdi_get_video_output_prev(void *data)
+{
+   video_context_driver_get_video_output_prev();
+}
+
+static void gdi_get_video_output_next(void *data)
+{
+   video_context_driver_get_video_output_next();
+}
+
+static void gdi_set_video_mode(void *data, unsigned width, unsigned height,
+      bool fullscreen)
+{
+   gfx_ctx_mode_t mode;
+
+   mode.width      = width;
+   mode.height     = height;
+   mode.fullscreen = fullscreen;
+
+   video_context_driver_set_video_mode(&mode);
+}
+
+static const video_poke_interface_t gdi_poke_interface = {
+   NULL,
+   NULL,
+   gdi_set_video_mode,
+   NULL,
+   gdi_get_video_output_size,
+   gdi_get_video_output_prev,
+   gdi_get_video_output_next,
+#ifdef HAVE_FBO
+   NULL,
+#else
+   NULL,
+#endif
+   NULL,
+   NULL,
+   NULL,
+#if defined(HAVE_MENU)
+   gdi_set_texture_frame,
+   NULL,
+   gdi_set_osd_msg,
+   NULL,
+#else
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+#endif
+
+   NULL,
+#ifdef HAVE_MENU
+   NULL,
+#endif
+};
+
+static void gdi_gfx_get_poke_interface(void *data,
+      const video_poke_interface_t **iface)
+{
+   (void)data;
+   *iface = &gdi_poke_interface;
+}
+
+static void gdi_gfx_set_viewport(void *data, unsigned viewport_width,
+      unsigned viewport_height, bool force_full, bool allow_rotate)
+{
+}
+
+bool gdi_has_menu_frame()
+{
+   return (gdi_menu_frame != NULL);
+}
+
+video_driver_t video_gdi = {
+   gdi_gfx_init,
+   gdi_gfx_frame,
+   gdi_gfx_set_nonblock_state,
+   gdi_gfx_alive,
+   gdi_gfx_focus,
+   gdi_gfx_suppress_screensaver,
+   gdi_gfx_has_windowed,
+   gdi_gfx_set_shader,
+   gdi_gfx_free,
+   "gdi",
+   gdi_gfx_set_viewport,
+   gdi_gfx_set_rotation,
+   gdi_gfx_viewport_info,
+   gdi_gfx_read_viewport,
+   NULL, /* read_frame_raw */
+
+#ifdef HAVE_OVERLAY
+  NULL, /* overlay_interface */
+#endif
+  gdi_gfx_get_poke_interface,
+};
diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c
index 160427cba2..5c42dcce36 100644
--- a/gfx/drivers/gl.c
+++ b/gfx/drivers/gl.c
@@ -2330,7 +2330,8 @@ static bool gl_set_shader(void *data,
    gl_set_shader_viewport(gl, 1);
    context_bind_hw_render(true);
 #if defined(_WIN32) && !defined(_XBOX)
-   shader_dlg_params_reload();
+   /* Shader dialog is disabled for now, until video_threaded issues are fixed.
+   shader_dlg_params_reload();*/
 #endif
 
 #endif
diff --git a/gfx/drivers_context/gdi_ctx.cpp b/gfx/drivers_context/gdi_ctx.cpp
new file mode 100644
index 0000000000..7f35a5a993
--- /dev/null
+++ b/gfx/drivers_context/gdi_ctx.cpp
@@ -0,0 +1,338 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ *  Copyright (C) 2011-2016 - Daniel De Matteis
+ *  Copyright (C) 2016 - Brad Parker
+ * 
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Win32/GDI context. */
+
+/* necessary for mingw32 multimon defines: */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500 //_WIN32_WINNT_WIN2K
+#endif
+
+#include <string.h>
+#include <math.h>
+
+#include <windows.h>
+#include <commdlg.h>
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#include "../../configuration.h"
+#include "../../dynamic.h"
+#include "../../runloop.h"
+#include "../../verbosity.h"
+#include "../video_context_driver.h"
+
+#include "../common/win32_common.h"
+
+static HDC   win32_gdi_hdc;
+
+static unsigned         win32_gdi_major       = 0;
+static unsigned         win32_gdi_minor       = 0;
+static unsigned         win32_gdi_interval    = 0;
+static enum gfx_ctx_api win32_gdi_api         = GFX_CTX_NONE;
+
+void *dinput_gdi;
+
+static void setup_gdi_pixel_format(HDC hdc)
+{
+   PIXELFORMATDESCRIPTOR pfd = {0};
+   pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
+   pfd.nVersion     = 1;
+   pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
+   pfd.iPixelType   = PFD_TYPE_RGBA;
+   pfd.cColorBits   = 32;
+   pfd.cDepthBits   = 0;
+   pfd.cStencilBits = 0;
+   pfd.iLayerType   = PFD_MAIN_PLANE;
+
+   SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
+}
+
+static void gfx_ctx_gdi_check_window(void *data, bool *quit,
+      bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
+{
+   win32_check_window(quit, resize, width, height);
+}
+
+static bool gfx_ctx_gdi_set_resize(void *data,
+      unsigned width, unsigned height)
+{
+   (void)data;
+   (void)width;
+   (void)height;
+
+   switch (win32_gdi_api)
+   {
+      case GFX_CTX_NONE:
+      default:
+         break;
+   }
+
+   return false;
+}
+
+static void gfx_ctx_gdi_update_window_title(void *data, video_frame_info_t video_info)
+{
+   char buf[128];
+   char buf_fps[128];
+   const ui_window_t *window = ui_companion_driver_get_window_ptr();
+
+   buf[0] = buf_fps[0] = '\0';
+
+   if (window && video_monitor_get_fps(video_info, buf, sizeof(buf),
+            buf_fps, sizeof(buf_fps)))
+      window->set_title(&main_window, buf);
+   if (video_info.fps_show)
+      runloop_msg_queue_push(buf_fps, 1, 1, false);
+}
+
+static void gfx_ctx_gdi_get_video_size(void *data,
+      unsigned *width, unsigned *height)
+{
+   (void)data;
+   HWND         window  = win32_get_window();
+
+   if (!window)
+   {
+      RECT mon_rect;
+      MONITORINFOEX current_mon;
+      unsigned mon_id           = 0;
+      HMONITOR hm_to_use        = NULL;
+
+      win32_monitor_info(&current_mon, &hm_to_use, &mon_id);
+      mon_rect = current_mon.rcMonitor;
+      *width  = mon_rect.right - mon_rect.left;
+      *height = mon_rect.bottom - mon_rect.top;
+   }
+   else
+   {
+      *width  = g_resize_width;
+      *height = g_resize_height;
+   }
+}
+
+static void *gfx_ctx_gdi_init(video_frame_info_t video_info, void *video_driver)
+{
+   WNDCLASSEX wndclass = {0};
+
+   (void)video_driver;
+
+   if (g_inited)
+      return NULL;
+   
+   win32_window_reset();
+   win32_monitor_init();
+
+   wndclass.lpfnWndProc   = WndProcGDI;
+   if (!win32_window_init(&wndclass, true, NULL))
+           return NULL;
+
+   switch (win32_gdi_api)
+   {
+      case GFX_CTX_NONE:
+      default:
+         break;
+   }
+
+   return (void*)"gdi";
+}
+
+static void gfx_ctx_gdi_destroy(void *data)
+{
+   HWND     window  = win32_get_window();
+
+   (void)data;
+
+   switch (win32_gdi_api)
+   {
+      case GFX_CTX_NONE:
+      default:
+         break;
+   }
+
+   if (window && win32_gdi_hdc)
+   {
+      ReleaseDC(window, win32_gdi_hdc);
+      win32_gdi_hdc = NULL;
+   }
+
+   if (window)
+   {
+      win32_monitor_from_window();
+      win32_destroy_window();
+   }
+
+   if (g_restore_desktop)
+   {
+      win32_monitor_get_info();
+      g_restore_desktop     = false;
+   }
+
+   g_inited                     = false;
+   win32_gdi_major                  = 0;
+   win32_gdi_minor                  = 0;
+}
+
+static bool gfx_ctx_gdi_set_video_mode(void *data,
+      video_frame_info_t video_info,
+      unsigned width, unsigned height,
+      bool fullscreen)
+{
+   if (!win32_set_video_mode(NULL, width, height, fullscreen))
+   {
+      RARCH_ERR("[GDI]: win32_set_video_mode failed.\n");
+      goto error;
+   }
+
+   switch (win32_gdi_api)
+   {
+      case GFX_CTX_NONE:
+      default:
+         break;
+   }
+
+   return true;
+
+error:
+   gfx_ctx_gdi_destroy(data);
+   return false;
+}
+
+
+static void gfx_ctx_gdi_input_driver(void *data,
+      const char *joypad_name,
+      const input_driver_t **input, void **input_data)
+{
+   (void)data;
+
+   dinput_gdi   = input_dinput.init(joypad_name);
+
+   *input       = dinput_gdi ? &input_dinput : NULL;
+   *input_data  = dinput_gdi;
+}
+
+static bool gfx_ctx_gdi_has_focus(void *data)
+{
+   return win32_has_focus();
+}
+
+static bool gfx_ctx_gdi_suppress_screensaver(void *data, bool enable)
+{
+   return win32_suppress_screensaver(data, enable);
+}
+
+static bool gfx_ctx_gdi_has_windowed(void *data)
+{
+   (void)data;
+
+   return true;
+}
+
+static bool gfx_ctx_gdi_get_metrics(void *data,
+	enum display_metric_types type, float *value)
+{
+   return win32_get_metrics(data, type, value);
+}
+
+static bool gfx_ctx_gdi_bind_api(void *data,
+      enum gfx_ctx_api api, unsigned major, unsigned minor)
+{
+   (void)data;
+
+   win32_gdi_major = major;
+   win32_gdi_minor = minor;
+   win32_gdi_api   = api;
+
+   return true;
+}
+
+static void gfx_ctx_gdi_show_mouse(void *data, bool state)
+{
+   (void)data;
+   win32_show_cursor(state);
+}
+
+static void gfx_ctx_gdi_swap_interval(void *data, unsigned interval)
+{
+   (void)data;
+   (void)interval;
+}
+
+static void gfx_ctx_gdi_set_flags(void *data, uint32_t flags)
+{
+   (void)data;
+   (void)flags;
+}
+
+static uint32_t gfx_ctx_gdi_get_flags(void *data)
+{
+   uint32_t flags = 0;
+   BIT32_SET(flags, GFX_CTX_FLAGS_NONE);
+   return flags;
+}
+
+static void gfx_ctx_gdi_swap_buffers(void *data, video_frame_info_t video_info)
+{
+   (void)data;
+
+   SwapBuffers(win32_gdi_hdc);
+}
+
+void create_gdi_context(HWND hwnd, bool *quit)
+{
+   (void)quit;
+   win32_gdi_hdc = GetDC(hwnd);
+
+   setup_gdi_pixel_format(win32_gdi_hdc);
+
+   g_inited = true;
+}
+
+const gfx_ctx_driver_t gfx_ctx_gdi = {
+   gfx_ctx_gdi_init,
+   gfx_ctx_gdi_destroy,
+   gfx_ctx_gdi_bind_api,
+   gfx_ctx_gdi_swap_interval,
+   gfx_ctx_gdi_set_video_mode,
+   gfx_ctx_gdi_get_video_size,
+   NULL, /* get_video_output_size */
+   NULL, /* get_video_output_prev */
+   NULL, /* get_video_output_next */
+   gfx_ctx_gdi_get_metrics,
+   NULL,
+   gfx_ctx_gdi_update_window_title,
+   gfx_ctx_gdi_check_window,
+   gfx_ctx_gdi_set_resize,
+   gfx_ctx_gdi_has_focus,
+   gfx_ctx_gdi_suppress_screensaver,
+   gfx_ctx_gdi_has_windowed,
+   gfx_ctx_gdi_swap_buffers,
+   gfx_ctx_gdi_input_driver,
+   NULL,
+   NULL,
+   NULL,
+   gfx_ctx_gdi_show_mouse,
+   "gdi",
+   gfx_ctx_gdi_get_flags,
+   gfx_ctx_gdi_set_flags,
+   NULL,
+   NULL,
+   NULL
+};
+
diff --git a/gfx/drivers_font/d3d_w32_font.cpp b/gfx/drivers_font/d3d_w32_font.cpp
index 1fd5065782..593dee0bff 100644
--- a/gfx/drivers_font/d3d_w32_font.cpp
+++ b/gfx/drivers_font/d3d_w32_font.cpp
@@ -46,7 +46,7 @@ static void *d3dfonts_w32_init_font(void *video_data,
       OUT_TT_PRECIS,
       CLIP_DEFAULT_PRECIS,
       DEFAULT_PITCH,
-#ifdef _MSC_VER  /* MSVC needs w_char* */
+#if defined(_MSC_VER) /* MSVC needs w_char* */
       L"Verdana" /* Hardcode FTL */
 #else
 	  "Verdana"
diff --git a/gfx/drivers_font/gdi_font.c b/gfx/drivers_font/gdi_font.c
new file mode 100644
index 0000000000..8b84baaad2
--- /dev/null
+++ b/gfx/drivers_font/gdi_font.c
@@ -0,0 +1,143 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ *  Copyright (C) 2011-2016 - Daniel De Matteis
+ *  Copyright (C) 2016 - Brad Parker
+ * 
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string/stdstring.h>
+#include <encodings/utf.h>
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#include "../font_driver.h"
+#include "../video_driver.h"
+#include "../../configuration.h"
+#include "../../verbosity.h"
+#include "../common/gdi_common.h"
+#include "../common/win32_common.h"
+
+#include <windows.h>
+#include <wingdi.h>
+
+typedef struct
+{
+   const font_renderer_driver_t *gdi_font_driver;
+   void *gdi_font_data;
+   gdi_t *gdi;
+} gdi_raster_t;
+
+static void *gdi_init_font(void *data,
+      const char *font_path, float font_size)
+{
+   gdi_raster_t *font  = (gdi_raster_t*)calloc(1, sizeof(*font));
+
+   if (!font)
+      return NULL;
+
+   font->gdi = (gdi_t*)data;
+
+   font_size = 1;
+
+   if (!font_renderer_create_default((const void**)&font->gdi_font_driver,
+            &font->gdi_font_data, font_path, font_size))
+   {
+      RARCH_WARN("Couldn't initialize font renderer.\n");
+      return NULL;
+   }
+
+   return font;
+}
+
+static void gdi_render_free_font(void *data)
+{
+
+}
+
+static int gdi_get_message_width(void *data, const char *msg,
+      unsigned msg_len, float scale)
+{
+   return 0;
+}
+
+static const struct font_glyph *gdi_font_get_glyph(
+      void *data, uint32_t code)
+{
+   return NULL;
+}
+
+static void gdi_render_msg(void *data, const char *msg,
+      const void *userdata)
+{
+   gdi_raster_t *font = (gdi_raster_t*)data;
+   float x, y;
+   unsigned width = 0, height = 0;
+   unsigned newX, newY, len;
+   settings_t *settings = config_get_ptr();
+   const struct font_params *params = (const struct font_params*)userdata;
+   HDC hdc;
+   HWND hwnd = win32_get_window();
+
+   if (!font || string_is_empty(msg))
+      return;
+
+   video_driver_get_size(&width, &height);
+
+   if (params)
+   {
+      x = params->x;
+      y = params->y;
+   }
+   else
+   {
+      x = settings->video.msg_pos_x;
+      y = settings->video.msg_pos_y;
+   }
+
+   if (!font->gdi)
+      return;
+
+   len = utf8len(msg);
+   newX = x * width;
+   newY = height - (y * height);
+
+   hdc = GetDC(hwnd);
+   SetBkMode(hdc, TRANSPARENT);
+   SetTextColor(hdc, RGB(255,255,255));
+   TextOut(hdc, newX, newY, msg, len);
+   ReleaseDC(hwnd, hdc);
+}
+
+static void gdi_font_flush_block(void* data)
+{
+   (void)data;
+}
+
+static void gdi_font_bind_block(void* data, void* userdata)
+{
+   (void)data;
+}
+
+font_renderer_t gdi_font = {
+   gdi_init_font,
+   gdi_render_free_font,
+   gdi_render_msg,
+   "gdi font",
+   gdi_font_get_glyph,       /* get_glyph */
+   gdi_font_bind_block,      /* bind_block */
+   gdi_font_flush_block,     /* flush */
+   gdi_get_message_width     /* get_message_width */
+};
diff --git a/gfx/font_driver.c b/gfx/font_driver.c
index 9b6900121f..5fd85f93d0 100644
--- a/gfx/font_driver.c
+++ b/gfx/font_driver.c
@@ -178,6 +178,35 @@ static bool caca_font_init_first(
 }
 #endif
 
+#if defined(_WIN32) && !defined(_XBOX)
+static const font_renderer_t *gdi_font_backends[] = {
+   &gdi_font,
+   NULL,
+};
+
+static bool gdi_font_init_first(
+      const void **font_driver, void **font_handle,
+      void *video_data, const char *font_path, float font_size)
+{
+   unsigned i;
+
+   for (i = 0; gdi_font_backends[i]; i++)
+   {
+      void *data = gdi_font_backends[i]->init(
+            video_data, font_path, font_size);
+
+      if (!data)
+         continue;
+
+      *font_driver = gdi_font_backends[i];
+      *font_handle = data;
+      return true;
+   }
+
+   return false;
+}
+#endif
+
 #ifdef HAVE_VULKAN
 static const font_renderer_t *vulkan_font_backends[] = {
    &vulkan_raster_font,
@@ -301,6 +330,11 @@ static bool font_init_first(
       case FONT_DRIVER_RENDER_CACA:
          return caca_font_init_first(font_driver, font_handle,
                video_data, font_path, font_size);
+#endif
+#if defined(_WIN32) && !defined(_XBOX)
+      case FONT_DRIVER_RENDER_GDI:
+         return gdi_font_init_first(font_driver, font_handle,
+               video_data, font_path, font_size);
 #endif
       case FONT_DRIVER_RENDER_DONT_CARE:
          /* TODO/FIXME - lookup graphics driver's 'API' */
diff --git a/gfx/font_driver.h b/gfx/font_driver.h
index 6d3e374780..f2484db51f 100644
--- a/gfx/font_driver.h
+++ b/gfx/font_driver.h
@@ -32,7 +32,8 @@ enum font_driver_render_api
    FONT_DRIVER_RENDER_VITA2D,
    FONT_DRIVER_RENDER_CTR,
    FONT_DRIVER_RENDER_VULKAN_API,
-   FONT_DRIVER_RENDER_CACA
+   FONT_DRIVER_RENDER_CACA,
+   FONT_DRIVER_RENDER_GDI
 };
 
 enum text_alignment
@@ -164,6 +165,7 @@ extern font_renderer_t vita2d_vita_font;
 extern font_renderer_t ctr_font;
 extern font_renderer_t vulkan_raster_font;
 extern font_renderer_t caca_font;
+extern font_renderer_t gdi_font;
 
 extern font_renderer_driver_t stb_font_renderer;
 extern font_renderer_driver_t stb_unicode_font_renderer;
diff --git a/gfx/video_context_driver.c b/gfx/video_context_driver.c
index f1b114ee61..59e223224b 100644
--- a/gfx/video_context_driver.c
+++ b/gfx/video_context_driver.c
@@ -88,6 +88,9 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
 #endif
 #if defined(HAVE_VULKAN) && defined(HAVE_VULKAN_DISPLAY)
    &gfx_ctx_khr_display,
+#endif
+#if defined(_WIN32) && !defined(_XBOX)
+   &gfx_ctx_gdi,
 #endif
    &gfx_ctx_null,
    NULL
diff --git a/gfx/video_context_driver.h b/gfx/video_context_driver.h
index 3b78e72a0a..55a150c177 100644
--- a/gfx/video_context_driver.h
+++ b/gfx/video_context_driver.h
@@ -37,7 +37,8 @@ enum gfx_ctx_api
    GFX_CTX_DIRECT3D8_API,
    GFX_CTX_DIRECT3D9_API,
    GFX_CTX_OPENVG_API,
-   GFX_CTX_VULKAN_API
+   GFX_CTX_VULKAN_API,
+   GFX_CTX_GDI_API
 };
 
 enum display_metric_types
@@ -249,6 +250,7 @@ extern const gfx_ctx_driver_t gfx_ctx_cocoagl;
 extern const gfx_ctx_driver_t gfx_ctx_emscripten;
 extern const gfx_ctx_driver_t gfx_ctx_opendingux_fbdev;
 extern const gfx_ctx_driver_t gfx_ctx_khr_display;
+extern const gfx_ctx_driver_t gfx_ctx_gdi;
 extern const gfx_ctx_driver_t gfx_ctx_null;
 
 /**
diff --git a/gfx/video_driver.c b/gfx/video_driver.c
index 40cfcaa5f7..ef7380267c 100644
--- a/gfx/video_driver.c
+++ b/gfx/video_driver.c
@@ -227,6 +227,9 @@ static const video_driver_t *video_drivers[] = {
 #ifdef HAVE_XSHM
    &video_xshm,
 #endif
+#if defined(_WIN32) && !defined(_XBOX)
+   &video_gdi,
+#endif
 #ifdef HAVE_CACA
    &video_caca,
 #endif
@@ -753,7 +756,7 @@ static bool init_video(void)
       if (!video_init_thread((const video_driver_t**)&current_video,
                &video_driver_data,
                input_get_double_ptr(), input_driver_get_data_ptr(),
-               current_video, &video))
+               current_video, video))
       {
          RARCH_ERR("Cannot open threaded video driver ... Exiting ...\n");
          goto error;
diff --git a/gfx/video_driver.h b/gfx/video_driver.h
index e6f83c1a21..6efb630b8b 100644
--- a/gfx/video_driver.h
+++ b/gfx/video_driver.h
@@ -563,6 +563,7 @@ extern video_driver_t video_sunxi;
 extern video_driver_t video_drm;
 extern video_driver_t video_xshm;
 extern video_driver_t video_caca;
+extern video_driver_t video_gdi;
 extern video_driver_t video_null;
 
 extern const void *frame_cache_data;
diff --git a/gfx/video_state_tracker.c b/gfx/video_state_tracker.c
index b1bf54d5bb..93a2f40338 100644
--- a/gfx/video_state_tracker.c
+++ b/gfx/video_state_tracker.c
@@ -28,8 +28,9 @@
 #endif
 
 #include "video_state_tracker.h"
+
 #include "../input/input_config.h"
-#include "../configuration.h"
+
 #include "../verbosity.h"
 
 struct state_tracker_internal
diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c
index 63720d0579..ed868fb1d7 100644
--- a/gfx/video_thread_wrapper.c
+++ b/gfx/video_thread_wrapper.c
@@ -809,7 +809,8 @@ static void video_thread_set_nonblock_state(void *data, bool state)
       thr->nonblock = state;
 }
 
-static bool video_thread_init(thread_video_t *thr, const video_info_t *info,
+static bool video_thread_init(thread_video_t *thr,
+      const video_info_t info,
       const input_driver_t **input, void **input_data)
 {
    size_t max_size;
@@ -822,15 +823,15 @@ static bool video_thread_init(thread_video_t *thr, const video_info_t *info,
    thr->cond_thread          = scond_new();
    thr->input                = input;
    thr->input_data           = input_data;
-   thr->info                 = *info;
+   thr->info                 = info;
    thr->alive                = true;
    thr->focus                = true;
    thr->has_windowed         = true;
    thr->suppress_screensaver = true;
 
-   max_size                  = info->input_scale * RARCH_SCALE_BASE;
+   max_size                  = info.input_scale * RARCH_SCALE_BASE;
    max_size                 *= max_size;
-   max_size                 *= info->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
+   max_size                 *= info.rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
    thr->frame.buffer         = (uint8_t*)malloc(max_size);
 
    if (!thr->frame.buffer)
@@ -1355,7 +1356,7 @@ static void video_thread_set_callbacks(
  **/
 bool video_init_thread(const video_driver_t **out_driver,
       void **out_data,  const input_driver_t **input, void **input_data,
-      const video_driver_t *drv, const video_info_t *info)
+      const video_driver_t *drv, const video_info_t info)
 {
    thread_video_t *thr = (thread_video_t*)calloc(1, sizeof(*thr));
    if (!thr)
diff --git a/gfx/video_thread_wrapper.h b/gfx/video_thread_wrapper.h
index 9cfad4160c..190b5f2226 100644
--- a/gfx/video_thread_wrapper.h
+++ b/gfx/video_thread_wrapper.h
@@ -53,7 +53,7 @@ typedef struct thread_video thread_video_t;
 bool video_init_thread(
       const video_driver_t **out_driver, void **out_data,
       const input_driver_t **input, void **input_data,
-      const video_driver_t *driver, const video_info_t *info);
+      const video_driver_t *driver, const video_info_t info);
 
 /**
  * video_thread_get_ptr:
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 041d9b92c9..2b040232cc 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -221,7 +221,6 @@ VIDEO CONTEXT
 
 #endif
 
-
 /*============================================================
 VIDEO SHADERS
 ============================================================ */
@@ -358,6 +357,10 @@ VIDEO DRIVER
 #endif
 #include "../gfx/drivers/nullgfx.c"
 
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../gfx/drivers/gdi_gfx.c"
+#endif
+
 /*============================================================
 FONTS
 ============================================================ */
@@ -402,6 +405,9 @@ FONTS
 #include "../gfx/drivers_font/caca_font.c"
 #endif
 
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../gfx/drivers_font/gdi_font.c"
+#endif
 
 #if defined(HAVE_VULKAN)
 #include "../gfx/drivers_font/vulkan_raster_font.c"
@@ -994,6 +1000,10 @@ MENU
 #include "../menu/drivers_display/menu_display_caca.c"
 #endif
 
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../menu/drivers_display/menu_display_gdi.c"
+#endif
+
 #endif
 
 
@@ -1001,7 +1011,7 @@ MENU
 #include "../menu/drivers/rgui.c"
 #endif
 
-#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) || defined(_3DS)
+#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) || defined(_3DS) || defined(_MSC_VER)
 #ifdef HAVE_XMB
 #include "../menu/drivers/xmb.c"
 #endif
diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp
index 0207179676..e01399c174 100644
--- a/griffin/griffin_cpp.cpp
+++ b/griffin/griffin_cpp.cpp
@@ -115,6 +115,10 @@ UI COMMON CONTEXT
 #include "../gfx/drivers_context/wgl_ctx.cpp"
 #endif
 
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../gfx/drivers_context/gdi_ctx.cpp"
+#endif
+
 #if defined(HAVE_FFMPEG)
 #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES3)
 #include "../cores/libretro-ffmpeg/fft/fft.cpp"
diff --git a/input/drivers/wiiu_input.c b/input/drivers/wiiu_input.c
index 35013bd6ef..c2e12b5ff6 100644
--- a/input/drivers/wiiu_input.c
+++ b/input/drivers/wiiu_input.c
@@ -30,7 +30,7 @@
 
 #include "wiiu_dbg.h"
 
-#define MAX_PADS 1
+#define MAX_PADS 5
 
 typedef struct wiiu_input
 {
@@ -56,7 +56,7 @@ static int16_t wiiu_input_state(void *data,
 {
    wiiu_input_t *wiiu         = (wiiu_input_t*)data;
 
-   if(!wiiu || (port > 0) || !binds || !binds[port])
+   if(!wiiu || !(port < MAX_PADS) || !binds || !binds[port])
       return 0;
 
    switch (device)
diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c
index e74e293818..f941254fab 100644
--- a/input/drivers_joypad/wiiu_joypad.c
+++ b/input/drivers_joypad/wiiu_joypad.c
@@ -19,6 +19,7 @@
 #endif
 
 #include <vpad/input.h>
+#include <padscore.h>
 
 #include "../input_config.h"
 #include "../input_driver.h"
@@ -32,28 +33,61 @@
 #include "wiiu_dbg.h"
 
 #ifndef MAX_PADS
-#define MAX_PADS 1
+#define MAX_PADS 5
 #endif
 
-static uint64_t pad_state;
-static int16_t analog_state[1][2][2];
+#define WIIUINPUT_TYPE_WIIMOTE               0x00
+#define WIIUINPUT_TYPE_NUNCHUK               0x01
+#define WIIUINPUT_TYPE_CLASSIC_CONTROLLER    0x02
+#define WIIUINPUT_TYPE_PRO_CONTROLLER        0x1F
+#define WIIUINPUT_TYPE_NONE                  0xFD
+
+static uint64_t pad_state[MAX_PADS];
+static u8 pad_type[MAX_PADS - 1] = {WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE};
+static int16_t analog_state[MAX_PADS][2][2];
 extern uint64_t lifecycle_state;
 static bool wiiu_pad_inited = false;
 
-static const char *wiiu_joypad_name(unsigned pad)
+
+
+static const char* wiiu_joypad_name(unsigned pad)
 {
-   return "WIIU Controller";
+   if (pad == 0)
+      return "WIIU Gamepad";
+
+   if (pad < MAX_PADS)
+   {
+      switch (pad_type[pad - 1])
+      {
+      case WIIUINPUT_TYPE_NONE:
+         return "N/A";
+
+      case WIIUINPUT_TYPE_PRO_CONTROLLER:
+         return "WIIU Pro Controller";
+
+      case WIIUINPUT_TYPE_WIIMOTE:
+         return "Wiimote Controller";
+
+      case WIIUINPUT_TYPE_NUNCHUK:
+         return "Nunchuk Controller";
+
+      case WIIUINPUT_TYPE_CLASSIC_CONTROLLER:
+         return "Classic Controller";
+      }
+   }
+
+   return "unknown";
 }
 
 static void wiiu_joypad_autodetect_add(unsigned autoconf_pad)
 {
    if (!input_autoconfigure_connect(
-         wiiu_joypad_name(autoconf_pad),
-         NULL,
-         wiiu_joypad.ident,
-         autoconf_pad,
-         0,
-         0
+            wiiu_joypad_name(autoconf_pad),
+            NULL,
+            wiiu_joypad.ident,
+            autoconf_pad,
+            0,
+            0
          ))
       input_config_set_device_name(autoconf_pad, wiiu_joypad_name(autoconf_pad));
 }
@@ -63,12 +97,12 @@ static bool wiiu_joypad_button(unsigned port_num, uint16_t key)
    if (port_num >= MAX_PADS)
       return false;
 
-   return (pad_state & (UINT64_C(1) << key));
+   return (pad_state[port_num] & (UINT64_C(1) << key));
 }
 
 static uint64_t wiiu_joypad_get_buttons(unsigned port_num)
 {
-   return pad_state;
+   return pad_state[port_num];
 }
 
 static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis)
@@ -94,18 +128,21 @@ static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis)
 
    switch (axis)
    {
-      case 0:
-         val = analog_state[port_num][0][0];
-         break;
-      case 1:
-         val = analog_state[port_num][0][1];
-         break;
-      case 2:
-         val = analog_state[port_num][1][0];
-         break;
-      case 3:
-         val = analog_state[port_num][1][1];
-         break;
+   case 0:
+      val = analog_state[port_num][0][0];
+      break;
+
+   case 1:
+      val = analog_state[port_num][0][1];
+      break;
+
+   case 2:
+      val = analog_state[port_num][1][0];
+      break;
+
+   case 3:
+      val = analog_state[port_num][1][1];
+      break;
    }
 
    if (is_neg && val > 0)
@@ -118,51 +155,144 @@ static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis)
 
 static void wiiu_joypad_poll(void)
 {
+   int c;
    VPADStatus vpad;
    VPADReadError vpadError;
+
    VPADRead(0, &vpad, 1, &vpadError);
 
-   if(vpadError)
-      return;
+   if (!vpadError)
+   {
+      pad_state[0] = 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_PLUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_MINUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_X) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_Y) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_B) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_A) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_ZR) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R2) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_ZL) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L2) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_STICK_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
+      pad_state[0] |= (vpad.hold & VPAD_BUTTON_STICK_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
 
-   pad_state = 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_PLUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_MINUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_X) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_Y) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_B) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_A) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_ZR) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R2) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_ZL) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L2) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_STICK_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
-   pad_state |= (vpad.hold & VPAD_BUTTON_STICK_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
+      analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X]  =  vpad.leftStick.x * 0x7FF0;
+      analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y]  = -vpad.leftStick.y * 0x7FF0;
+      analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] =  vpad.rightStick.x * 0x7FF0;
+      analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] = -vpad.rightStick.y * 0x7FF0;
 
-   analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X]  =  vpad.leftStick.x * 0x7FF0;
-   analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y]  = -vpad.leftStick.y * 0x7FF0;
-   analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] =  vpad.rightStick.x * 0x7FF0;
-   analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] = -vpad.rightStick.y * 0x7FF0;
+      BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
 
-   BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
+      if (((vpad.tpNormal.touched) && (vpad.tpNormal.x > 200) && (vpad.tpNormal.validity) == 0) ||
+            (vpad.trigger & VPAD_BUTTON_HOME))
+         BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
 
-   if(((vpad.tpNormal.touched) && (vpad.tpNormal.x > 200) && (vpad.tpNormal.validity) == 0) ||
-      (vpad.trigger & VPAD_BUTTON_HOME))
-      BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
+      /* panic button */
+      if ((vpad.hold & VPAD_BUTTON_R) &&
+            (vpad.hold & VPAD_BUTTON_L) &&
+            (vpad.hold & VPAD_BUTTON_STICK_R) &&
+            (vpad.hold & VPAD_BUTTON_STICK_L))
+         command_event(CMD_EVENT_QUIT, NULL);
+   }
 
-   /* panic button */
-   if((vpad.hold & VPAD_BUTTON_R) &&
-      (vpad.hold & VPAD_BUTTON_L) &&
-      (vpad.hold & VPAD_BUTTON_STICK_R) &&
-      (vpad.hold & VPAD_BUTTON_STICK_L))
-      command_event(CMD_EVENT_QUIT, NULL);
+   for (c = 0; c < 4; c++)
+   {
+      KPADData kpad;
+      u32 result;
+
+      result = KPADRead(c, &kpad, 1);
+
+      if (!result)
+         continue;
+
+      if (pad_type[c] != kpad.device_type)
+      {
+         pad_type[c] = kpad.device_type;
+         wiiu_joypad_autodetect_add(c + 1);
+      }
+
+      pad_state[c + 1] = 0;
+
+      switch (kpad.device_type)
+      {
+      case WIIUINPUT_TYPE_WIIMOTE:
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_PLUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_MINUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_B) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_A) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
+
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X]  =  0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y]  =  0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] =  0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] =  0;
+         break;
+
+      case WIIUINPUT_TYPE_NUNCHUK:
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_PLUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_MINUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_B) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_A) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_Z) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
+         pad_state[c + 1] |= (kpad.btns_h & WPAD_BUTTON_C) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
+
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X]  =  kpad.nunchuck.stick_x * 0x7FF0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y]  = -kpad.nunchuck.stick_y * 0x7FF0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] =  0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] =  0;
+         break;
+
+      case WIIUINPUT_TYPE_PRO_CONTROLLER:
+
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_PRO_BUTTON_STICK_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_PRO_BUTTON_STICK_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
+
+      /* fallthrough */
+      case WIIUINPUT_TYPE_CLASSIC_CONTROLLER:
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) :
+                             0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_PLUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) :
+                             0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_MINUS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) :
+                             0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_X) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_Y) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_B) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_A) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_R) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_L) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_ZR) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R2) : 0;
+         pad_state[c + 1] |= (kpad.classic.btns_h & WPAD_CLASSIC_BUTTON_ZL) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L2) : 0;
+
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X]  =  kpad.classic.lstick_x * 0x7FF0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y]  = -kpad.classic.lstick_y * 0x7FF0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] =  kpad.classic.rstick_x * 0x7FF0;
+         analog_state[c + 1][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] = -kpad.classic.rstick_y * 0x7FF0;
+         break;
+      }
+   }
 }
 
-static bool wiiu_joypad_init(void *data)
+static bool wiiu_joypad_init(void* data)
 {
    wiiu_joypad_autodetect_add(0);
    wiiu_joypad_poll();
@@ -174,7 +304,7 @@ static bool wiiu_joypad_init(void *data)
 
 static bool wiiu_joypad_query_pad(unsigned pad)
 {
-   return pad < MAX_USERS && wiiu_pad_inited;
+   return pad < MAX_PADS && wiiu_pad_inited;
 }
 
 static void wiiu_joypad_destroy(void)
@@ -182,7 +312,8 @@ static void wiiu_joypad_destroy(void)
    wiiu_pad_inited = false;
 }
 
-input_device_driver_t wiiu_joypad = {
+input_device_driver_t wiiu_joypad =
+{
    wiiu_joypad_init,
    wiiu_joypad_query_pad,
    wiiu_joypad_destroy,
diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c
index 78bfd2fc35..3061277223 100644
--- a/input/input_autodetect_builtin.c
+++ b/input/input_autodetect_builtin.c
@@ -193,7 +193,9 @@ DECL_AXIS(r_x_minus, -2) \
 DECL_AXIS(r_y_plus,  -3) \
 DECL_AXIS(r_y_minus, +3)
 
-#define WIIUINPUT_DEFAULT_BINDS \
+#ifdef WIIU
+
+#define WIIUINPUT_GAMEPAD_DEFAULT_BINDS \
 DECL_BTN(a, 8) \
 DECL_BTN(b, 0) \
 DECL_BTN(x, 9) \
@@ -217,6 +219,103 @@ DECL_AXIS(r_x_minus, -2) \
 DECL_AXIS(r_y_plus,  -3) \
 DECL_AXIS(r_y_minus, +3)
 
+#define WIIUINPUT_PRO_CONTROLLER_DEFAULT_BINDS \
+DECL_BTN(a, 8) \
+DECL_BTN(b, 0) \
+DECL_BTN(x, 9) \
+DECL_BTN(y, 1) \
+DECL_BTN(start, 3) \
+DECL_BTN(select, 2) \
+DECL_BTN(up, 4) \
+DECL_BTN(down, 5) \
+DECL_BTN(left, 6) \
+DECL_BTN(right, 7) \
+DECL_BTN(l, 10) \
+DECL_BTN(r, 11) \
+DECL_BTN(l2, 12) \
+DECL_BTN(r2, 13) \
+DECL_AXIS(l_x_plus,  +0) \
+DECL_AXIS(l_x_minus, -0) \
+DECL_AXIS(l_y_plus,  +1) \
+DECL_AXIS(l_y_minus, -1) \
+DECL_AXIS(r_x_plus,  +2) \
+DECL_AXIS(r_x_minus, -2) \
+DECL_AXIS(r_y_plus,  -3) \
+DECL_AXIS(r_y_minus, +3)
+
+#define WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS \
+DECL_BTN(a, 8) \
+DECL_BTN(b, 0) \
+DECL_BTN(x, 9) \
+DECL_BTN(y, 1) \
+DECL_BTN(start, 3) \
+DECL_BTN(select, 2) \
+DECL_BTN(up, 4) \
+DECL_BTN(down, 5) \
+DECL_BTN(left, 6) \
+DECL_BTN(right, 7) \
+DECL_BTN(l, 10) \
+DECL_BTN(r, 11) \
+DECL_BTN(l2, 12) \
+DECL_BTN(r2, 13) \
+DECL_AXIS(l_x_plus,  +0) \
+DECL_AXIS(l_x_minus, -0) \
+DECL_AXIS(l_y_plus,  +1) \
+DECL_AXIS(l_y_minus, -1) \
+DECL_AXIS(r_x_plus,  +2) \
+DECL_AXIS(r_x_minus, -2) \
+DECL_AXIS(r_y_plus,  -3) \
+DECL_AXIS(r_y_minus, +3)
+
+#define WIIUINPUT_WIIMOTE_DEFAULT_BINDS \
+DECL_BTN(a, 8) \
+DECL_BTN(b, 0) \
+DECL_BTN(x, 9) \
+DECL_BTN(y, 1) \
+DECL_BTN(start, 3) \
+DECL_BTN(select, 2) \
+DECL_BTN(up, 4) \
+DECL_BTN(down, 5) \
+DECL_BTN(left, 6) \
+DECL_BTN(right, 7) \
+DECL_BTN(l, 10) \
+DECL_BTN(r, 11) \
+DECL_BTN(l2, 12) \
+DECL_BTN(r2, 13) \
+DECL_AXIS(l_x_plus,  +0) \
+DECL_AXIS(l_x_minus, -0) \
+DECL_AXIS(l_y_plus,  +1) \
+DECL_AXIS(l_y_minus, -1) \
+DECL_AXIS(r_x_plus,  +2) \
+DECL_AXIS(r_x_minus, -2) \
+DECL_AXIS(r_y_plus,  -3) \
+DECL_AXIS(r_y_minus, +3)
+
+#define WIIUINPUT_NUNCHUK_DEFAULT_BINDS \
+DECL_BTN(a, 8) \
+DECL_BTN(b, 0) \
+DECL_BTN(x, 9) \
+DECL_BTN(y, 1) \
+DECL_BTN(start, 3) \
+DECL_BTN(select, 2) \
+DECL_BTN(up, 4) \
+DECL_BTN(down, 5) \
+DECL_BTN(left, 6) \
+DECL_BTN(right, 7) \
+DECL_BTN(l, 10) \
+DECL_BTN(r, 11) \
+DECL_BTN(l2, 12) \
+DECL_BTN(r2, 13) \
+DECL_AXIS(l_x_plus,  +0) \
+DECL_AXIS(l_x_minus, -0) \
+DECL_AXIS(l_y_plus,  +1) \
+DECL_AXIS(l_y_minus, -1) \
+DECL_AXIS(r_x_plus,  +2) \
+DECL_AXIS(r_x_minus, -2) \
+DECL_AXIS(r_y_plus,  -3) \
+DECL_AXIS(r_y_minus, +3)
+#endif
+
 #define GXINPUT_GAMECUBE_DEFAULT_BINDS \
 DECL_BTN(a, 0) \
 DECL_BTN(b, 1) \
@@ -417,7 +516,11 @@ const char* const input_builtin_autoconfs[] =
 #endif
 #endif
 #ifdef WIIU
-   DECL_AUTOCONF_DEVICE("WIIU Controller", "wiiu", WIIUINPUT_DEFAULT_BINDS),
+   DECL_AUTOCONF_DEVICE("WIIU Gamepad", "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
+   DECL_AUTOCONF_DEVICE("WIIU Pro Controller", "wiiu", WIIUINPUT_PRO_CONTROLLER_DEFAULT_BINDS),
+   DECL_AUTOCONF_DEVICE("Wiimote Controller", "wiiu", WIIUINPUT_WIIMOTE_DEFAULT_BINDS),
+   DECL_AUTOCONF_DEVICE("Nunchuk Controller", "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS),
+   DECL_AUTOCONF_DEVICE("Classic Controller", "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
 #endif
 #ifdef __CELLOS_LV2__
    DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),
diff --git a/input/input_config.c b/input/input_config.c
index 093c37debd..1f41f3a199 100644
--- a/input/input_config.c
+++ b/input/input_config.c
@@ -486,11 +486,13 @@ const char *input_config_get_device_name(unsigned port)
 
 void input_config_set_device_name(unsigned port, const char *name)
 {
-   settings_t *settings = config_get_ptr();
    if (!string_is_empty(name))
+   {
+      settings_t *settings = config_get_ptr();
       strlcpy(settings->input.device_names[port],
             name,
             sizeof(settings->input.device_names[port]));
+   }
 }
 
 bool input_config_get_bind_idx(unsigned port, unsigned *joy_idx_real)
diff --git a/input/input_driver.c b/input/input_driver.c
index 562770edb3..2003087627 100644
--- a/input/input_driver.c
+++ b/input/input_driver.c
@@ -289,8 +289,8 @@ void input_poll(void)
 
          if (bind_valid)
          {
-            joypad_info.joy_idx        = i;
-            joypad_info.auto_binds     = settings->input.autoconf_binds[i];
+            joypad_info.joy_idx        = settings->input.joypad_map[i];
+            joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
 
             input_driver_turbo_btns.frame_enable[i] = current_input->input_state(
                   current_input_data, joypad_info, libretro_input_binds,
@@ -383,8 +383,8 @@ int16_t input_state(unsigned port, unsigned device,
 
          if (bind_valid)
          {
-            joypad_info.joy_idx        = port;
-            joypad_info.auto_binds     = settings->input.autoconf_binds[port];
+            joypad_info.joy_idx        = settings->input.joypad_map[port];
+            joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
             res = current_input->input_state(
                   current_input_data, joypad_info, libretro_input_binds, port, device, idx, id);
          }
@@ -508,16 +508,16 @@ void state_tracker_update_input(uint16_t *input1, uint16_t *input2)
 
          if (binds[0][id].valid)
          {
-            joypad_info.joy_idx        = 0;
-            joypad_info.auto_binds     = settings->input.autoconf_binds[0];
+            joypad_info.joy_idx        = settings->input.joypad_map[0];
+            joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
             *input1 |= (current_input->input_state(current_input_data, joypad_info,
                      binds,
                      0, RETRO_DEVICE_JOYPAD, 0, id) ? 1 : 0) << i;
          }
          if (binds[1][id].valid)
          {
-            joypad_info.joy_idx        = 1;
-            joypad_info.auto_binds     = settings->input.autoconf_binds[1];
+            joypad_info.joy_idx        = settings->input.joypad_map[1];
+            joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
             *input2 |= (current_input->input_state(current_input_data, joypad_info,
                      binds,
                      1, RETRO_DEVICE_JOYPAD, 0, id) ? 1 : 0) << i;
@@ -559,8 +559,8 @@ static INLINE bool input_menu_keys_pressed_internal(
          const input_device_driver_t *sec   = current_input->get_sec_joypad_driver 
             ? current_input->get_sec_joypad_driver(current_input_data) : NULL;
 
-         joypad_info.joy_idx        = port;
-         joypad_info.auto_binds     = settings->input.autoconf_binds[port];
+         joypad_info.joy_idx        = settings->input.joypad_map[port];
+         joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
          joypad_info.axis_threshold = settings->input.axis_threshold;
 
          if (sec   && input_joypad_pressed(sec,
@@ -710,8 +710,8 @@ uint64_t input_menu_keys_pressed(
 
       if (check_input_driver_block_hotkey(binds_norm, binds_auto))
       {
-         joypad_info.joy_idx        = 0;
-         joypad_info.auto_binds     = settings->input.autoconf_binds[0];
+         joypad_info.joy_idx        = settings->input.joypad_map[0];
+         joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
 
          if (settings->input.binds[0][RARCH_ENABLE_HOTKEY].valid 
                && current_input->input_state(current_input_data, joypad_info,
@@ -826,8 +826,8 @@ static INLINE bool input_keys_pressed_internal(
    {
       bool bind_valid = binds[i].valid;
 
-      joypad_info.joy_idx        = 0;
-      joypad_info.auto_binds     = settings->input.autoconf_binds[0];
+      joypad_info.joy_idx        = settings->input.joypad_map[0];
+      joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
 
       if (bind_valid && current_input->input_state(current_input_data,
                joypad_info, &binds,
@@ -912,8 +912,8 @@ uint64_t input_keys_pressed(
 
    if (check_input_driver_block_hotkey(binds_norm, binds_auto))
    {
-      joypad_info.joy_idx        = 0;
-      joypad_info.auto_binds     = settings->input.autoconf_binds[0];
+      joypad_info.joy_idx        = settings->input.joypad_map[0];
+      joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
       if (     enable_hotkey_valid 
             && current_input->input_state(
                current_input_data, joypad_info, &binds, 0,
@@ -930,8 +930,8 @@ uint64_t input_keys_pressed(
    if (check_input_driver_block_hotkey(
             focus_normal, focus_binds_auto) && game_focus_toggle_valid)
    {
-      joypad_info.joy_idx        = 0;
-      joypad_info.auto_binds     = settings->input.autoconf_binds[0];
+      joypad_info.joy_idx        = settings->input.joypad_map[0];
+      joypad_info.auto_binds     = settings->input.autoconf_binds[joypad_info.joy_idx];
       if (current_input->input_state(current_input_data, joypad_info, &binds, 0,
                RETRO_DEVICE_JOYPAD, 0, RARCH_GAME_FOCUS_TOGGLE))
          input_driver_block_hotkey = false;
diff --git a/intl/msg_hash_chs.c b/intl/msg_hash_chs.c
index 5afbaa8a9e..b0505b3990 100644
--- a/intl/msg_hash_chs.c
+++ b/intl/msg_hash_chs.c
@@ -26,6 +26,7 @@
 #if defined(_MSC_VER) && !defined(_XBOX)
 /* https://support.microsoft.com/en-us/kb/980263 */
 #pragma execution_character_set("utf-8")
+#pragma warning( disable : 4566 )
 #endif
 
 int menu_hash_get_help_chs_enum(enum msg_hash_enums msg, char *s, size_t len)
diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h
index 40541cdcec..76b3dda148 100644
--- a/intl/msg_hash_ja.h
+++ b/intl/msg_hash_ja.h
@@ -484,6 +484,8 @@ MSG_HASH(
       MENU_ENUM_LABEL_VALUE_CONTENT_HISTORY_SIZE,
       "履歴リストのサイズ"
       )
+MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_REMOVE,
+      "エントリー削除を許す")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS,
       "クイックメニュー"
       )
@@ -1318,7 +1320,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_STATUS,
 MSG_HASH(MENU_ENUM_LABEL_VALUE_STDIN_CMD_ENABLE,
       "stdinコマンド")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_SUPPORTED_CORES,
-      "対応するコア")
+      "提案するコア")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSPEND_SCREENSAVER_ENABLE,
       "スクリーンセーバーをサスペンド")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_BGM_ENABLE,
@@ -1538,7 +1540,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ALLOW_ROTATE,
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_AUTO,
       "自動アスペクト比")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX,
-      "アスペクト比のインデックス")
+      "アスペクト比")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_BLACK_FRAME_INSERTION,
       "黒いフレームを挿入")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_CROP_OVERSCAN,
@@ -1590,7 +1592,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_POST_FILTER_RECORD,
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE,
       "リフレッシュレート")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO,
-      "モニタの予想フレームレート")
+      "画面の予想フレームレート")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION,
       "回転")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE,
@@ -1798,7 +1800,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_WINDOW_SCALE,
 MSG_HASH(MENU_ENUM_SUBLABEL_USER_LANGUAGE,
       "インタフェースの言語を変更する。")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_BLACK_FRAME_INSERTION,
-      "フレームの間で黒フレームを挿入する。60Hzコンテンツを120Hzモニターでやることを役に立つ。")
+      "フレームの間で黒フレームを挿入する。60Hzコンテンツを120Hz画面でやることを役に立つ。")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FRAME_DELAY,
       "遅延が減るけどビデオ途切れの危険率が増す。")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC_FRAMES,
@@ -1806,9 +1808,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC_FRAMES,
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES,
       "指定するバッファーモードをビデオドライバに伝える。")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX,
-      "希望するモニターを選択する。")
+      "希望する画面を選択する。")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO,
-      "モニターの正確な推定のモニターリフレッシュレート")
+      "画面の正確な推定のリフレッシュレート")
 MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS,
       "ビデオ出力の設定を変える。")
 MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS,
@@ -2370,15 +2372,15 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED,
       "コンテンツをロードする後にネットプレイは開始します。")
 MSG_HASH(
       MENU_ENUM_LABEL_VALUE_BROWSE_URL_LIST,
-      "Browse URL"
+      "URLを参照"
       )
 MSG_HASH(
       MENU_ENUM_LABEL_VALUE_BROWSE_URL,
-      "URL Path"
+      "URLのパス"
       )
 MSG_HASH(
       MENU_ENUM_LABEL_VALUE_BROWSE_START,
-      "Start"
+      "スタート"
       )
 MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_BOKEH,
-      "Bokeh")
+      "ボケ")
diff --git a/intl/msg_hash_pl.c b/intl/msg_hash_pl.c
index ec477cd01c..edd84cdf75 100644
--- a/intl/msg_hash_pl.c
+++ b/intl/msg_hash_pl.c
@@ -20,6 +20,7 @@
 #if defined(_MSC_VER) && !defined(_XBOX)
 /* https://support.microsoft.com/en-us/kb/980263 */
 #pragma execution_character_set("utf-8")
+#pragma warning( disable: 4566 )
 #endif
 
 int menu_hash_get_help_pl_enum(enum msg_hash_enums msg, char *s, size_t len)
diff --git a/libretro-common/net/net_ifinfo.c b/libretro-common/net/net_ifinfo.c
index 5432f5a73d..8cec6432bf 100644
--- a/libretro-common/net/net_ifinfo.c
+++ b/libretro-common/net/net_ifinfo.c
@@ -71,10 +71,10 @@ bool net_ifinfo_new(net_ifinfo_t *list)
 {
    unsigned k              = 0;
 #if defined(_WIN32) && !defined(_XBOX)
+   PIP_ADAPTER_ADDRESSES adapter_addresses = NULL, aa = NULL;
+   PIP_ADAPTER_UNICAST_ADDRESS ua = NULL;
+#ifdef _WIN32_WINNT_WINXP
    DWORD size;
-   PIP_ADAPTER_ADDRESSES adapter_addresses, aa;
-   PIP_ADAPTER_UNICAST_ADDRESS ua;
-
    DWORD rv = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &size);
 
    adapter_addresses = (PIP_ADAPTER_ADDRESSES)malloc(size);
@@ -85,7 +85,7 @@ bool net_ifinfo_new(net_ifinfo_t *list)
 
    if (rv != ERROR_SUCCESS)
       goto error;
-
+#endif
    for (aa = adapter_addresses; aa != NULL; aa = aa->Next)
    {
       char name[PATH_MAX_LENGTH];
diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c
index 1744705642..1043199135 100644
--- a/libretro-common/rthreads/rthreads.c
+++ b/libretro-common/rthreads/rthreads.c
@@ -37,6 +37,9 @@
 #include <xtl.h>
 #else
 #define WIN32_LEAN_AND_MEAN
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500 /*_WIN32_WINNT_WIN2K */
+#endif
 #include <windows.h>
 #endif
 #elif defined(GEKKO)
diff --git a/media/rarch.rc b/media/rarch.rc
index 57758d4aec..5bad253138 100644
--- a/media/rarch.rc
+++ b/media/rarch.rc
@@ -69,7 +69,8 @@ IDR_MENU MENU
             MENUITEM "10x", ID_M_WINDOW_SCALE_10X
         }
         MENUITEM "Toggle Exclusive Full Screen", ID_M_FULL_SCREEN
-        MENUITEM "Shader Parameters", ID_M_SHADER_PARAMETERS
+        // Shader dialog is disabled for now, until video_threaded issues are fixed.
+        //MENUITEM "Shader Parameters", ID_M_SHADER_PARAMETERS
     }
 }
 
diff --git a/media/rarch_ja.rc b/media/rarch_ja.rc
index d479e651ad..45f5423ba5 100644
--- a/media/rarch_ja.rc
+++ b/media/rarch_ja.rc
@@ -65,7 +65,8 @@ IDR_MENU MENU
             MENUITEM "10x", ID_M_WINDOW_SCALE_10X
         }
         MENUITEM "�r���I�ȃt���X�N���[���؂�ւ�", ID_M_FULL_SCREEN
-        MENUITEM "�V�F�[�_�[�̃p�����[�^", ID_M_SHADER_PARAMETERS
+        // Shader dialog is disabled for now, until video_threaded issues are fixed.
+        //MENUITEM "�V�F�[�_�[�̃p�����[�^", ID_M_SHADER_PARAMETERS
     }
 }
 
diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c
index 2a436e6fbd..faa82f3e0d 100644
--- a/menu/drivers/xmb.c
+++ b/menu/drivers/xmb.c
@@ -376,7 +376,7 @@ float gradient_dark[16] = {
    0.0, 0.0, 0.0, 1.00,
 };
 
-const char *xmb_theme_ident(void)
+const char* xmb_theme_ident(void)
 {
    settings_t *settings = config_get_ptr();
    switch (settings->menu.xmb.theme)
@@ -890,7 +890,7 @@ static void xmb_update_thumbnail_path(void *data, unsigned i)
 
    menu_entry_get(&entry, 0, i, NULL, true);
 
-   if (entry.type == FILE_TYPE_IMAGEVIEWER)
+   if (entry.type == FILE_TYPE_IMAGEVIEWER || entry.type == FILE_TYPE_IMAGE)
    {
       file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
       xmb_node_t *node = (xmb_node_t*)
@@ -907,7 +907,7 @@ static void xmb_update_thumbnail_path(void *data, unsigned i)
          return;
       }
    }
-   else if (xmb_list_get_selection(xmb) == 0)
+   else if (xmb_list_get_selection(xmb) <= XMB_SYSTEM_TAB_SETTINGS)
    {
       xmb->thumbnail_file_path[0] = '\0';
       xmb->thumbnail = 0;
@@ -1048,7 +1048,7 @@ static void xmb_update_savestate_thumbnail_image(void *data)
 static void xmb_selection_pointer_changed(
       xmb_handle_t *xmb, bool allow_animations)
 {
-   unsigned i, end, height, depth;
+   unsigned i, end, height;
    menu_animation_ctx_tag_t tag;
    size_t selection, num      = 0;
    int threshold              = 0;
@@ -1088,13 +1088,14 @@ static void xmb_selection_pointer_changed(
 
       if (i == selection)
       {
-         ia = xmb->items.active.alpha;
-         iz = xmb->items.active.zoom;
+         unsigned depth = xmb_list_get_size(xmb, MENU_LIST_PLAIN);
+
+         ia             = xmb->items.active.alpha;
+         iz             = xmb->items.active.zoom;
 
-         depth = xmb_list_get_size(xmb, MENU_LIST_PLAIN);
          if (!string_is_equal(xmb_thumbnails_ident(),
                msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))
-               && (depth == 1 || xmb->categories.selection_ptr == 0))
+               && (depth == 1 || xmb_list_get_selection(xmb) <= XMB_SYSTEM_TAB_SETTINGS))
          {
             xmb_update_thumbnail_path(xmb, i);
             xmb_update_thumbnail_image(xmb);
@@ -1272,7 +1273,7 @@ static void xmb_list_open_new(xmb_handle_t *xmb,
    xmb->old_depth = xmb->depth;
    menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &skip);
 
-   if (xmb_list_get_selection(xmb) == 0)
+   if (xmb_list_get_selection(xmb) <= XMB_SYSTEM_TAB_SETTINGS)
       xmb_update_thumbnail_path(xmb, 0);
 }
 
diff --git a/menu/drivers_display/menu_display_gdi.c b/menu/drivers_display/menu_display_gdi.c
new file mode 100644
index 0000000000..e04541c9ea
--- /dev/null
+++ b/menu/drivers_display/menu_display_gdi.c
@@ -0,0 +1,119 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2011-2016 - Daniel De Matteis
+ *  Copyright (C) 2016 - Brad Parker
+ *
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+
+#include <queues/message_queue.h>
+#include <retro_miscellaneous.h>
+
+#include "../../config.def.h"
+#include "../../gfx/font_driver.h"
+#include "../../gfx/video_context_driver.h"
+
+#include "../menu_display.h"
+
+#if defined(_WIN32) && !defined(_XBOX)
+#include "../../gfx/common/win32_common.h"
+#endif
+
+static void *menu_display_gdi_get_default_mvp(void)
+{
+   return NULL;
+}
+
+static void menu_display_gdi_blend_begin(void)
+{
+}
+
+static void menu_display_gdi_blend_end(void)
+{
+}
+
+static void menu_display_gdi_draw(void *data)
+{
+   (void)data;
+}
+
+static void menu_display_gdi_draw_pipeline(void *data)
+{
+   (void)data;
+}
+
+static void menu_display_gdi_viewport(void *data)
+{
+   (void)data;
+}
+
+static void menu_display_gdi_restore_clear_color(void)
+{
+   /*HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+   RECT rect;
+   HWND hwnd = win32_get_window();
+   HDC hdc = GetDC(hwnd);
+
+   GetClientRect(hwnd, &rect);
+
+   FillRect(hdc, &rect, brush);
+
+   DeleteObject(brush);
+
+   ReleaseDC(hwnd, hdc);*/
+}
+
+static void menu_display_gdi_clear_color(menu_display_ctx_clearcolor_t *clearcolor)
+{
+   (void)clearcolor;
+
+   menu_display_gdi_restore_clear_color();
+}
+
+static bool menu_display_gdi_font_init_first(
+      void **font_handle, void *video_data,
+      const char *font_path, float font_size)
+{
+   font_data_t **handle = (font_data_t**)font_handle;
+   *handle = font_driver_init_first(video_data,
+         font_path, font_size, true, FONT_DRIVER_RENDER_GDI);
+   return *handle;
+}
+
+static const float *menu_display_gdi_get_default_vertices(void)
+{
+   static float dummy[16] = {0.0f};
+   return &dummy[0];
+}
+
+static const float *menu_display_gdi_get_default_tex_coords(void)
+{
+   static float dummy[16] = {0.0f};
+   return &dummy[0];
+}
+
+menu_display_ctx_driver_t menu_display_ctx_gdi = {
+   menu_display_gdi_draw,
+   menu_display_gdi_draw_pipeline,
+   menu_display_gdi_viewport,
+   menu_display_gdi_blend_begin,
+   menu_display_gdi_blend_end,
+   menu_display_gdi_restore_clear_color,
+   menu_display_gdi_clear_color,
+   menu_display_gdi_get_default_mvp,
+   menu_display_gdi_get_default_vertices,
+   menu_display_gdi_get_default_tex_coords,
+   menu_display_gdi_font_init_first,
+   MENU_VIDEO_DRIVER_GDI,
+   "menu_display_gdi",
+};
diff --git a/menu/menu_display.c b/menu/menu_display.c
index d2eaf151e0..6e45e1fbc7 100644
--- a/menu/menu_display.c
+++ b/menu/menu_display.c
@@ -82,6 +82,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = {
 #endif
 #ifdef HAVE_CACA
    &menu_display_ctx_caca,
+#endif
+#if defined(_WIN32) && !defined(_XBOX)
+   &menu_display_ctx_gdi,
 #endif
    &menu_display_ctx_null,
    NULL,
@@ -140,6 +143,10 @@ static bool menu_display_check_compatibility(
          if (string_is_equal(video_driver, "caca"))
             return true;
          break;
+      case MENU_VIDEO_DRIVER_GDI:
+         if (string_is_equal(video_driver, "gdi"))
+            return true;
+         break;
    }
 
    return false;
diff --git a/menu/menu_display.h b/menu/menu_display.h
index d58c00df12..6e7faa5c42 100644
--- a/menu/menu_display.h
+++ b/menu/menu_display.h
@@ -95,7 +95,8 @@ enum menu_display_driver_type
    MENU_VIDEO_DRIVER_DIRECT3D,
    MENU_VIDEO_DRIVER_VITA2D,
    MENU_VIDEO_DRIVER_CTR,
-   MENU_VIDEO_DRIVER_CACA
+   MENU_VIDEO_DRIVER_CACA,
+   MENU_VIDEO_DRIVER_GDI
 };
 
 typedef struct menu_display_ctx_clearcolor
@@ -294,6 +295,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_d3d;
 extern menu_display_ctx_driver_t menu_display_ctx_vita2d;
 extern menu_display_ctx_driver_t menu_display_ctx_ctr;
 extern menu_display_ctx_driver_t menu_display_ctx_caca;
+extern menu_display_ctx_driver_t menu_display_ctx_gdi;
 extern menu_display_ctx_driver_t menu_display_ctx_null;
 
 RETRO_END_DECLS
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index 84f802422e..c637fa9fd2 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -318,7 +318,6 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info)
    unsigned i;
    char tmp[PATH_MAX_LENGTH];
    core_info_t *core_info    = NULL;
-   settings_t *settings      = config_get_ptr();
 
    tmp[0] = '\0';
 
@@ -440,6 +439,7 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info)
    if (core_info->firmware_count > 0)
    {
       core_info_ctx_firmware_t firmware_info;
+      settings_t *settings           = config_get_ptr();
 
       firmware_info.path             = core_info->path;
       firmware_info.directory.system = settings->directory.system;
@@ -1715,7 +1715,6 @@ static int menu_displaylist_parse_database_entry(menu_displaylist_info_t *info)
       char tmp[PATH_MAX_LENGTH];
       char crc_str[20];
       database_info_t *db_info_entry = &db_info->list[i];
-      settings_t *settings           = config_get_ptr();
       bool show_advanced_settings    = false;
 
       crc_str[0] = tmp[0] = '\0';
diff --git a/menu/menu_shader.c b/menu/menu_shader.c
index aa299e49b6..a96319acb6 100644
--- a/menu/menu_shader.c
+++ b/menu/menu_shader.c
@@ -309,7 +309,6 @@ bool menu_shader_manager_save_preset(
    config_file_t *conf                    = NULL;
    bool ret                               = false;
    struct video_shader *shader            = menu_shader_get();
-   settings_t *settings                   = config_get_ptr();
 
    buffer[0] = config_directory[0]        = '\0';
    preset_path[0]                         = '\0';
@@ -385,9 +384,10 @@ bool menu_shader_manager_save_preset(
 
    if (!fullpath)
    {
-      dirs[0] = settings->directory.video_shader;
-      dirs[1] = settings->directory.menu_config;
-      dirs[2] = config_directory;
+      settings_t *settings = config_get_ptr();
+      dirs[0]              = settings->directory.video_shader;
+      dirs[1]              = settings->directory.menu_config;
+      dirs[2]              = config_directory;
    }
 
    conf = (config_file_t*)config_file_new(NULL);
diff --git a/menu/widgets/menu_input_bind_dialog.c b/menu/widgets/menu_input_bind_dialog.c
index c80206d09b..cc782330e9 100644
--- a/menu/widgets/menu_input_bind_dialog.c
+++ b/menu/widgets/menu_input_bind_dialog.c
@@ -382,15 +382,8 @@ bool menu_input_key_bind_set_min_max(menu_input_ctx_bind_limits_t *lim)
 bool menu_input_key_bind_iterate(menu_input_ctx_bind_t *bind)
 {
    struct menu_bind_state binds;
-   /* single binds can have latching issues,
-    * single_bind_delay = 0 (single bind not yet bound)
-    * single_bind_delay = 1 (latching procedure)
-    * single_bind_delay = 2 (second iteration, will quit iteration loop)
-    */
-   static unsigned single_bind_delay = 0;
-   bool           trigger_found  = false;
-   bool               timed_out  = false;
-   settings_t *settings          = config_get_ptr();
+   bool               timed_out = false;
+   settings_t *settings         = config_get_ptr();
 
    rarch_timer_tick(&menu_input_binds.timer);
 
@@ -407,27 +400,12 @@ bool menu_input_key_bind_iterate(menu_input_ctx_bind_t *bind)
       timed_out = true;
    }
 
-   if (single_bind_delay > 0)
-   {
-      snprintf(bind->s, bind->len, "Confirming key %s ...",
-            input_config_bind_map_get_desc(
-               menu_input_binds.begin - MENU_SETTINGS_BIND_BEGIN)
-            );
-      single_bind_delay++;
-   }
-   else
-      snprintf(bind->s, bind->len,
-            "[%s]\npress keyboard or joypad\n(timeout %d %s)",
-            input_config_bind_map_get_desc(
-               menu_input_binds.begin - MENU_SETTINGS_BIND_BEGIN),
-            rarch_timer_get_timeout(&menu_input_binds.timer),
-            msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS));
-
-   if (single_bind_delay == 2)
-   {
-      single_bind_delay = 0;
-      return true;
-   }
+   snprintf(bind->s, bind->len,
+         "[%s]\npress keyboard or joypad\n(timeout %d %s)",
+         input_config_bind_map_get_desc(
+            menu_input_binds.begin - MENU_SETTINGS_BIND_BEGIN),
+         rarch_timer_get_timeout(&menu_input_binds.timer),
+         msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS));
 
    /* binds.begin is updated in keyboard_press callback. */
    if (menu_input_binds.begin > menu_input_binds.last)
@@ -439,13 +417,6 @@ bool menu_input_key_bind_iterate(menu_input_ctx_bind_t *bind)
       if (timed_out)
          input_keyboard_ctl(RARCH_INPUT_KEYBOARD_CTL_CANCEL_WAIT_KEYS, NULL);
 
-      /* If this is a single bind, add another delay of one second */
-      if (!timed_out && (binds.begin == binds.last))
-      {
-         single_bind_delay = 1;
-         return false;
-      }
-
       return true;
    }
 
@@ -454,23 +425,14 @@ bool menu_input_key_bind_iterate(menu_input_ctx_bind_t *bind)
    input_driver_keyboard_mapping_set_block(true);
    menu_input_key_bind_poll_bind_state(&binds, menu_bind_port, timed_out);
 
-   if (single_bind_delay == 0)
-      trigger_found = menu_input_key_bind_poll_find_trigger(&menu_input_binds, &binds);
-
-   if ((binds.skip && !menu_input_binds.skip) || trigger_found)
+   if ((binds.skip && !menu_input_binds.skip) ||
+         menu_input_key_bind_poll_find_trigger(&menu_input_binds, &binds))
    {
       input_driver_keyboard_mapping_set_block(false);
 
       /* Avoid new binds triggering things right away. */
       input_driver_set_flushing_input();
 
-      /* If this is a single bind, add a latching delay */
-      if (binds.begin == binds.last)
-      {
-         single_bind_delay = 1;
-         return false;
-      }
-
       binds.begin++;
 
       if (binds.begin > binds.last)
diff --git a/menu/widgets/menu_osk.c b/menu/widgets/menu_osk.c
index db9c8c1488..bfafb3b579 100644
--- a/menu/widgets/menu_osk.c
+++ b/menu/widgets/menu_osk.c
@@ -1,4 +1,4 @@
-/*  RetroArch - A frontend for libretro.
+/*  RetroArch - A frontend for libretro.
  *  Copyright (C) 2011-2016 - Daniel De Matteis
  *
  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
diff --git a/pkg/msvc/RetroArch-msvc2005.sln b/pkg/msvc/RetroArch-msvc2005.sln
new file mode 100644
index 0000000000..8fd5a544c9
--- /dev/null
+++ b/pkg/msvc/RetroArch-msvc2005.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RetroArch-msvc2005", "msvc-2005\RetroArch-msvc2005.vcproj", "{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}.Debug|Win32.Build.0 = Debug|Win32
+		{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}.Release|Win32.ActiveCfg = Release|Win32
+		{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/pkg/msvc/RetroArch-msvc2010.sln b/pkg/msvc/RetroArch-msvc2010.sln
index f72b91f832..8e5df75e23 100644
--- a/pkg/msvc/RetroArch-msvc2010.sln
+++ b/pkg/msvc/RetroArch-msvc2010.sln
@@ -1,6 +1,6 @@
 
 Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+# Visual C++ Express 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RetroArch-msvc2010", "msvc-2010\RetroArch-msvc2010.vcxproj", "{27FF7CE1-4059-4AA1-8062-FD529560FA54}"
 EndProject
 Global
@@ -17,20 +17,16 @@ Global
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|Win32.ActiveCfg = Debug Cg|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|Win32.Build.0 = Debug Cg|Win32
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.ActiveCfg = Debug Cg|x64
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.Build.0 = Debug Cg|x64
+		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug Cg|x64.ActiveCfg = Debug Cg|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.ActiveCfg = Debug|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.Build.0 = Debug|Win32
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.ActiveCfg = Debug|x64
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.Build.0 = Debug|x64
+		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|x64.ActiveCfg = Debug|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|Win32.ActiveCfg = Release Cg|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|Win32.Build.0 = Release Cg|Win32
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.ActiveCfg = Release Cg|x64
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.Build.0 = Release Cg|x64
+		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release Cg|x64.ActiveCfg = Release Cg|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.ActiveCfg = Release|Win32
 		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.Build.0 = Release|Win32
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.ActiveCfg = Release|x64
-		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.Build.0 = Release|x64
+		{27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/pkg/msvc/msvc-2005/RetroArch-msvc2005.vcproj b/pkg/msvc/msvc-2005/RetroArch-msvc2005.vcproj
new file mode 100644
index 0000000000..cd6fe31110
--- /dev/null
+++ b/pkg/msvc/msvc-2005/RetroArch-msvc2005.vcproj
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="RetroArch-msvc2005"
+	ProjectGUID="{1FEFA874-F6A6-4CE6-9DB4-3B291A364CE5}"
+	RootNamespace="RetroArch-msvc2005"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)\..\..\libretro-common\include&quot;;&quot;$(SolutionDir)\..\..\libretro-common\include\compat\msvc&quot;;&quot;$(SolutionDir)\..\..\gfx\include&quot;"
+				PreprocessorDefinitions="_WIN32_WINNT=0x0500;_WIN32;RARCH_INTERNAL;HAVE_THREADS;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_SHADERPIPELINE;HAVE_OPENGL;HAVE_CC_RESAMPLER;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;WANT_ZLIB;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_RTHREADS;HAVE_DYNAMIC;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT;__STDC_CONSTANT_MACROS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msimg32.lib"
+				OutputFile="$(OutDir)/RetroArch-msvc2005.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/RetroArch-msvc2005.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)\..\..\libretro-common\include&quot;;&quot;$(SolutionDir)\..\..\libretro-common\include\compat\msvc&quot;;&quot;$(SolutionDir)\..\..\gfx\include&quot;"
+				PreprocessorDefinitions="_WIN32_WINNT=0x0500;_WIN32;RARCH_INTERNAL;HAVE_THREADS;HAVE_CC_RESAMPLER;HAVE_D3D;HAVE_D3D9;HAVE_GLSL;HAVE_GRIFFIN;HAVE_LANGEXTRA;HAVE_FBO;HAVE_ZLIB;HAVE_RPNG;HAVE_RJPEG;HAVE_RBMP;HAVE_RTGA;HAVE_IMAGEVIEWER;HAVE_XMB;HAVE_SHADERPIPELINE;WANT_ZLIB;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETWORKING;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_RTHREADS;HAVE_DYNAMIC;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC;HAVE_MENU;HAVE_7ZIP;HAVE_MATERIALUI;HAVE_LIBRETRODB;HAVE_STB_FONT;__STDC_CONSTANT_MACROS"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msimg32.lib"
+				OutputFile="$(OutDir)/RetroArch-msvc2005.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\..\griffin\griffin.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						CompileAs="2"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\griffin\griffin_cpp.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/pkg/msvc/msvc-2010/RetroArch-msvc2010.vcxproj b/pkg/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
index 77486ca2c9..9cf3332eed 100644
--- a/pkg/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
+++ b/pkg/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug Cg|Win32">
@@ -192,7 +192,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Cg|Win32'">
@@ -211,7 +211,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(CG_LIB_PATH)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -231,7 +231,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Cg|x64'">
@@ -250,7 +250,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(CG_LIB64_PATH)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -275,7 +275,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Cg|Win32'">
@@ -299,7 +299,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(CG_LIB_PATH)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -324,7 +324,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Cg|x64'">
@@ -348,7 +348,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>msimg32.lib;winmm.lib;Dinput8.lib;dxguid.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(CG_LIB64_PATH)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
diff --git a/qb/config.libs.sh b/qb/config.libs.sh
index 06298da402..f000fe40b4 100644
--- a/qb/config.libs.sh
+++ b/qb/config.libs.sh
@@ -451,13 +451,23 @@ if [ "$HAVE_MATERIALUI" != 'no' ] || [ "$HAVE_XMB" != 'no' ] || [ "$HAVE_ZARCH"
 	if [ "$HAVE_RGUI" = 'no' ]; then
 		HAVE_MATERIALUI=no
 		HAVE_XMB=no
-      HAVE_ZARCH=no
+    HAVE_ZARCH=no
 		echo "Notice: RGUI not available, MaterialUI, XMB and ZARCH will also be disabled."
 	elif [ "$HAVE_OPENGL" = 'no' ] && [ "$HAVE_OPENGLES" = 'no' ] && [ "$HAVE_VULKAN" = 'no' ]; then
-		HAVE_MATERIALUI=no
-		HAVE_XMB=no
-      HAVE_ZARCH=no
-		echo "Notice: Hardware rendering context not available, XMB, MaterialUI and ZARCH will also be disabled."
+    if [ "$OS" = 'Win32' ]; then
+      HAVE_SHADERPIPELINE=no
+      HAVE_VULKAN=no
+		  echo "Notice: Hardware rendering context not available."
+    else
+      if [ "$HAVE_CACA" = 'yes' ]; then
+		    echo "Notice: Hardware rendering context not available."
+      else
+    		HAVE_MATERIALUI=no
+	    	HAVE_XMB=no
+        HAVE_ZARCH=no
+		    echo "Notice: Hardware rendering context not available, XMB, MaterialUI and ZARCH will also be disabled."
+      fi
+    fi
 	fi
 fi
 
diff --git a/qb/qb.params.sh b/qb/qb.params.sh
index 3964fe26fb..4b822298a8 100644
--- a/qb/qb.params.sh
+++ b/qb/qb.params.sh
@@ -72,6 +72,7 @@ parse_input() # Parse stuff :V
 			--disable-*)
 				opt_exists "${1##--disable-}" "$1"
 				eval "HAVE_$opt=no"
+				eval "HAVE_NO_$opt=yes"
 			;;
 			--with-*)
 				arg="${1##--with-}"
diff --git a/retroarch.c b/retroarch.c
index 2fe95be733..9da45ef39e 100644
--- a/retroarch.c
+++ b/retroarch.c
@@ -1074,7 +1074,7 @@ bool retroarch_main_init(int argc, char *argv[])
       }
    }
 
-   driver_ctl(RARCH_DRIVER_CTL_INIT_ALL, NULL);
+   drivers_init(DRIVERS_CMD_ALL);
    command_event(CMD_EVENT_COMMAND_INIT, NULL);
    command_event(CMD_EVENT_REMOTE_INIT, NULL);
    command_event(CMD_EVENT_REWIND_INIT, NULL);
diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m
index f22d355be4..f86ceca170 100644
--- a/ui/drivers/ui_cocoa.m
+++ b/ui/drivers/ui_cocoa.m
@@ -109,9 +109,10 @@ static void app_terminate(void)
         case NSFlagsChanged:
          {
             static uint32_t old_flags = 0;
-            uint32_t new_flags = event.modifierFlags;
-            bool down = (new_flags & old_flags) == old_flags;
-            old_flags = new_flags;
+            uint32_t new_flags        = event.modifierFlags;
+            bool down                 = (new_flags & old_flags) == old_flags;
+
+            old_flags                 = new_flags;
 
             apple_input_keyboard_event(down, event.keyCode,
                   0, event.modifierFlags, RETRO_DEVICE_KEYBOARD);
@@ -148,27 +149,27 @@ static void app_terminate(void)
         case NSLeftMouseDown:
         case NSRightMouseDown:
         case NSOtherMouseDown:
-       {
-           NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil];
-         apple = (cocoa_input_data_t*)input_driver_get_data();
-         if (!apple || pos.y < 0)
-            return;
-         apple->mouse_buttons |= 1 << event.buttonNumber;
-        
-           apple->touch_count = 1;
-       }
+         {
+            NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil];
+            apple = (cocoa_input_data_t*)input_driver_get_data();
+            if (!apple || pos.y < 0)
+               return;
+            apple->mouse_buttons |= 1 << event.buttonNumber;
+
+            apple->touch_count = 1;
+         }
          break;
       case NSLeftMouseUp:
       case NSRightMouseUp:
       case NSOtherMouseUp:
-       {
-         NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil];
-         apple = (cocoa_input_data_t*)input_driver_get_data();
-         if (!apple || pos.y < 0)
-            return;
-         apple->mouse_buttons &= ~(1 << event.buttonNumber);
-         apple->touch_count = 0;
-       }
+         {
+            NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil];
+            apple = (cocoa_input_data_t*)input_driver_get_data();
+            if (!apple || pos.y < 0)
+               return;
+            apple->mouse_buttons &= ~(1 << event.buttonNumber);
+            apple->touch_count = 0;
+         }
          break;
    }
 }
diff --git a/ui/drivers/ui_win32.c b/ui/drivers/ui_win32.c
index b11764bd19..8194e30433 100644
--- a/ui/drivers/ui_win32.c
+++ b/ui/drivers/ui_win32.c
@@ -41,6 +41,7 @@
 #include <retro_inline.h>
 #include <retro_miscellaneous.h>
 #include <file/file_path.h>
+#include <string/stdstring.h>
 #include <compat/strl.h>
 
 #include "../ui_companion_driver.h"
@@ -115,32 +116,28 @@ typedef struct
 
 static shader_dlg_t g_shader_dlg = {{0}};
 
-static void shader_dlg_refresh_trackbar_label(int index)
+static bool shader_dlg_refresh_trackbar_label(int index, 
+      video_shader_ctx_t *shader_info)
 {
-   video_shader_ctx_t shader_info;
    char val_buffer[32]         = {0};
 
-   video_shader_driver_get_current_shader(&shader_info);
-
-   if (floorf(shader_info.data->parameters[index].current) 
-         == shader_info.data->parameters[index].current)
+   if (floorf(shader_info->data->parameters[index].current) 
+         == shader_info->data->parameters[index].current)
       snprintf(val_buffer, sizeof(val_buffer), "%.0f",
-            shader_info.data->parameters[index].current);
+            shader_info->data->parameters[index].current);
    else
       snprintf(val_buffer, sizeof(val_buffer), "%.2f",
-            shader_info.data->parameters[index].current);
+            shader_info->data->parameters[index].current);
 
    SendMessage(g_shader_dlg.controls[index].trackbar.label_val,
          WM_SETTEXT, 0, (LPARAM)val_buffer);
 
+   return true;
 }
 
 static void shader_dlg_params_refresh(void)
 {
    int i;
-   video_shader_ctx_t shader_info;
-
-   video_shader_driver_get_current_shader(&shader_info);
 
    for (i = 0; i < GFX_MAX_PARAMETERS; i++)
    {
@@ -153,26 +150,37 @@ static void shader_dlg_params_refresh(void)
       {
          case SHADER_PARAM_CTRL_CHECKBOX:
             {
-               bool checked = 
+               video_shader_ctx_t shader_info;
+               video_shader_driver_get_current_shader(&shader_info);
+
+               bool checked = shader_info.data ?
                   (shader_info.data->parameters[i].current == 
-                   shader_info.data->parameters[i].maximum);
+                   shader_info.data->parameters[i].maximum) : false;
                SendMessage(control->checkbox.hwnd, BM_SETCHECK, checked, 0);
             }
             break;
          case SHADER_PARAM_CTRL_TRACKBAR:
-            shader_dlg_refresh_trackbar_label(i);
+            {
+               video_shader_ctx_t shader_info;
+               video_shader_driver_get_current_shader(&shader_info);
+               if (shader_info.data && !shader_dlg_refresh_trackbar_label(i, &shader_info))
+                  break;
 
-            SendMessage(control->trackbar.hwnd,
-                  TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0);
-            SendMessage(control->trackbar.hwnd,
-                  TBM_SETRANGEMAX, (WPARAM)TRUE,
-                  (LPARAM)((shader_info.data->parameters[i].maximum - 
-                        shader_info.data->parameters[i].minimum) 
-                     / shader_info.data->parameters[i].step));
-            SendMessage(control->trackbar.hwnd, TBM_SETPOS, (WPARAM)TRUE,
-                  (LPARAM)((shader_info.data->parameters[i].current - 
-                        shader_info.data->parameters[i].minimum) / 
-                     shader_info.data->parameters[i].step));
+               if (shader_info.data)
+               {
+                  SendMessage(control->trackbar.hwnd,
+                        TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0);
+                  SendMessage(control->trackbar.hwnd,
+                        TBM_SETRANGEMAX, (WPARAM)TRUE,
+                        (LPARAM)((shader_info.data->parameters[i].maximum - 
+                              shader_info.data->parameters[i].minimum) 
+                           / shader_info.data->parameters[i].step));
+                  SendMessage(control->trackbar.hwnd, TBM_SETPOS, (WPARAM)TRUE,
+                        (LPARAM)((shader_info.data->parameters[i].current - 
+                              shader_info.data->parameters[i].minimum) / 
+                           shader_info.data->parameters[i].step));
+               }
+            }
             break;
          case SHADER_PARAM_CTRL_NONE:
          default:
@@ -187,10 +195,9 @@ static void shader_dlg_params_clear(void)
 
    for (i = 0; i < GFX_MAX_PARAMETERS; i++)
    {
-      const ui_window_t *window = ui_companion_driver_get_window_ptr();
       shader_param_ctrl_t*control = &g_shader_dlg.controls[i];
 
-      if (control->type == SHADER_PARAM_CTRL_NONE)
+      if (!control || control->type == SHADER_PARAM_CTRL_NONE)
          break;
 
       switch (control->type)
@@ -198,8 +205,11 @@ static void shader_dlg_params_clear(void)
          case SHADER_PARAM_CTRL_NONE:
             break;
          case SHADER_PARAM_CTRL_CHECKBOX:
-            if (window)
-               window->destroy(&control->checkbox);
+            {
+               const ui_window_t *window = ui_companion_driver_get_window_ptr();
+               if (window)
+                  window->destroy(&control->checkbox);
+            }
             break;
          case SHADER_PARAM_CTRL_TRACKBAR:
             DestroyWindow(control->trackbar.label_title);
@@ -214,23 +224,24 @@ static void shader_dlg_params_clear(void)
 
 void shader_dlg_params_reload(void)
 {
+#ifdef HAVE_SHADERPIPELINE
    HFONT hFont;
    RECT parent_rect;
    int i, pos_x, pos_y;
    video_shader_ctx_t shader_info;
-   const ui_window_t *window = ui_companion_driver_get_window_ptr();
-   video_shader_driver_get_current_shader(&shader_info);
-
+   const ui_window_t *window = NULL;
+   
    shader_dlg_params_clear();
 
-   if (!shader_info.data)
-      return;
-   if (shader_info.data->num_parameters > GFX_MAX_PARAMETERS)
+   video_shader_driver_get_current_shader(&shader_info);
+
+   if (!shader_info.data || shader_info.data->num_parameters > GFX_MAX_PARAMETERS)
       return;
 
-   hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
-   pos_y = g_shader_dlg.parameters_start_y;
-   pos_x = SHADER_DLG_CTRL_X;
+   window = ui_companion_driver_get_window_ptr();
+   hFont  = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+   pos_y  = g_shader_dlg.parameters_start_y;
+   pos_x  = SHADER_DLG_CTRL_X;
 
    for (i = 0; i < (int)shader_info.data->num_parameters; i++)
    {
@@ -315,7 +326,7 @@ void shader_dlg_params_reload(void)
          (pos_x - SHADER_DLG_CTRL_X) + SHADER_DLG_WIDTH,
          (pos_x == SHADER_DLG_CTRL_X) ? pos_y + 30 : SHADER_DLG_MAX_HEIGHT,
          SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
-
+#endif
 }
 
 static void shader_dlg_update_on_top_state(void)
@@ -354,15 +365,13 @@ void shader_dlg_show(HWND parent_hwnd)
    window->set_focused(&g_shader_dlg.window);
 }
 
+#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
 static LRESULT CALLBACK ShaderDlgWndProc(HWND hwnd, UINT message,
       WPARAM wparam, LPARAM lparam)
 {
    int i, pos;
-   video_shader_ctx_t shader_info;
    const ui_window_t *window = ui_companion_driver_get_window_ptr();
 
-   video_shader_driver_get_current_shader(&shader_info);
-
    switch (message)
    {
       case WM_CREATE:
@@ -390,36 +399,50 @@ static LRESULT CALLBACK ShaderDlgWndProc(HWND hwnd, UINT message,
          if (g_shader_dlg.controls[i].type != SHADER_PARAM_CTRL_CHECKBOX)
             break;
 
-         if (SendMessage(g_shader_dlg.controls[i].checkbox.hwnd,
-                  BM_GETCHECK, 0, 0) == BST_CHECKED)
-            shader_info.data->parameters[i].current = 
-               shader_info.data->parameters[i].maximum;
-         else
-            shader_info.data->parameters[i].current = 
-               shader_info.data->parameters[i].minimum;
+         {
+            video_shader_ctx_t shader_info;
+            video_shader_driver_get_current_shader(&shader_info);
 
+            if (SendMessage(g_shader_dlg.controls[i].checkbox.hwnd,
+                     BM_GETCHECK, 0, 0) == BST_CHECKED)
+               shader_info.data->parameters[i].current = 
+                  shader_info.data->parameters[i].maximum;
+            else
+               shader_info.data->parameters[i].current = 
+                  shader_info.data->parameters[i].minimum;
+         }
          break;
 
       case WM_HSCROLL:
-         i = GetWindowLong((HWND)lparam, GWL_ID);
+         {
+            video_shader_ctx_t shader_info;
+            video_shader_driver_get_current_shader(&shader_info);
+            i = GetWindowLong((HWND)lparam, GWL_ID);
 
-         if (i >= GFX_MAX_PARAMETERS)
-            break;
+            if (i >= GFX_MAX_PARAMETERS)
+               break;
 
-         if (g_shader_dlg.controls[i].type != SHADER_PARAM_CTRL_TRACKBAR)
-            break;
+            if (g_shader_dlg.controls[i].type != SHADER_PARAM_CTRL_TRACKBAR)
+               break;
 
-         pos = (int)SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_GETPOS, 0, 0);
-         shader_info.data->parameters[i].current = 
-            shader_info.data->parameters[i].minimum + pos * shader_info.data->parameters[i].step;
+            pos = (int)SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_GETPOS, 0, 0);
 
-         shader_dlg_refresh_trackbar_label(i);
+            {
+
+               shader_info.data->parameters[i].current = 
+                  shader_info.data->parameters[i].minimum + pos * shader_info.data->parameters[i].step;
+            }
+
+            if (shader_info.data)
+               shader_dlg_refresh_trackbar_label(i, &shader_info);
+         }
          break;
 
    }
 
    return DefWindowProc(hwnd, message, wparam, lparam);
 }
+#endif
 
 bool win32_window_init(WNDCLASSEX *wndclass,
       bool fullscreen, const char *class_name)
@@ -447,13 +470,15 @@ bool win32_window_init(WNDCLASSEX *wndclass,
    if (class_name != NULL) 
       return true;
 
+   /* Shader dialog is disabled for now, until video_threaded issues are fixed.
    if (!win32_shader_dlg_init())
-      RARCH_ERR("[WGL]: wgl_shader_dlg_init() failed.\n");
+      RARCH_ERR("[WGL]: wgl_shader_dlg_init() failed.\n");*/
    return true;
 }
 
 bool win32_shader_dlg_init(void)
 {
+#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
    static bool inited = false;
    int pos_y;
    HFONT hFont;
@@ -501,7 +526,7 @@ bool win32_shader_dlg_init(void)
    pos_y +=  SHADER_DLG_SEPARATOR_HEIGHT + SHADER_DLG_CTRL_MARGIN;
 
    g_shader_dlg.parameters_start_y = pos_y;
-
+#endif
    return true;
 }
 
@@ -530,7 +555,7 @@ static bool win32_browser(
       new_title[0] = '\0';
       new_file[0] = '\0';
 
-      if (title && *title)
+      if (!string_is_empty(title))
          strlcpy(new_title, title, sizeof(new_title));
 
       if (filename && *filename)
@@ -589,7 +614,12 @@ LRESULT win32_menu_loop(HWND owner, WPARAM wparam)
              * This is needed for proper multi-byte string display until Unicode is fully supported.
              */
             MultiByteToWideChar(CP_UTF8, 0, title, -1, title_wide, sizeof(title_wide) / sizeof(title_wide[0]));
+#if !defined(_MSC_VER) && (_WIN32_WINNT > _WIN32_WINNT_WINXP)
+            /* MinGW does not define wcstombs_s for XP, but MSVC does */
             wcstombs_s(&converted, title_cp, sizeof(title_cp), title_wide, sizeof(title_cp) - 1);
+#else
+            wcstombs(title_cp, title_wide, sizeof(title_cp) - 1);
+#endif
 
             if (!win32_browser(owner, win32_file,
                      extensions, title_cp, initial_dir))
diff --git a/wiiu/padscore.h b/wiiu/padscore.h
new file mode 100644
index 0000000000..962dff02d4
--- /dev/null
+++ b/wiiu/padscore.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+ * Copyright (C) 2015
+ * by Dimok
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose, including commercial applications, and to alter it and
+ * redistribute it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you use
+ * this software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and
+ * must not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ ***************************************************************************/
+#ifndef __PAD_SCORE_FUNCTIONS_H_
+#define __PAD_SCORE_FUNCTIONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <wut_types.h>
+
+#define WPAD_BUTTON_LEFT                    0x0001
+#define WPAD_BUTTON_RIGHT                   0x0002
+#define WPAD_BUTTON_DOWN                    0x0004
+#define WPAD_BUTTON_UP                      0x0008
+#define WPAD_BUTTON_PLUS                    0x0010
+#define WPAD_BUTTON_2                       0x0100
+#define WPAD_BUTTON_1                       0x0200
+#define WPAD_BUTTON_B                       0x0400
+#define WPAD_BUTTON_A                       0x0800
+#define WPAD_BUTTON_MINUS                   0x1000
+#define WPAD_BUTTON_Z                       0x2000
+#define WPAD_BUTTON_C                       0x4000
+#define WPAD_BUTTON_HOME                    0x8000
+
+#define WPAD_CLASSIC_BUTTON_UP              0x0001
+#define WPAD_CLASSIC_BUTTON_LEFT            0x0002
+#define WPAD_CLASSIC_BUTTON_ZR              0x0004
+#define WPAD_CLASSIC_BUTTON_X               0x0008
+#define WPAD_CLASSIC_BUTTON_A               0x0010
+#define WPAD_CLASSIC_BUTTON_Y               0x0020
+#define WPAD_CLASSIC_BUTTON_B               0x0040
+#define WPAD_CLASSIC_BUTTON_ZL              0x0080
+#define WPAD_CLASSIC_BUTTON_R               0x0200
+#define WPAD_CLASSIC_BUTTON_PLUS            0x0400
+#define WPAD_CLASSIC_BUTTON_HOME            0x0800
+#define WPAD_CLASSIC_BUTTON_MINUS           0x1000
+#define WPAD_CLASSIC_BUTTON_L               0x2000
+#define WPAD_CLASSIC_BUTTON_DOWN            0x4000
+#define WPAD_CLASSIC_BUTTON_RIGHT           0x8000
+
+#define WPAD_PRO_BUTTON_STICK_R             0x10000
+#define WPAD_PRO_BUTTON_STICK_L             0x20000
+
+void InitPadScoreFunctionPointers(void);
+
+
+typedef struct _KPADData
+{
+    u32 btns_h;
+    u32 btns_d;
+    u32 btns_r;
+    u32 unused_1[5];
+    f32 pos_x;
+    f32 pos_y;
+    u32 unused_2[3];
+    f32 angle_x;
+    f32 angle_y;
+    u32 unused_3[8];
+    u8 device_type;
+    u8 wpad_error;
+    u8 pos_valid;
+    u8 unused_4[1];
+
+    union
+    {
+        struct
+        {
+            f32 stick_x;
+            f32 stick_y;
+        } nunchuck;
+
+        struct
+        {
+            u32 btns_h;
+            u32 btns_d;
+            u32 btns_r;
+            f32 lstick_x;
+            f32 lstick_y;
+            f32 rstick_x;
+            f32 rstick_y;
+            f32 ltrigger;
+            f32 rtrigger;
+        } classic;
+
+        u32 unused_6[20];
+    };
+    u32 unused_7[16];
+} KPADData;
+
+typedef void (* wpad_connect_callback_t)(s32 chan, s32 status);
+
+void KPADInit (void);
+s32 WPADProbe (s32 chan, u32 * pad_type);
+s32 WPADSetDataFormat(s32 chan, s32 format);
+void WPADEnableURCC(s32 enable);
+void WPADEnableWiiRemote(s32 enable);
+void WPADRead(s32 chan, void * data);
+s32 KPADRead(s32 chan, void * data, u32 size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __PAD_SCORE_FUNCTIONS_H_
diff --git a/wiiu/system/imports.h b/wiiu/system/imports.h
index 144d4518fb..b6f6a9d8b1 100644
--- a/wiiu/system/imports.h
+++ b/wiiu/system/imports.h
@@ -178,3 +178,17 @@ IMPORT(VPADRead);
 IMPORT(VPADInit);
 
 IMPORT_END();
+
+/* padscore */
+IMPORT_BEGIN(padscore);
+
+IMPORT(KPADInit);
+IMPORT(WPADProbe);
+IMPORT(WPADSetDataFormat);
+IMPORT(WPADEnableURCC);
+IMPORT(WPADEnableWiiRemote);
+IMPORT(WPADRead);
+IMPORT(KPADRead);
+
+IMPORT_END();
+