]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - menu.c
fix GL11/GL13 fogged sprite rendering and q1bsp sky rendering - the
[xonotic/darkplaces.git] / menu.c
diff --git a/menu.c b/menu.c
index c2a1d5abf41e0c7a980910b8ad8f1c325151afde..062526508663c8c3871610fd0f4b0d1756f9ab56 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -82,30 +82,30 @@ static void M_ServerList_Draw (void);
 static void M_ModList_Draw (void);
 
 
-static void M_Main_Key (int key, char ascii);
-       static void M_SinglePlayer_Key (int key, char ascii);
-               static void M_Transfusion_Episode_Key (int key, char ascii);
-                       static void M_Transfusion_Skill_Key (int key, char ascii);
-               static void M_Load_Key (int key, char ascii);
-               static void M_Save_Key (int key, char ascii);
-       static void M_MultiPlayer_Key (int key, char ascii);
-               static void M_Setup_Key (int key, char ascii);
-       static void M_Options_Key (int key, char ascii);
-       static void M_Options_Effects_Key (int key, char ascii);
-       static void M_Options_Graphics_Key (int key, char ascii);
-       static void M_Options_ColorControl_Key (int key, char ascii);
-               static void M_Keys_Key (int key, char ascii);
-               static void M_Reset_Key (int key, char ascii);
-               static void M_Video_Key (int key, char ascii);
-       static void M_Help_Key (int key, char ascii);
-       static void M_Credits_Key (int key, char ascii);
-       static void M_Quit_Key (int key, char ascii);
-static void M_LanConfig_Key (int key, char ascii);
-static void M_GameOptions_Key (int key, char ascii);
-static void M_ServerList_Key (int key, char ascii);
-static void M_ModList_Key (int key, char ascii);
-
-static qboolean        m_entersound;           // play after drawing a frame, so caching won't disrupt the sound
+static void M_Main_Key (int key, int ascii);
+       static void M_SinglePlayer_Key (int key, int ascii);
+               static void M_Transfusion_Episode_Key (int key, int ascii);
+                       static void M_Transfusion_Skill_Key (int key, int ascii);
+               static void M_Load_Key (int key, int ascii);
+               static void M_Save_Key (int key, int ascii);
+       static void M_MultiPlayer_Key (int key, int ascii);
+               static void M_Setup_Key (int key, int ascii);
+       static void M_Options_Key (int key, int ascii);
+       static void M_Options_Effects_Key (int key, int ascii);
+       static void M_Options_Graphics_Key (int key, int ascii);
+       static void M_Options_ColorControl_Key (int key, int ascii);
+               static void M_Keys_Key (int key, int ascii);
+               static void M_Reset_Key (int key, int ascii);
+               static void M_Video_Key (int key, int ascii);
+       static void M_Help_Key (int key, int ascii);
+       static void M_Credits_Key (int key, int ascii);
+       static void M_Quit_Key (int key, int ascii);
+static void M_LanConfig_Key (int key, int ascii);
+static void M_GameOptions_Key (int key, int ascii);
+static void M_ServerList_Key (int key, int ascii);
+static void M_ModList_Key (int key, int ascii);
+
+static qboolean        m_entersound;           ///< play after drawing a frame, so caching won't disrupt the sound
 
 void M_Update_Return_Reason(char *s)
 {
@@ -316,7 +316,7 @@ void M_Menu_Demos_f (void)
 }
 
 
-static void M_Demo_Key (int k, char ascii)
+static void M_Demo_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -467,7 +467,7 @@ static void M_Main_Draw (void)
 }
 
 
-static void M_Main_Key (int key, char ascii)
+static void M_Main_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -748,7 +748,7 @@ static void M_SinglePlayer_Draw (void)
 }
 
 
-static void M_SinglePlayer_Key (int key, char ascii)
+static void M_SinglePlayer_Key (int key, int ascii)
 {
        if (gamemode == GAME_GOODVSBAD2 || gamemode == GAME_BATTLEMECH)
        {
@@ -810,9 +810,8 @@ static void M_SinglePlayer_Key (int key, char ascii)
 //=============================================================================
 /* LOAD/SAVE MENU */
 
-static int             load_cursor;            // 0 < load_cursor < MAX_SAVEGAMES
+static int             load_cursor;            ///< 0 < load_cursor < MAX_SAVEGAMES
 
-#define        MAX_SAVEGAMES           12
 static char    m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
 static int             loadable[MAX_SAVEGAMES];
 
@@ -913,7 +912,7 @@ static void M_Save_Draw (void)
 }
 
 
-static void M_Load_Key (int k, char ascii)
+static void M_Load_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -954,7 +953,7 @@ static void M_Load_Key (int k, char ascii)
 }
 
 
