]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - vid_wgl.c
Remove the last remnants of DPSOFTRAST support in vid_glx.c.
[xonotic/darkplaces.git] / vid_wgl.c
index 4405533d6312422beed076fcccde81668b7a7d6e..fa0091dcb4ed10b5d2cde13c9908dcf04236e8a7 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -19,10 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 // vid_wgl.c -- NT GL vid component
 
+#ifdef _MSC_VER
+#pragma comment(lib, "comctl32.lib")
+#endif
+
 #ifdef SUPPORTDIRECTX
 // Include DX libs
+#ifdef _MSC_VER
 #pragma comment(lib, "dinput8.lib")
 #pragma comment(lib, "dxguid.lib")
+#endif
 #ifndef DIRECTINPUT_VERSION
 #      define DIRECTINPUT_VERSION 0x0500  /* Version 5.0 */
 #endif
@@ -42,6 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 extern HINSTANCE global_hInstance;
 
+static HINSTANCE gldll;
 
 #ifndef WM_MOUSEWHEEL
 #define WM_MOUSEWHEEL                   0x020A
@@ -98,6 +105,7 @@ static dllfunction_t wglpixelformatfuncs[] =
 };
 
 static DEVMODE gdevmode, initialdevmode;
+static vid_mode_t desktop_mode;
 static qboolean vid_initialized = false;
 static qboolean vid_wassuspended = false;
 static qboolean vid_usingmouse = false;
@@ -119,10 +127,11 @@ static qboolean vid_isfullscreen;
 //void VID_MenuDraw (void);
 //void VID_MenuKey (int key);
 
-//LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-//void AppActivate(BOOL fActive, BOOL minimize);
-//void ClearAllStates (void);
-//void VID_UpdateWindowStatus (void);
+LONG WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void AppActivate(BOOL fActive, BOOL minimize);
+static void ClearAllStates(void);
+qboolean VID_InitModeGL(viddef_mode_t *mode);
+qboolean VID_InitModeSOFT(viddef_mode_t *mode);
 
 //====================================
 
@@ -171,100 +180,43 @@ static qboolean  dinput_acquired;
 static unsigned int            mstate_di;
 #endif
 
