]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
Change directory text colour in console from blue to light cyan (#197)
[xonotic/darkplaces.git] / cl_screen.c
index 8238ff6240f6e59f0b504351870bbe0922f0452c..fcec138368ea9de6dbcbae4e3ceed98730e24c10 100644 (file)
@@ -7,6 +7,7 @@
 #include "cl_collision.h"
 #include "libcurl.h"
 #include "csprogs.h"
 #include "cl_collision.h"
 #include "libcurl.h"
 #include "csprogs.h"
+#include "r_stats.h"
 #ifdef CONFIG_VIDEO_CAPTURE
 #include "cap_avi.h"
 #include "cap_ogg.h"
 #ifdef CONFIG_VIDEO_CAPTURE
 #include "cap_avi.h"
 #include "cap_ogg.h"
 // we have to include snd_main.h here only to get access to snd_renderbuffer->format.speed when writing the AVI headers
 #include "snd_main.h"
 
 // we have to include snd_main.h here only to get access to snd_renderbuffer->format.speed when writing the AVI headers
 #include "snd_main.h"
 
-cvar_t scr_viewsize = {CVAR_CLIENT | CVAR_SAVE, "viewsize","100", "how large the view should be, 110 disables inventory bar, 120 disables status bar"};
-cvar_t scr_fov = {CVAR_CLIENT | CVAR_SAVE, "fov","90", "field of vision, 1-170 degrees, default 90, some players use 110-130"};
-cvar_t scr_conalpha = {CVAR_CLIENT | CVAR_SAVE, "scr_conalpha", "1", "opacity of console background gfx/conback"};
-cvar_t scr_conalphafactor = {CVAR_CLIENT | CVAR_SAVE, "scr_conalphafactor", "1", "opacity of console background gfx/conback relative to scr_conalpha; when 0, gfx/conback is not drawn"};
-cvar_t scr_conalpha2factor = {CVAR_CLIENT | CVAR_SAVE, "scr_conalpha2factor", "0", "opacity of console background gfx/conback2 relative to scr_conalpha; when 0, gfx/conback2 is not drawn"};
-cvar_t scr_conalpha3factor = {CVAR_CLIENT | CVAR_SAVE, "scr_conalpha3factor", "0", "opacity of console background gfx/conback3 relative to scr_conalpha; when 0, gfx/conback3 is not drawn"};
-cvar_t scr_conbrightness = {CVAR_CLIENT | CVAR_SAVE, "scr_conbrightness", "1", "brightness of console background (0 = black, 1 = image)"};
-cvar_t scr_conforcewhiledisconnected = {CVAR_CLIENT, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
-cvar_t scr_conscroll_x = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll_x", "0", "scroll speed of gfx/conback in x direction"};
-cvar_t scr_conscroll_y = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll_y", "0", "scroll speed of gfx/conback in y direction"};
-cvar_t scr_conscroll2_x = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll2_x", "0", "scroll speed of gfx/conback2 in x direction"};
-cvar_t scr_conscroll2_y = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll2_y", "0", "scroll speed of gfx/conback2 in y direction"};
-cvar_t scr_conscroll3_x = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll3_x", "0", "scroll speed of gfx/conback3 in x direction"};
-cvar_t scr_conscroll3_y = {CVAR_CLIENT | CVAR_SAVE, "scr_conscroll3_y", "0", "scroll speed of gfx/conback3 in y direction"};
+cvar_t scr_viewsize = {CF_CLIENT | CF_ARCHIVE, "viewsize","100", "how large the view should be, 110 disables inventory bar, 120 disables status bar"};
+cvar_t scr_fov = {CF_CLIENT | CF_ARCHIVE, "fov","90", "field of vision, 1-170 degrees, default 90, some players use 110-130"};
+cvar_t scr_conalpha = {CF_CLIENT | CF_ARCHIVE, "scr_conalpha", "0.9", "opacity of console background gfx/conback (when console isn't forced fullscreen)"};
+cvar_t scr_conalphafactor = {CF_CLIENT | CF_ARCHIVE, "scr_conalphafactor", "1", "opacity of console background gfx/conback relative to scr_conalpha; when 0, gfx/conback is not drawn"};
+cvar_t scr_conalpha2factor = {CF_CLIENT | CF_ARCHIVE, "scr_conalpha2factor", "0", "opacity of console background gfx/conback2 relative to scr_conalpha; when 0, gfx/conback2 is not drawn"};
+cvar_t scr_conalpha3factor = {CF_CLIENT | CF_ARCHIVE, "scr_conalpha3factor", "0", "opacity of console background gfx/conback3 relative to scr_conalpha; when 0, gfx/conback3 is not drawn"};
+cvar_t scr_conbrightness = {CF_CLIENT | CF_ARCHIVE, "scr_conbrightness", "1", "brightness of console background (0 = black, 1 = image)"};
+cvar_t scr_conforcewhiledisconnected = {CF_CLIENT, "scr_conforcewhiledisconnected", "1", "1 forces fullscreen console while disconnected, 2 also forces it when the listen server has started but the client is still loading"};
+cvar_t scr_conheight = {CF_CLIENT | CF_ARCHIVE, "scr_conheight", "0.5", "fraction of screen height occupied by console (reduced as necessary for visibility of loading progress and infobar)"};
+cvar_t scr_conscroll_x = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll_x", "0", "scroll speed of gfx/conback in x direction"};
+cvar_t scr_conscroll_y = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll_y", "0", "scroll speed of gfx/conback in y direction"};
+cvar_t scr_conscroll2_x = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll2_x", "0", "scroll speed of gfx/conback2 in x direction"};
+cvar_t scr_conscroll2_y = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll2_y", "0", "scroll speed of gfx/conback2 in y direction"};
+cvar_t scr_conscroll3_x = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll3_x", "0", "scroll speed of gfx/conback3 in x direction"};
+cvar_t scr_conscroll3_y = {CF_CLIENT | CF_ARCHIVE, "scr_conscroll3_y", "0", "scroll speed of gfx/conback3 in y direction"};
 #ifdef CONFIG_MENU
 #ifdef CONFIG_MENU
-cvar_t scr_menuforcewhiledisconnected = {CVAR_CLIENT, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
+cvar_t scr_menuforcewhiledisconnected = {CF_CLIENT, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
 #endif
 #endif
-cvar_t scr_centertime = {CVAR_CLIENT, "scr_centertime","2", "how long centerprint messages show"};
-cvar_t scr_showram = {CVAR_CLIENT | CVAR_SAVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
-cvar_t scr_showturtle = {CVAR_CLIENT | CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low"};
-cvar_t scr_showpause = {CVAR_CLIENT | CVAR_SAVE, "showpause","1", "show pause icon when game is paused"};
-cvar_t scr_showbrand = {CVAR_CLIENT, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
-cvar_t scr_printspeed = {CVAR_CLIENT, "scr_printspeed","0", "speed of intermission printing (episode end texts), a value of 0 disables the slow printing"};
-cvar_t scr_loadingscreen_background = {CVAR_CLIENT, "scr_loadingscreen_background","0", "show the last visible background during loading screen (costs one screenful of video memory)"};
-cvar_t scr_loadingscreen_scale = {CVAR_CLIENT, "scr_loadingscreen_scale","1", "scale factor of the background"};
-cvar_t scr_loadingscreen_scale_base = {CVAR_CLIENT, "scr_loadingscreen_scale_base","0", "0 = console pixels, 1 = video pixels"};
-cvar_t scr_loadingscreen_scale_limit = {CVAR_CLIENT, "scr_loadingscreen_scale_limit","0", "0 = no limit, 1 = until first edge hits screen edge, 2 = until last edge hits screen edge, 3 = until width hits screen width, 4 = until height hits screen height"};
-cvar_t scr_loadingscreen_picture = {CVAR_CLIENT, "scr_loadingscreen_picture", "gfx/loading", "picture shown during loading"};
-cvar_t scr_loadingscreen_count = {CVAR_CLIENT, "scr_loadingscreen_count","1", "number of loading screen files to use randomly (named loading.tga, loading2.tga, loading3.tga, ...)"};
-cvar_t scr_loadingscreen_firstforstartup = {CVAR_CLIENT, "scr_loadingscreen_firstforstartup","0", "remove loading.tga from random scr_loadingscreen_count selection and only display it on client startup, 0 = normal, 1 = firstforstartup"};
-cvar_t scr_loadingscreen_barcolor = {CVAR_CLIENT, "scr_loadingscreen_barcolor", "0 0 1", "rgb color of loadingscreen progress bar"};
-cvar_t scr_loadingscreen_barheight = {CVAR_CLIENT, "scr_loadingscreen_barheight", "8", "the height of the loadingscreen progress bar"};
-cvar_t scr_loadingscreen_maxfps = {CVAR_CLIENT, "scr_loadingscreen_maxfps", "10", "restrict maximal FPS for loading screen so it will not update very often (this will make lesser loading times on a maps loading large number of models)"};
-cvar_t scr_infobar_height = {CVAR_CLIENT, "scr_infobar_height", "8", "the height of the infobar items"};
-cvar_t vid_conwidthauto = {CVAR_CLIENT | CVAR_SAVE, "vid_conwidthauto", "1", "automatically update vid_conwidth to match aspect ratio"};
-cvar_t vid_conwidth = {CVAR_CLIENT | CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system (note: changes may be overwritten, see vid_conwidthauto)"};
-cvar_t vid_conheight = {CVAR_CLIENT | CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
-cvar_t vid_pixelheight = {CVAR_CLIENT | CVAR_SAVE, "vid_pixelheight", "1", "adjusts vertical field of vision to account for non-square pixels (1280x1024 on a CRT monitor for example)"};
-cvar_t scr_screenshot_jpeg = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg instead of targa"};
-cvar_t scr_screenshot_jpeg_quality = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
-cvar_t scr_screenshot_png = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_png","0", "save png instead of targa"};
-cvar_t scr_screenshot_gammaboost = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
-cvar_t scr_screenshot_alpha = {CVAR_CLIENT, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
-cvar_t scr_screenshot_timestamp = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
+cvar_t scr_centertime = {CF_CLIENT, "scr_centertime","2", "how long centerprint messages show"};
+cvar_t scr_showram = {CF_CLIENT | CF_ARCHIVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
+cvar_t scr_showturtle = {CF_CLIENT | CF_ARCHIVE, "showturtle","0", "show turtle icon when framerate is too low"};
+cvar_t scr_showpause = {CF_CLIENT | CF_ARCHIVE, "showpause","1", "show pause icon when game is paused"};
+cvar_t scr_showbrand = {CF_CLIENT, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
+cvar_t scr_printspeed = {CF_CLIENT, "scr_printspeed","0", "speed of intermission printing (episode end texts), a value of 0 disables the slow printing"};
+cvar_t scr_loadingscreen_background = {CF_CLIENT, "scr_loadingscreen_background","0", "show the last visible background during loading screen (costs one screenful of video memory)"};
+cvar_t scr_loadingscreen_scale = {CF_CLIENT, "scr_loadingscreen_scale","1", "scale factor of the background"};
+cvar_t scr_loadingscreen_scale_base = {CF_CLIENT, "scr_loadingscreen_scale_base","0", "0 = console pixels, 1 = video pixels"};
+cvar_t scr_loadingscreen_scale_limit = {CF_CLIENT, "scr_loadingscreen_scale_limit","0", "0 = no limit, 1 = until first edge hits screen edge, 2 = until last edge hits screen edge, 3 = until width hits screen width, 4 = until height hits screen height"};
+cvar_t scr_loadingscreen_picture = {CF_CLIENT, "scr_loadingscreen_picture", "gfx/loading", "picture shown during loading"};
+cvar_t scr_loadingscreen_count = {CF_CLIENT, "scr_loadingscreen_count","1", "number of loading screen files to use randomly (named loading.tga, loading2.tga, loading3.tga, ...)"};
+cvar_t scr_loadingscreen_firstforstartup = {CF_CLIENT, "scr_loadingscreen_firstforstartup","0", "remove loading.tga from random scr_loadingscreen_count selection and only display it on client startup, 0 = normal, 1 = firstforstartup"};
+cvar_t scr_loadingscreen_barcolor = {CF_CLIENT, "scr_loadingscreen_barcolor", "0 0 1", "rgb color of loadingscreen progress bar"};
+cvar_t scr_loadingscreen_barheight = {CF_CLIENT, "scr_loadingscreen_barheight", "8", "the height of the loadingscreen progress bar"};
+cvar_t scr_loadingscreen_maxfps = {CF_CLIENT, "scr_loadingscreen_maxfps", "20", "maximum FPS for loading screen so it will not update very often (this reduces loading time with lots of models)"};
+cvar_t scr_infobar_height = {CF_CLIENT, "scr_infobar_height", "8", "the height of the infobar items"};
+cvar_t scr_sbarscale = {CF_CLIENT | CF_READONLY, "scr_sbarscale", "1", "current vid_height/vid_conheight, for compatibility with csprogs that read this cvar (found in Fitzquake-derived engines and FTEQW; despite the name it's not specific to the status bar)"};
+cvar_t vid_conwidthauto = {CF_CLIENT | CF_ARCHIVE, "vid_conwidthauto", "1", "automatically update vid_conwidth to match aspect ratio"};
+cvar_t vid_conwidth = {CF_CLIENT | CF_ARCHIVE, "vid_conwidth", "640", "virtual width of 2D graphics system (note: changes may be overwritten, see vid_conwidthauto)"};
+cvar_t vid_conheight = {CF_CLIENT | CF_ARCHIVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
+cvar_t vid_pixelheight = {CF_CLIENT | CF_ARCHIVE, "vid_pixelheight", "1", "adjusts vertical field of vision to account for non-square pixels (1280x1024 on a CRT monitor for example)"};
+cvar_t scr_screenshot_jpeg = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_jpeg","1", "save jpeg instead of targa or PNG"};
+cvar_t scr_screenshot_jpeg_quality = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
+cvar_t scr_screenshot_png = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_png","0", "save png instead of targa"};
+cvar_t scr_screenshot_gammaboost = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
+cvar_t scr_screenshot_alpha = {CF_CLIENT, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
+cvar_t scr_screenshot_timestamp = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
 // scr_screenshot_name is defined in fs.c
 #ifdef CONFIG_VIDEO_CAPTURE
 // scr_screenshot_name is defined in fs.c
 #ifdef CONFIG_VIDEO_CAPTURE
-cvar_t cl_capturevideo = {CVAR_CLIENT, "cl_capturevideo", "0", "enables saving of video to a .avi file using uncompressed I420 colorspace and PCM audio, note that scr_screenshot_gammaboost affects the brightness of the output)"};
-cvar_t cl_capturevideo_demo_stop = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_demo_stop", "1", "automatically stops video recording when demo ends"};
-cvar_t cl_capturevideo_printfps = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_printfps", "1", "prints the frames per second captured in capturevideo (is only written to the log file, not to the console, as that would be visible on the video)"};
-cvar_t cl_capturevideo_width = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_width", "0", "scales all frames to this resolution before saving the video"};
-cvar_t cl_capturevideo_height = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_height", "0", "scales all frames to this resolution before saving the video"};
-cvar_t cl_capturevideo_realtime = {CVAR_CLIENT, "cl_capturevideo_realtime", "0", "causes video saving to operate in realtime (mostly useful while playing, not while capturing demos), this can produce a much lower quality video due to poor sound/video sync and will abort saving if your machine stalls for over a minute"};
-cvar_t cl_capturevideo_fps = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
-cvar_t cl_capturevideo_nameformat = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_nameformat", "dpvideo", "prefix for saved videos (the date is encoded using strftime escapes)"};
-cvar_t cl_capturevideo_number = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
-cvar_t cl_capturevideo_ogg = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_ogg", "1", "save captured video data as Ogg/Vorbis/Theora streams"};
-cvar_t cl_capturevideo_framestep = {CVAR_CLIENT | CVAR_SAVE, "cl_capturevideo_framestep", "1", "when set to n >= 1, render n frames to capture one (useful for motion blur like effects)"};
+cvar_t cl_capturevideo = {CF_CLIENT, "cl_capturevideo", "0", "enables saving of video to a .avi file using uncompressed I420 colorspace and PCM audio, note that scr_screenshot_gammaboost affects the brightness of the output)"};
+cvar_t cl_capturevideo_demo_stop = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_demo_stop", "1", "automatically stops video recording when demo ends"};
+cvar_t cl_capturevideo_printfps = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_printfps", "1", "prints the frames per second captured in capturevideo (is only written to stdout and any log file, not to the console as that would be visible on the video), value is seconds of wall time between prints"};
+cvar_t cl_capturevideo_width = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_width", "0", "scales all frames to this resolution before saving the video"};
+cvar_t cl_capturevideo_height = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_height", "0", "scales all frames to this resolution before saving the video"};
+cvar_t cl_capturevideo_realtime = {CF_CLIENT, "cl_capturevideo_realtime", "0", "causes video saving to operate in realtime (mostly useful while playing, not while capturing demos), this can produce a much lower quality video due to poor sound/video sync and will abort saving if your machine stalls for over a minute"};
+cvar_t cl_capturevideo_fps = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
+cvar_t cl_capturevideo_nameformat = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_nameformat", "dpvideo", "prefix for saved videos (the date is encoded using strftime escapes)"};
+cvar_t cl_capturevideo_number = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
+cvar_t cl_capturevideo_ogg = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_ogg", "1", "save captured video data as Ogg/Vorbis/Theora streams"};
+cvar_t cl_capturevideo_framestep = {CF_CLIENT | CF_ARCHIVE, "cl_capturevideo_framestep", "1", "when set to n >= 1, render n frames to capture one (useful for motion blur like effects)"};
 #endif
 #endif
-cvar_t r_letterbox = {CVAR_CLIENT, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
-cvar_t r_stereo_separation = {CVAR_CLIENT, "r_stereo_separation", "4", "separation distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
-cvar_t r_stereo_sidebyside = {CVAR_CLIENT, "r_stereo_sidebyside", "0", "side by side views for those who can't afford glasses but can afford eye strain (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
-cvar_t r_stereo_horizontal = {CVAR_CLIENT, "r_stereo_horizontal", "0", "aspect skewed side by side view for special decoder/display hardware"};
-cvar_t r_stereo_vertical = {CVAR_CLIENT, "r_stereo_vertical", "0", "aspect skewed top and bottom view for special decoder/display hardware"};
-cvar_t r_stereo_redblue = {CVAR_CLIENT, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
-cvar_t r_stereo_redcyan = {CVAR_CLIENT, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
-cvar_t r_stereo_redgreen = {CVAR_CLIENT, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
-cvar_t r_stereo_angle = {CVAR_CLIENT, "r_stereo_angle", "0", "separation angle of eyes (makes the views look different directions, as an example, 90 gives a 90 degree separation where the views are 45 degrees left and 45 degrees right)"};
-cvar_t scr_stipple = {CVAR_CLIENT, "scr_stipple", "0", "interlacing-like stippling of the display"};
-cvar_t scr_refresh = {CVAR_CLIENT, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"};
-cvar_t scr_screenshot_name_in_mapdir = {CVAR_CLIENT | CVAR_SAVE, "scr_screenshot_name_in_mapdir", "0", "if set to 1, screenshots are placed in a subdirectory named like the map they are from"};
-cvar_t net_graph = {CVAR_CLIENT | CVAR_SAVE, "net_graph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"};
-cvar_t cl_demo_mousegrab = {CVAR_CLIENT, "cl_demo_mousegrab", "0", "Allows reading the mouse input while playing demos. Useful for camera mods developed in csqc. (0: never, 1: always)"};
-cvar_t timedemo_screenshotframelist = {CVAR_CLIENT, "timedemo_screenshotframelist", "", "when performing a timedemo, take screenshots of each frame in this space-separated list - example: 1 201 401"};
-cvar_t vid_touchscreen_outlinealpha = {CVAR_CLIENT, "vid_touchscreen_outlinealpha", "0", "opacity of touchscreen area outlines"};
-cvar_t vid_touchscreen_overlayalpha = {CVAR_CLIENT, "vid_touchscreen_overlayalpha", "0.25", "opacity of touchscreen area icons"};
-cvar_t r_speeds_graph = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph", "0", "display a graph of renderer statistics "};
-cvar_t r_speeds_graph_filter[8] =
-{
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_r", "timedelta", "Red - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_g", "batch_batches", "Green - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_b", "batch_triangles", "Blue - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_y", "fast_triangles", "Yellow - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_c", "copytriangles_triangles", "Cyan - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_m", "dynamic_triangles", "Magenta - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_w", "animcache_shade_vertices", "White - display the specified renderer statistic"},
-       {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_filter_o", "animcache_shape_vertices", "Orange - display the specified renderer statistic"},
-};
-cvar_t r_speeds_graph_length = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_length", "1024", "number of frames in statistics graph, can be from 4 to 8192"};
-cvar_t r_speeds_graph_seconds = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_seconds", "2", "number of seconds in graph, can be from 0.1 to 120"};
-cvar_t r_speeds_graph_x = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_x", "0", "position of graph"};
-cvar_t r_speeds_graph_y = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_y", "0", "position of graph"};
-cvar_t r_speeds_graph_width = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_width", "256", "size of graph"};
-cvar_t r_speeds_graph_height = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_height", "128", "size of graph"};
-cvar_t r_speeds_graph_maxtimedelta = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_maxtimedelta", "16667", "maximum timedelta to display in the graph (this value will be the top line)"};
-cvar_t r_speeds_graph_maxdefault = {CVAR_CLIENT | CVAR_SAVE, "r_speeds_graph_maxdefault", "100", "if the minimum and maximum observed values are closer than this, use this value as the graph range (keeps small numbers from being big graphs)"};
-
-
+cvar_t r_letterbox = {CF_CLIENT, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
+cvar_t r_stereo_separation = {CF_CLIENT, "r_stereo_separation", "4", "separation distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
+cvar_t r_stereo_sidebyside = {CF_CLIENT, "r_stereo_sidebyside", "0", "side by side views for those who can't afford glasses but can afford eye strain (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
+cvar_t r_stereo_horizontal = {CF_CLIENT, "r_stereo_horizontal", "0", "aspect skewed side by side view for special decoder/display hardware"};
+cvar_t r_stereo_vertical = {CF_CLIENT, "r_stereo_vertical", "0", "aspect skewed top and bottom view for special decoder/display hardware"};
+cvar_t r_stereo_redblue = {CF_CLIENT, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
+cvar_t r_stereo_redcyan = {CF_CLIENT, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
+cvar_t r_stereo_redgreen = {CF_CLIENT, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
+cvar_t r_stereo_angle = {CF_CLIENT, "r_stereo_angle", "0", "separation angle of eyes (makes the views look different directions, as an example, 90 gives a 90 degree separation where the views are 45 degrees left and 45 degrees right)"};
+cvar_t scr_stipple = {CF_CLIENT, "scr_stipple", "0", "interlacing-like stippling of the display"};
+cvar_t scr_refresh = {CF_CLIENT, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"};
+cvar_t scr_screenshot_name_in_mapdir = {CF_CLIENT | CF_ARCHIVE, "scr_screenshot_name_in_mapdir", "0", "if set to 1, screenshots are placed in a subdirectory named like the map they are from"};
+cvar_t net_graph = {CF_CLIENT | CF_ARCHIVE, "net_graph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"};
+cvar_t cl_demo_mousegrab = {CF_CLIENT, "cl_demo_mousegrab", "0", "Allows reading the mouse input while playing demos. Useful for camera mods developed in csqc. (0: never, 1: always)"};
+cvar_t timedemo_screenshotframelist = {CF_CLIENT, "timedemo_screenshotframelist", "", "when performing a timedemo, take screenshots of each frame in this space-separated list - example: 1 201 401"};
+cvar_t vid_touchscreen_outlinealpha = {CF_CLIENT, "vid_touchscreen_outlinealpha", "0", "opacity of touchscreen area outlines"};
+cvar_t vid_touchscreen_overlayalpha = {CF_CLIENT, "vid_touchscreen_overlayalpha", "0.25", "opacity of touchscreen area icons"};
 
 extern cvar_t sbar_info_pos;
 extern cvar_t r_fog_clear;
 
 int jpeg_supported = false;
 
 
 extern cvar_t sbar_info_pos;
 extern cvar_t r_fog_clear;
 
 int jpeg_supported = false;
 
-qboolean       scr_initialized;                // ready to draw
+qbool  scr_initialized;                // ready to draw
+
+qbool scr_loading = false;  // we are in a loading screen
 
 
-float          scr_con_current;
-int                    scr_con_margin_bottom;
+unsigned int        scr_con_current;
+static unsigned int scr_con_margin_bottom;
 
 extern int     con_vislines;
 
 
 extern int     con_vislines;
 
@@ -131,7 +114,7 @@ static void SCR_ScreenShot_f(cmd_state_t *cmd);
 static void R_Envmap_f(cmd_state_t *cmd);
 
 // backend
 static void R_Envmap_f(cmd_state_t *cmd);
 
 // backend
-void R_ClearScreen(qboolean fogcolor);
+void R_ClearScreen(qbool fogcolor);
 
 /*
 ===============================================================================
 
 /*
 ===============================================================================
@@ -160,12 +143,20 @@ for a few moments
 */
 void SCR_CenterPrint(const char *str)
 {
 */
 void SCR_CenterPrint(const char *str)
 {
-       strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
        scr_centertime_off = scr_centertime.value;
        scr_centertime_start = cl.time;
 
        scr_centertime_off = scr_centertime.value;
        scr_centertime_start = cl.time;
 
-// count the number of lines for centering
+       // Print the message to the console and update the scr buffer
+       // but only if it's different to the previous message
+       if (strcmp(str, scr_centerstring) == 0)
+               return;
+       dp_strlcpy(scr_centerstring, str, sizeof(scr_centerstring));
        scr_center_lines = 1;
        scr_center_lines = 1;
+       if (str[0] == '\0') // happens when stepping out of a centreprint trigger on alk1.2 start.bsp
+               return;
+       Con_CenterPrint(str);
+
+// count the number of lines for centering
        while (*str)
        {
                if (*str == '\n')
        while (*str)
        {
                if (*str == '\n')
@@ -174,6 +165,51 @@ void SCR_CenterPrint(const char *str)
        }
 }
 
        }
 }
 
+/*
+============
+SCR_Centerprint_f
+
+Print something to the center of the screen using SCR_Centerprint
+============
+*/
+static void SCR_Centerprint_f (cmd_state_t *cmd)
+{
+       char msg[MAX_INPUTLINE];
+       unsigned int i, c, p;
+
+       c = Cmd_Argc(cmd);
+       if(c >= 2)
+       {
+               // Merge all the cprint arguments into one string
+               dp_strlcpy(msg, Cmd_Argv(cmd,1), sizeof(msg));
+               for(i = 2; i < c; ++i)
+               {
+                       dp_strlcat(msg, " ", sizeof(msg));
+                       dp_strlcat(msg, Cmd_Argv(cmd, i), sizeof(msg));
+               }
+
+               c = (unsigned int)strlen(msg);
+               for(p = 0, i = 0; i < c; ++i)
+               {
+                       if(msg[i] == '\\')
+                       {
+                               if(msg[i+1] == 'n')
+                                       msg[p++] = '\n';
+                               else if(msg[i+1] == '\\')
+                                       msg[p++] = '\\';
+                               else {
+                                       msg[p++] = '\\';
+                                       msg[p++] = msg[i+1];
+                               }
+                               ++i;
+                       } else {
+                               msg[p++] = msg[i];
+                       }
+               }
+               msg[p] = '\0';
+               SCR_CenterPrint(msg);
+       }
+}
 
 static void SCR_DrawCenterString (void)
 {
 
 static void SCR_DrawCenterString (void)
 {
@@ -611,11 +647,13 @@ SCR_DrawInfobar
 */
 static void SCR_DrawInfobar(void)
 {
 */
 static void SCR_DrawInfobar(void)
 {
-       int offset = 0;
+       unsigned int offset = 0;
        offset += SCR_DrawQWDownload(offset);
        offset += SCR_DrawCurlDownload(offset);
        if(scr_infobartime_off > 0)
                offset += SCR_DrawInfobarString(offset);
        offset += SCR_DrawQWDownload(offset);
        offset += SCR_DrawCurlDownload(offset);
        if(scr_infobartime_off > 0)
                offset += SCR_DrawInfobarString(offset);
+       if(!offset && scr_loading)
+               offset = scr_loadingscreen_barheight.integer;
        if(offset != scr_con_margin_bottom)
                Con_DPrintf("broken console margin calculation: %d != %d\n", offset, scr_con_margin_bottom);
 }
        if(offset != scr_con_margin_bottom)
                Con_DPrintf("broken console margin calculation: %d != %d\n", offset, scr_con_margin_bottom);
 }
@@ -656,7 +694,7 @@ static void SCR_InfoBar_f(cmd_state_t *cmd)
        if(Cmd_Argc(cmd) == 3)
        {
                scr_infobartime_off = atof(Cmd_Argv(cmd, 1));
        if(Cmd_Argc(cmd) == 3)
        {
                scr_infobartime_off = atof(Cmd_Argv(cmd, 1));
-               strlcpy(scr_infobarstring, Cmd_Argv(cmd, 2), sizeof(scr_infobarstring));
+               dp_strlcpy(scr_infobarstring, Cmd_Argv(cmd, 2), sizeof(scr_infobarstring));
        }
        else
        {
        }
        else
        {
@@ -672,8 +710,6 @@ SCR_SetUpToDrawConsole
 */
 static void SCR_SetUpToDrawConsole (void)
 {
 */
 static void SCR_SetUpToDrawConsole (void)
 {
-       // lines of console to display
-       float conlines;
 #ifdef CONFIG_MENU
        static int framecounter = 0;
 #endif
 #ifdef CONFIG_MENU
        static int framecounter = 0;
 #endif
@@ -699,13 +735,11 @@ static void SCR_SetUpToDrawConsole (void)
        else
                key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
 
        else
                key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
 
-// decide on the height of the console
+       // decide on the height of the console
        if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
        if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
-               conlines = vid_conheight.integer/2;     // half screen
+               scr_con_current = vid_conheight.integer * scr_conheight.value;
        else
        else
-               conlines = 0;                           // none visible
-
-       scr_con_current = conlines;
+               scr_con_current = 0; // none visible
 }
 
 /*
 }
 
 /*
@@ -715,533 +749,23 @@ SCR_DrawConsole
 */
 void SCR_DrawConsole (void)
 {
 */
 void SCR_DrawConsole (void)
 {
+       // infobar and loading progress are not drawn simultaneously
        scr_con_margin_bottom = SCR_InfobarHeight();
        scr_con_margin_bottom = SCR_InfobarHeight();
+       if (!scr_con_margin_bottom && scr_loading)
+               scr_con_margin_bottom = scr_loadingscreen_barheight.integer;
        if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
        {
                // full screen
        if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
        {
                // full screen
-               Con_DrawConsole (vid_conheight.integer - scr_con_margin_bottom);
+               Con_DrawConsole (vid_conheight.integer - scr_con_margin_bottom, true);
        }
        else if (scr_con_current)
        }
        else if (scr_con_current)
-               Con_DrawConsole (min((int)scr_con_current, vid_conheight.integer - scr_con_margin_bottom));
+               Con_DrawConsole (min(scr_con_current, vid_conheight.integer - scr_con_margin_bottom), false);
        else
                con_vislines = 0;
 }
 
        else
                con_vislines = 0;
 }
 
-qboolean scr_loading = false;
-
-/*
-===============
-SCR_BeginLoadingPlaque
-
-================
-*/
-void SCR_BeginLoadingPlaque (qboolean startup)
-{
-       scr_loading = true;
-       SCR_UpdateLoadingScreen(false, startup);
-}
-
-void SCR_EndLoadingPlaque(void)
-{
-       scr_loading = false;
-}
-
 //=============================================================================
 
 //=============================================================================
 
-const char *r_stat_name[r_stat_count] =
-{
-       "timedelta",
-       "quality",
-       "renders",
-       "entities",
-       "entities_surfaces",
-       "entities_triangles",
-       "world_leafs",
-       "world_portals",
-       "world_surfaces",
-       "world_triangles",
-       "lightmapupdates",
-       "lightmapupdatepixels",
-       "particles",
-       "drawndecals",
-       "totaldecals",
-       "draws",
-       "draws_vertices",
-       "draws_elements",
-       "lights",
-       "lights_clears",
-       "lights_scissored",
-       "lights_lighttriangles",
-       "lights_shadowtriangles",
-       "lights_dynamicshadowtriangles",
-       "bouncegrid_lights",
-       "bouncegrid_particles",
-       "bouncegrid_traces",
-       "bouncegrid_hits",
-       "bouncegrid_splats",
-       "bouncegrid_bounces",
-       "photoncache_animated",
-       "photoncache_cached",
-       "photoncache_traced",
-       "bloom",
-       "bloom_copypixels",
-       "bloom_drawpixels",
-       "rendertargets_used",
-       "rendertargets_pixels",
-       "indexbufferuploadcount",
-       "indexbufferuploadsize",
-       "vertexbufferuploadcount",
-       "vertexbufferuploadsize",
-       "framedatacurrent",
-       "framedatasize",
-       "bufferdatacurrent_vertex", // R_BUFFERDATA_ types are added to this index
-       "bufferdatacurrent_index16",
-       "bufferdatacurrent_index32",
-       "bufferdatacurrent_uniform",
-       "bufferdatasize_vertex", // R_BUFFERDATA_ types are added to this index
-       "bufferdatasize_index16",
-       "bufferdatasize_index32",
-       "bufferdatasize_uniform",
-       "animcache_skeletal_count",
-       "animcache_skeletal_bones",
-       "animcache_skeletal_maxbones",
-       "animcache_shade_count",
-       "animcache_shade_vertices",
-       "animcache_shade_maxvertices",
-       "animcache_shape_count",
-       "animcache_shape_vertices",
-       "animcache_shape_maxvertices",
-       "batch_batches",
-       "batch_withgaps",
-       "batch_surfaces",
-       "batch_vertices",
-       "batch_triangles",
-       "fast_batches",
-       "fast_surfaces",
-       "fast_vertices",
-       "fast_triangles",
-       "copytriangles_batches",
-       "copytriangles_surfaces",
-       "copytriangles_vertices",
-       "copytriangles_triangles",
-       "dynamic_batches",
-       "dynamic_surfaces",
-       "dynamic_vertices",
-       "dynamic_triangles",
-       "dynamicskeletal_batches",
-       "dynamicskeletal_surfaces",
-       "dynamicskeletal_vertices",
-       "dynamicskeletal_triangles",
-       "dynamic_batches_because_cvar",
-       "dynamic_surfaces_because_cvar",
-       "dynamic_vertices_because_cvar",
-       "dynamic_triangles_because_cvar",
-       "dynamic_batches_because_lightmapvertex",
-       "dynamic_surfaces_because_lightmapvertex",
-       "dynamic_vertices_because_lightmapvertex",
-       "dynamic_triangles_because_lightmapvertex",
-       "dynamic_batches_because_deformvertexes_autosprite",
-       "dynamic_surfaces_because_deformvertexes_autosprite",
-       "dynamic_vertices_because_deformvertexes_autosprite",
-       "dynamic_triangles_because_deformvertexes_autosprite",
-       "dynamic_batches_because_deformvertexes_autosprite2",
-       "dynamic_surfaces_because_deformvertexes_autosprite2",
-       "dynamic_vertices_because_deformvertexes_autosprite2",
-       "dynamic_triangles_because_deformvertexes_autosprite2",
-       "dynamic_batches_because_deformvertexes_normal",
-       "dynamic_surfaces_because_deformvertexes_normal",
-       "dynamic_vertices_because_deformvertexes_normal",
-       "dynamic_triangles_because_deformvertexes_normal",
-       "dynamic_batches_because_deformvertexes_wave",
-       "dynamic_surfaces_because_deformvertexes_wave",
-       "dynamic_vertices_because_deformvertexes_wave",
-       "dynamic_triangles_because_deformvertexes_wave",
-       "dynamic_batches_because_deformvertexes_bulge",
-       "dynamic_surfaces_because_deformvertexes_bulge",
-       "dynamic_vertices_because_deformvertexes_bulge",
-       "dynamic_triangles_because_deformvertexes_bulge",
-       "dynamic_batches_because_deformvertexes_move",
-       "dynamic_surfaces_because_deformvertexes_move",
-       "dynamic_vertices_because_deformvertexes_move",
-       "dynamic_triangles_because_deformvertexes_move",
-       "dynamic_batches_because_tcgen_lightmap",
-       "dynamic_surfaces_because_tcgen_lightmap",
-       "dynamic_vertices_because_tcgen_lightmap",
-       "dynamic_triangles_because_tcgen_lightmap",
-       "dynamic_batches_because_tcgen_vector",
-       "dynamic_surfaces_because_tcgen_vector",
-       "dynamic_vertices_because_tcgen_vector",
-       "dynamic_triangles_because_tcgen_vector",
-       "dynamic_batches_because_tcgen_environment",
-       "dynamic_surfaces_because_tcgen_environment",
-       "dynamic_vertices_because_tcgen_environment",
-       "dynamic_triangles_because_tcgen_environment",
-       "dynamic_batches_because_tcmod_turbulent",
-       "dynamic_surfaces_because_tcmod_turbulent",
-       "dynamic_vertices_because_tcmod_turbulent",
-       "dynamic_triangles_because_tcmod_turbulent",
-       "dynamic_batches_because_nogaps",
-       "dynamic_surfaces_because_nogaps",
-       "dynamic_vertices_because_nogaps",
-       "dynamic_triangles_because_nogaps",
-       "dynamic_batches_because_derived",
-       "dynamic_surfaces_because_derived",
-       "dynamic_vertices_because_derived",
-       "dynamic_triangles_because_derived",
-       "entitycache_count",
-       "entitycache_surfaces",
-       "entitycache_vertices",
-       "entitycache_triangles",
-       "entityanimate_count",
-       "entityanimate_surfaces",
-       "entityanimate_vertices",
-       "entityanimate_triangles",
-       "entityskeletal_count",
-       "entityskeletal_surfaces",
-       "entityskeletal_vertices",
-       "entityskeletal_triangles",
-       "entitystatic_count",
-       "entitystatic_surfaces",
-       "entitystatic_vertices",
-       "entitystatic_triangles",
-       "entitycustom_count",
-       "entitycustom_surfaces",
-       "entitycustom_vertices",
-       "entitycustom_triangles",
-};
-
-char r_speeds_timestring[4096];
-int speedstringcount, r_timereport_active;
-double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
-int r_speeds_longestitem = 0;
-
-void R_TimeReport(const char *desc)
-{
-       char tempbuf[256];
-       int length;
-       int t;
-
-       if (r_speeds.integer < 2 || !r_timereport_active)
-               return;
-
-       CHECKGLERROR
-       if (r_speeds.integer == 2)
-               GL_Finish();
-       CHECKGLERROR
-       r_timereport_temp = r_timereport_current;
-       r_timereport_current = Sys_DirtyTime();
-       t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
-
-       length = dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %s", t, desc);
-       if (length < 0)
-               length = (int)sizeof(tempbuf) - 1;
-       if (r_speeds_longestitem < length)
-               r_speeds_longestitem = length;
-       for (;length < r_speeds_longestitem;length++)
-               tempbuf[length] = ' ';
-       tempbuf[length] = 0;
-
-       if (speedstringcount + length > (vid_conwidth.integer / 8))
-       {
-               strlcat(r_speeds_timestring, "\n", sizeof(r_speeds_timestring));
-               speedstringcount = 0;
-       }
-       strlcat(r_speeds_timestring, tempbuf, sizeof(r_speeds_timestring));
-       speedstringcount += length;
-}
-
-static void R_TimeReport_BeginFrame(void)
-{
-       speedstringcount = 0;
-       r_speeds_timestring[0] = 0;
-       r_timereport_active = false;
-       memset(&r_refdef.stats, 0, sizeof(r_refdef.stats));
-
-       if (r_speeds.integer >= 2)
-       {
-               r_timereport_active = true;
-               r_timereport_start = r_timereport_current = Sys_DirtyTime();
-       }
-}
-
-static int R_CountLeafTriangles(const dp_model_t *model, const mleaf_t *leaf)
-{
-       int i, triangles = 0;
-       for (i = 0;i < leaf->numleafsurfaces;i++)
-               triangles += model->data_surfaces[leaf->firstleafsurface[i]].num_triangles;
-       return triangles;
-}
-
-#define R_SPEEDS_GRAPH_COLORS 8
-#define R_SPEEDS_GRAPH_TEXTLENGTH 64
-static float r_speeds_graph_colors[R_SPEEDS_GRAPH_COLORS][4] = {{1, 0, 0, 1}, {0, 1, 0, 1}, {0, 0, 1, 1}, {1, 1, 0, 1}, {0, 1, 1, 1}, {1, 0, 1, 1}, {1, 1, 1, 1}, {1, 0.5f, 0, 1}};
-
-extern cvar_t r_viewscale;
-extern float viewscalefpsadjusted;
-static void R_TimeReport_EndFrame(void)
-{
-       int j, lines;
-       cl_locnode_t *loc;
-       char string[1024+4096];
-       mleaf_t *viewleaf;
-       static double oldtime = 0;
-
-       r_refdef.stats[r_stat_timedelta] = (int)((host.realtime - oldtime) * 1000000.0);
-       oldtime = host.realtime;
-       r_refdef.stats[r_stat_quality] = (int)(100 * r_refdef.view.quality);
-
-       string[0] = 0;
-       if (r_speeds.integer)
-       {
-               // put the location name in the r_speeds display as it greatly helps
-               // when creating loc files
-               loc = CL_Locs_FindNearest(cl.movement_origin);
-               viewleaf = (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.PointInLeaf) ? r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, r_refdef.view.origin) : NULL;
-               dpsnprintf(string, sizeof(string),
-"%6ius time delta %s%s %.3f cl.time%2.4f brightness\n"
-"%3i renders org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n"
-"%5i viewleaf%5i cluster%3i area%4i brushes%4i surfaces(%7i triangles)\n"
-"%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n"
-"%5i leafs%5i portals%6i/%6i particles%6i/%6i decals %3i%% quality\n"
-"%7i lightmap updates (%7i pixels)%8i/%8i framedata\n"
-"%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n"
-"bouncegrid:%4i lights%6i particles%6i traces%6i hits%6i splats%6i bounces\n"
-"photon cache efficiency:%6i cached%6i traced%6ianimated\n"
-"%6i draws%8i vertices%8i triangles bloompixels%8i copied%8i drawn\n"
-"%3i rendertargets%8i pixels\n"
-"updated%5i indexbuffers%8i bytes%5i vertexbuffers%8i bytes\n"
-"animcache%5ib gpuskeletal%7i vertices (%7i with normals)\n"
-"fastbatch%5i count%5i surfaces%7i vertices %7i triangles\n"
-"copytris%5i count%5i surfaces%7i vertices %7i triangles\n"
-"dynamic%5i count%5i surfaces%7i vertices%7i triangles\n"
-"%s"
-, r_refdef.stats[r_stat_timedelta], loc ? "Location: " : "", loc ? loc->name : "", cl.time, r_refdef.view.colorscale
-, r_refdef.stats[r_stat_renders], r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2]
-, viewleaf ? (int)(viewleaf - r_refdef.scene.worldmodel->brush.data_leafs) : -1, viewleaf ? viewleaf->clusterindex : -1, viewleaf ? viewleaf->areaindex : -1, viewleaf ? viewleaf->numleafbrushes : 0, viewleaf ? viewleaf->numleafsurfaces : 0, viewleaf ? R_CountLeafTriangles(r_refdef.scene.worldmodel, viewleaf) : 0
-, r_refdef.stats[r_stat_world_surfaces], r_refdef.stats[r_stat_world_triangles], r_refdef.stats[r_stat_entities], r_refdef.stats[r_stat_entities_surfaces], r_refdef.stats[r_stat_entities_triangles]
-, r_refdef.stats[r_stat_world_leafs], r_refdef.stats[r_stat_world_portals], r_refdef.stats[r_stat_particles], cl.num_particles, r_refdef.stats[r_stat_drawndecals], r_refdef.stats[r_stat_totaldecals], r_refdef.stats[r_stat_quality]
-, r_refdef.stats[r_stat_lightmapupdates], r_refdef.stats[r_stat_lightmapupdatepixels], r_refdef.stats[r_stat_framedatacurrent], r_refdef.stats[r_stat_framedatasize]
-, r_refdef.stats[r_stat_lights], r_refdef.stats[r_stat_lights_clears], r_refdef.stats[r_stat_lights_scissored], r_refdef.stats[r_stat_lights_lighttriangles], r_refdef.stats[r_stat_lights_shadowtriangles], r_refdef.stats[r_stat_lights_dynamicshadowtriangles]
-, r_refdef.stats[r_stat_bouncegrid_lights], r_refdef.stats[r_stat_bouncegrid_particles], r_refdef.stats[r_stat_bouncegrid_traces], r_refdef.stats[r_stat_bouncegrid_hits], r_refdef.stats[r_stat_bouncegrid_splats], r_refdef.stats[r_stat_bouncegrid_bounces]
-, r_refdef.stats[r_stat_photoncache_cached], r_refdef.stats[r_stat_photoncache_traced], r_refdef.stats[r_stat_photoncache_animated]
-, r_refdef.stats[r_stat_draws], r_refdef.stats[r_stat_draws_vertices], r_refdef.stats[r_stat_draws_elements] / 3, r_refdef.stats[r_stat_bloom_copypixels], r_refdef.stats[r_stat_bloom_drawpixels]
-, r_refdef.stats[r_stat_rendertargets_used], r_refdef.stats[r_stat_rendertargets_pixels]
-, r_refdef.stats[r_stat_indexbufferuploadcount], r_refdef.stats[r_stat_indexbufferuploadsize], r_refdef.stats[r_stat_vertexbufferuploadcount], r_refdef.stats[r_stat_vertexbufferuploadsize]
-, r_refdef.stats[r_stat_animcache_skeletal_bones], r_refdef.stats[r_stat_animcache_shape_vertices], r_refdef.stats[r_stat_animcache_shade_vertices]
-, r_refdef.stats[r_stat_batch_fast_batches], r_refdef.stats[r_stat_batch_fast_surfaces], r_refdef.stats[r_stat_batch_fast_vertices], r_refdef.stats[r_stat_batch_fast_triangles]
-, r_refdef.stats[r_stat_batch_copytriangles_batches], r_refdef.stats[r_stat_batch_copytriangles_surfaces], r_refdef.stats[r_stat_batch_copytriangles_vertices], r_refdef.stats[r_stat_batch_copytriangles_triangles]
-, r_refdef.stats[r_stat_batch_dynamic_batches], r_refdef.stats[r_stat_batch_dynamic_surfaces], r_refdef.stats[r_stat_batch_dynamic_vertices], r_refdef.stats[r_stat_batch_dynamic_triangles]
-, r_speeds_timestring);
-       }
-
-       speedstringcount = 0;
-       r_speeds_timestring[0] = 0;
-       r_timereport_active = false;
-
-       if (r_speeds.integer >= 2)
-       {
-               r_timereport_active = true;
-               r_timereport_start = r_timereport_current = Sys_DirtyTime();
-       }
-
-       if (string[0])
-       {
-               int i, y;
-               if (string[strlen(string)-1] == '\n')
-                       string[strlen(string)-1] = 0;
-               lines = 1;
-               for (i = 0;string[i];i++)
-                       if (string[i] == '\n')
-                               lines++;
-               y = vid_conheight.integer - sb_lines - lines * 8;
-               i = j = 0;
-               r_draw2d_force = true;
-               DrawQ_Fill(0, y, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
-               while (string[i])
-               {
-                       j = i;
-                       while (string[i] && string[i] != '\n')
-                               i++;
-                       if (i - j > 0)
-                               DrawQ_String(0, y, string + j, i - j, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);
-                       if (string[i] == '\n')
-                               i++;
-                       y += 8;
-               }
-               r_draw2d_force = false;
-       }
-
-       if (r_speeds_graph_length.integer != bound(4, r_speeds_graph_length.integer, 8192))
-               Cvar_SetValueQuick(&r_speeds_graph_length, bound(4, r_speeds_graph_length.integer, 8192));
-       if (fabs(r_speeds_graph_seconds.value - bound(0.1f, r_speeds_graph_seconds.value, 120.0f)) > 0.01f)
-               Cvar_SetValueQuick(&r_speeds_graph_seconds, bound(0.1f, r_speeds_graph_seconds.value, 120.0f));
-       if (r_speeds_graph.integer)
-       {
-               // if we currently have no graph data, reset the graph data entirely
-               int i;
-               if (!cls.r_speeds_graph_data)
-                       for (i = 0;i < r_stat_count;i++)
-                               cls.r_speeds_graph_datamin[i] = cls.r_speeds_graph_datamax[i] = 0;
-               if (cls.r_speeds_graph_length != r_speeds_graph_length.integer)
-               {
-                       int stat, index, d, graph_length, *graph_data;
-                       cls.r_speeds_graph_length = r_speeds_graph_length.integer;
-                       cls.r_speeds_graph_current = 0;
-                       if (cls.r_speeds_graph_data)
-                               Mem_Free(cls.r_speeds_graph_data);
-                       cls.r_speeds_graph_data = (int *)Mem_Alloc(cls.permanentmempool, cls.r_speeds_graph_length * sizeof(r_refdef.stats));
-                       // initialize the graph to have the current values throughout history
-                       graph_data = cls.r_speeds_graph_data;
-                       graph_length = cls.r_speeds_graph_length;
-                       index = 0;
-                       for (stat = 0;stat < r_stat_count;stat++)
-                       {
-                               d = r_refdef.stats[stat];
-                               if (stat == r_stat_timedelta)
-                                       d = 0;
-                               for (i = 0;i < graph_length;i++)
-                                       graph_data[index++] = d;
-                       }
-               }
-       }
-       else
-       {
-               if (cls.r_speeds_graph_length)
-               {
-                       cls.r_speeds_graph_length = 0;
-                       Mem_Free(cls.r_speeds_graph_data);
-                       cls.r_speeds_graph_data = NULL;
-                       cls.r_speeds_graph_current = 0;
-               }
-       }
-
-       if (cls.r_speeds_graph_length)
-       {
-               char legend[128];
-               int i;
-               const int *data;
-               float x, y, width, height, scalex, scaley;
-               int range_default = max(r_speeds_graph_maxdefault.integer, 1);
-               int color, stat, stats, index, range_min, range_max;
-               int graph_current, graph_length, *graph_data;
-               int statindex[R_SPEEDS_GRAPH_COLORS];
-               int sum;
-
-               // add current stats to the graph_data
-               cls.r_speeds_graph_current++;
-               if (cls.r_speeds_graph_current >= cls.r_speeds_graph_length)
-                       cls.r_speeds_graph_current = 0;
-               // poke each new stat into the current offset of its graph
-               graph_data = cls.r_speeds_graph_data;
-               graph_current = cls.r_speeds_graph_current;
-               graph_length = cls.r_speeds_graph_length;
-               for (stat = 0;stat < r_stat_count;stat++)
-                       graph_data[stat * graph_length + graph_current] = r_refdef.stats[stat];
-
-               // update the graph ranges
-               for (stat = 0;stat < r_stat_count;stat++)
-               {
-                       if (cls.r_speeds_graph_datamin[stat] > r_refdef.stats[stat])
-                               cls.r_speeds_graph_datamin[stat] = r_refdef.stats[stat];
-                       if (cls.r_speeds_graph_datamax[stat] < r_refdef.stats[stat])
-                               cls.r_speeds_graph_datamax[stat] = r_refdef.stats[stat];
-               }
-
-               // force 2D drawing to occur even if r_render is 0
-               r_draw2d_force = true;
-
-               // position the graph
-               width = r_speeds_graph_width.value;
-               height = r_speeds_graph_height.value;
-               x = bound(0, r_speeds_graph_x.value, vid_conwidth.value - width);
-               y = bound(0, r_speeds_graph_y.value, vid_conheight.value - height);
-
-               // fill background with a pattern of gray and black at one second intervals
-               scalex = (float)width / (float)r_speeds_graph_seconds.value;
-               for (i = 0;i < r_speeds_graph_seconds.integer + 1;i++)
-               {
-                       float x1 = x + width - (i + 1) * scalex;
-                       float x2 = x + width - i * scalex;
-                       if (x1 < x)
-                               x1 = x;
-                       if (i & 1)
-                               DrawQ_Fill(x1, y, x2 - x1, height, 0.0f, 0.0f, 0.0f, 0.5f, 0);
-                       else
-                               DrawQ_Fill(x1, y, x2 - x1, height, 0.2f, 0.2f, 0.2f, 0.5f, 0);
-               }
-
-               // count how many stats match our pattern
-               stats = 0;
-               color = 0;
-               for (color = 0;color < R_SPEEDS_GRAPH_COLORS;color++)
-               {
-                       // look at all stat names and find ones matching the filter
-                       statindex[color] = -1;
-                       if (!r_speeds_graph_filter[color].string)
-                               continue;
-                       for (stat = 0;stat < r_stat_count;stat++)
-                               if (!strcmp(r_stat_name[stat], r_speeds_graph_filter[color].string))
-                                       break;
-                       if (stat >= r_stat_count)
-                               continue;
-                       // record that this color is this stat for the line drawing loop
-                       statindex[color] = stat;
-                       // draw the legend text in the background of the graph
-                       dpsnprintf(legend, sizeof(legend), "%10i :%s", graph_data[stat * graph_length + graph_current], r_stat_name[stat]);
-                       DrawQ_String(x, y + stats * 8, legend, 0, 8, 8, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3] * 1.00f, 0, NULL, true, FONT_DEFAULT);
-                       // count how many stats we need to graph in vertex buffer
-                       stats++;
-               }
-
-               if (stats)
-               {
-                       // legend text is drawn after the graphs
-                       // render the graph lines, we'll go back and render the legend text later
-                       scalex = (float)width / (1000000.0 * r_speeds_graph_seconds.value);
-                       stats = 0;
-                       for (color = 0;color < R_SPEEDS_GRAPH_COLORS;color++)
-                       {
-                               // look at all stat names and find ones matching the filter
-                               stat = statindex[color];
-                               if (stat < 0)
-                                       continue;
-                               // prefer to graph stats with 0 base, but if they are
-                               // negative we have no choice
-                               range_min = cls.r_speeds_graph_datamin[stat];
-                               range_max = max(cls.r_speeds_graph_datamax[stat], range_min + range_default);
-                               // some stats we specifically override the graph scale on
-                               if (stat == r_stat_timedelta)
-                                       range_max = r_speeds_graph_maxtimedelta.integer;
-                               scaley = height / (range_max - range_min);
-                               // generate lines (2 vertices each)
-                               // to deal with incomplete data we walk right to left
-                               data = graph_data + stat * graph_length;
-                               index = graph_current;
-                               sum = 0;
-                               for (i = 0;i < graph_length - 1;)
-                               {
-                                       float x1, y1, x2, y2;
-                                       x1 = max(x, x + width - sum * scalex);
-                                       y1 = y + height - (data[index] - range_min) * scaley;
-                                       sum += graph_data[r_stat_timedelta * graph_length + index];
-                                       index--;
-                                       if (index < 0)
-                                               index = graph_length - 1;
-                                       i++;
-                                       x2 = max(x, x + width - sum * scalex);
-                                       y2 = y + height - (data[index] - range_min) * scaley;
-                                       DrawQ_Line(1, x1, y1, x2, y2, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3], 0);
-                               }
-                       }
-               }
-
-               // return to not drawing anything if r_render is 0
-               r_draw2d_force = false;
-       }
-
-       memset(&r_refdef.stats, 0, sizeof(r_refdef.stats));
-}
-
 /*
 =================
 SCR_SizeUp_f
 /*
 =================
 SCR_SizeUp_f
@@ -1294,6 +818,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_conscroll3_y);
        Cvar_RegisterVariable (&scr_conbrightness);
        Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
        Cvar_RegisterVariable (&scr_conscroll3_y);
        Cvar_RegisterVariable (&scr_conbrightness);
        Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
+       Cvar_RegisterVariable (&scr_conheight);
 #ifdef CONFIG_MENU
        Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
 #endif
 #ifdef CONFIG_MENU
        Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
 #endif
@@ -1314,6 +839,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_showbrand);
        Cvar_RegisterVariable (&scr_centertime);
        Cvar_RegisterVariable (&scr_printspeed);
        Cvar_RegisterVariable (&scr_showbrand);
        Cvar_RegisterVariable (&scr_centertime);
        Cvar_RegisterVariable (&scr_printspeed);
+       Cvar_RegisterVariable (&scr_sbarscale);
        Cvar_RegisterVariable (&vid_conwidth);
        Cvar_RegisterVariable (&vid_conheight);
        Cvar_RegisterVariable (&vid_pixelheight);
        Cvar_RegisterVariable (&vid_conwidth);
        Cvar_RegisterVariable (&vid_conheight);
        Cvar_RegisterVariable (&vid_pixelheight);
@@ -1350,7 +876,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable(&scr_stipple);
        Cvar_RegisterVariable(&scr_refresh);
        Cvar_RegisterVariable(&net_graph);
        Cvar_RegisterVariable(&scr_stipple);
        Cvar_RegisterVariable(&scr_refresh);
        Cvar_RegisterVariable(&net_graph);
-       Cvar_RegisterAlias(&net_graph, "shownetgraph");
+       Cvar_RegisterVirtual(&net_graph, "shownetgraph");
        Cvar_RegisterVariable(&cl_demo_mousegrab);
        Cvar_RegisterVariable(&timedemo_screenshotframelist);
        Cvar_RegisterVariable(&vid_touchscreen_outlinealpha);
        Cvar_RegisterVariable(&cl_demo_mousegrab);
        Cvar_RegisterVariable(&timedemo_screenshotframelist);
        Cvar_RegisterVariable(&vid_touchscreen_outlinealpha);
@@ -1371,11 +897,12 @@ void CL_Screen_Init(void)
        if (Sys_CheckParm ("-noconsole"))
                Cvar_SetQuick(&scr_conforcewhiledisconnected, "0");
 
        if (Sys_CheckParm ("-noconsole"))
                Cvar_SetQuick(&scr_conforcewhiledisconnected, "0");
 
-       Cmd_AddCommand(CMD_CLIENT, "sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
-       Cmd_AddCommand(CMD_CLIENT, "sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
-       Cmd_AddCommand(CMD_CLIENT, "screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
-       Cmd_AddCommand(CMD_CLIENT, "envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
-       Cmd_AddCommand(CMD_CLIENT, "infobar", SCR_InfoBar_f, "display a text in the infobar (usage: infobar expiretime string)");
+       Cmd_AddCommand(CF_CLIENT, "cprint", SCR_Centerprint_f, "print something at the screen center");
+       Cmd_AddCommand(CF_CLIENT, "sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
+       Cmd_AddCommand(CF_CLIENT, "sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
+       Cmd_AddCommand(CF_CLIENT, "screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
+       Cmd_AddCommand(CF_CLIENT, "envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
+       Cmd_AddCommand(CF_CLIENT, "infobar", SCR_InfoBar_f, "display a text in the infobar (usage: infobar expiretime string)");
 
 #ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo_Ogg_Init();
 
 #ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo_Ogg_Init();
@@ -1397,14 +924,14 @@ void SCR_ScreenShot_f(cmd_state_t *cmd)
        char filename[MAX_QPATH];
        unsigned char *buffer1;
        unsigned char *buffer2;
        char filename[MAX_QPATH];
        unsigned char *buffer1;
        unsigned char *buffer2;
-       qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
-       qboolean png = (scr_screenshot_png.integer != 0) && !jpeg;
+       qbool jpeg = (scr_screenshot_jpeg.integer != 0);
+       qbool png = (scr_screenshot_png.integer != 0) && !jpeg;
        char vabuf[1024];
 
        if (Cmd_Argc(cmd) == 2)
        {
                const char *ext;
        char vabuf[1024];
 
        if (Cmd_Argc(cmd) == 2)
        {
                const char *ext;
-               strlcpy(filename, Cmd_Argv(cmd, 1), sizeof(filename));
+               dp_strlcpy(filename, Cmd_Argv(cmd, 1), sizeof(filename));
                ext = FS_FileExtension(filename);
                if (!strcasecmp(ext, "jpg"))
                {
                ext = FS_FileExtension(filename);
                if (!strcasecmp(ext, "jpg"))
                {
@@ -1432,10 +959,11 @@ void SCR_ScreenShot_f(cmd_state_t *cmd)
                int shotnumber100;
 
                // TODO maybe make capturevideo and screenshot use similar name patterns?
                int shotnumber100;
 
                // TODO maybe make capturevideo and screenshot use similar name patterns?
+               Sys_TimeString(vabuf, sizeof(vabuf), "%Y%m%d%H%M%S");
                if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
                if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
-                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s%s", cl.worldbasename, scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S"));
+                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s%s", cl.worldbasename, scr_screenshot_name.string, vabuf);
                else
                else
-                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s%s", scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S"));
+                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s%s", scr_screenshot_name.string, vabuf);
 
                // find a file name to save it to
                for (shotnumber100 = 0;shotnumber100 < 100;shotnumber100++)
 
                // find a file name to save it to
                for (shotnumber100 = 0;shotnumber100 < 100;shotnumber100++)
@@ -1454,10 +982,11 @@ void SCR_ScreenShot_f(cmd_state_t *cmd)
        else
        {
                // TODO maybe make capturevideo and screenshot use similar name patterns?
        else
        {
                // TODO maybe make capturevideo and screenshot use similar name patterns?
+               Sys_TimeString(vabuf, sizeof(vabuf), scr_screenshot_name.string);
                if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
                if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
-                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, Sys_TimeString(scr_screenshot_name.string));
+                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, vabuf);
                else
                else
-                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string));
+                       dpsnprintf(prefix_name, sizeof(prefix_name), "%s", vabuf);
 
                // if prefix changed, gamedir or map changed, reset the shotnumber so
                // we scan again
 
                // if prefix changed, gamedir or map changed, reset the shotnumber so
                // we scan again
@@ -1485,19 +1014,19 @@ void SCR_ScreenShot_f(cmd_state_t *cmd)
                shotnumber++;
        }
 
                shotnumber++;
        }
 
-       buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
-       buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (scr_screenshot_alpha.integer ? 4 : 3));
+       buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.mode.width * vid.mode.height * 4);
+       buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.mode.width * vid.mode.height * (scr_screenshot_alpha.integer ? 4 : 3));
 
 
-       if (SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, jpeg, png, true, scr_screenshot_alpha.integer != 0))
+       if (SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.mode.width, vid.mode.height, false, false, false, jpeg, png, true, scr_screenshot_alpha.integer != 0))
                Con_Printf("Wrote %s\n", filename);
        else
        {
                Con_Printf(CON_ERROR "Unable to write %s\n", filename);
                if(jpeg || png)
                {
                Con_Printf("Wrote %s\n", filename);
        else
        {
                Con_Printf(CON_ERROR "Unable to write %s\n", filename);
                if(jpeg || png)
                {
-                       if(SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, false, false, true, scr_screenshot_alpha.integer != 0))
+                       if(SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.mode.width, vid.mode.height, false, false, false, false, false, true, scr_screenshot_alpha.integer != 0))
                        {
                        {
-                               strlcpy(filename + strlen(filename) - 3, "tga", 4);
+                               dp_strlcpy(filename + strlen(filename) - 3, "tga", 4);
                                Con_Printf("Wrote %s\n", filename);
                        }
                }
                                Con_Printf("Wrote %s\n", filename);
                        }
                }
@@ -1513,20 +1042,22 @@ static void SCR_CaptureVideo_BeginVideo(void)
        double r, g, b;
        unsigned int i;
        int width = cl_capturevideo_width.integer, height = cl_capturevideo_height.integer;
        double r, g, b;
        unsigned int i;
        int width = cl_capturevideo_width.integer, height = cl_capturevideo_height.integer;
+       char timestring[128];
+
        if (cls.capturevideo.active)
                return;
        memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
        // soundrate is figured out on the first SoundFrame
 
        if(width == 0 && height != 0)
        if (cls.capturevideo.active)
                return;
        memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
        // soundrate is figured out on the first SoundFrame
 
        if(width == 0 && height != 0)
-               width = (int) (height * (double)vid.width / ((double)vid.height * vid_pixelheight.value)); // keep aspect
+               width = (int) (height * (double)vid.mode.width / ((double)vid.mode.height * vid_pixelheight.value)); // keep aspect
        if(width != 0 && height == 0)
        if(width != 0 && height == 0)
-               height = (int) (width * ((double)vid.height * vid_pixelheight.value) / (double)vid.width); // keep aspect
+               height = (int) (width * ((double)vid.mode.height * vid_pixelheight.value) / (double)vid.mode.width); // keep aspect
 
 
-       if(width < 2 || width > vid.width) // can't scale up
-               width = vid.width;
-       if(height < 2 || height > vid.height) // can't scale up
-               height = vid.height;
+       if(width < 2 || width > vid.mode.width) // can't scale up
+               width = vid.mode.width;
+       if(height < 2 || height > vid.mode.height) // can't scale up
+               height = vid.mode.height;
 
        // ensure it's all even; if not, scale down a little
        if(width % 1)
 
        // ensure it's all even; if not, scale down a little
        if(width % 1)
@@ -1546,11 +1077,14 @@ static void SCR_CaptureVideo_BeginVideo(void)
        cls.capturevideo.starttime = cls.capturevideo.lastfpstime = host.realtime;
        cls.capturevideo.soundsampleframe = 0;
        cls.capturevideo.realtime = cl_capturevideo_realtime.integer != 0;
        cls.capturevideo.starttime = cls.capturevideo.lastfpstime = host.realtime;
        cls.capturevideo.soundsampleframe = 0;
        cls.capturevideo.realtime = cl_capturevideo_realtime.integer != 0;
-       cls.capturevideo.screenbuffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
-       cls.capturevideo.outbuffer = (unsigned char *)Mem_Alloc(tempmempool, width * height * (4+4) + 18);
-       dpsnprintf(cls.capturevideo.basename, sizeof(cls.capturevideo.basename), "video/%s%03i", Sys_TimeString(cl_capturevideo_nameformat.string), cl_capturevideo_number.integer);
+       cls.capturevideo.outbuffer = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4 + 18); // +18 ?
+       Sys_TimeString(timestring, sizeof(timestring), cl_capturevideo_nameformat.string);
+       dpsnprintf(cls.capturevideo.basename, sizeof(cls.capturevideo.basename), "video/%s%03i", timestring, cl_capturevideo_number.integer);
        Cvar_SetValueQuick(&cl_capturevideo_number, cl_capturevideo_number.integer + 1);
 
        Cvar_SetValueQuick(&cl_capturevideo_number, cl_capturevideo_number.integer + 1);
 
+       // capture demos as fast as possible
+       host.restless = !cls.capturevideo.realtime;
+
        /*
        for (i = 0;i < 256;i++)
        {
        /*
        for (i = 0;i < 256;i++)
        {
@@ -1604,6 +1138,8 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
                cls.capturevideo.yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
        }
 
                cls.capturevideo.yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
        }
 
+       GL_CaptureVideo_BeginVideo();
+
        if (cl_capturevideo_ogg.integer)
        {
                if(SCR_CaptureVideo_Ogg_Available())
        if (cl_capturevideo_ogg.integer)
        {
                if(SCR_CaptureVideo_Ogg_Available())
@@ -1623,19 +1159,14 @@ void SCR_CaptureVideo_EndVideo(void)
        if (!cls.capturevideo.active)
                return;
        cls.capturevideo.active = false;
        if (!cls.capturevideo.active)
                return;
        cls.capturevideo.active = false;
+       host.restless = false;
 
        Con_Printf("Finishing capture of %s.%s (%d frames, %d audio frames)\n", cls.capturevideo.basename, cls.capturevideo.formatextension, cls.capturevideo.frame, cls.capturevideo.soundsampleframe);
 
 
        Con_Printf("Finishing capture of %s.%s (%d frames, %d audio frames)\n", cls.capturevideo.basename, cls.capturevideo.formatextension, cls.capturevideo.frame, cls.capturevideo.soundsampleframe);
 
-       if (cls.capturevideo.videofile)
-       {
-               cls.capturevideo.endvideo();
-       }
+       GL_CaptureVideo_EndVideo(); // must be called before writeEndVideo !
 
 
-       if (cls.capturevideo.screenbuffer)
-       {
-               Mem_Free (cls.capturevideo.screenbuffer);
-               cls.capturevideo.screenbuffer = NULL;
-       }
+       if (cls.capturevideo.videofile)
+               cls.capturevideo.writeEndVideo();
 
        if (cls.capturevideo.outbuffer)
        {
 
        if (cls.capturevideo.outbuffer)
        {
@@ -1643,107 +1174,40 @@ void SCR_CaptureVideo_EndVideo(void)
                cls.capturevideo.outbuffer = NULL;
        }
 
                cls.capturevideo.outbuffer = NULL;
        }
 
-       memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
-}
-
-static void SCR_ScaleDownBGRA(unsigned char *in, int inw, int inh, unsigned char *out, int outw, int outh)
-{
-       // TODO optimize this function
-
-       int x, y;
-       float area;
-
-       // memcpy is faster than me
-       if(inw == outw && inh == outh)
-       {
-               memcpy(out, in, 4 * inw * inh);
-               return;
-       }
-
-       // otherwise: a box filter
-       area = (float)outw * (float)outh / (float)inw / (float)inh;
-       for(y = 0; y < outh; ++y)
-       {
-               float iny0 =  y    / (float)outh * inh; int iny0_i = (int) floor(iny0);
-               float iny1 = (y+1) / (float)outh * inh; int iny1_i = (int) ceil(iny1);
-               for(x = 0; x < outw; ++x)
-               {
-                       float inx0 =  x    / (float)outw * inw; int inx0_i = (int) floor(inx0);
-                       float inx1 = (x+1) / (float)outw * inw; int inx1_i = (int) ceil(inx1);
-                       float r = 0, g = 0, b = 0, alpha = 0;
-                       int xx, yy;
-
-                       for(yy = iny0_i; yy < iny1_i; ++yy)
-                       {
-                               float ya = min(yy+1, iny1) - max(iny0, yy);
-                               for(xx = inx0_i; xx < inx1_i; ++xx)
-                               {
-                                       float a = ya * (min(xx+1, inx1) - max(inx0, xx));
-                                       r += a * in[4*(xx + inw * yy)+0];
-                                       g += a * in[4*(xx + inw * yy)+1];
-                                       b += a * in[4*(xx + inw * yy)+2];
-                                       alpha += a * in[4*(xx + inw * yy)+3];
-                               }
-                       }
-
-                       out[4*(x + outw * y)+0] = (unsigned char) (r * area);
-                       out[4*(x + outw * y)+1] = (unsigned char) (g * area);
-                       out[4*(x + outw * y)+2] = (unsigned char) (b * area);
-                       out[4*(x + outw * y)+3] = (unsigned char) (alpha * area);
-               }
-       }
-}
-
-static void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
-{
-       int x = 0, y = 0;
-       int width = cls.capturevideo.width, height = cls.capturevideo.height;
+       // If demo capture failed don't leave the demo playing.
+       // CL_StopPlayback shuts down when demo capture finishes successfully.
+       if (cls.capturevideo.error && Sys_CheckParm("-capturedemo"))
+               host.state = host_shutdown;
 
 
-       if(newframestepframenum == cls.capturevideo.framestepframe)
-               return;
-
-       CHECKGLERROR
-       // speed is critical here, so do saving as directly as possible
-
-       GL_ReadPixelsBGRA(x, y, vid.width, vid.height, cls.capturevideo.screenbuffer);
-
-       SCR_ScaleDownBGRA (cls.capturevideo.screenbuffer, vid.width, vid.height, cls.capturevideo.outbuffer, width, height);
-
-       cls.capturevideo.videoframes(newframestepframenum - cls.capturevideo.framestepframe);
-       cls.capturevideo.framestepframe = newframestepframenum;
-
-       if(cl_capturevideo_printfps.integer)
-       {
-               char buf[80];
-               double t = host.realtime;
-               if(t > cls.capturevideo.lastfpstime + 1)
-               {
-                       double fps1 = (cls.capturevideo.frame - cls.capturevideo.lastfpsframe) / (t - cls.capturevideo.lastfpstime + 0.0000001);
-                       double fps  = (cls.capturevideo.frame                                ) / (t - cls.capturevideo.starttime   + 0.0000001);
-                       dpsnprintf(buf, sizeof(buf), "capturevideo: (%.1fs) last second %.3ffps, total %.3ffps\n", cls.capturevideo.frame / cls.capturevideo.framerate, fps1, fps);
-                       Sys_PrintToTerminal(buf);
-                       cls.capturevideo.lastfpstime = t;
-                       cls.capturevideo.lastfpsframe = cls.capturevideo.frame;
-               }
-       }
+       memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
 }
 
 void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
 {
        cls.capturevideo.soundsampleframe += (int)length;
 }
 
 void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
 {
        cls.capturevideo.soundsampleframe += (int)length;
-       cls.capturevideo.soundframe(paintbuffer, length);
+       cls.capturevideo.writeSoundFrame(paintbuffer, length);
 }
 
 static void SCR_CaptureVideo(void)
 {
        int newframenum;
 }
 
 static void SCR_CaptureVideo(void)
 {
        int newframenum;
+       int newframestepframenum;
+
        if (cl_capturevideo.integer)
        {
                if (!cls.capturevideo.active)
                        SCR_CaptureVideo_BeginVideo();
        if (cl_capturevideo.integer)
        {
                if (!cls.capturevideo.active)
                        SCR_CaptureVideo_BeginVideo();
+               if (cls.capturevideo.error)
+               {
+                       // specific error message was printed already
+                       Cvar_SetValueQuick(&cl_capturevideo, 0);
+                       SCR_CaptureVideo_EndVideo();
+                       return;
+               }
+
                if (cls.capturevideo.framerate != cl_capturevideo_fps.value * cl_capturevideo_framestep.integer)
                {
                if (cls.capturevideo.framerate != cl_capturevideo_fps.value * cl_capturevideo_framestep.integer)
                {
-                       Con_Printf("You can not change the video framerate while recording a video.\n");
+                       Con_Printf(CON_WARN "You can not change the video framerate while recording a video.\n");
                        Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo.framerate / (double) cl_capturevideo_framestep.integer);
                }
                // for AVI saving we have to make sure that sound is saved before video
                        Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo.framerate / (double) cl_capturevideo_framestep.integer);
                }
                // for AVI saving we have to make sure that sound is saved before video
@@ -1760,17 +1224,32 @@ static void SCR_CaptureVideo(void)
                if (newframenum - cls.capturevideo.frame > 60 * (int)ceil(cls.capturevideo.framerate))
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
                if (newframenum - cls.capturevideo.frame > 60 * (int)ceil(cls.capturevideo.framerate))
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
-                       Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo.frame);
+                       Con_Printf(CON_ERROR "video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo.frame);
                        SCR_CaptureVideo_EndVideo();
                        return;
                }
                // write frames
                        SCR_CaptureVideo_EndVideo();
                        return;
                }
                // write frames
-               SCR_CaptureVideo_VideoFrame(newframenum / cls.capturevideo.framestep);
+               newframestepframenum = newframenum / cls.capturevideo.framestep;
+               if (newframestepframenum != cls.capturevideo.framestepframe)
+                       GL_CaptureVideo_VideoFrame(newframestepframenum);
+               cls.capturevideo.framestepframe = newframestepframenum;
+               // report progress
+               if(cl_capturevideo_printfps.value && host.realtime > cls.capturevideo.lastfpstime + cl_capturevideo_printfps.value)
+               {
+                       double fps1 = (cls.capturevideo.frame - cls.capturevideo.lastfpsframe) / (host.realtime - cls.capturevideo.lastfpstime + 0.0000001);
+                       double fps  = (cls.capturevideo.frame                                ) / (host.realtime - cls.capturevideo.starttime   + 0.0000001);
+                       Sys_Printf("captured %.1fs of video, last second %.3ffps (%.1fx), total %.3ffps (%.1fx)\n",
+                                       cls.capturevideo.frame / cls.capturevideo.framerate,
+                                       fps1, fps1 / cls.capturevideo.framerate,
+                                       fps, fps / cls.capturevideo.framerate);
+                       cls.capturevideo.lastfpstime = host.realtime;
+                       cls.capturevideo.lastfpsframe = cls.capturevideo.frame;
+               }
                cls.capturevideo.frame = newframenum;
                if (cls.capturevideo.error)
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
                cls.capturevideo.frame = newframenum;
                if (cls.capturevideo.error)
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
-                       Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo.frame);
+                       Con_Printf(CON_ERROR "video saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo.frame);
                        SCR_CaptureVideo_EndVideo();
                }
        }
                        SCR_CaptureVideo_EndVideo();
                }
        }
@@ -1790,7 +1269,7 @@ struct envmapinfo_s
 {
        float angles[3];
        const char *name;
 {
        float angles[3];
        const char *name;
-       qboolean flipx, flipy, flipdiagonaly;
+       qbool flipx, flipy, flipdiagonaly;
 }
 envmapinfo[12] =
 {
 }
 envmapinfo[12] =
 {
@@ -1828,14 +1307,14 @@ static void R_Envmap_f(cmd_state_t *cmd)
                return;
        }
 
                return;
        }
 
-       strlcpy (basename, Cmd_Argv(cmd, 1), sizeof (basename));
+       dp_strlcpy (basename, Cmd_Argv(cmd, 1), sizeof (basename));
        size = atoi(Cmd_Argv(cmd, 2));
        if (size != 128 && size != 256 && size != 512 && size != 1024)
        {
                Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
                return;
        }
        size = atoi(Cmd_Argv(cmd, 2));
        if (size != 128 && size != 256 && size != 512 && size != 1024)
        {
                Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
                return;
        }
-       if (size > vid.width || size > vid.height)
+       if (size > vid.mode.width || size > vid.mode.height)
        {
                Con_Print("envmap: your resolution is not big enough to render that size\n");
                return;
        {
                Con_Print("envmap: your resolution is not big enough to render that size\n");
                return;
@@ -1875,7 +1354,7 @@ static void R_Envmap_f(cmd_state_t *cmd)
                R_Mesh_Start();
                R_RenderView(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, size, size);
                R_Mesh_Finish();
                R_Mesh_Start();
                R_RenderView(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, size, size);
                R_Mesh_Finish();
-               SCR_ScreenShot(filename, buffer1, buffer2, 0, vid.height - (r_refdef.view.y + r_refdef.view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false, false, false);
+               SCR_ScreenShot(filename, buffer1, buffer2, 0, vid.mode.height - (r_refdef.view.y + r_refdef.view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false, false, false);
        }
 
        Mem_Free (buffer1);
        }
 
        Mem_Free (buffer1);
@@ -1904,8 +1383,8 @@ void SHOWLMP_decodeshow(void)
        int k;
        char lmplabel[256], picname[256];
        float x, y;
        int k;
        char lmplabel[256], picname[256];
        float x, y;
-       strlcpy (lmplabel,MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (lmplabel));
-       strlcpy (picname, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (picname));
+       dp_strlcpy (lmplabel,MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (lmplabel));
+       dp_strlcpy (picname, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (picname));
        if (gamemode == GAME_NEHAHRA) // LadyHavoc: nasty old legacy junk
        {
                x = MSG_ReadByte(&cl_message);
        if (gamemode == GAME_NEHAHRA) // LadyHavoc: nasty old legacy junk
        {
                x = MSG_ReadByte(&cl_message);
@@ -1936,8 +1415,8 @@ void SHOWLMP_decodeshow(void)
                        if (!cl.showlmps[k].isactive)
                                break;
        cl.showlmps[k].isactive = true;
                        if (!cl.showlmps[k].isactive)
                                break;
        cl.showlmps[k].isactive = true;
-       strlcpy (cl.showlmps[k].label, lmplabel, sizeof (cl.showlmps[k].label));
-       strlcpy (cl.showlmps[k].pic, picname, sizeof (cl.showlmps[k].pic));
+       dp_strlcpy (cl.showlmps[k].label, lmplabel, sizeof (cl.showlmps[k].label));
+       dp_strlcpy (cl.showlmps[k].pic, picname, sizeof (cl.showlmps[k].pic));
        cl.showlmps[k].x = x;
        cl.showlmps[k].y = y;
        cl.num_showlmps = max(cl.num_showlmps, k + 1);
        cl.showlmps[k].x = x;
        cl.showlmps[k].y = y;
        cl.num_showlmps = max(cl.num_showlmps, k + 1);
@@ -1961,10 +1440,10 @@ void SHOWLMP_drawall(void)
 
 // buffer1: 4*w*h
 // buffer2: 3*w*h (or 4*w*h if screenshotting alpha too)
 
 // buffer1: 4*w*h
 // buffer2: 3*w*h (or 4*w*h if screenshotting alpha too)
-qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *buffer2, int x, int y, int width, int height, qboolean flipx, qboolean flipy, qboolean flipdiagonal, qboolean jpeg, qboolean png, qboolean gammacorrect, qboolean keep_alpha)
+qbool SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *buffer2, int x, int y, int width, int height, qbool flipx, qbool flipy, qbool flipdiagonal, qbool jpeg, qbool png, qbool gammacorrect, qbool keep_alpha)
 {
        int     indices[4] = {0,1,2,3}; // BGRA
 {
        int     indices[4] = {0,1,2,3}; // BGRA
-       qboolean ret;
+       qbool ret;
 
        GL_ReadPixelsBGRA(x, y, width, height, buffer1);
 
 
        GL_ReadPixelsBGRA(x, y, width, height, buffer1);
 
@@ -2052,7 +1531,7 @@ static void SCR_DrawTouchscreenOverlay(void)
        }
 }
 
        }
 }
 
-void R_ClearScreen(qboolean fogcolor)
+void R_ClearScreen(qbool fogcolor)
 {
        float clearcolor[4];
        if (scr_screenshot_alpha.integer)
 {
        float clearcolor[4];
        if (scr_screenshot_alpha.integer)
@@ -2085,32 +1564,27 @@ typedef struct loadingscreenstack_s
 }
 loadingscreenstack_t;
 static loadingscreenstack_t *loadingscreenstack = NULL;
 }
 loadingscreenstack_t;
 static loadingscreenstack_t *loadingscreenstack = NULL;
-static qboolean loadingscreendone = false;
-static qboolean loadingscreencleared = false;
-static float loadingscreenheight = 0;
-rtexture_t *loadingscreentexture = NULL;
+rtexture_t *loadingscreentexture = NULL; // last framebuffer before loading screen, kept for the background
 static float loadingscreentexture_vertex3f[12];
 static float loadingscreentexture_texcoord2f[8];
 static int loadingscreenpic_number = 0;
 static float loadingscreentexture_vertex3f[12];
 static float loadingscreentexture_texcoord2f[8];
 static int loadingscreenpic_number = 0;
+/// User-friendly connection status for the menu and/or loading screen,
+/// colours and \n not supported.
+char cl_connect_status[MAX_QPATH]; // should match size of loadingscreenstack_t msg[]
 
 static void SCR_DrawLoadingScreen(void);
 static void SCR_DrawScreen (void)
 {
        Draw_Frame();
 
 static void SCR_DrawLoadingScreen(void);
 static void SCR_DrawScreen (void)
 {
        Draw_Frame();
-
+       DrawQ_Start();
        R_Mesh_Start();
        R_Mesh_Start();
-
        R_UpdateVariables();
 
        R_UpdateVariables();
 
-       // this will be set back to 0 by R_RenderView during CL_VM_UpdateView
-       r_refdef.draw2dstage = 1;
-       R_ResetViewRendering2D_Common(0, NULL, NULL, 0, 0, vid.width, vid.height, vid_conwidth.integer, vid_conheight.integer);
-
        // Quake uses clockwise winding, so these are swapped
        r_refdef.view.cullface_front = GL_BACK;
        r_refdef.view.cullface_back = GL_FRONT;
 
        // Quake uses clockwise winding, so these are swapped
        r_refdef.view.cullface_front = GL_BACK;
        r_refdef.view.cullface_back = GL_FRONT;
 
-       if (cls.signon == SIGNONS)
+       if (!scr_loading && cls.signon == SIGNONS)
        {
                float size;
 
        {
                float size;
 
@@ -2119,44 +1593,44 @@ static void SCR_DrawScreen (void)
 
                if (r_stereo_sidebyside.integer)
                {
 
                if (r_stereo_sidebyside.integer)
                {
-                       r_refdef.view.width = (int)(vid.width * size / 2.5);
-                       r_refdef.view.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
+                       r_refdef.view.width = (int)(vid.mode.width * size / 2.5);
+                       r_refdef.view.height = (int)(vid.mode.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
                        r_refdef.view.depth = 1;
                        r_refdef.view.depth = 1;
-                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width * 2.5) * 0.5);
-                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.x = (int)((vid.mode.width - r_refdef.view.width * 2.5) * 0.5);
+                       r_refdef.view.y = (int)((vid.mode.height - r_refdef.view.height)/2);
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.x += (int)(r_refdef.view.width * 1.5);
                }
                else if (r_stereo_horizontal.integer)
                {
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.x += (int)(r_refdef.view.width * 1.5);
                }
                else if (r_stereo_horizontal.integer)
                {
-                       r_refdef.view.width = (int)(vid.width * size / 2);
-                       r_refdef.view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
+                       r_refdef.view.width = (int)(vid.mode.width * size / 2);
+                       r_refdef.view.height = (int)(vid.mode.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
                        r_refdef.view.depth = 1;
                        r_refdef.view.depth = 1;
-                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width * 2.0)/2);
-                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.x = (int)((vid.mode.width - r_refdef.view.width * 2.0)/2);
+                       r_refdef.view.y = (int)((vid.mode.height - r_refdef.view.height)/2);
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.x += (int)(r_refdef.view.width);
                }
                else if (r_stereo_vertical.integer)
                {
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.x += (int)(r_refdef.view.width);
                }
                else if (r_stereo_vertical.integer)
                {
-                       r_refdef.view.width = (int)(vid.width * size);
-                       r_refdef.view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100) / 2);
+                       r_refdef.view.width = (int)(vid.mode.width * size);
+                       r_refdef.view.height = (int)(vid.mode.height * size * (1 - bound(0, r_letterbox.value, 100) / 100) / 2);
                        r_refdef.view.depth = 1;
                        r_refdef.view.depth = 1;
-                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width)/2);
-                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height * 2.0)/2);
+                       r_refdef.view.x = (int)((vid.mode.width - r_refdef.view.width)/2);
+                       r_refdef.view.y = (int)((vid.mode.height - r_refdef.view.height * 2.0)/2);
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.y += (int)(r_refdef.view.height);
                }
                else
                {
                        r_refdef.view.z = 0;
                        if (r_stereo_side)
                                r_refdef.view.y += (int)(r_refdef.view.height);
                }
                else
                {
-                       r_refdef.view.width = (int)(vid.width * size);
-                       r_refdef.view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
+                       r_refdef.view.width = (int)(vid.mode.width * size);
+                       r_refdef.view.height = (int)(vid.mode.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
                        r_refdef.view.depth = 1;
                        r_refdef.view.depth = 1;
-                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width)/2);
-                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.x = (int)((vid.mode.width - r_refdef.view.width)/2);
+                       r_refdef.view.y = (int)((vid.mode.height - r_refdef.view.height)/2);
                        r_refdef.view.z = 0;
                }
 
                        r_refdef.view.z = 0;
                }
 
@@ -2179,7 +1653,7 @@ static void SCR_DrawScreen (void)
 
                // if CSQC is loaded, it is required to provide the CSQC_UpdateView function,
                // and won't render a view if it does not call that.
 
                // if CSQC is loaded, it is required to provide the CSQC_UpdateView function,
                // and won't render a view if it does not call that.
-               if (cl.csqc_loaded)
+               if (CLVM_prog->loaded && !(CLVM_prog->flag & PRVM_CSQC_SIMPLE))
                        CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime));
                else
                {
                        CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime));
                else
                {
@@ -2190,27 +1664,14 @@ static void SCR_DrawScreen (void)
                        R_RenderView(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
                }
        }
                        R_RenderView(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
                }
        }
-       else if (key_dest == key_game && key_consoleactive == 0 && (cls.state == ca_connected || cls.connect_trying))
-       {
-               // draw the loading screen for a while if we're still connecting and not forcing the console or menu to show up
-               char temp[64];
-               if (cls.signon > 0)
-                       SCR_PushLoadingScreen(va(temp, sizeof(temp), "Connect: Signon stage %i of %i", cls.signon, SIGNONS), 1.0);
-               else if (cls.connect_remainingtries > 0)
-                       SCR_PushLoadingScreen(va(temp, sizeof(temp), "Connect: Trying...  %i", cls.connect_remainingtries), 1.0);
-               else
-                       SCR_PushLoadingScreen(va(temp, sizeof(temp), "Connect: Waiting %i seconds for reply", 10 + cls.connect_remainingtries), 1.0);
-               SCR_DrawLoadingScreen();
-               SCR_PopLoadingScreen(false);
-       }
 
        // Don't apply debugging stuff like r_showsurfaces to the UI
        r_refdef.view.showdebug = false;
 
        if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
        {
 
        // Don't apply debugging stuff like r_showsurfaces to the UI
        r_refdef.view.showdebug = false;
 
        if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
        {
-               r_refdef.view.width = vid.width;
-               r_refdef.view.height = vid.height;
+               r_refdef.view.width = vid.mode.width;
+               r_refdef.view.height = vid.mode.height;
                r_refdef.view.depth = 1;
                r_refdef.view.x = 0;
                r_refdef.view.y = 0;
                r_refdef.view.depth = 1;
                r_refdef.view.x = 0;
                r_refdef.view.y = 0;
@@ -2242,9 +1703,9 @@ static void SCR_DrawScreen (void)
                        unsigned char *buffer1;
                        unsigned char *buffer2;
                        dpsnprintf(filename, sizeof(filename), "timedemoscreenshots/%s%06d.tga", cls.demoname, cls.td_frames);
                        unsigned char *buffer1;
                        unsigned char *buffer2;
                        dpsnprintf(filename, sizeof(filename), "timedemoscreenshots/%s%06d.tga", cls.demoname, cls.td_frames);
-                       buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
-                       buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
-                       SCR_ScreenShot(filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, false, false, true, false);
+                       buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.mode.width * vid.mode.height * 4);
+                       buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.mode.width * vid.mode.height * 3);
+                       SCR_ScreenShot(filename, buffer1, buffer2, 0, 0, vid.mode.width, vid.mode.height, false, false, false, false, false, true, false);
                        Mem_Free(buffer1);
                        Mem_Free(buffer2);
                }
                        Mem_Free(buffer1);
                        Mem_Free(buffer2);
                }
@@ -2252,10 +1713,6 @@ static void SCR_DrawScreen (void)
 
        // draw 2D stuff
 
 
        // draw 2D stuff
 
-       // Don't flicker when starting a local server.
-       if(scr_loading && !loadingscreenstack && ((!cls.signon && !sv.active) || (cls.signon == SIGNONS)))
-               SCR_EndLoadingPlaque();
-
        if(!scr_con_current && !(key_consoleactive & KEY_CONSOLEACTIVE_FORCED))
                if ((key_dest == key_game || key_dest == key_message) && !r_letterbox.value && !scr_loading)
                        Con_DrawNotify ();      // only draw notify in game
        if(!scr_con_current && !(key_consoleactive & KEY_CONSOLEACTIVE_FORCED))
                if ((key_dest == key_game || key_dest == key_message) && !r_letterbox.value && !scr_loading)
                        Con_DrawNotify ();      // only draw notify in game
@@ -2265,13 +1722,17 @@ static void SCR_DrawScreen (void)
        else
                host.paused = false;
 
        else
                host.paused = false;
 
-       if (cls.signon == SIGNONS)
+       if (!scr_loading && cls.signon == SIGNONS)
        {
                SCR_DrawNet ();
                SCR_DrawTurtle ();
                SCR_DrawPause ();
                if (!r_letterbox.value)
        {
                SCR_DrawNet ();
                SCR_DrawTurtle ();
                SCR_DrawPause ();
                if (!r_letterbox.value)
+               {
                        Sbar_Draw();
                        Sbar_Draw();
+                       if (CLVM_prog->loaded && CLVM_prog->flag & PRVM_CSQC_SIMPLE)
+                               CL_VM_DrawHud(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime));
+               }
                SHOWLMP_drawall();
                SCR_CheckDrawCenterString();
        }
                SHOWLMP_drawall();
                SCR_CheckDrawCenterString();
        }
@@ -2283,13 +1744,29 @@ static void SCR_DrawScreen (void)
        CL_DrawVideo();
        R_Shadow_EditLights_DrawSelectedLightProperties();
 
        CL_DrawVideo();
        R_Shadow_EditLights_DrawSelectedLightProperties();
 
-       SCR_DrawConsole();
-       
-       if(!scr_loading) {
-               SCR_DrawBrand();
+       if (scr_loading)
+       {
+               // connect_status replaces any dummy_status
+               if ((!loadingscreenstack || loadingscreenstack->msg[0] == '\0') && cl_connect_status[0] != '\0')
+               {
+                       loadingscreenstack_t connect_status, *og_ptr = loadingscreenstack;
 
 
-               SCR_DrawInfobar();
+                       connect_status.absolute_loading_amount_min = 0;
+                       dp_strlcpy(connect_status.msg, cl_connect_status, sizeof(cl_connect_status));
+                       loadingscreenstack = &connect_status;
+                       SCR_DrawLoadingScreen();
+                       loadingscreenstack = og_ptr;
+               }
+               else
+                       SCR_DrawLoadingScreen();
+       }
 
 
+       SCR_DrawConsole();
+       SCR_DrawInfobar();
+
+       if (!scr_loading)
+       {
+               SCR_DrawBrand();
                SCR_DrawTouchscreenOverlay();
        }
        if (r_timereport_active)
                SCR_DrawTouchscreenOverlay();
        }
        if (r_timereport_active)
@@ -2301,9 +1778,8 @@ static void SCR_DrawScreen (void)
        if(!scr_loading)
                Sbar_ShowFPS();
 
        if(!scr_loading)
                Sbar_ShowFPS();
 
-       DrawQ_Finish();
-
        R_Mesh_Finish();
        R_Mesh_Finish();
+       DrawQ_Finish();
        R_RenderTarget_FreeUnused(false);
 }
 
        R_RenderTarget_FreeUnused(false);
 }
 
@@ -2323,11 +1799,11 @@ static void SCR_SetLoadingScreenTexture(void)
 
        SCR_ClearLoadingScreenTexture();
 
 
        SCR_ClearLoadingScreenTexture();
 
-       w = vid.width; h = vid.height;
+       w = vid.mode.width; h = vid.mode.height;
        loadingscreentexture_w = loadingscreentexture_h = 1;
 
        loadingscreentexture = R_LoadTexture2D(r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
        loadingscreentexture_w = loadingscreentexture_h = 1;
 
        loadingscreentexture = R_LoadTexture2D(r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
-       R_Mesh_CopyToTexture(loadingscreentexture, 0, 0, 0, 0, vid.width, vid.height);
+       R_Mesh_CopyToTexture(loadingscreentexture, 0, 0, 0, 0, vid.mode.width, vid.mode.height);
 
        loadingscreentexture_vertex3f[2] = loadingscreentexture_vertex3f[5] = loadingscreentexture_vertex3f[8] = loadingscreentexture_vertex3f[11] = 0;
        loadingscreentexture_vertex3f[0] = loadingscreentexture_vertex3f[9] = 0;
 
        loadingscreentexture_vertex3f[2] = loadingscreentexture_vertex3f[5] = loadingscreentexture_vertex3f[8] = loadingscreentexture_vertex3f[11] = 0;
        loadingscreentexture_vertex3f[0] = loadingscreentexture_vertex3f[9] = 0;
@@ -2340,19 +1816,67 @@ static void SCR_SetLoadingScreenTexture(void)
        loadingscreentexture_texcoord2f[6] = 0;loadingscreentexture_texcoord2f[7] = 0;
 }
 
        loadingscreentexture_texcoord2f[6] = 0;loadingscreentexture_texcoord2f[7] = 0;
 }
 
-void SCR_UpdateLoadingScreenIfShown(void)
+static void SCR_ChooseLoadingPic(qbool startup)
+{
+       if(startup && scr_loadingscreen_firstforstartup.integer)
+               loadingscreenpic_number = 0;
+       else if(scr_loadingscreen_firstforstartup.integer)
+               if(scr_loadingscreen_count.integer > 1)
+                       loadingscreenpic_number = rand() % (scr_loadingscreen_count.integer - 1) + 1;
+               else
+                       loadingscreenpic_number = 0;
+       else
+               loadingscreenpic_number = rand() % (scr_loadingscreen_count.integer > 1 ? scr_loadingscreen_count.integer : 1);
+}
+
+/*
+===============
+SCR_BeginLoadingPlaque
+
+================
+*/
+void SCR_BeginLoadingPlaque(qbool startup)
+{
+       loadingscreenstack_t dummy_status;
+
+       // we need to push a dummy status so CL_UpdateScreen knows we have things to load...
+       if (!loadingscreenstack)
+       {
+               dummy_status.msg[0] = '\0';
+               dummy_status.absolute_loading_amount_min = 0;
+               loadingscreenstack = &dummy_status;
+       }
+
+       SCR_DeferLoadingPlaque(startup);
+       if (scr_loadingscreen_background.integer)
+               SCR_SetLoadingScreenTexture();
+       CL_UpdateScreen();
+
+       if (loadingscreenstack == &dummy_status)
+               loadingscreenstack = NULL;
+}
+
+void SCR_DeferLoadingPlaque(qbool startup)
+{
+       SCR_ChooseLoadingPic(startup);
+       scr_loading = true;
+}
+
+void SCR_EndLoadingPlaque(void)
 {
 {
-       if(loadingscreendone)
-               SCR_UpdateLoadingScreen(loadingscreencleared, false);
+       scr_loading = false;
+       SCR_ClearLoadingScreenTexture();
 }
 
 }
 
+//=============================================================================
+
 void SCR_PushLoadingScreen (const char *msg, float len_in_parent)
 {
        loadingscreenstack_t *s = (loadingscreenstack_t *) Z_Malloc(sizeof(loadingscreenstack_t));
        s->prev = loadingscreenstack;
        loadingscreenstack = s;
 
 void SCR_PushLoadingScreen (const char *msg, float len_in_parent)
 {
        loadingscreenstack_t *s = (loadingscreenstack_t *) Z_Malloc(sizeof(loadingscreenstack_t));
        s->prev = loadingscreenstack;
        loadingscreenstack = s;
 
-       strlcpy(s->msg, msg, sizeof(s->msg));
+       dp_strlcpy(s->msg, msg, sizeof(s->msg));
        s->relative_completion = 0;
 
        if(s->prev)
        s->relative_completion = 0;
 
        if(s->prev)
@@ -2368,10 +1892,11 @@ void SCR_PushLoadingScreen (const char *msg, float len_in_parent)
                s->absolute_loading_amount_len = 1;
        }
 
                s->absolute_loading_amount_len = 1;
        }
 
-               SCR_UpdateLoadingScreenIfShown();
+       if (scr_loading)
+               CL_UpdateScreen();
 }
 
 }
 
-void SCR_PopLoadingScreen (qboolean redraw)
+void SCR_PopLoadingScreen (qbool redraw)
 {
        loadingscreenstack_t *s = loadingscreenstack;
 
 {
        loadingscreenstack_t *s = loadingscreenstack;
 
@@ -2386,11 +1911,11 @@ void SCR_PopLoadingScreen (qboolean redraw)
                s->prev->relative_completion = (s->absolute_loading_amount_min + s->absolute_loading_amount_len - s->prev->absolute_loading_amount_min) / s->prev->absolute_loading_amount_len;
        Z_Free(s);
 
                s->prev->relative_completion = (s->absolute_loading_amount_min + s->absolute_loading_amount_len - s->prev->absolute_loading_amount_min) / s->prev->absolute_loading_amount_len;
        Z_Free(s);
 
-       if(redraw)
-               SCR_UpdateLoadingScreenIfShown();
+       if (scr_loading && redraw)
+               CL_UpdateScreen();
 }
 
 }
 
-void SCR_ClearLoadingScreen (qboolean redraw)
+void SCR_ClearLoadingScreen (qbool redraw)
 {
        while(loadingscreenstack)
                SCR_PopLoadingScreen(redraw && !loadingscreenstack->prev);
 {
        while(loadingscreenstack)
                SCR_PopLoadingScreen(redraw && !loadingscreenstack->prev);
@@ -2413,7 +1938,6 @@ static float SCR_DrawLoadingStack_r(loadingscreenstack_t *s, float y, float size
                        len = strlen(s->msg);
                        x = (vid_conwidth.integer - DrawQ_TextWidth(s->msg, len, size, size, true, FONT_INFOBAR)) / 2;
                        y -= size;
                        len = strlen(s->msg);
                        x = (vid_conwidth.integer - DrawQ_TextWidth(s->msg, len, size, size, true, FONT_INFOBAR)) / 2;
                        y -= size;
-                       DrawQ_Fill(0, y, vid_conwidth.integer, size, 0, 0, 0, 1, 0);
                        DrawQ_String(x, y, s->msg, len, size, size, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                        total += size;
                }
                        DrawQ_String(x, y, s->msg, len, size, size, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                        total += size;
                }
@@ -2424,7 +1948,6 @@ static float SCR_DrawLoadingStack_r(loadingscreenstack_t *s, float y, float size
                len = strlen(s->msg);
                x = (vid_conwidth.integer - DrawQ_TextWidth(s->msg, len, size, size, true, FONT_INFOBAR)) / 2;
                y -= size;
                len = strlen(s->msg);
                x = (vid_conwidth.integer - DrawQ_TextWidth(s->msg, len, size, size, true, FONT_INFOBAR)) / 2;
                y -= size;
-               DrawQ_Fill(0, y, vid_conwidth.integer, size, 0, 0, 0, 1, 0);
                DrawQ_String(x, y, s->msg, len, size, size, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                total += size;
        }
                DrawQ_String(x, y, s->msg, len, size, size, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                total += size;
        }
@@ -2437,7 +1960,7 @@ static void SCR_DrawLoadingStack(void)
        float verts[12];
        float colors[16];
 
        float verts[12];
        float colors[16];
 
-       loadingscreenheight = SCR_DrawLoadingStack_r(loadingscreenstack, vid_conheight.integer, scr_loadingscreen_barheight.value);
+       SCR_DrawLoadingStack_r(loadingscreenstack, vid_conheight.integer, scr_loadingscreen_barheight.value);
        if(loadingscreenstack)
        {
                // height = 32; // sorry, using the actual one is ugly
        if(loadingscreenstack)
        {
                // height = 32; // sorry, using the actual one is ugly
@@ -2445,7 +1968,7 @@ static void SCR_DrawLoadingStack(void)
                GL_DepthRange(0, 1);
                GL_PolygonOffset(0, 0);
                GL_DepthTest(false);
                GL_DepthRange(0, 1);
                GL_PolygonOffset(0, 0);
                GL_DepthTest(false);
-//             R_Mesh_ResetTextureState();
+               //R_Mesh_ResetTextureState();
                verts[2] = verts[5] = verts[8] = verts[11] = 0;
                verts[0] = verts[9] = 0;
                verts[1] = verts[4] = vid_conheight.integer - scr_loadingscreen_barheight.value;
                verts[2] = verts[5] = verts[8] = verts[11] = 0;
                verts[0] = verts[9] = 0;
                verts[1] = verts[4] = vid_conheight.integer - scr_loadingscreen_barheight.value;
@@ -2455,9 +1978,6 @@ static void SCR_DrawLoadingStack(void)
 #if _MSC_VER >= 1400
 #define sscanf sscanf_s
 #endif
 #if _MSC_VER >= 1400
 #define sscanf sscanf_s
 #endif
-               //                                        ^^^^^^^^^^ blue component
-               //                              ^^^^^^ bottom row
-               //          ^^^^^^^^^^^^ alpha is always on
                colors[0] = 0; colors[1] = 0; colors[2] = 0; colors[3] = 1;
                colors[4] = 0; colors[5] = 0; colors[6] = 0; colors[7] = 1;
                sscanf(scr_loadingscreen_barcolor.string, "%f %f %f", &colors[8], &colors[9], &colors[10]); colors[11] = 1;
                colors[0] = 0; colors[1] = 0; colors[2] = 0; colors[3] = 1;
                colors[4] = 0; colors[5] = 0; colors[6] = 0; colors[7] = 1;
                sscanf(scr_loadingscreen_barcolor.string, "%f %f %f", &colors[8], &colors[9], &colors[10]); colors[11] = 1;
@@ -2466,40 +1986,31 @@ static void SCR_DrawLoadingStack(void)
                R_Mesh_PrepareVertices_Generic_Arrays(4, verts, colors, NULL);
                R_SetupShader_Generic_NoTexture(true, true);
                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                R_Mesh_PrepareVertices_Generic_Arrays(4, verts, colors, NULL);
                R_SetupShader_Generic_NoTexture(true, true);
                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-
-               // make sure everything is cleared, including the progress indicator
-               if(loadingscreenheight < 8)
-                       loadingscreenheight = 8;
        }
 }
 
        }
 }
 
-static cachepic_t *loadingscreenpic;
-static float loadingscreenpic_vertex3f[12];
-static float loadingscreenpic_texcoord2f[8];
-
-static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
+static void SCR_DrawLoadingScreen (void)
 {
 {
-       r_viewport_t viewport;
+       cachepic_t *loadingscreenpic;
+       float loadingscreenpic_vertex3f[12];
+       float loadingscreenpic_texcoord2f[8];
        float x, y, w, h, sw, sh, f;
        char vabuf[1024];
        float x, y, w, h, sw, sh, f;
        char vabuf[1024];
-       // release mouse grab while loading
-       if (!vid.fullscreen)
-               VID_SetMouse(false, false, false);
-//     CHECKGLERROR
-       r_refdef.draw2dstage = true;
-       R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
-       R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
-       R_SetViewport(&viewport);
-       GL_ColorMask(1,1,1,1);
-       // when starting up a new video mode, make sure the screen is cleared to black
-       if (clear || loadingscreentexture)
-               GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
-       R_Textures_Frame();
-       R_Mesh_Start();
-       R_EntityMatrix(&identitymatrix);
-       // draw the loading plaque
-       loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "%s%d", scr_loadingscreen_picture.string, loadingscreenpic_number+1) : scr_loadingscreen_picture.string, loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
 
 
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       GL_DepthRange(0, 1);
+       GL_PolygonOffset(0, 0);
+       GL_DepthTest(false);
+       GL_Color(1,1,1,1);
+
+       if(loadingscreentexture)
+       {
+               R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreentexture_vertex3f, NULL, loadingscreentexture_texcoord2f);
+               R_SetupShader_Generic(loadingscreentexture, false, true, true);
+               R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+       }
+
+       loadingscreenpic = Draw_CachePic_Flags(loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "%s%d", scr_loadingscreen_picture.string, loadingscreenpic_number+1) : scr_loadingscreen_picture.string, loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
        w = Draw_GetPicWidth(loadingscreenpic);
        h = Draw_GetPicHeight(loadingscreenpic);
 
        w = Draw_GetPicWidth(loadingscreenpic);
        h = Draw_GetPicHeight(loadingscreenpic);
 
@@ -2510,8 +2021,8 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
        // apply scale base
        if(scr_loadingscreen_scale_base.integer)
        {
        // apply scale base
        if(scr_loadingscreen_scale_base.integer)
        {
-               w *= vid_conwidth.integer / (float) vid.width;
-               h *= vid_conheight.integer / (float) vid.height;
+               w *= vid_conwidth.integer / (float) vid.mode.width;
+               h *= vid_conheight.integer / (float) vid.mode.height;
        }
 
        // apply scale limit
        }
 
        // apply scale limit
@@ -2550,139 +2061,37 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
        loadingscreenpic_texcoord2f[2] = 1;loadingscreenpic_texcoord2f[3] = 0;
        loadingscreenpic_texcoord2f[4] = 1;loadingscreenpic_texcoord2f[5] = 1;
        loadingscreenpic_texcoord2f[6] = 0;loadingscreenpic_texcoord2f[7] = 1;
        loadingscreenpic_texcoord2f[2] = 1;loadingscreenpic_texcoord2f[3] = 0;
        loadingscreenpic_texcoord2f[4] = 1;loadingscreenpic_texcoord2f[5] = 1;
        loadingscreenpic_texcoord2f[6] = 0;loadingscreenpic_texcoord2f[7] = 1;
-}
 
 
-static void SCR_DrawLoadingScreen (void)
-{
-       // we only need to draw the image if it isn't already there
-       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       GL_DepthRange(0, 1);
-       GL_PolygonOffset(0, 0);
-       GL_DepthTest(false);
-//     R_Mesh_ResetTextureState();
-       GL_Color(1,1,1,1);
-       if(loadingscreentexture)
-       {
-               R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreentexture_vertex3f, NULL, loadingscreentexture_texcoord2f);
-               R_SetupShader_Generic(loadingscreentexture, false, true, true);
-               R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-       }
        R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreenpic_vertex3f, NULL, loadingscreenpic_texcoord2f);
        R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), true, true, false);
        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
        R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreenpic_vertex3f, NULL, loadingscreenpic_texcoord2f);
        R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), true, true, false);
        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-       SCR_DrawLoadingStack();
-}
-
-static double loadingscreen_lastupdate;
-
-static void SCR_UpdateVars(void);
-
-void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
-{
-       keydest_t       old_key_dest;
-       int                     old_key_consoleactive;
 
 
-       // don't do anything if not initialized yet
-       if (vid_hidden || cls.state == ca_dedicated)
-               return;
-
-       // limit update rate
-       if (scr_loadingscreen_maxfps.value)
-       {
-               double t = Sys_DirtyTime();
-               if ((t - loadingscreen_lastupdate) < 1.0f/scr_loadingscreen_maxfps.value)
-                       return;
-               loadingscreen_lastupdate = t;
-       }
-
-       // set up the r_texture_gammaramps texture which we need for rendering the loadingscreenpic
-       R_UpdateVariables();
-
-       if(!scr_loadingscreen_background.integer)
-               clear = true;
-       
-       if(loadingscreendone)
-               clear |= loadingscreencleared;
-
-       if(!loadingscreendone)
-       {
-               if(startup && scr_loadingscreen_firstforstartup.integer)
-                       loadingscreenpic_number = 0;
-               else if(scr_loadingscreen_firstforstartup.integer)
-                       if(scr_loadingscreen_count.integer > 1)
-                               loadingscreenpic_number = rand() % (scr_loadingscreen_count.integer - 1) + 1;
-                       else
-                               loadingscreenpic_number = 0;
-               else
-                       loadingscreenpic_number = rand() % (scr_loadingscreen_count.integer > 1 ? scr_loadingscreen_count.integer : 1);
-       }
-
-       if(clear)
-               SCR_ClearLoadingScreenTexture();
-       else if(!loadingscreendone)
-               SCR_SetLoadingScreenTexture();
-
-       if(!loadingscreendone)
-       {
-               loadingscreendone = true;
-               loadingscreenheight = 0;
-       }
-       loadingscreencleared = clear;
-
-#ifdef USE_GLES2
-       SCR_DrawLoadingScreen_SharedSetup(clear);
-       SCR_DrawLoadingScreen();
-#else
-       SCR_DrawLoadingScreen_SharedSetup(clear);
-       if (vid.stereobuffer)
-       {
-               qglDrawBuffer(GL_BACK_LEFT);
-               SCR_DrawLoadingScreen();
-               qglDrawBuffer(GL_BACK_RIGHT);
-               SCR_DrawLoadingScreen();
-       }
-       else
-       {
-               qglDrawBuffer(GL_BACK);
-               SCR_DrawLoadingScreen();
-       }
-#endif
-
-       DrawQ_Finish();
-       R_Mesh_Finish();
-       // refresh
-       VID_Finish();
-
-       // this goes into the event loop, and should prevent unresponsive cursor on vista
-       old_key_dest = key_dest;
-       old_key_consoleactive = key_consoleactive;
-       key_dest = key_void;
-       key_consoleactive = false;
-       Key_EventQueue_Block(); Sys_SendKeyEvents();
-       key_dest = old_key_dest;
-       key_consoleactive = old_key_consoleactive;
+       SCR_DrawLoadingStack();
 }
 
 }
 
-qboolean R_Stereo_ColorMasking(void)
+qbool R_Stereo_ColorMasking(void)
 {
        return r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer;
 }
 
 {
        return r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer;
 }
 
-qboolean R_Stereo_Active(void)
+qbool R_Stereo_Active(void)
 {
 {
-       return (vid.stereobuffer || r_stereo_sidebyside.integer || r_stereo_horizontal.integer || r_stereo_vertical.integer || R_Stereo_ColorMasking());
+       return (vid.mode.stereobuffer || r_stereo_sidebyside.integer || r_stereo_horizontal.integer || r_stereo_vertical.integer || R_Stereo_ColorMasking());
 }
 
 }
 
-void SCR_UpdateVars(void)
+static void SCR_UpdateVars(void)
 {
        float conwidth = bound(160, vid_conwidth.value, 32768);
        float conheight = bound(90, vid_conheight.value, 24576);
 {
        float conwidth = bound(160, vid_conwidth.value, 32768);
        float conheight = bound(90, vid_conheight.value, 24576);
+       float conscale = vid.mode.height / vid_conheight.value;
        if (vid_conwidthauto.integer)
        if (vid_conwidthauto.integer)
-               conwidth = floor(conheight * vid.width / (vid.height * vid_pixelheight.value));
+               conwidth = floor(conheight * vid.mode.width / (vid.mode.height * vid_pixelheight.value));
        if (vid_conwidth.value != conwidth)
                Cvar_SetValueQuick(&vid_conwidth, conwidth);
        if (vid_conheight.value != conheight)
                Cvar_SetValueQuick(&vid_conheight, conheight);
        if (vid_conwidth.value != conwidth)
                Cvar_SetValueQuick(&vid_conwidth, conwidth);
        if (vid_conheight.value != conheight)
                Cvar_SetValueQuick(&vid_conheight, conheight);
+       if (scr_sbarscale.value != conscale)
+               Cvar_SetValueQuick(&scr_sbarscale, conscale);
 
        // bound viewsize
        if (scr_viewsize.value < 30)
 
        // bound viewsize
        if (scr_viewsize.value < 30)
@@ -2718,9 +2127,10 @@ extern cvar_t cl_minfps_qualitymultiply;
 extern cvar_t cl_minfps_qualityhysteresis;
 extern cvar_t cl_minfps_qualitystepmax;
 extern cvar_t cl_minfps_force;
 extern cvar_t cl_minfps_qualityhysteresis;
 extern cvar_t cl_minfps_qualitystepmax;
 extern cvar_t cl_minfps_force;
-static double cl_updatescreen_quality = 1;
 void CL_UpdateScreen(void)
 {
 void CL_UpdateScreen(void)
 {
+       static double cl_updatescreen_quality = 1;
+
        vec3_t vieworigin;
        static double drawscreenstart = 0.0;
        double drawscreendelta;
        vec3_t vieworigin;
        static double drawscreenstart = 0.0;
        double drawscreendelta;
@@ -2809,8 +2219,6 @@ void CL_UpdateScreen(void)
        if (!scr_initialized || !con_initialized || !scr_refresh.integer)
                return;                         // not initialized yet
 
        if (!scr_initialized || !con_initialized || !scr_refresh.integer)
                return;                         // not initialized yet
 
-       loadingscreendone = false;
-
        if(IS_NEXUIZ_DERIVED(gamemode))
        {
                // play a bit with the palette (experimental)
        if(IS_NEXUIZ_DERIVED(gamemode))
        {
                // play a bit with the palette (experimental)
@@ -2824,12 +2232,30 @@ void CL_UpdateScreen(void)
                memcpy(palette_rgb_shirtscoreboard[15], palette_rgb_shirtcolormap[15], sizeof(*palette_rgb_shirtcolormap));
        }
 
                memcpy(palette_rgb_shirtscoreboard[15], palette_rgb_shirtcolormap[15], sizeof(*palette_rgb_shirtcolormap));
        }
 
+#ifdef CONFIG_VIDEO_CAPTURE
+       if (vid_hidden && !cls.capturevideo.active
+       && !cl_capturevideo.integer) // so we can start capturing while hidden
+#else
        if (vid_hidden)
        if (vid_hidden)
+#endif
        {
                VID_Finish();
                return;
        }
 
        {
                VID_Finish();
                return;
        }
 
+       if (scr_loading)
+       {
+               if(!loadingscreenstack && !cls.connect_trying && (cls.state != ca_connected || cls.signon == SIGNONS))
+                       SCR_EndLoadingPlaque();
+               else if (scr_loadingscreen_maxfps.value > 0)
+               {
+                       static double lastupdate;
+                       if (host.realtime - lastupdate < min(1.0f / scr_loadingscreen_maxfps.value, 0.1))
+                               return;
+                       lastupdate = host.realtime;
+               }
+       }
+
        SCR_UpdateVars();
 
        R_FrameData_NewFrame();
        SCR_UpdateVars();
 
        R_FrameData_NewFrame();
@@ -2849,8 +2275,8 @@ void CL_UpdateScreen(void)
        qglDrawBuffer(GL_BACK);CHECKGLERROR
 #endif
 
        qglDrawBuffer(GL_BACK);CHECKGLERROR
 #endif
 
-       R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
-       R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
+       R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.mode.width, vid.mode.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
+       R_Mesh_SetRenderTargets(0);
        R_SetViewport(&viewport);
        GL_ScissorTest(false);
        GL_ColorMask(1,1,1,1);
        R_SetViewport(&viewport);
        GL_ScissorTest(false);
        GL_ColorMask(1,1,1,1);
@@ -2881,7 +2307,7 @@ void CL_UpdateScreen(void)
                        r_refdef.view.colormask[2] = 0;
                }
 
                        r_refdef.view.colormask[2] = 0;
                }
 
-               if (vid.stereobuffer)
+               if (vid.mode.stereobuffer)
                        qglDrawBuffer(GL_BACK_RIGHT);
 
                SCR_DrawScreen();
                        qglDrawBuffer(GL_BACK_RIGHT);
 
                SCR_DrawScreen();
@@ -2896,7 +2322,7 @@ void CL_UpdateScreen(void)
                        r_refdef.view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
                }
 
                        r_refdef.view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
                }
 
-               if (vid.stereobuffer)
+               if (vid.mode.stereobuffer)
                        qglDrawBuffer(GL_BACK_LEFT);
 
                SCR_DrawScreen();
                        qglDrawBuffer(GL_BACK_LEFT);
 
                SCR_DrawScreen();
@@ -2914,18 +2340,6 @@ void CL_UpdateScreen(void)
 #endif
 
        qglFlush(); // ensure that the commands are submitted to the GPU before we do other things
 #endif
 
        qglFlush(); // ensure that the commands are submitted to the GPU before we do other things
-
-       if (!vid_activewindow)
-               VID_SetMouse(false, false, false);
-       else if (key_consoleactive)
-               VID_SetMouse(vid.fullscreen, false, false);
-       else if (key_dest == key_menu_grabbed)
-               VID_SetMouse(true, vid_mouse.integer && !in_client_mouse && !vid_touchscreen.integer, !vid_touchscreen.integer);
-       else if (key_dest == key_menu)
-               VID_SetMouse(vid.fullscreen, vid_mouse.integer && !in_client_mouse && !vid_touchscreen.integer, !vid_touchscreen.integer);
-       else
-               VID_SetMouse(vid.fullscreen, vid_mouse.integer && !cl.csqc_wantsmousemove && cl_prydoncursor.integer <= 0 && (!cls.demoplayback || cl_demo_mousegrab.integer) && !vid_touchscreen.integer, !vid_touchscreen.integer);
-
        VID_Finish();
 }
 
        VID_Finish();
 }