-static void M_Save_Key (int k, char ascii)
+static void M_Save_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -1017,7 +1016,7 @@ static void M_Transfusion_Episode_Draw (void)
        M_DrawPic (0, 120 + (m_episode_cursor + 1) * 40, va("gfx/menu/episode%iselected", m_episode_cursor + 1));
 }
 
-static void M_Transfusion_Episode_Key (int key, char ascii)
+static void M_Transfusion_Episode_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -1075,7 +1074,7 @@ static void M_Transfusion_Skill_Draw (void)
        M_DrawPic (0, 140 + (m_skill_cursor + 1) *40, va("gfx/menu/difficulty%iselected", m_skill_cursor + 1));
 }
 
-static void M_Transfusion_Skill_Key (int key, char ascii)
+static void M_Transfusion_Skill_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -1189,7 +1188,7 @@ static void M_MultiPlayer_Draw (void)
 }
 
 
-static void M_MultiPlayer_Key (int key, char ascii)
+static void M_MultiPlayer_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -1382,7 +1381,7 @@ static void M_Setup_Draw (void)
 }
 
 
-static void M_Setup_Key (int k, char ascii)
+static void M_Setup_Key (int k, int ascii)
 {
        int                     l;
 
@@ -1553,7 +1552,7 @@ static void M_Menu_Options_AdjustSliders (int dir)
        else if (options_cursor == optnum++) ;
        else if (options_cursor == optnum++) ;
        else if (options_cursor == optnum++) ;
-       else if (options_cursor == optnum++) Cvar_SetValueQuick(&crosshair, bound(0, crosshair.integer + dir, 6));
+       else if (options_cursor == optnum++) Cvar_SetValueQuick(&crosshair, bound(0, crosshair.integer + dir, 7));
        else if (options_cursor == optnum++) Cvar_SetValueQuick(&sensitivity, bound(1, sensitivity.value + dir * 0.5, 50));
        else if (options_cursor == optnum++) Cvar_SetValueQuick(&m_pitch, -m_pitch.value);
        else if (options_cursor == optnum++) Cvar_SetValueQuick(&scr_fov, bound(1, scr_fov.integer + dir * 1, 170));
@@ -1642,7 +1641,7 @@ static void M_Options_Draw (void)
        M_Options_PrintCommand( "         Go to console", true);
        M_Options_PrintCommand( "     Reset to defaults", true);
        M_Options_PrintCommand( "     Change Video Mode", true);
-       M_Options_PrintSlider(  "             Crosshair", true, crosshair.value, 0, 5);
+       M_Options_PrintSlider(  "             Crosshair", true, crosshair.value, 0, 7);
        M_Options_PrintSlider(  "           Mouse Speed", true, sensitivity.value, 1, 50);
        M_Options_PrintCheckbox("          Invert Mouse", true, m_pitch.value < 0);
        M_Options_PrintSlider(  "         Field of View", true, scr_fov.integer, 1, 170);
@@ -1668,7 +1667,7 @@ static void M_Options_Draw (void)
 }
 
 
-static void M_Options_Key (int k, char ascii)
+static void M_Options_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -1883,7 +1882,7 @@ static void M_Options_Effects_Draw (void)
 }
 
 
-static void M_Options_Effects_Key (int k, char ascii)
+static void M_Options_Effects_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -2019,7 +2018,7 @@ static void M_Options_Graphics_Draw (void)
 }
 
 
-static void M_Options_Graphics_Key (int k, char ascii)
+static void M_Options_Graphics_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -2246,7 +2245,7 @@ static void M_Options_ColorControl_Draw (void)
 }
 
 