-// joystick defines and variables
-// where should defines be moved?
-#define JOY_ABSOLUTE_AXIS      0x00000000              // control like a joystick
-#define JOY_RELATIVE_AXIS      0x00000010              // control like a mouse, spinner, trackball
-#define        JOY_MAX_AXES            6                               // X, Y, Z, R, U, V
-#define JOY_AXIS_X                     0
-#define JOY_AXIS_Y                     1
-#define JOY_AXIS_Z                     2
-#define JOY_AXIS_R                     3
-#define JOY_AXIS_U                     4
-#define JOY_AXIS_V                     5
-
-enum _ControlList
-{
-       AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
-};
-
-static DWORD   dwAxisFlags[JOY_MAX_AXES] =
-{
-       JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
-};
-
-static DWORD   dwAxisMap[JOY_MAX_AXES];
-static DWORD   dwControlMap[JOY_MAX_AXES];
-static PDWORD  pdwRawValue[JOY_MAX_AXES];
-
-// none of these cvars are saved over a session
-// this means that advanced controller configuration needs to be executed
-// each time.  this avoids any problems with getting back to a default usage
-// or when changing from one controller to another.  this way at least something
-// works.
-static cvar_t in_joystick = {CVAR_SAVE, "joystick","0", "enables joysticks"};
-static cvar_t joy_name = {0, "joyname", "joystick", "name of joystick to use (informational only, used only by joyadvanced 1 mode)"};
-static cvar_t joy_advanced = {0, "joyadvanced", "0", "use more than 2 axis joysticks (configuring this is very technical)"};
-static cvar_t joy_advaxisx = {0, "joyadvaxisx", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisy = {0, "joyadvaxisy", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisz = {0, "joyadvaxisz", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisr = {0, "joyadvaxisr", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisu = {0, "joyadvaxisu", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_advaxisv = {0, "joyadvaxisv", "0", "axis mapping for joyadvanced 1 mode"};
-static cvar_t joy_forwardthreshold = {0, "joyforwardthreshold", "0.15", "minimum joystick movement necessary to move forward"};
-static cvar_t joy_sidethreshold = {0, "joysidethreshold", "0.15", "minimum joystick movement necessary to move sideways (strafing)"};
-static cvar_t joy_pitchthreshold = {0, "joypitchthreshold", "0.15", "minimum joystick movement necessary to look up/down"};
-static cvar_t joy_yawthreshold = {0, "joyyawthreshold", "0.15", "minimum joystick movement necessary to turn left/right"};
-static cvar_t joy_forwardsensitivity = {0, "joyforwardsensitivity", "-1.0", "how fast the joystick moves forward"};
-static cvar_t joy_sidesensitivity = {0, "joysidesensitivity", "-1.0", "how fast the joystick moves sideways (strafing)"};
-static cvar_t joy_pitchsensitivity = {0, "joypitchsensitivity", "1.0", "how fast the joystick looks up/down"};
-static cvar_t joy_yawsensitivity = {0, "joyyawsensitivity", "-1.0", "how fast the joystick turns left/right"};
-static cvar_t joy_wwhack1 = {0, "joywwhack1", "0.0", "special hack for wingman warrior"};
-static cvar_t joy_wwhack2 = {0, "joywwhack2", "0.0", "special hack for wingman warrior"};
-
 static cvar_t vid_forcerefreshrate = {0, "vid_forcerefreshrate", "0", "try to set the given vid_refreshrate even if Windows doesn't list it as valid video mode"};
 
-static qboolean        joy_avail, joy_advancedinit, joy_haspov;
-static DWORD           joy_oldbuttonstate, joy_oldpovstate;
-
-static int                     joy_id;
-static DWORD           joy_flags;
-static DWORD           joy_numbuttons;
-
 #ifdef SUPPORTDIRECTX
 static LPDIRECTINPUT           g_pdi;
 static LPDIRECTINPUTDEVICE     g_pMouse;
 static HINSTANCE hInstDI;
 #endif
 
-static JOYINFOEX       ji;
-
 // forward-referenced functions
-static void IN_StartupJoystick (void);
-static void Joy_AdvancedUpdate_f (void);
-static void IN_JoyMove (void);
 static void IN_StartupMouse (void);
-
+static void AdjustWindowBounds(int fullscreen, int *width, int *height, viddef_mode_t *mode, DWORD WindowStyle, RECT *rect);
 
 //====================================
 
+qboolean vid_reallyhidden = true;
 void VID_Finish (void)
 {
-       vid_usevsync = vid_vsync.integer && !cls.timedemo && gl_videosyncavailable;
-       if (vid_usingvsync != vid_usevsync && gl_videosyncavailable)
-       {
-               vid_usingvsync = vid_usevsync;
-               qwglSwapIntervalEXT (vid_usevsync);
-       }
+       vid_hidden = vid_reallyhidden;
+
+       vid_usevsync = vid_vsync.integer && !cls.timedemo && qwglSwapIntervalEXT;
 
        if (!vid_hidden)
        {
-               CHECKGLERROR
-               if (r_speeds.integer == 2 || gl_finish.integer)
+               switch(vid.renderpath)
                {
-                       qglFinish();CHECKGLERROR
+               case RENDERPATH_GL20:
+               case RENDERPATH_GLES2:
+                       if (vid_usingvsync != vid_usevsync)
+                       {
+                               vid_usingvsync = vid_usevsync;
+                               qwglSwapIntervalEXT (vid_usevsync);
+                       }
+                       if (r_speeds.integer == 2 || gl_finish.integer)
+                               GL_Finish();
+                       SwapBuffers(baseDC);
+                       break;
                }
-               SwapBuffers(baseDC);
        }
 
        // make sure a context switch can happen every frame - Logitech drivers
@@ -272,25 +224,23 @@ void VID_Finish (void)
        // without this help
        Sleep(0);
 
-       VID_UpdateGamma(false, 256);
+       VID_UpdateGamma();
 }
 
 //==========================================================================
 
 
-
-
 static unsigned char scantokey[128] =
 {
-//  0           1       2    3     4     5       6       7      8         9      A          B           C       D           E           F
-       0          ,27    ,'1'  ,'2'  ,'3'  ,'4'    ,'5'    ,'6'   ,'7'      ,'8'   ,'9'       ,'0'        ,'-'   ,'='         ,K_BACKSPACE,9    ,//0
-       'q'        ,'w'   ,'e'  ,'r'  ,'t'  ,'y'    ,'u'    ,'i'   ,'o'      ,'p'   ,'['       ,']'        ,13    ,K_CTRL      ,'a'        ,'s'  ,//1
-       'd'        ,'f'   ,'g'  ,'h'  ,'j'  ,'k'    ,'l'    ,';'   ,'\''     ,'`'   ,K_SHIFT   ,'\\'       ,'z'   ,'x'         ,'c'        ,'v'  ,//2
-       'b'        ,'n'   ,'m'  ,','  ,'.'  ,'/'    ,K_SHIFT,'*'   ,K_ALT    ,' '   ,0         ,K_F1       ,K_F2  ,K_F3        ,K_F4       ,K_F5 ,//3
-       K_F6       ,K_F7  ,K_F8 ,K_F9 ,K_F10,K_PAUSE,0      ,K_HOME,K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS  ,K_END,//4
-       K_DOWNARROW,K_PGDN,K_INS,K_DEL,0    ,0      ,0      ,K_F11 ,K_F12    ,0     ,0         ,0          ,0     ,0           ,0          ,0    ,//5
-       0          ,0     ,0    ,0    ,0    ,0      ,0      ,0     ,0        ,0     ,0         ,0          ,0     ,0           ,0          ,0    ,//6
-       0          ,0     ,0    ,0    ,0    ,0      ,0      ,0     ,0        ,0     ,0         ,0          ,0     ,0           ,0          ,0     //7
+//  0           1        2     3     4     5       6           7      8         9      A          B           C       D            E           F
+       0          ,K_ESCAPE,'1'  ,'2'  ,'3'  ,'4'    ,'5'        ,'6'   ,'7'      ,'8'   ,'9'       ,'0'        ,'-'    ,'='         ,K_BACKSPACE,K_TAB,//0
+       'q'        ,'w'     ,'e'  ,'r'  ,'t'  ,'y'    ,'u'        ,'i'   ,'o'      ,'p'   ,'['       ,']'        ,K_ENTER,K_CTRL      ,'a'        ,'s'  ,//1
+       'd'        ,'f'     ,'g'  ,'h'  ,'j'  ,'k'    ,'l'        ,';'   ,'\''     ,'`'   ,K_SHIFT   ,'\\'       ,'z'    ,'x'         ,'c'        ,'v'  ,//2
+       'b'        ,'n'     ,'m'  ,','  ,'.'  ,'/'    ,K_SHIFT    ,'*'   ,K_ALT    ,' '   ,K_CAPSLOCK,K_F1       ,K_F2   ,K_F3        ,K_F4       ,K_F5 ,//3
+       K_F6       ,K_F7    ,K_F8 ,K_F9 ,K_F10,K_PAUSE,K_SCROLLOCK,K_HOME,K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5 ,K_RIGHTARROW,K_KP_PLUS  ,K_END,//4
+       K_DOWNARROW,K_PGDN  ,K_INS,K_DEL,0    ,0      ,0          ,K_F11 ,K_F12    ,0     ,0         ,0          ,0      ,0           ,0          ,0    ,//5
+       0          ,0       ,0    ,0    ,0    ,0      ,0          ,0     ,0        ,0     ,0         ,0          ,0      ,0           ,0          ,0    ,//6
+       0          ,0       ,0    ,0    ,0    ,0      ,0          ,0     ,0        ,0     ,0         ,0          ,0      ,0           ,0          ,0     //7
 };
 
 
@@ -320,6 +270,9 @@ static int MapKey (int key, int virtualkey)
 
        if ( !is_extended )
        {
+               if(((GetKeyState(VK_NUMLOCK)) & 0xffff) == 0)
+                       return result;
+
                switch ( result )
                {
                case K_HOME:
@@ -348,6 +301,9 @@ static int MapKey (int key, int virtualkey)
        }
        else
        {
+               if(virtualkey == VK_NUMLOCK)
+                       return K_NUMLOCK;
+
                switch ( result )
                {
                case 0x0D:
@@ -376,7 +332,7 @@ ClearAllStates
 */
 static void ClearAllStates (void)
 {
-       Key_ClearStates ();
+       Key_ReleaseAll();
        if (vid_usingmouse)
                mouse_oldbuttonstate = 0;
 }
@@ -396,10 +352,10 @@ void AppActivate(BOOL fActive, BOOL minimize)
        static qboolean sound_active = false;  // initially blocked by Sys_InitConsole()
 
        vid_activewindow = fActive != FALSE;
-       vid_hidden = minimize != FALSE;
+       vid_reallyhidden = minimize != FALSE;
 
        // enable/disable sound on focus gain/loss
-       if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
+       if ((!vid_reallyhidden && vid_activewindow) || !snd_mutewhenidle.integer)
        {
                if (!sound_active)
                {
@@ -423,12 +379,16 @@ void AppActivate(BOOL fActive, BOOL minimize)
                        if (vid_wassuspended)
                        {
                                vid_wassuspended = false;
-                               ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
-                               ShowWindow(mainwindow, SW_SHOWNORMAL);
+                               if (gldll)
+                               {
+                                       ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
+                                       ShowWindow(mainwindow, SW_SHOWNORMAL);
+                               }
                        }
 
                        // LordHavoc: from dabb, fix for alt-tab bug in NVidia drivers
-                       MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false);
+                       if (gldll)
+                               MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false);
                }
        }
 
@@ -437,10 +397,10 @@ void AppActivate(BOOL fActive, BOOL minimize)
                VID_SetMouse(false, false, false);
                if (vid_isfullscreen)
                {
-                       ChangeDisplaySettings (NULL, 0);
+                       if (gldll)
+                               ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
                        vid_wassuspended = true;
                }
-               VID_RestoreSystemGamma();
        }
 }
 
@@ -459,7 +419,9 @@ void Sys_SendKeyEvents (void)
        }
 }
 
+#ifdef CONFIG_CD
 LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+#endif
 
 static keynum_t buttonremap[16] =
 {
@@ -487,7 +449,8 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
        LONG    lRet = 1;
        int             fActive, fMinimized, temp;
        unsigned char state[256];
-       unsigned char asciichar[4];
+       const unsigned int UNICODE_BUFFER_LENGTH = 4;
+       WCHAR unicode[UNICODE_BUFFER_LENGTH];
        int             vkey;
        int             charlength;
        qboolean down = false;
@@ -506,8 +469,8 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
                        break;
 
                case WM_MOVE:
-                       window_x = (int) LOWORD(lParam);
-                       window_y = (int) HIWORD(lParam);
+                       window_x = (short) LOWORD(lParam);
+                       window_y = (short) HIWORD(lParam);
                        VID_SetMouse(false, false, false);
                        break;
 
@@ -520,13 +483,13 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
                        GetKeyboardState (state);
                        // alt/ctrl/shift tend to produce funky ToAscii values,
                        // and if it's not a single character we don't know care about it
-                       charlength = ToAscii (wParam, lParam >> 16, state, (LPWORD)asciichar, 0);
-                       if (vkey == K_ALT || vkey == K_CTRL || vkey == K_SHIFT || charlength == 0)
-                               asciichar[0] = 0;
-                       else if( charlength == 2 ) {
-                               asciichar[0] = asciichar[1];
-                       }
-                       Key_Event (vkey, asciichar[0], down);
+                       charlength = ToUnicode(wParam, lParam >> 16, state, unicode, UNICODE_BUFFER_LENGTH, 0);
+                       if(vkey == K_ALT || vkey == K_CTRL || vkey == K_SHIFT || charlength == 0)
+                               unicode[0] = 0;
+                       else if(charlength == 2)
+                               unicode[0] = unicode[1];
+                       if (!VID_JoyBlockEmulatedKeys(vkey))
+                               Key_Event(vkey, unicode[0], down);
                        break;
 
                case WM_SYSCHAR:
@@ -635,7 +598,9 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
                //      break;
 
                case MM_MCINOTIFY:
+#ifdef CONFIG_CD
                        lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
+#endif
                        break;
 
                default:
@@ -648,33 +613,18 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
        return lRet;
 }
 
-int VID_SetGamma(unsigned short *ramps, int rampsize)
-{
-       HDC hdc = GetDC (NULL);
-       int i = SetDeviceGammaRamp(hdc, ramps);
-       ReleaseDC (NULL, hdc);
-       return i; // return success or failure
-}
-
-int VID_GetGamma(unsigned short *ramps, int rampsize)
-{
-       HDC hdc = GetDC (NULL);
-       int i = GetDeviceGammaRamp(hdc, ramps);
-       ReleaseDC (NULL, hdc);
-       return i; // return success or failure
-}
-
-static HINSTANCE gldll;
-
 static void GL_CloseLibrary(void)
 {
-       FreeLibrary(gldll);
-       gldll = 0;
-       gl_driver[0] = 0;
-       qwglGetProcAddress = NULL;
-       gl_extensions = "";
-       gl_platform = "";
-       gl_platformextensions = "";
+       if (gldll)
+       {
+               FreeLibrary(gldll);
+               gldll = 0;
+               gl_driver[0] = 0;
+               qwglGetProcAddress = NULL;
+               gl_extensions = "";
+               gl_platform = "";
+               gl_platformextensions = "";
+       }
 }
 
 static int GL_OpenLibrary(const char *name)
@@ -692,12 +642,17 @@ static int GL_OpenLibrary(const char *name)
 
 void *GL_GetProcAddress(const char *name)
 {
-       void *p = NULL;
-       if (qwglGetProcAddress != NULL)
-               p = (void *) qwglGetProcAddress(name);
-       if (p == NULL)
-               p = (void *) GetProcAddress(gldll, name);
-       return p;
+       if (gldll)
+       {
+               void *p = NULL;
+               if (qwglGetProcAddress != NULL)
+                       p = (void *) qwglGetProcAddress(name);
+               if (p == NULL)
+                       p = (void *) GetProcAddress(gldll, name);
+               return p;
+       }
+       else
+               return NULL;
 }
 
 #ifndef WGL_ARB_pixel_format
@@ -784,10 +739,17 @@ void VID_Init(void)
        memset(&initialdevmode, 0, sizeof(initialdevmode));
        EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &initialdevmode);
 
+       desktop_mode.width = initialdevmode.dmPelsWidth;
+       desktop_mode.height = initialdevmode.dmPelsHeight;
+       desktop_mode.bpp = initialdevmode.dmBitsPerPel;
+       desktop_mode.refreshrate = initialdevmode.dmDisplayFrequency;
+       desktop_mode.pixelheight_num = 1;
+       desktop_mode.pixelheight_denom = 1; // Win32 apparently does not provide this (FIXME)
+
        IN_Init();
 }
 
