]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - vid_wgl.c
Reworked v_isometric code significantly, it now defaults to a proper isometric view...
[xonotic/darkplaces.git] / vid_wgl.c
index 2d0ac602f5865c1fd2c3daa30a50a05c9ae3ded0..7a4840886f0165fae39591890a582419c42a50a7 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -126,6 +126,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;
@@ -152,10 +153,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);
 
 //====================================
 
@@ -204,92 +206,17 @@ 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
-
-// joystick axes state
-typedef struct
-{
-       float oldmove;
-       float move;
-       float mdelta;
-       double keytime;
-}joy_axiscache_t;
-static joy_axiscache_t joy_axescache[JOY_MAX_AXES];
-
-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 joy_axiskeyevents = {CVAR_SAVE, "joy_axiskeyevents", "0", "generate uparrow/leftarrow etc. keyevents for joystick axes, use if your joystick driver is not generating them"};
-static cvar_t joy_axiskeyevents_deadzone = {CVAR_SAVE, "joy_axiskeyevents_deadzone", "0.5", "deadzone value for axes"};
-
 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);
 
 //====================================
 
@@ -394,25 +321,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
 };
 
 
@@ -442,6 +367,9 @@ static int MapKey (int key, int virtualkey)
 
        if ( !is_extended )
        {
+               if(((GetKeyState(VK_NUMLOCK)) & 0xffff) == 0)
+                       return result;
+
                switch ( result )
                {
                case K_HOME:
@@ -470,6 +398,9 @@ static int MapKey (int key, int virtualkey)
        }
        else
        {
+               if(virtualkey == VK_NUMLOCK)
+                       return K_NUMLOCK;
+
                switch ( result )
                {
                case 0x0D:
@@ -498,7 +429,7 @@ ClearAllStates
 */
 static void ClearAllStates (void)
 {
-       Key_ClearStates ();
+       Key_ReleaseAll();
        if (vid_usingmouse)
                mouse_oldbuttonstate = 0;
 }
@@ -564,10 +495,9 @@ void AppActivate(BOOL fActive, BOOL minimize)
                if (vid_isfullscreen)
                {
                        if (gldll)
-                               ChangeDisplaySettings (NULL, 0);
+                               ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
                        vid_wassuspended = true;
                }
-               VID_RestoreSystemGamma();
        }
 }
 
@@ -586,7 +516,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] =
 {
@@ -609,13 +541,13 @@ static keynum_t buttonremap[16] =
 };
 
 /* main window procedure */
-static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode);
 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;
@@ -634,8 +566,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;
 
@@ -648,14 +580,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];
-                       }
-                       if (!IN_JoystickBlockDoubledKeyEvents(vkey))
-                               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:
@@ -764,7 +695,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:
@@ -777,32 +710,6 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
        return lRet;
 }
 
-int VID_SetGamma(unsigned short *ramps, int rampsize)
-{
-       if (qwglMakeCurrent)
-       {
-               HDC hdc = GetDC (NULL);
-               int i = SetDeviceGammaRamp(hdc, ramps);
-               ReleaseDC (NULL, hdc);
-               return i; // return success or failure
-       }
-       else
-               return 0;
-}
-
-int VID_GetGamma(unsigned short *ramps, int rampsize)
-{
-       if (qwglMakeCurrent)
-       {
-               HDC hdc = GetDC (NULL);
-               int i = GetDeviceGammaRamp(hdc, ramps);
-               ReleaseDC (NULL, hdc);
-               return i; // return success or failure
-       }
-       else
-               return 0;
-}
-
 static void GL_CloseLibrary(void)
 {
        if (gldll)
@@ -938,6 +845,13 @@ 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();
 }
 
@@ -972,7 +886,6 @@ qboolean VID_InitModeGL(viddef_mode_t *mode)
        int pixelformat, newpixelformat;
        UINT numpixelformats;
        DWORD WindowStyle, ExWindowStyle;
-       int CenterX, CenterY;
        const char *gldrivername;
        int depth;
        DEVMODE thismode;