-static void M_Options_ColorControl_Key (int k, char ascii)
+static void M_Options_ColorControl_Key (int k, int ascii)
 {
        switch (k)
        {
@@ -2511,7 +2510,7 @@ static int                bind_grab;
 
 void M_Menu_Keys_f (void)
 {
-       key_dest = key_menu;
+       key_dest = key_menu_grabbed;
        m_state = m_keys;
        m_entersound = true;
 }
@@ -2620,7 +2619,7 @@ static void M_Keys_Draw (void)
 }
 
 
-static void M_Keys_Key (int k, char ascii)
+static void M_Keys_Key (int k, int ascii)
 {
        char    cmd[80];
        int             keys[NUMKEYS];
@@ -2696,7 +2695,7 @@ void M_Menu_Reset_f (void)
 }
 
 
-static void M_Reset_Key (int key, char ascii)
+static void M_Reset_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -2729,8 +2728,7 @@ static void M_Reset_Draw (void)
 //=============================================================================
 /* VIDEO MENU */
 
-// note: if modes are added to the beginning of this list, update VID_DEFAULT
-video_resolution_t video_resolutions[] =
+video_resolution_t video_resolutions_hardcoded[] =
 {
 {"Standard 4x3"              ,  320, 240, 320, 240, 1     },
 {"Standard 4x3"              ,  400, 300, 400, 300, 1     },
@@ -2791,61 +2789,90 @@ video_resolution_t video_resolutions[] =
 {NULL, 0, 0, 0, 0, 0}
 };
 // this is the number of the default mode (640x480) in the list above
-#define VID_DEFAULT 3
-#define VID_RES_COUNT ((int)(sizeof(video_resolutions) / sizeof(video_resolutions[0])) - 1)
+int video_resolutions_hardcoded_count = sizeof(video_resolutions_hardcoded) / sizeof(*video_resolutions_hardcoded) - 1;
 
 #define VIDEO_ITEMS 11
 static int video_cursor = 0;
 static int video_cursor_table[VIDEO_ITEMS] = {68, 88, 96, 104, 112, 120, 128, 136, 144, 152, 168};
-static int video_resolution;
+static int menu_video_resolution;
 
-void M_Menu_Video_f (void)
+video_resolution_t *video_resolutions;
+int video_resolutions_count;
+
+static video_resolution_t *menu_video_resolutions;
+static int menu_video_resolutions_count;
+static qboolean menu_video_resolutions_forfullscreen;
+
+static void M_Menu_Video_FindResolution(int w, int h, float a)
 {
        int i;
 
-       key_dest = key_menu;
-       m_state = m_video;
-       m_entersound = true;
+       if(menu_video_resolutions_forfullscreen)
+       {
+               menu_video_resolutions = video_resolutions;
+               menu_video_resolutions_count = video_resolutions_count;
+       }
+       else
+       {
+               menu_video_resolutions = video_resolutions_hardcoded;
+               menu_video_resolutions_count = video_resolutions_hardcoded_count;
+       }
 
        // Look for the closest match to the current resolution
-       video_resolution = 0;
-       for (i = 1;i < VID_RES_COUNT;i++)
+       menu_video_resolution = 0;
+       for (i = 1;i < menu_video_resolutions_count;i++)
        {
                // if the new mode would be a worse match in width, skip it
-               if (fabs(video_resolutions[i].width - vid.width) > fabs(video_resolutions[video_resolution].width - vid.width))
+               if (abs(menu_video_resolutions[i].width - w) > abs(menu_video_resolutions[menu_video_resolution].width - w))
                        continue;
                // if it is equal in width, check height
-               if (video_resolutions[i].width == vid.width && video_resolutions[video_resolution].width == vid.width)
+               if (menu_video_resolutions[i].width == w && menu_video_resolutions[menu_video_resolution].width == w)
                {
                        // if the new mode would be a worse match in height, skip it
-                       if (fabs(video_resolutions[i].height - vid.height) > fabs(video_resolutions[video_resolution].height - vid.height))
+                       if (abs(menu_video_resolutions[i].height - h) > abs(menu_video_resolutions[menu_video_resolution].height - h))
                                continue;
                        // if it is equal in width and height, check pixel aspect
-                       if (video_resolutions[i].height == vid.height && video_resolutions[video_resolution].height == vid.height)
+                       if (menu_video_resolutions[i].height == h && menu_video_resolutions[menu_video_resolution].height == h)
                        {
                                // if the new mode would be a worse match in pixel aspect, skip it
-                               if (fabs(video_resolutions[i].pixelheight - vid_pixelheight.value) > fabs(video_resolutions[video_resolution].pixelheight - vid_pixelheight.value))
+                               if (abs(menu_video_resolutions[i].pixelheight - a) > abs(menu_video_resolutions[menu_video_resolution].pixelheight - a))
                                        continue;
                                // if it is equal in everything, skip it (prefer earlier modes)
-                               if (video_resolutions[i].pixelheight == vid_pixelheight.value && video_resolutions[video_resolution].pixelheight == vid_pixelheight.value)
+                               if (menu_video_resolutions[i].pixelheight == a && menu_video_resolutions[menu_video_resolution].pixelheight == a)
                                        continue;
                                // better match for width, height, and pixel aspect
-                               video_resolution = i;
+                               menu_video_resolution = i;
                        }
                        else // better match for width and height
-                               video_resolution = i;
+                               menu_video_resolution = i;
                }
                else // better match for width
-                       video_resolution = i;
+                       menu_video_resolution = i;
        }
 }
 
+void M_Menu_Video_f (void)
+{
+       key_dest = key_menu;
+       m_state = m_video;
+       m_entersound = true;
+
+       M_Menu_Video_FindResolution(vid.width, vid.height, vid_pixelheight.value);
+}
+
 
 static void M_Video_Draw (void)
 {
        int t;
        cachepic_t      *p;
 
+       if(!!vid_fullscreen.integer != menu_video_resolutions_forfullscreen)
+       {
+               video_resolution_t *res = &menu_video_resolutions[menu_video_resolution];
+               menu_video_resolutions_forfullscreen = !!vid_fullscreen.integer;
+               M_Menu_Video_FindResolution(res->width, res->height, res->pixelheight);
+       }
+
        M_Background(320, 200);
 
        M_DrawPic(16, 4, "gfx/qplaque");
@@ -2857,12 +2884,12 @@ static void M_Video_Draw (void)
        // Current and Proposed Resolution
        M_Print(16, video_cursor_table[t] - 12, "    Current Resolution");
        if (vid_supportrefreshrate && vid.userefreshrate && vid.fullscreen)
-               M_Print(220, video_cursor_table[t] - 12, va("%dx%d %dhz", vid.width, vid.height, vid.refreshrate));
+               M_Print(220, video_cursor_table[t] - 12, va("%dx%d %.2fhz", vid.width, vid.height, vid.refreshrate));
        else
                M_Print(220, video_cursor_table[t] - 12, va("%dx%d", vid.width, vid.height));
        M_Print(16, video_cursor_table[t], "        New Resolution");
-       M_Print(220, video_cursor_table[t], va("%dx%d", video_resolutions[video_resolution].width, video_resolutions[video_resolution].height));
-       M_Print(96, video_cursor_table[t] + 8, va("Type: %s", video_resolutions[video_resolution].type));
+       M_Print(220, video_cursor_table[t], va("%dx%d", menu_video_resolutions[menu_video_resolution].width, menu_video_resolutions[menu_video_resolution].height));
+       M_Print(96, video_cursor_table[t] + 8, va("Type: %s", menu_video_resolutions[menu_video_resolution].type));
        t++;
 
        // Bits per pixel
@@ -2882,7 +2909,7 @@ static void M_Video_Draw (void)
 
        // Refresh Rate
        M_ItemPrint(16, video_cursor_table[t], "          Refresh Rate", vid_supportrefreshrate && vid_userefreshrate.integer);
-       M_DrawSlider(220, video_cursor_table[t], vid_refreshrate.integer, 60, 150);
+       M_DrawSlider(220, video_cursor_table[t], vid_refreshrate.value, 50, 150);
        t++;
 
        // Fullscreen
@@ -2891,19 +2918,19 @@ static void M_Video_Draw (void)
        t++;
 
        // Vertical Sync
-       M_ItemPrint(16, video_cursor_table[t], "         Vertical Sync", gl_videosyncavailable);
+       M_ItemPrint(16, video_cursor_table[t], "         Vertical Sync", true);
        M_DrawCheckbox(220, video_cursor_table[t], vid_vsync.integer);
        t++;
 
-       M_ItemPrint(16, video_cursor_table[t], "    Anisotropic Filter", gl_support_anisotropy);
-       M_DrawSlider(220, video_cursor_table[t], gl_texture_anisotropy.integer, 1, gl_max_anisotropy);
+       M_ItemPrint(16, video_cursor_table[t], "    Anisotropic Filter", vid.support.ext_texture_filter_anisotropic);
+       M_DrawSlider(220, video_cursor_table[t], gl_texture_anisotropy.integer, 1, vid.max_anisotropy);
        t++;
 
        M_ItemPrint(16, video_cursor_table[t], "       Texture Quality", true);
        M_DrawSlider(220, video_cursor_table[t], gl_picmip.value, 3, 0);
        t++;
 
-       M_ItemPrint(16, video_cursor_table[t], "   Texture Compression", gl_support_texture_compression);
+       M_ItemPrint(16, video_cursor_table[t], "   Texture Compression", vid.support.arb_texture_compression);
        M_DrawCheckbox(220, video_cursor_table[t], gl_texturecompression.integer);
        t++;
 
@@ -2927,14 +2954,14 @@ static void M_Menu_Video_AdjustSliders (int dir)
        {
                // Resolution
                int r;
-               for(r = 0;r < VID_RES_COUNT;r++)
+               for(r = 0;r < menu_video_resolutions_count;r++)
                {
-                       video_resolution += dir;
-                       if (video_resolution >= VID_RES_COUNT)
-                               video_resolution = 0;
-                       if (video_resolution < 0)
-                               video_resolution = VID_RES_COUNT - 1;
-                       if (video_resolutions[video_resolution].width >= vid_minwidth.integer && video_resolutions[video_resolution].height >= vid_minheight.integer)
+                       menu_video_resolution += dir;
+                       if (menu_video_resolution >= menu_video_resolutions_count)
+                               menu_video_resolution = 0;
+                       if (menu_video_resolution < 0)
+                               menu_video_resolution = menu_video_resolutions_count - 1;
+                       if (menu_video_resolutions[menu_video_resolution].width >= vid_minwidth.integer && menu_video_resolutions[menu_video_resolution].height >= vid_minheight.integer)
                                break;
                }
        }
@@ -2945,13 +2972,13 @@ static void M_Menu_Video_AdjustSliders (int dir)
        else if (video_cursor == t++)
                Cvar_SetValueQuick (&vid_userefreshrate, !vid_userefreshrate.integer);
        else if (video_cursor == t++)
-               Cvar_SetValueQuick (&vid_refreshrate, bound(60, vid_refreshrate.integer + dir, 150));
+               Cvar_SetValueQuick (&vid_refreshrate, bound(50, vid_refreshrate.value + dir, 150));
        else if (video_cursor == t++)
                Cvar_SetValueQuick (&vid_fullscreen, !vid_fullscreen.integer);
        else if (video_cursor == t++)
                Cvar_SetValueQuick (&vid_vsync, !vid_vsync.integer);
        else if (video_cursor == t++)
-               Cvar_SetValueQuick (&gl_texture_anisotropy, bound(1, gl_texture_anisotropy.value * (dir < 0 ? 0.5 : 2.0), gl_max_anisotropy));
+               Cvar_SetValueQuick (&gl_texture_anisotropy, bound(1, gl_texture_anisotropy.value * (dir < 0 ? 0.5 : 2.0), vid.max_anisotropy));
        else if (video_cursor == t++)
                Cvar_SetValueQuick (&gl_picmip, bound(0, gl_picmip.value - dir, 3));
        else if (video_cursor == t++)
@@ -2959,7 +2986,7 @@ static void M_Menu_Video_AdjustSliders (int dir)
 }
 
 
-static void M_Video_Key (int key, char ascii)
+static void M_Video_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -2981,11 +3008,11 @@ static void M_Video_Key (int key, char ascii)
                        switch (video_cursor)
                        {
                                case (VIDEO_ITEMS - 1):
-                                       Cvar_SetValueQuick (&vid_width, video_resolutions[video_resolution].width);
-                                       Cvar_SetValueQuick (&vid_height, video_resolutions[video_resolution].height);
-                                       Cvar_SetValueQuick (&vid_conwidth, video_resolutions[video_resolution].conwidth);
-                                       Cvar_SetValueQuick (&vid_conheight, video_resolutions[video_resolution].conheight);
-                                       Cvar_SetValueQuick (&vid_pixelheight, video_resolutions[video_resolution].pixelheight);
+                                       Cvar_SetValueQuick (&vid_width, menu_video_resolutions[menu_video_resolution].width);
+                                       Cvar_SetValueQuick (&vid_height, menu_video_resolutions[menu_video_resolution].height);
+                                       Cvar_SetValueQuick (&vid_conwidth, menu_video_resolutions[menu_video_resolution].conwidth);
+                                       Cvar_SetValueQuick (&vid_conheight, menu_video_resolutions[menu_video_resolution].conheight);
+                                       Cvar_SetValueQuick (&vid_pixelheight, menu_video_resolutions[menu_video_resolution].pixelheight);
                                        Cbuf_AddText ("vid_restart\n");
                                        M_Menu_Options_f ();
                                        break;
@@ -3042,7 +3069,7 @@ static void M_Help_Draw (void)
 }
 
 
-static void M_Help_Key (int key, char ascii)
+static void M_Help_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -3089,7 +3116,7 @@ static void M_Credits_Draw (void)
 }
 
 