-int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshrate, int stereobuffer, int samples)
+qboolean VID_InitModeGL(viddef_mode_t *mode)
 {
        int i;
        HDC hdc;
@@ -818,7 +780,6 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        int pixelformat, newpixelformat;
        UINT numpixelformats;
        DWORD WindowStyle, ExWindowStyle;
-       int CenterX, CenterY;
        const char *gldrivername;
        int depth;
        DEVMODE thismode;
@@ -827,6 +788,13 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        float *af;
        int attribs[128];
        float attribsf[16];
+       int bpp = mode->bitsperpixel;
+       int width = mode->width;
+       int height = mode->height;
+       int refreshrate = (int)floor(mode->refreshrate+0.5);
+       int stereobuffer = mode->stereobuffer;
+       int samples = mode->samples;
+       int fullscreen = mode->fullscreen;
 
        if (vid_initialized)
                Sys_Error("VID_InitMode called when video is already initialised");
@@ -923,13 +891,21 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        vid_isfullscreen = false;
        if (fullscreen)
        {
-               if(vid_forcerefreshrate.integer)
+               if(vid_desktopfullscreen.integer)
+               {
+                       foundmode = true;
+                       gdevmode = initialdevmode;
+                       width = mode->width = gdevmode.dmPelsWidth;
+                       height = mode->height = gdevmode.dmPelsHeight;
+                       bpp = mode->bitsperpixel = gdevmode.dmBitsPerPel;
+               }
+               else if(vid_forcerefreshrate.integer)
                {
                        foundmode = true;
                        gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
                        gdevmode.dmBitsPerPel = bpp;
-                       gdevmode.dmPelsWidth = *width;
-                       gdevmode.dmPelsHeight = *height;
+                       gdevmode.dmPelsWidth = width;
+                       gdevmode.dmPelsHeight = height;
                        gdevmode.dmSize = sizeof (gdevmode);
                        if(refreshrate)
                        {
@@ -954,24 +930,24 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                                        Con_DPrintf("enumerating modes yielded a bogus item... please debug this\n");
                                        continue;
                                }
-                               if(developer.integer >= 100)
-                                       Con_Printf("Found mode %dx%dx%dbpp %dHz... ", (int)thismode.dmPelsWidth, (int)thismode.dmPelsHeight, (int)thismode.dmBitsPerPel, (int)thismode.dmDisplayFrequency);
+                               if(developer_extra.integer)
+                                       Con_DPrintf("Found mode %dx%dx%dbpp %dHz... ", (int)thismode.dmPelsWidth, (int)thismode.dmPelsHeight, (int)thismode.dmBitsPerPel, (int)thismode.dmDisplayFrequency);
                                if(thismode.dmBitsPerPel != (DWORD)bpp)
                                {
-                                       if(developer.integer >= 100)
-                                               Con_Printf("wrong bpp\n");
+                                       if(developer_extra.integer)
+                                               Con_DPrintf("wrong bpp\n");
                                        continue;
                                }
-                               if(thismode.dmPelsWidth != (DWORD)*width)
+                               if(thismode.dmPelsWidth != (DWORD)width)
                                {
-                                       if(developer.integer >= 100)
-                                               Con_Printf("wrong width\n");
+                                       if(developer_extra.integer)
+                                               Con_DPrintf("wrong width\n");
                                        continue;
                                }
-                               if(thismode.dmPelsHeight != (DWORD)*height)
+                               if(thismode.dmPelsHeight != (DWORD)height)
                                {
-                                       if(developer.integer >= 100)
-                                               Con_Printf("wrong height\n");
+                                       if(developer_extra.integer)
+                                               Con_DPrintf("wrong height\n");
                                        continue;
                                }
 
@@ -980,14 +956,14 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                                        // if we have a good mode, make sure this mode is better than the previous one, and allowed by the refreshrate
                                        if(thismode.dmDisplayFrequency > (DWORD)refreshrate)
                                        {
-                                               if(developer.integer >= 100)
-                                                       Con_Printf("too high refresh rate\n");
+                                               if(developer_extra.integer)
+                                                       Con_DPrintf("too high refresh rate\n");
                                                continue;
                                        }
                                        else if(thismode.dmDisplayFrequency <= gdevmode.dmDisplayFrequency)
                                        {
-                                               if(developer.integer >= 100)
-                                                       Con_Printf("doesn't beat previous best match (too low)\n");
+                                               if(developer_extra.integer)
+                                                       Con_DPrintf("doesn't beat previous best match (too low)\n");
                                                continue;
                                        }
                                }
@@ -996,8 +972,8 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                                        // we do have one, but it isn't good... make sure it has a lower frequency than the previous one
                                        if(thismode.dmDisplayFrequency >= gdevmode.dmDisplayFrequency)
                                        {
-                                               if(developer.integer >= 100)
-                                                       Con_Printf("doesn't beat previous best match (too high)\n");
+                                               if(developer_extra.integer)
+                                                       Con_DPrintf("doesn't beat previous best match (too high)\n");
                                                continue;
                                        }
                                }
@@ -1008,25 +984,25 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                                        foundgoodmode = true;
                                else
                                {
-                                       if(developer.integer >= 100)
-                                               Con_Printf("(out of range)\n");
+                                       if(developer_extra.integer)
+                                               Con_DPrintf("(out of range)\n");
                                }
                                foundmode = true;
-                               if(developer.integer >= 100)
-                                       Con_Printf("accepted\n");
+                               if(developer_extra.integer)
+                                       Con_DPrintf("accepted\n");
                        }
                }
 
                if (!foundmode)
                {
                        VID_Shutdown();
-                       Con_Printf("Unable to find the requested mode %dx%dx%dbpp\n", *width, *height, bpp);
+                       Con_Printf("Unable to find the requested mode %dx%dx%dbpp\n", width, height, bpp);
                        return false;
                }
                else if(ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
                {
                        VID_Shutdown();
-                       Con_Printf("Unable to change to requested mode %dx%dx%dbpp\n", *width, *height, bpp);
+                       Con_Printf("Unable to change to requested mode %dx%dx%dbpp\n", width, height, bpp);
                        return false;
                }
 
@@ -1057,32 +1033,7 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                ExWindowStyle = 0;
        }
 