@@ -1084,7 +997,15 @@ qboolean VID_InitModeGL(viddef_mode_t *mode)
        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;
@@ -1218,32 +1139,7 @@ qboolean VID_InitModeGL(viddef_mode_t *mode)
                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;
@@ -1390,7 +1286,6 @@ qboolean VID_InitModeGL(viddef_mode_t *mode)
        vid_initialized = true;
 
        IN_StartupMouse ();
-       IN_StartupJoystick ();
 
        if (qwglSwapIntervalEXT)
        {
@@ -1402,6 +1297,56 @@ qboolean VID_InitModeGL(viddef_mode_t *mode)
        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;
+}
+
 #ifdef SUPPORTD3D
 static D3DADAPTER_IDENTIFIER9 d3d9adapteridentifier;
 
@@ -1417,7 +1362,6 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        RECT rect;
        MSG msg;
        DWORD WindowStyle, ExWindowStyle;
-       int CenterX, CenterY;
        int bpp = mode->bitsperpixel;
        int width = mode->width;
        int height = mode->height;
@@ -1442,32 +1386,7 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
                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);
 
        gl_extensions = "";
        gl_platformextensions = "";
@@ -1577,6 +1496,7 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        vid.support.arb_depth_texture = true;
        vid.support.arb_draw_buffers = vid_d3d9caps.NumSimultaneousRTs > 1;
        vid.support.arb_occlusion_query = true; // can't find a cap for this
+       vid.support.arb_query_buffer_object = true;
        vid.support.arb_shadow = true;
        vid.support.arb_texture_compression = true;
        vid.support.arb_texture_cube_map = true;
@@ -1585,6 +1505,7 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        vid.support.ext_blend_subtract = true;
        vid.support.ext_draw_range_elements = true;
        vid.support.ext_framebuffer_object = true;
+
        vid.support.ext_texture_3d = true;
        vid.support.ext_texture_compression_s3tc = true;
        vid.support.ext_texture_filter_anisotropic = true;
@@ -1636,7 +1557,6 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        vid_initialized = true;
 
        IN_StartupMouse ();
-       IN_StartupJoystick ();
 
        return true;
 }
@@ -1650,7 +1570,6 @@ qboolean VID_InitModeSOFT(viddef_mode_t *mode)
        MSG msg;
        int pixelformat, newpixelformat;
        DWORD WindowStyle, ExWindowStyle;
-       int CenterX, CenterY;
        int depth;
        DEVMODE thismode;
        qboolean foundmode, foundgoodmode;
@@ -1802,32 +1721,7 @@ qboolean VID_InitModeSOFT(viddef_mode_t *mode)
                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;
@@ -1918,7 +1812,6 @@ qboolean VID_InitModeSOFT(viddef_mode_t *mode)
        vid_initialized = true;
 
        IN_StartupMouse ();
-       IN_StartupJoystick ();
 
        return true;
 }
@@ -1948,8 +1841,8 @@ void VID_Shutdown (void)
        if(vid_initialized == false)
                return;
 
+       VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
-       VID_RestoreSystemGamma();
 
        vid_initialized = false;
        isgl = gldll != NULL;
@@ -1978,8 +1871,8 @@ void VID_Shutdown (void)
                if (vid_begunscene)
                        IDirect3DDevice9_EndScene(vid_d3d9dev);
                vid_begunscene = false;
-//             Cmd_ExecuteString("r_texturestats", src_command);
-//             Cmd_ExecuteString("memlist", src_command);
+//             Cmd_ExecuteString("r_texturestats", src_command, true);
+//             Cmd_ExecuteString("memlist", src_command, true);
                IDirect3DDevice9_Release(vid_d3d9dev);
        }
        vid_d3d9dev = NULL;
@@ -2003,7 +1896,7 @@ void VID_Shutdown (void)
                DestroyWindow(mainwindow);
        mainwindow = 0;
        if (vid_isfullscreen && isgl)