-static void M_Credits_Key (int key, char ascii)
+static void M_Credits_Key (int key, int ascii)
 {
                M_Menu_Main_f ();
 }
@@ -3177,7 +3204,7 @@ static int M_ChooseQuitMessage(int request)
                break;
        }
        return 0;
-};
+}
 
 void M_Menu_Quit_f (void)
 {
@@ -3196,7 +3223,7 @@ void M_Menu_Quit_f (void)
 }
 
 
-static void M_Quit_Key (int key, char ascii)
+static void M_Quit_Key (int key, int ascii)
 {
        switch (key)
        {
@@ -3257,7 +3284,7 @@ static int                lanConfig_cursor_table [] = {56, 76, 84, 120};
 
 static int     lanConfig_port;
 static char    lanConfig_portname[6];
-static char    lanConfig_joinname[22];
+static char    lanConfig_joinname[40];
 
 void M_Menu_LanConfig_f (void)
 {
@@ -3301,7 +3328,7 @@ static void M_LanConfig_Draw (void)
        basex += 8;
 
        M_Print(basex, lanConfig_cursor_table[0], "Port");
-       M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1);
+       M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, sizeof(lanConfig_portname), 1);
        M_Print(basex+9*8, lanConfig_cursor_table[0], lanConfig_portname);
 
        if (JoiningGame)
@@ -3309,7 +3336,7 @@ static void M_LanConfig_Draw (void)
                M_Print(basex, lanConfig_cursor_table[1], "Search for DarkPlaces games...");
                M_Print(basex, lanConfig_cursor_table[2], "Search for QuakeWorld games...");
                M_Print(basex, lanConfig_cursor_table[3]-16, "Join game at:");
-               M_DrawTextBox (basex+8, lanConfig_cursor_table[3]-8, 22, 1);
+               M_DrawTextBox (basex+8, lanConfig_cursor_table[3]-8, sizeof(lanConfig_joinname), 1);
                M_Print(basex+16, lanConfig_cursor_table[3], lanConfig_joinname);
        }
        else