-       rect.top = 0;
-       rect.left = 0;
-       rect.right = *width;
-       rect.bottom = *height;
-       AdjustWindowRectEx(&rect, WindowStyle, false, 0);
-
-       if (fullscreen)
-       {
-               CenterX = 0;
-               CenterY = 0;
-       }
-       else
-       {
-               CenterX = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
-               CenterY = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
-       }
-       CenterX = max(0, CenterX);
-       CenterY = max(0, CenterY);
-
-       // x and y may be changed by WM_MOVE messages
-       window_x = CenterX;
-       window_y = CenterY;
-       rect.left += CenterX;
-       rect.right += CenterX;
-       rect.top += CenterY;
-       rect.bottom += CenterY;
+       AdjustWindowBounds(fullscreen, &width, &height, mode, WindowStyle, &rect);
 
        pixelformat = 0;
        newpixelformat = 0;
@@ -1095,7 +1046,7 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlacesWindowClass", gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL);
                if (!mainwindow)
                {
-                       Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %d, %p) failed\n", (int)ExWindowStyle, "DarkPlacesWindowClass", gamename, (int)WindowStyle, (int)(rect.left), (int)(rect.top), (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), NULL, NULL, (int)global_hInstance, NULL);
+                       Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %p, %p) failed\n", (int)ExWindowStyle, "DarkPlacesWindowClass", gamename, (int)WindowStyle, (int)(rect.left), (int)(rect.top), (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), (void *)NULL, (void *)NULL, (void *)global_hInstance, (void *)NULL);
                        VID_Shutdown();
                        return false;
                }