-               ChangeDisplaySettings (NULL, 0);
+               ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
        vid_isfullscreen = false;
 }
 
@@ -2087,6 +1980,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
 /*
@@ -2198,7 +2113,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 ();
 
@@ -2308,580 +2223,19 @@ IN_Move
 */
 void IN_Move (void)
 {
+       vid_joystate_t joystate;
        if (vid_activewindow && !vid_reallyhidden)
-       {
                IN_MouseMove ();
-               IN_JoyMove ();
-       }
+       VID_EnableJoystick(true);
+       VID_BuildJoyState(&joystate);
+       VID_ApplyJoyState(&joystate);
 }
 
 
-/*
-===============
-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;
-       }
-}
-
-/*
-===========
- IN_JoystickGetAxisNum
-===========
-*/
-
-int IN_JoystickGetAxisNum(int ControlListType)
-{
-       int i;
-
-       for (i = 0; i < JOY_MAX_AXES; i++)
-               if (dwAxisMap[i] == (DWORD) ControlListType)
-                       return i;
-       return -1;
-}
-
-/*
-===========
- IN_JoystickGetAxis
-===========
-*/
-static double IN_JoystickGetAxis(int axis, double sensitivity, double deadzone)
-{
-       float   fAxisValue, fTemp;
-
-       if (!joy_avail || axis < 0 || axis >= JOY_MAX_AXES)
-               return 0; // no such axis on this joystick
-
-       // get the floating point zero-centered, potentially-inverted data for the current axis
-       fAxisValue = (float) *pdwRawValue[axis];
-
-       // move centerpoint to zero
-       fAxisValue -= 32768.0;
-
-       if (joy_wwhack2.integer != 0.0)
-       {
-               if (dwAxisMap[axis] == 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;
-
-       // deadzone around center
-       if (fabs(fAxisValue) < deadzone)
-               return 0; 
-
-       // apply sensitivity
-       return fAxisValue * sensitivity;
-}
-
-/*
-===========
- IN_JoystickKeyeventForAxis
-===========
-*/
-
-static void IN_JoystickKeyeventForAxis(int axis, int key_pos, int key_neg)
-{
-       double joytime;
-
-       if (axis < 0 || axis >= JOY_MAX_AXES)
-               return; // no such axis on this joystick
-
-       joytime = Sys_DoubleTime();
-       // no key event, continuous keydown event
-       if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
-       {
-               if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
-               {
-                       //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
-                       Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
-                       joy_axescache[axis].keytime = joytime + 0.5 / 20;
-               }
-               return;
-       }
-       // generate key up event
-       if (joy_axescache[axis].oldmove)
-       {
-               //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
-               Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
-       }
-       // generate key down event
-       if (joy_axescache[axis].move)
-       {
-               //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
-               Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
-               joy_axescache[axis].keytime = joytime + 0.5;
-       }
-}
-
-/*
-===========
- IN_JoystickBlockDoubledKeyEvents
-===========
-*/
-
-static qboolean IN_ReadJoystick (void);
-static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
-{
-       int axis;
-
-       if (!joy_axiskeyevents.integer)
-               return false;
-
-       // block keyevent if it's going to be provided by joystick keyevent system
-       if (joy_avail)
-       {
-               // collect the joystick data, if possible
-               if (IN_ReadJoystick() != true)
-                       return false;
-               axis = IN_JoystickGetAxisNum(AxisForward);
-               if (keycode == K_UPARROW || keycode == K_DOWNARROW)
-                       if (IN_JoystickGetAxis(axis, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[axis].move || joy_axescache[axis].oldmove)
-                               return true;
-               axis = IN_JoystickGetAxisNum(AxisSide);
-               if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
-                       if (IN_JoystickGetAxis(axis, 1, joy_axiskeyevents_deadzone.value) || joy_axescache[axis].move || joy_axescache[axis].oldmove)
-                               return true;
-       }
-
-       return false;
-}
-
-/*
-===========
- IN_JoyMove
-===========
-*/
-static void IN_JoyMove (void)
-{
-       float   speed, aspeed;
-       float   fAxisValue;
-       int             i, mouselook = (in_mlook.state & 1) || freelook.integer, AxisForwardIndex = -1, AxisSideIndex = -1;
-
-       // 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++)
-       {
-               // convert axis to real move
-               switch (dwAxisMap[i])
-               {
-                       case AxisForward:
-                               if (AxisForwardIndex < 0)
-                                       AxisForwardIndex = i;
-                               if ((joy_advanced.integer == 0) && mouselook)
-                               {
-                                       // user wants forward control to become look control
-                                       fAxisValue = IN_JoystickGetAxis(i, joy_pitchsensitivity.value, joy_pitchthreshold.value);
-                                       if (fAxisValue != 0)
-                                       {
-                                               // 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 * aspeed * cl_pitchspeed.value;
-                                               else
-                                                       cl.viewangles[PITCH] += fAxisValue * 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
-                                       fAxisValue = IN_JoystickGetAxis(i, joy_forwardsensitivity.value, joy_forwardthreshold.value);
-                                       cl.cmd.forwardmove += fAxisValue * speed * cl_forwardspeed.value;
-                               }
-                               break;
-
-                       case AxisSide:
-                               if (AxisSideIndex < 0)
-                                       AxisSideIndex = i;
-                               fAxisValue = IN_JoystickGetAxis(i, joy_sidesensitivity.value, joy_sidethreshold.value);
-                               cl.cmd.sidemove += fAxisValue * speed * cl_sidespeed.value;
-                               break;
-
-                       case AxisTurn:
-                               if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook))
-                               {
-                                       // user wants turn control to become side control
-                                       fAxisValue = IN_JoystickGetAxis(i, joy_sidesensitivity.value, joy_sidethreshold.value);
-                                       cl.cmd.sidemove -= fAxisValue * speed * cl_sidespeed.value;
-                               }
-                               else
-                               {
-                                       // user wants turn control to be turn control
-                                       fAxisValue = IN_JoystickGetAxis(i, joy_yawsensitivity.value, joy_yawthreshold.value);
-                                       if (dwControlMap[i] == JOY_ABSOLUTE_AXIS)
-                                               cl.viewangles[YAW] += fAxisValue * aspeed * cl_yawspeed.value;
-                                       else
-                                               cl.viewangles[YAW] += fAxisValue * speed * 180.0;
-                               }
-                               break;
-
-                       case AxisLook:
-                               fAxisValue = IN_JoystickGetAxis(i, joy_pitchsensitivity.value, joy_pitchthreshold.value);
-                               if (mouselook)
-                               {
-                                       if (fAxisValue != 0)
-                                       {
-                                               // pitch movement detected and pitch movement desired by user
-                                               if (dwControlMap[i] == JOY_ABSOLUTE_AXIS)
-                                                       cl.viewangles[PITCH] += fAxisValue * aspeed * cl_pitchspeed.value;
-                                               else
-                                                       cl.viewangles[PITCH] += fAxisValue * 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:
-                               fAxisValue = IN_JoystickGetAxis(i, 1, 0.01);
-                               break;
-               }
-       
-               // cache for keyevents
-               joy_axescache[i].oldmove = joy_axescache[i].move;
-               joy_axescache[i].move = IN_JoystickGetAxis(i, 1, joy_axiskeyevents_deadzone.value);
-       }
-
-       // run keyevents
-       if (joy_axiskeyevents.integer)
-       {
-               IN_JoystickKeyeventForAxis(AxisForwardIndex, K_DOWNARROW, K_UPARROW);
-               IN_JoystickKeyeventForAxis(AxisSideIndex, K_RIGHTARROW, K_LEFTARROW);
-       }
-}
-
 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 (&joy_axiskeyevents);
-       Cvar_RegisterVariable (&joy_axiskeyevents_deadzone);
        Cvar_RegisterVariable (&vid_forcerefreshrate);
-       Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver");
 }
 
 static void IN_Shutdown(void)
@@ -2897,6 +2251,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;