@@ -3331,7 +3358,7 @@ static void M_LanConfig_Draw (void)
 }
 
 
-static void M_LanConfig_Key (int key, char ascii)
+static void M_LanConfig_Key (int key, int ascii)
 {
        int             l;
 
@@ -3407,7 +3434,7 @@ static void M_LanConfig_Key (int key, char ascii)
                if (lanConfig_cursor == 3)
                {
                        l = (int)strlen(lanConfig_joinname);
-                       if (l < 21)
+                       if (l < (int)sizeof(lanConfig_joinname) - 1)
                        {
                                lanConfig_joinname[l+1] = 0;
                                lanConfig_joinname[l] = ascii;
@@ -3419,7 +3446,7 @@ static void M_LanConfig_Key (int key, char ascii)
                if (lanConfig_cursor == 0)
                {
                        l = (int)strlen(lanConfig_portname);
-                       if (l < 5)
+                       if (l < (int)sizeof(lanConfig_portname) - 1)
                        {
                                lanConfig_portname[l+1] = 0;
                                lanConfig_portname[l] = ascii;
@@ -4239,7 +4266,7 @@ static void M_NetStart_Change (int dir)
        }
 }
 
-static void M_GameOptions_Key (int key, char ascii)
+static void M_GameOptions_Key (int key, int ascii)
 {
        gamelevels_t *g;
        int l;
@@ -4395,7 +4422,7 @@ static void M_ServerList_Draw (void)
 }
 
 
-static void M_ServerList_Key(int k, char ascii)
+static void M_ServerList_Key(int k, int ascii)
 {
        switch (k)
        {
@@ -4615,7 +4642,7 @@ static void M_ModList_Draw (void)
        }
 }
 
-static void M_ModList_Key(int k, char ascii)
+static void M_ModList_Key(int k, int ascii)
 {
        switch (k)
        {
@@ -4665,7 +4692,7 @@ static void M_ModList_Key(int k, char ascii)
 //=============================================================================
 /* Menu Subsystem */
 
-static void M_KeyEvent(int key, char ascii, qboolean downevent);
+static void M_KeyEvent(int key, int ascii, qboolean downevent);
 static void M_Draw(void);
 void M_ToggleMenu_f(void);
 static void M_Shutdown(void);
@@ -4902,7 +4929,7 @@ void M_Draw (void)
 }
 
 
-void M_KeyEvent (int key, char ascii, qboolean downevent)
+void M_KeyEvent (int key, int ascii, qboolean downevent)
 {
        if (!downevent)
                return;
@@ -5067,7 +5094,7 @@ void MP_Error(const char *format, ...)
        Host_AbortCurrentFrame();
 }
 
-void MP_KeyEvent (int key, char ascii, qboolean downevent)
+void MP_KeyEvent (int key, int ascii, qboolean downevent)
 {
        PRVM_Begin;
        PRVM_SetProg(PRVM_MENUPROG);
@@ -5157,6 +5184,7 @@ void MP_Init (void)
        prog->init_cmd = VM_M_Cmd_Init;
        prog->reset_cmd = VM_M_Cmd_Reset;
        prog->error_cmd = MP_Error;
+       prog->ExecuteProgram = MVM_ExecuteProgram;
 
        // allocate the mempools
        prog->progs_mempool = Mem_AllocPool(M_PROG_FILENAME, 0, NULL);
@@ -5182,7 +5210,7 @@ void MP_Restart(void)
 //============================================================================
 // Menu router
 
-void (*MR_KeyEvent) (int key, char ascii, qboolean downevent);
+void (*MR_KeyEvent) (int key, int ascii, qboolean downevent);
 void (*MR_Draw) (void);
 void (*MR_ToggleMenu_f) (void);
 void (*MR_Shutdown) (void);
@@ -5245,12 +5273,135 @@ void MR_Init_Commands(void)
        // set router console commands
        Cvar_RegisterVariable (&forceqmenu);
        Cvar_RegisterVariable (&menu_options_colorcontrol_correctionvalue);
-       Cmd_AddCommand ("menu_restart",MR_Restart, "restart menu system (reloads menu.dat");
+       Cmd_AddCommand ("menu_restart",MR_Restart, "restart menu system (reloads menu.dat)");
        Cmd_AddCommand ("togglemenu", Call_MR_ToggleMenu_f, "opens or closes menu");
 }
 
 void MR_Init(void)
 {
+       vid_mode_t res[1024];
+       size_t res_count, i;
+
+       res_count = VID_ListModes(res, sizeof(res) / sizeof(*res));
+       res_count = VID_SortModes(res, res_count, false, false, true);
+       if(res_count)
+       {
+               video_resolutions_count = res_count;
+               video_resolutions = (video_resolution_t *) Mem_Alloc(cls.permanentmempool, sizeof(*video_resolutions) * (video_resolutions_count + 1));
+               memset(&video_resolutions[video_resolutions_count], 0, sizeof(video_resolutions[video_resolutions_count]));
+               for(i = 0; i < res_count; ++i)
+               {
+                       int n, d, t;
+                       video_resolutions[i].type = "Detected mode"; // FIXME make this more dynamic
+                       video_resolutions[i].width = res[i].width;
+                       video_resolutions[i].height = res[i].height;
+                       video_resolutions[i].pixelheight = res[i].pixelheight_num / (double) res[i].pixelheight_denom;
+                       n = res[i].pixelheight_denom * video_resolutions[i].width;
+                       d = res[i].pixelheight_num * video_resolutions[i].height;
+                       while(d)
+                       {
+                               t = n;
+                               n = d;
+                               d = t % d;
+                       }
+                       d = (res[i].pixelheight_num * video_resolutions[i].height) / n;
+                       n = (res[i].pixelheight_denom * video_resolutions[i].width) / n;
+                       switch(n * 0x10000 | d)
+                       {
+                               case 0x00040003:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 480;
+                                       video_resolutions[i].type = "Standard 4x3";
+                                       break;
+                               case 0x00050004:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 512;
+                                       if(res[i].pixelheight_denom == res[i].pixelheight_num)
+                                               video_resolutions[i].type = "Square Pixel (LCD) 5x4";
+                                       else
+                                               video_resolutions[i].type = "Short Pixel (CRT) 5x4";
+                                       break;
+                               case 0x00080005:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 400;
+                                       if(res[i].pixelheight_denom == res[i].pixelheight_num)
+                                               video_resolutions[i].type = "Widescreen 8x5";
+                                       else
+                                               video_resolutions[i].type = "Tall Pixel (CRT) 8x5";
+
+                                       break;
+                               case 0x00050003:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 384;
+                                       video_resolutions[i].type = "Widescreen 5x3";
+                                       break;
+                               case 0x000D0009:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 400;
+                                       video_resolutions[i].type = "Widescreen 14x9";
+                                       break;
+                               case 0x00100009:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 480;
+                                       video_resolutions[i].type = "Widescreen 16x9";
+                                       break;
+                               case 0x00030002:
+                                       video_resolutions[i].conwidth = 720;
+                                       video_resolutions[i].conheight = 480;
+                                       video_resolutions[i].type = "NTSC 3x2";
+                                       break;
+                               case 0x000D000B:
+                                       video_resolutions[i].conwidth = 720;
+                                       video_resolutions[i].conheight = 566;
+                                       video_resolutions[i].type = "PAL 14x11";
+                                       break;
+                               case 0x00080007:
+                                       if(video_resolutions[i].width >= 512)
+                                       {
+                                               video_resolutions[i].conwidth = 512;
+                                               video_resolutions[i].conheight = 448;
+                                               video_resolutions[i].type = "SNES 8x7";
+                                       }
+                                       else
+                                       {
+                                               video_resolutions[i].conwidth = 256;
+                                               video_resolutions[i].conheight = 224;
+                                               video_resolutions[i].type = "NES 8x7";
+                                       }
+                                       break;
+                               default:
+                                       video_resolutions[i].conwidth = 640;
+                                       video_resolutions[i].conheight = 640 * d / n;
+                                       video_resolutions[i].type = "Detected mode";
+                                       break;
+                       }
+                       if(video_resolutions[i].conwidth > video_resolutions[i].width || video_resolutions[i].conheight > video_resolutions[i].height)
+                       {
+                               int f1, f2;
+                               f1 = video_resolutions[i].conwidth > video_resolutions[i].width;
+                               f2 = video_resolutions[i].conheight > video_resolutions[i].height;
+                               if(f1 > f2)
+                               {
+                                       video_resolutions[i].conwidth = video_resolutions[i].width;
+                                       video_resolutions[i].conheight = video_resolutions[i].conheight / f1;
+                               }
+                               else
+                               {
+                                       video_resolutions[i].conwidth = video_resolutions[i].conwidth / f2;
+                                       video_resolutions[i].conheight = video_resolutions[i].height;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               video_resolutions = video_resolutions_hardcoded;
+               video_resolutions_count = sizeof(video_resolutions_hardcoded) / sizeof(*video_resolutions_hardcoded) - 1;
+       }
+
+       menu_video_resolutions_forfullscreen = !!vid_fullscreen.integer;
+       M_Menu_Video_FindResolution(vid.width, vid.height, vid_pixelheight.value);
+
        // use -forceqmenu to use always the normal quake menu (it sets forceqmenu to 1)
 // COMMANDLINEOPTION: Client: -forceqmenu disables menu.dat (same as +forceqmenu 1)
        if(COM_CheckParm("-forceqmenu"))