@@ -1108,14 +1059,14 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                if (!pixelformat)
                {
                        VID_Shutdown();
-                       Con_Printf("ChoosePixelFormat(%d, %p) failed\n", (int)baseDC, &pfd);
+                       Con_Printf("ChoosePixelFormat(%p, %p) failed\n", (void *)baseDC, (void *)&pfd);
                        return false;
                }
 
                if (SetPixelFormat(baseDC, pixelformat, &pfd) == false)
                {
                        VID_Shutdown();
-                       Con_Printf("SetPixelFormat(%d, %d, %p) failed\n", (int)baseDC, pixelformat, &pfd);
+                       Con_Printf("SetPixelFormat(%p, %d, %p) failed\n", (void *)baseDC, pixelformat, (void *)&pfd);
                        return false;
                }
 
@@ -1136,7 +1087,7 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
                if (!qwglMakeCurrent(baseDC, baseRC))
                {
                        VID_Shutdown();
-                       Con_Printf("wglMakeCurrent(%d, %d) failed\n", (int)baseDC, (int)baseRC);
+                       Con_Printf("wglMakeCurrent(%p, %p) failed\n", (void *)baseDC, (void *)baseRC);
                        return false;
                }
 
@@ -1215,10 +1166,8 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        // fix the leftover Alt from any Alt-Tab or the like that switched us away
        ClearAllStates ();
 
-       gl_videosyncavailable = false;
-
 // COMMANDLINEOPTION: Windows WGL: -novideosync disables WGL_EXT_swap_control
-       gl_videosyncavailable = GL_CheckExtension("WGL_EXT_swap_control", wglswapintervalfuncs, "-novideosync", false);
+       GL_CheckExtension("WGL_EXT_swap_control", wglswapintervalfuncs, "-novideosync", false);
 
        GL_Init ();
 
@@ -1227,13 +1176,12 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        vid_usingmouse = false;
        vid_usinghidecursor = false;
        vid_usingvsync = false;
-       vid_hidden = false;
+       vid_reallyhidden = vid_hidden = false;
        vid_initialized = true;
 
        IN_StartupMouse ();
-       IN_StartupJoystick ();
 
-       if (gl_videosyncavailable)
+       if (qwglSwapIntervalEXT)
        {
                vid_usevsync = vid_vsync.integer != 0;
                vid_usingvsync = vid_vsync.integer != 0;
@@ -1243,31 +1191,96 @@ int VID_InitMode (int fullscreen, int *width, int *height, int bpp, int refreshr
        return true;
 }
 
+static void AdjustWindowBounds(int fullscreen, int *width, int *height, viddef_mode_t *mode, DWORD WindowStyle, RECT *rect)
+{
+       int CenterX, CenterY;
+
+       rect->top = 0;
+       rect->left = 0;
+       rect->right = *width;
+       rect->bottom = *height;
+       AdjustWindowRectEx(rect, WindowStyle, false, 0);
+
+       if (fullscreen)
+       {
+               CenterX = 0;
+               CenterY = 0;
+       }
+       else
+       {
+               RECT workArea;
+               SystemParametersInfo(SPI_GETWORKAREA, NULL, &workArea, 0);
+               int workWidth = workArea.right - workArea.left;
+               int workHeight = workArea.bottom - workArea.top;
+
+               // if height/width matches physical screen height/width, adjust it to available desktop size
+               // and allow 2 pixels on top for the title bar so the window can be moved
+               const int titleBarPixels = 2;
+               if (*width == GetSystemMetrics(SM_CXSCREEN) && (*height == GetSystemMetrics(SM_CYSCREEN) || *height == workHeight - titleBarPixels))
+               {
+                       rect->right -= *width - workWidth;
+                       *width = mode->width = workWidth;
+                       rect->bottom -= *height - (workHeight - titleBarPixels);
+                       *height = mode->height = workHeight - titleBarPixels;
+                       CenterX = 0;
+                       CenterY = titleBarPixels;
+               }
+               else
+               {
+                       CenterX = max(0, (workWidth - *width) / 2);
+                       CenterY = max(0, (workHeight - *height) / 2);
+               }
+       }
+
+       // x and y may be changed by WM_MOVE messages
+       window_x = CenterX;
+       window_y = CenterY;
+       rect->left += CenterX;
+       rect->right += CenterX;
+       rect->top += CenterY;
+       rect->bottom += CenterY;
+}
+
+qboolean VID_InitMode(viddef_mode_t *mode)
+{
+       return VID_InitModeGL(mode);
+}
+
+
 static void IN_Shutdown(void);
 void VID_Shutdown (void)
 {
+       qboolean isgl;
        if(vid_initialized == false)
                return;
 
+       VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
-       VID_RestoreSystemGamma();
 
        vid_initialized = false;
+       isgl = gldll != NULL;
        IN_Shutdown();
+       gl_driver[0] = 0;
+       gl_extensions = "";
+       gl_platform = "";
+       gl_platformextensions = "";
        if (qwglMakeCurrent)
                qwglMakeCurrent(NULL, NULL);
+       qwglMakeCurrent = NULL;
        if (baseRC && qwglDeleteContext)
                qwglDeleteContext(baseRC);
+       qwglDeleteContext = NULL;
        // close the library before we get rid of the window
        GL_CloseLibrary();
        if (baseDC && mainwindow)
                ReleaseDC(mainwindow, baseDC);
+       baseDC = NULL;
        AppActivate(false, false);
        if (mainwindow)
                DestroyWindow(mainwindow);
        mainwindow = 0;
-       if (vid_isfullscreen)
-               ChangeDisplaySettings (NULL, 0);
+       if (vid_isfullscreen && isgl)
+               ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
        vid_isfullscreen = false;
 }
 
@@ -1351,6 +1364,28 @@ void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecurso
        }
 }
 
+void VID_BuildJoyState(vid_joystate_t *joystate)
+{
+       VID_Shared_BuildJoyState_Begin(joystate);
+       VID_Shared_BuildJoyState_Finish(joystate);
+}
+
+void VID_EnableJoystick(qboolean enable)
+{
+       int index = joy_enable.integer > 0 ? joy_index.integer : -1;
+       qboolean success = false;
+       int sharedcount = 0;
+       sharedcount = VID_Shared_SetJoystick(index);
+       if (index >= 0 && index < sharedcount)
+               success = true;
+
+       // update cvar containing count of XInput joysticks
+       if (joy_detected.integer != sharedcount)
+               Cvar_SetValueQuick(&joy_detected, sharedcount);
+
+       if (joy_active.integer != (success ? 1 : 0))
+               Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
+}
 
 #ifdef SUPPORTDIRECTX
 /*
@@ -1462,7 +1497,7 @@ static void IN_StartupMouse (void)
        mouseinitialized = true;
 
 #ifdef SUPPORTDIRECTX
-// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse/joystick input
+// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse input
        if (COM_CheckParm ("-dinput"))
                dinput = IN_InitDInput ();
 
@@ -1519,57 +1554,31 @@ static void IN_MouseMove (void)
 
                        /* Look at the element to see what happened */
 
-                       switch (od.dwOfs)
+                       if ((int)od.dwOfs == DIMOFS_X)
+                               in_mouse_x += (LONG) od.dwData;
+                       if ((int)od.dwOfs == DIMOFS_Y)
+                               in_mouse_y += (LONG) od.dwData;
+                       if ((int)od.dwOfs == DIMOFS_Z)
                        {
-                               case DIMOFS_X:
-                                       in_mouse_x += (LONG) od.dwData;
-                                       break;
-
-                               case DIMOFS_Y:
-                                       in_mouse_y += (LONG) od.dwData;
-                                       break;
-
-                               case DIMOFS_Z:
-                                       if((LONG) od.dwData < 0)
-                                       {
-                                               Key_Event (K_MWHEELDOWN, 0, true);
-                                               Key_Event (K_MWHEELDOWN, 0, false);
-                                       }
-                                       else if((LONG) od.dwData > 0)
-                                       {
-                                               Key_Event (K_MWHEELUP, 0, true);
-                                               Key_Event (K_MWHEELUP, 0, false);
-                                       }
-                                       break;
-
-                               case DIMOFS_BUTTON0:
-                                       if (od.dwData & 0x80)
-                                               mstate_di |= 1;
-                                       else
-                                               mstate_di &= ~1;
-                                       break;
-
-                               case DIMOFS_BUTTON1:
-                                       if (od.dwData & 0x80)
-                                               mstate_di |= (1<<1);
-                                       else
-                                               mstate_di &= ~(1<<1);
-                                       break;
-
-                               case DIMOFS_BUTTON2:
-                                       if (od.dwData & 0x80)
-                                               mstate_di |= (1<<2);
-                                       else
-                                               mstate_di &= ~(1<<2);
-                                       break;
-
-                               case DIMOFS_BUTTON3:
-                                       if (od.dwData & 0x80)
-                                               mstate_di |= (1<<3);
-                                       else
-                                               mstate_di &= ~(1<<3);
-                                       break;
+                               if((LONG)od.dwData < 0)
+                               {
+                                       Key_Event(K_MWHEELDOWN, 0, true);
+                                       Key_Event(K_MWHEELDOWN, 0, false);
+                               }
+                               else if((LONG)od.dwData > 0)
+                               {
+                                       Key_Event(K_MWHEELUP, 0, true);
+                                       Key_Event(K_MWHEELUP, 0, false);
+                               }
                        }
+                       if ((int)od.dwOfs == DIMOFS_BUTTON0)
+                               mstate_di = (mstate_di & ~1) | ((od.dwData & 0x80) >> 7);
+                       if ((int)od.dwOfs == DIMOFS_BUTTON1)
+                               mstate_di = (mstate_di & ~2) | ((od.dwData & 0x80) >> 6);
+                       if ((int)od.dwOfs == DIMOFS_BUTTON2)
+                               mstate_di = (mstate_di & ~4) | ((od.dwData & 0x80) >> 5);
+                       if ((int)od.dwOfs == DIMOFS_BUTTON3)
+                               mstate_di = (mstate_di & ~8) | ((od.dwData & 0x80) >> 4);
                }
 
                // perform button actions
@@ -1598,472 +1607,19 @@ IN_Move
 */
 void IN_Move (void)
 {
-       if (vid_activewindow && !vid_hidden)
-       {
+       vid_joystate_t joystate;
+       if (vid_activewindow && !vid_reallyhidden)
                IN_MouseMove ();
-               IN_JoyMove ();
-       }
-}
-
-
-/*
-===============
-IN_StartupJoystick
-===============
-*/
-static void IN_StartupJoystick (void)
-{
-       int                     numdevs;
-       JOYCAPS         jc;
-       MMRESULT        mmr;
-       mmr = 0;
-
-       // assume no joystick
-       joy_avail = false;
-
-       // abort startup if user requests no joystick
-// COMMANDLINEOPTION: Windows Input: -nojoy disables joystick support, may be a small speed increase
-       if (COM_CheckParm ("-nojoy"))
-               return;
-
-       // verify joystick driver is present
-       if ((numdevs = joyGetNumDevs ()) == 0)
-       {
-               Con_Print("\njoystick not found -- driver not present\n\n");
-               return;
-       }
-
-       // cycle through the joystick ids for the first valid one
-       for (joy_id=0 ; joy_id<numdevs ; joy_id++)
-       {
-               memset (&ji, 0, sizeof(ji));
-               ji.dwSize = sizeof(ji);
-               ji.dwFlags = JOY_RETURNCENTERED;
-
-               if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
-                       break;
-       }
-
-       // abort startup if we didn't find a valid joystick
-       if (mmr != JOYERR_NOERROR)
-       {
-               Con_Printf("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
-               return;
-       }
-
-       // get the capabilities of the selected joystick
-       // abort startup if command fails
-       memset (&jc, 0, sizeof(jc));
-       if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
-       {
-               Con_Printf("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
-               return;
-       }
-
-       // save the joystick's number of buttons and POV status
-       joy_numbuttons = jc.wNumButtons;
-       joy_haspov = (jc.wCaps & JOYCAPS_HASPOV) != 0;
-
-       // old button and POV states default to no buttons pressed
-       joy_oldbuttonstate = joy_oldpovstate = 0;
-
-       // mark the joystick as available and advanced initialization not completed
-       // this is needed as cvars are not available during initialization
-
-       joy_avail = true;
-       joy_advancedinit = false;
-
-       Con_Print("\njoystick detected\n\n");
-}
-
-
-/*
-===========
-RawValuePointer
-===========
-*/
-static PDWORD RawValuePointer (int axis)
-{
-       switch (axis)
-       {
-       case JOY_AXIS_X:
-               return &ji.dwXpos;
-       case JOY_AXIS_Y:
-               return &ji.dwYpos;
-       case JOY_AXIS_Z:
-               return &ji.dwZpos;
-       case JOY_AXIS_R:
-               return &ji.dwRpos;
-       case JOY_AXIS_U:
-               return &ji.dwUpos;
-       case JOY_AXIS_V:
-               return &ji.dwVpos;
-       }
-       return NULL; // LordHavoc: hush compiler warning
-}
-
-
-/*
-===========
-Joy_AdvancedUpdate_f
-===========
-*/
-static void Joy_AdvancedUpdate_f (void)
-{
-
-       // called once by IN_ReadJoystick and by user whenever an update is needed
-       // cvars are now available
-       int     i;
-       DWORD dwTemp;
-
-       // initialize all the maps
-       for (i = 0; i < JOY_MAX_AXES; i++)
-       {
-               dwAxisMap[i] = AxisNada;
-               dwControlMap[i] = JOY_ABSOLUTE_AXIS;
-               pdwRawValue[i] = RawValuePointer(i);
-       }
-
-       if( joy_advanced.integer == 0)
-       {
-               // default joystick initialization
-               // 2 axes only with joystick control
-               dwAxisMap[JOY_AXIS_X] = AxisTurn;
-               // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
-               dwAxisMap[JOY_AXIS_Y] = AxisForward;
-               // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
-       }
-       else
-       {
-               if (strcmp (joy_name.string, "joystick") != 0)
-               {
-                       // notify user of advanced controller
-                       Con_Printf("\n%s configured\n\n", joy_name.string);
-               }
-
-               // advanced initialization here
-               // data supplied by user via joy_axisn cvars
-               dwTemp = (DWORD) joy_advaxisx.value;
-               dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
-               dwTemp = (DWORD) joy_advaxisy.value;
-               dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
-               dwTemp = (DWORD) joy_advaxisz.value;
-               dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
-               dwTemp = (DWORD) joy_advaxisr.value;
-               dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
-               dwTemp = (DWORD) joy_advaxisu.value;
-               dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
-               dwTemp = (DWORD) joy_advaxisv.value;
-               dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
-               dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
-       }
-
-       // compute the axes to collect from DirectInput
-       joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
-       for (i = 0; i < JOY_MAX_AXES; i++)
-       {
-               if (dwAxisMap[i] != AxisNada)
-               {
-                       joy_flags |= dwAxisFlags[i];
-               }
-       }
-}
-
-/*
-===============
-IN_ReadJoystick
-===============
-*/
-static qboolean IN_ReadJoystick (void)
-{
-
-       memset (&ji, 0, sizeof(ji));
-       ji.dwSize = sizeof(ji);
-       ji.dwFlags = joy_flags;
-
-       if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
-       {
-               // this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
-               // rather than having 32768 be the zero point, they have the zero point at 32668
-               // go figure -- anyway, now we get the full resolution out of the device
-               if (joy_wwhack1.integer != 0.0)
-               {
-                       ji.dwUpos += 100;
-               }
-               return true;
-       }
-       else
-       {
-               // read error occurred
-               // turning off the joystick seems too harsh for 1 read error,
-               // but what should be done?
-               return false;
-       }
+       VID_EnableJoystick(true);
+       VID_BuildJoyState(&joystate);
+       VID_ApplyJoyState(&joystate);
 }
 
 
-/*
-===========
-IN_JoyMove
-===========
-*/
-static void IN_JoyMove (void)
-{
-       float   speed, aspeed;
-       float   fAxisValue, fTemp;
-       int             i, mouselook = (in_mlook.state & 1) || freelook.integer;
-
-       // complete initialization if first time in
-       // this is needed as cvars are not available at initialization time
-       if( joy_advancedinit != true )
-       {
-               Joy_AdvancedUpdate_f();
-               joy_advancedinit = true;
-       }
-
-       if (joy_avail)
-       {
-               int             i, key_index;
-               DWORD   buttonstate, povstate;
-
-               // loop through the joystick buttons
-               // key a joystick event or auxillary event for higher number buttons for each state change
-               buttonstate = ji.dwButtons;
-               for (i=0 ; i < (int) joy_numbuttons ; i++)
-               {
-                       if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
-                       {
-                               key_index = (i < 16) ? K_JOY1 : K_AUX1;
-                               Key_Event (key_index + i, 0, true);
-                       }
-
-                       if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
-                       {
-                               key_index = (i < 16) ? K_JOY1 : K_AUX1;
-                               Key_Event (key_index + i, 0, false);
-                       }
-               }
-               joy_oldbuttonstate = buttonstate;
-
-               if (joy_haspov)
-               {
-                       // convert POV information into 4 bits of state information
-                       // this avoids any potential problems related to moving from one
-                       // direction to another without going through the center position
-                       povstate = 0;
-                       if(ji.dwPOV != JOY_POVCENTERED)
-                       {
-                               if (ji.dwPOV == JOY_POVFORWARD)
-                                       povstate |= 0x01;
-                               if (ji.dwPOV == JOY_POVRIGHT)
-                                       povstate |= 0x02;
-                               if (ji.dwPOV == JOY_POVBACKWARD)
-                                       povstate |= 0x04;
-                               if (ji.dwPOV == JOY_POVLEFT)
-                                       povstate |= 0x08;
-                       }
-                       // determine which bits have changed and key an auxillary event for each change
-                       for (i=0 ; i < 4 ; i++)
-                       {
-                               if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
-                               {
-                                       Key_Event (K_AUX29 + i, 0, true);
-                               }
-
-                               if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
-                               {
-                                       Key_Event (K_AUX29 + i, 0, false);
-                               }
-                       }
-                       joy_oldpovstate = povstate;
-               }
-       }
-
-       // verify joystick is available and that the user wants to use it
-       if (!joy_avail || !in_joystick.integer)
-       {
-               return;
-       }
-
-       // collect the joystick data, if possible
-       if (IN_ReadJoystick () != true)
-       {
-               return;
-       }
-
-       if (in_speed.state & 1)
-               speed = cl_movespeedkey.value;
-       else
-               speed = 1;
-       // LordHavoc: viewzoom affects sensitivity for sniping
-       aspeed = speed * cl.realframetime * cl.viewzoom;
-
-       // loop through the axes
-       for (i = 0; i < JOY_MAX_AXES; i++)
-       {
-               // get the floating point zero-centered, potentially-inverted data for the current axis
-               fAxisValue = (float) *pdwRawValue[i];
-               // move centerpoint to zero
-               fAxisValue -= 32768.0;
-
-               if (joy_wwhack2.integer != 0.0)
-               {
-                       if (dwAxisMap[i] == AxisTurn)
-                       {
-                               // this is a special formula for the Logitech WingMan Warrior
-                               // y=ax^b; where a = 300 and b = 1.3
-                               // also x values are in increments of 800 (so this is factored out)
-                               // then bounds check result to level out excessively high spin rates
-                               fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
-                               if (fTemp > 14000.0)
-                                       fTemp = 14000.0;
-                               // restore direction information
-                               fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
-                       }
-               }
-
-               // convert range from -32768..32767 to -1..1
-               fAxisValue /= 32768.0;
-
-               switch (dwAxisMap[i])
-               {
-               case AxisForward:
-                       if ((joy_advanced.integer == 0) && mouselook)
-                       {
-                               // user wants forward control to become look control
-                               if (fabs(fAxisValue) > joy_pitchthreshold.value)
-                               {
-                                       // if mouse invert is on, invert the joystick pitch value
-                                       // only absolute control support here (joy_advanced is false)
-                                       if (m_pitch.value < 0.0)
-                                       {
-                                               cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
-                                       }
-                                       else
-                                       {
-                                               cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
-                                       }
-                                       V_StopPitchDrift();
-                               }
-                               else
-                               {
-                                       // no pitch movement
-                                       // disable pitch return-to-center unless requested by user
-                                       // *** this code can be removed when the lookspring bug is fixed
-                                       // *** the bug always has the lookspring feature on
-                                       if(lookspring.value == 0.0)
-                                               V_StopPitchDrift();
-                               }
-                       }
-                       else
-                       {
-                               // user wants forward control to be forward control
-                               if (fabs(fAxisValue) > joy_forwardthreshold.value)
-                               {
-                                       cl.cmd.forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value;
-                               }
-                       }
-                       break;
-
-               case AxisSide:
-                       if (fabs(fAxisValue) > joy_sidethreshold.value)
-                       {
-                               cl.cmd.sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
-                       }
-                       break;
-
-               case AxisTurn:
-                       if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook))
-                       {
-                               // user wants turn control to become side control
-                               if (fabs(fAxisValue) > joy_sidethreshold.value)
-                               {
-                                       cl.cmd.sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
-                               }
-                       }
-                       else
-                       {
-                               // user wants turn control to be turn control
-                               if (fabs(fAxisValue) > joy_yawthreshold.value)
-                               {
-                                       if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
-                                       {
-                                               cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value;
-                                       }
-                                       else
-                                       {
-                                               cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0;
-                                       }
-
-                               }
-                       }
-                       break;
-
-               case AxisLook:
-                       if (mouselook)
-                       {
-                               if (fabs(fAxisValue) > joy_pitchthreshold.value)
-                               {
-                                       // pitch movement detected and pitch movement desired by user
-                                       if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
-                                       {
-                                               cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
-                                       }
-                                       else
-                                       {
-                                               cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0;
-                                       }
-                                       V_StopPitchDrift();
-                               }
-                               else
-                               {
-                                       // no pitch movement
-                                       // disable pitch return-to-center unless requested by user
-                                       // *** this code can be removed when the lookspring bug is fixed
-                                       // *** the bug always has the lookspring feature on
-                                       if(lookspring.integer == 0)
-                                               V_StopPitchDrift();
-                               }
-                       }
-                       break;
-
-               default:
-                       break;
-               }
-       }
-}
-
 static void IN_Init(void)
 {
        uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" );
-
-       // joystick variables
-       Cvar_RegisterVariable (&in_joystick);
-       Cvar_RegisterVariable (&joy_name);
-       Cvar_RegisterVariable (&joy_advanced);
-       Cvar_RegisterVariable (&joy_advaxisx);
-       Cvar_RegisterVariable (&joy_advaxisy);
-       Cvar_RegisterVariable (&joy_advaxisz);
-       Cvar_RegisterVariable (&joy_advaxisr);
-       Cvar_RegisterVariable (&joy_advaxisu);
-       Cvar_RegisterVariable (&joy_advaxisv);
-       Cvar_RegisterVariable (&joy_forwardthreshold);
-       Cvar_RegisterVariable (&joy_sidethreshold);
-       Cvar_RegisterVariable (&joy_pitchthreshold);
-       Cvar_RegisterVariable (&joy_yawthreshold);
-       Cvar_RegisterVariable (&joy_forwardsensitivity);
-       Cvar_RegisterVariable (&joy_sidesensitivity);
-       Cvar_RegisterVariable (&joy_pitchsensitivity);
-       Cvar_RegisterVariable (&joy_yawsensitivity);
-       Cvar_RegisterVariable (&joy_wwhack1);
-       Cvar_RegisterVariable (&joy_wwhack2);
        Cvar_RegisterVariable (&vid_forcerefreshrate);
-       Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver");
 }
 
 static void IN_Shutdown(void)
@@ -2079,6 +1635,11 @@ static void IN_Shutdown(void)
 #endif
 }
 
+vid_mode_t *VID_GetDesktopMode(void)
+{
+       return &desktop_mode;
+}
+
 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
 {
        int i;