5 #include "cl_collision.h"
7 cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"};
8 cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 1 - 170
9 cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300
10 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
11 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "0.2"};
12 cvar_t scr_conforcewhiledisconnected = {CVAR_SAVE, "scr_conforcewhiledisconnected", "1"};
13 cvar_t scr_centertime = {0, "scr_centertime","2"};
14 cvar_t scr_showram = {CVAR_SAVE, "showram","1"};
15 cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"};
16 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"};
17 cvar_t scr_showbrand = {0, "showbrand","0"};
18 cvar_t scr_printspeed = {0, "scr_printspeed","8"};
19 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640"};
20 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480"};
21 cvar_t vid_pixelaspect = {CVAR_SAVE, "vid_pixelaspect", "1"};
22 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1"};
23 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9"};
24 cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2"};
25 // scr_screenshot_name is defined in fs.c
26 cvar_t cl_capturevideo = {0, "cl_capturevideo", "0"};
27 cvar_t cl_capturevideo_sound = {0, "cl_capturevideo_sound", "0"};
28 cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30"};
29 cvar_t cl_capturevideo_rawrgb = {0, "cl_capturevideo_rawrgb", "0"};
30 cvar_t cl_capturevideo_rawyv12 = {0, "cl_capturevideo_rawyv12", "0"};
31 cvar_t r_textshadow = {0, "r_textshadow", "0"};
32 cvar_t r_letterbox = {0, "r_letterbox", "0"};
34 int jpeg_supported = false;
36 qboolean scr_initialized; // ready to draw
38 float scr_con_current;
40 extern int con_vislines;
42 void DrawCrosshair(int num);
43 static void SCR_ScreenShot_f (void);
44 static void R_Envmap_f (void);
47 void R_ClearScreen(void);
50 static vec4_t string_colors[] =
53 // LordHavoc: why on earth is cyan before magenta in Quake3?
54 // LordHavoc: note: Doom3 uses white for [0] and [7]
55 {0.0, 0.0, 0.0, 1.0}, // black
56 {1.0, 0.0, 0.0, 1.0}, // red
57 {0.0, 1.0, 0.0, 1.0}, // green
58 {1.0, 1.0, 0.0, 1.0}, // yellow
59 {0.0, 0.0, 1.0, 1.0}, // blue
60 {0.0, 1.0, 1.0, 1.0}, // cyan
61 {1.0, 0.0, 1.0, 1.0}, // magenta
62 {1.0, 1.0, 1.0, 1.0}, // white
63 // [515]'s BX_COLOREDTEXT extension
64 {1.0, 1.0, 1.0, 0.5}, // half transparent
65 {0.5, 0.5, 0.5, 1.0} // half brightness
66 // Black's color table
67 //{1.0, 1.0, 1.0, 1.0},
68 //{1.0, 0.0, 0.0, 1.0},
69 //{0.0, 1.0, 0.0, 1.0},
70 //{0.0, 0.0, 1.0, 1.0},
71 //{1.0, 1.0, 0.0, 1.0},
72 //{0.0, 1.0, 1.0, 1.0},
73 //{1.0, 0.0, 1.0, 1.0},
74 //{0.1, 0.1, 0.1, 1.0}
77 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
79 // color is read and changed in the end
80 void DrawQ_ColoredString( float x, float y, const char *text, int maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor )
85 const char *start, *current;
87 if( !outcolor || *outcolor == -1 ) {
88 colorindex = STRING_COLOR_DEFAULT;
90 colorindex = *outcolor;
92 color = string_colors[colorindex];
95 len = (int)strlen( text );
97 len = min( maxlen, (int) strlen( text ) );
99 start = current = text;
101 // check for color control char
102 if( *current == STRING_COLOR_TAG ) {
109 // display the tag char?
110 if( *current == STRING_COLOR_TAG ) {
111 // only display one of the two
116 } else if( '0' <= *current && *current <= '9' ) {
119 colorindex = colorindex * 10 + (*current - '0');
120 // only read as long as it makes a valid index
121 if( colorindex >= (int)STRING_COLORS_COUNT ) {
122 // undo the last operation
128 } while( len > 0 && '0' <= *current && *current <= '9' );
130 color = string_colors[colorindex];
131 // we jump over the color tag
135 // go on and read normal text in until the next control char
136 while( len > 0 && *current != STRING_COLOR_TAG ) {
141 if( start != current ) {
143 DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
144 // update x to be at the new start position
145 x += (current - start) * scalex;
146 // set start accordingly
151 // return the last colorindex
153 *outcolor = colorindex;
158 ===============================================================================
162 ===============================================================================
165 char scr_centerstring[MAX_INPUTLINE];
166 float scr_centertime_start; // for slow victory printing
167 float scr_centertime_off;
168 int scr_center_lines;
170 int scr_erase_center;
176 Called for important messages that should stay in the center of the screen
180 void SCR_CenterPrint(char *str)
182 strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
183 scr_centertime_off = scr_centertime.value;
184 scr_centertime_start = cl.time;
186 // count the number of lines for centering
187 scr_center_lines = 1;
197 void SCR_DrawCenterString (void)
205 // the finale prints the characters one at a time
207 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
211 scr_erase_center = 0;
212 start = scr_centerstring;
217 if (scr_center_lines <= 4)
218 y = vid_conheight.integer*0.35;
225 // scan the width of the line
226 for (l=0 ; l<vid_conwidth.integer/8 ; l++)
227 if (start[l] == '\n' || !start[l])
229 x = (vid_conwidth.integer - l*8)/2;
234 DrawQ_ColoredString(x, y, start, l, 8, 8, 1, 1, 1, 1, 0, &color);
242 while (*start && *start != '\n')
247 start++; // skip the \n
251 void SCR_CheckDrawCenterString (void)
253 if (scr_center_lines > scr_erase_lines)
254 scr_erase_lines = scr_center_lines;
256 scr_centertime_off -= host_frametime;
258 // don't draw if this is a normal stats-screen intermission,
259 // only if it is not an intermission, or a finale intermission
260 if (cl.intermission == 1)
262 if (scr_centertime_off <= 0 && !cl.intermission)
264 if (key_dest != key_game)
267 SCR_DrawCenterString ();
275 void SCR_DrawTurtle (void)
279 if (cls.state != ca_connected)
282 if (!scr_showturtle.integer)
285 if (host_frametime < 0.1)
295 DrawQ_Pic (0, 0, "gfx/turtle", 0, 0, 1, 1, 1, 1, 0);
303 void SCR_DrawNet (void)
305 if (cls.state != ca_connected)
307 if (realtime - cl.last_received_message < 0.3)
309 if (cls.demoplayback)
312 DrawQ_Pic (64, 0, "gfx/net", 0, 0, 1, 1, 1, 1, 0);
320 void SCR_DrawPause (void)
324 if (cls.state != ca_connected)
327 if (!scr_showpause.integer) // turn off for screenshots
333 pic = Draw_CachePic ("gfx/pause", true);
334 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, "gfx/pause", 0, 0, 1, 1, 1, 1, 0);
342 void SCR_DrawBrand (void)
347 if (!scr_showbrand.value)
350 pic = Draw_CachePic ("gfx/brand", true);
352 switch ((int)scr_showbrand.value)
354 case 1: // bottom left
356 y = vid_conheight.integer - pic->height;
358 case 2: // bottom centre
359 x = (vid_conwidth.integer - pic->width) / 2;
360 y = vid_conheight.integer - pic->height;
362 case 3: // bottom right
363 x = vid_conwidth.integer - pic->width;
364 y = vid_conheight.integer - pic->height;
366 case 4: // centre right
367 x = vid_conwidth.integer - pic->width;
368 y = (vid_conheight.integer - pic->height) / 2;
371 x = vid_conwidth.integer - pic->width;
374 case 6: // top centre
375 x = (vid_conwidth.integer - pic->width) / 2;
382 case 8: // centre left
384 y = (vid_conheight.integer - pic->height) / 2;
390 DrawQ_Pic (x, y, "gfx/brand", 0, 0, 1, 1, 1, 1, 0);
393 //=============================================================================
398 SCR_SetUpToDrawConsole
401 void SCR_SetUpToDrawConsole (void)
403 // lines of console to display
408 if (key_dest == key_game && cls.signon != SIGNONS && scr_conforcewhiledisconnected.integer)
409 key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
411 key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
413 // decide on the height of the console
414 if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
415 conlines = vid_conheight.integer/2; // half screen
417 conlines = 0; // none visible
419 if (scr_conspeed.value)
421 if (scr_con_current > conlines)
423 scr_con_current -= scr_conspeed.value*host_realframetime;
424 if (scr_con_current < conlines)
425 scr_con_current = conlines;
428 else if (scr_con_current < conlines)
430 scr_con_current += scr_conspeed.value*host_realframetime;
431 if (scr_con_current > conlines)
432 scr_con_current = conlines;
436 scr_con_current = conlines;
444 void SCR_DrawConsole (void)
446 if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
449 Con_DrawConsole (vid_conheight.integer);
451 else if (scr_con_current)
452 Con_DrawConsole (scr_con_current);
456 if (key_dest == key_game || key_dest == key_message)
457 Con_DrawNotify (); // only draw notify in game
463 SCR_BeginLoadingPlaque
467 void SCR_BeginLoadingPlaque (void)
471 SCR_UpdateLoadingScreen();
474 //=============================================================================
476 char r_speeds_string[1024];
477 int speedstringcount, r_timereport_active;
478 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
480 void R_TimeReport(char *desc)
486 if (!r_timereport_active || r_showtrispass)
490 r_timereport_temp = r_timereport_current;
491 r_timereport_current = Sys_DoubleTime();
492 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0);
494 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %s", t, desc);
495 length = (int)strlen(tempbuf);
497 tempbuf[length++] = ' ';
499 if (speedstringcount + length > (vid_conwidth.integer / 8))
501 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
502 speedstringcount = 0;
504 // skip the space at the beginning if it's the first on the line
505 if (speedstringcount == 0)
507 strlcat(r_speeds_string, tempbuf + 1, sizeof(r_speeds_string));
508 speedstringcount = length - 1;
512 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
513 speedstringcount += length;
517 void R_TimeReport_Start(void)
519 r_timereport_active = r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected;
520 r_speeds_string[0] = 0;
521 if (r_timereport_active)
523 speedstringcount = 0;
524 sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]);
525 sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", renderstats.entities, renderstats.entities_surfaces, renderstats.entities_triangles, renderstats.world_leafs, renderstats.world_portals, renderstats.particles);
526 sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%i7 dynamic\n", renderstats.lights, renderstats.lights_clears, renderstats.lights_scissored, renderstats.lights_lighttriangles, renderstats.lights_shadowtriangles, renderstats.lights_dynamicshadowtriangles);
527 if (renderstats.bloom)
528 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", renderstats.meshes, renderstats.meshes_elements / 3, renderstats.bloom_copypixels, renderstats.bloom_drawpixels);
530 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
532 r_timereport_start = Sys_DoubleTime();
535 memset(&renderstats, 0, sizeof(renderstats));
538 void R_TimeReport_End(void)
540 r_timereport_current = r_timereport_start;
541 R_TimeReport("total");
543 if (r_timereport_active)
547 for (i = 0;r_speeds_string[i];i++)
548 if (r_speeds_string[i] == '\n')
550 y = vid_conheight.integer - sb_lines - lines * 8;
552 DrawQ_Fill(0, y, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
553 while (r_speeds_string[i])
556 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
559 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
560 if (r_speeds_string[i] == '\n')
574 void SCR_SizeUp_f (void)
576 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
587 void SCR_SizeDown_f (void)
589 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
592 void CL_Screen_Init(void)
594 Cvar_RegisterVariable (&scr_fov);
595 Cvar_RegisterVariable (&scr_viewsize);
596 Cvar_RegisterVariable (&scr_conspeed);
597 Cvar_RegisterVariable (&scr_conalpha);
598 Cvar_RegisterVariable (&scr_conbrightness);
599 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
600 Cvar_RegisterVariable (&scr_showram);
601 Cvar_RegisterVariable (&scr_showturtle);
602 Cvar_RegisterVariable (&scr_showpause);
603 Cvar_RegisterVariable (&scr_showbrand);
604 Cvar_RegisterVariable (&scr_centertime);
605 Cvar_RegisterVariable (&scr_printspeed);
606 Cvar_RegisterVariable (&vid_conwidth);
607 Cvar_RegisterVariable (&vid_conheight);
608 Cvar_RegisterVariable (&vid_pixelaspect);
609 Cvar_RegisterVariable (&scr_screenshot_jpeg);
610 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
611 Cvar_RegisterVariable (&scr_screenshot_gamma);
612 Cvar_RegisterVariable (&cl_capturevideo);
613 Cvar_RegisterVariable (&cl_capturevideo_sound);
614 Cvar_RegisterVariable (&cl_capturevideo_fps);
615 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
616 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
617 Cvar_RegisterVariable (&r_textshadow);
618 Cvar_RegisterVariable (&r_letterbox);
620 Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
621 Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
622 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
623 Cmd_AddCommand ("envmap", R_Envmap_f);
625 scr_initialized = true;
628 void DrawQ_Clear(void)
630 r_refdef.drawqueuesize = 0;
633 static int picelements[6] = {0, 1, 2, 0, 2, 3};
634 void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
636 DrawQ_SuperPic(x,y,picname,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
639 void DrawQ_String_Real(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
644 if (alpha < (1.0f / 255.0f))
647 len = (int)strlen(string);
649 for (len = 0;len < maxlen && string[len];len++);
650 for (;len > 0 && string[0] == ' ';string++, x += scalex, len--);
651 for (;len > 0 && string[len - 1] == ' ';len--);
654 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || x < (-scalex * len) || y < (-scaley))
656 size = sizeof(*dq) + ((len + 1 + 3) & ~3);
657 if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize)
659 red = bound(0, red, 1);
660 green = bound(0, green, 1);
661 blue = bound(0, blue, 1);
662 alpha = bound(0, alpha, 1);
663 dq = (drawqueue_t *)(r_refdef.drawqueue + r_refdef.drawqueuesize);
665 dq->command = DRAWQUEUE_STRING;
667 dq->color = ((unsigned int) (red * 255.0f) << 24) | ((unsigned int) (green * 255.0f) << 16) | ((unsigned int) (blue * 255.0f) << 8) | ((unsigned int) (alpha * 255.0f));
672 out = (char *)(dq + 1);
673 memcpy(out, string, len);
675 r_refdef.drawqueuesize += dq->size;
678 void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
680 if (r_textshadow.integer)
681 DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,0,0,0,alpha*0.8,flags);
683 DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags);
688 void DrawQ_Fill (float x, float y, float w, float h, float red, float green, float blue, float alpha, int flags)
690 DrawQ_SuperPic(x,y,NULL,w,h,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
693 void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
697 drawqueuemesh_t mesh;
698 memset(&mesh, 0, sizeof(mesh));
699 if (picname && picname[0])
701 pic = Draw_CachePic(picname, false);
705 height = pic->height;
706 mesh.texture = pic->tex;
708 mesh.num_triangles = 2;
709 mesh.num_vertices = 4;
710 mesh.data_element3i = picelements;
711 mesh.data_vertex3f = floats;
712 mesh.data_texcoord2f = floats + 12;
713 mesh.data_color4f = floats + 20;
714 memset(floats, 0, sizeof(floats));
715 mesh.data_vertex3f[0] = mesh.data_vertex3f[9] = x;
716 mesh.data_vertex3f[1] = mesh.data_vertex3f[4] = y;
717 mesh.data_vertex3f[3] = mesh.data_vertex3f[6] = x + width;
718 mesh.data_vertex3f[7] = mesh.data_vertex3f[10] = y + height;
719 mesh.data_texcoord2f[0] = s1;mesh.data_texcoord2f[1] = t1;mesh.data_color4f[ 0] = r1;mesh.data_color4f[ 1] = g1;mesh.data_color4f[ 2] = b1;mesh.data_color4f[ 3] = a1;
720 mesh.data_texcoord2f[2] = s2;mesh.data_texcoord2f[3] = t2;mesh.data_color4f[ 4] = r2;mesh.data_color4f[ 5] = g2;mesh.data_color4f[ 6] = b2;mesh.data_color4f[ 7] = a2;
721 mesh.data_texcoord2f[4] = s4;mesh.data_texcoord2f[5] = t4;mesh.data_color4f[ 8] = r4;mesh.data_color4f[ 9] = g4;mesh.data_color4f[10] = b4;mesh.data_color4f[11] = a4;
722 mesh.data_texcoord2f[6] = s3;mesh.data_texcoord2f[7] = t3;mesh.data_color4f[12] = r3;mesh.data_color4f[13] = g3;mesh.data_color4f[14] = b3;mesh.data_color4f[15] = a3;
723 DrawQ_Mesh (&mesh, flags);
726 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
733 size += sizeof(drawqueuemesh_t);
734 size += sizeof(int[3]) * mesh->num_triangles;
735 size += sizeof(float[3]) * mesh->num_vertices;
736 size += sizeof(float[2]) * mesh->num_vertices;
737 size += sizeof(float[4]) * mesh->num_vertices;
738 if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize)
740 dq = (drawqueue_t *)(r_refdef.drawqueue + r_refdef.drawqueuesize);
742 dq->command = DRAWQUEUE_MESH;
749 p = (void *)(dq + 1);
750 m = (drawqueuemesh_t *)p;p = (unsigned char*)p + sizeof(drawqueuemesh_t);
751 m->num_triangles = mesh->num_triangles;
752 m->num_vertices = mesh->num_vertices;
753 m->texture = mesh->texture;
754 m->data_element3i = (int *)p;memcpy(m->data_element3i , mesh->data_element3i , m->num_triangles * sizeof(int[3]));p = (unsigned char*)p + m->num_triangles * sizeof(int[3]);
755 m->data_vertex3f = (float *)p;memcpy(m->data_vertex3f , mesh->data_vertex3f , m->num_vertices * sizeof(float[3]));p = (unsigned char*)p + m->num_vertices * sizeof(float[3]);
756 m->data_texcoord2f = (float *)p;memcpy(m->data_texcoord2f, mesh->data_texcoord2f, m->num_vertices * sizeof(float[2]));p = (unsigned char*)p + m->num_vertices * sizeof(float[2]);
757 m->data_color4f = (float *)p;memcpy(m->data_color4f , mesh->data_color4f , m->num_vertices * sizeof(float[4]));p = (unsigned char*)p + m->num_vertices * sizeof(float[4]);
758 r_refdef.drawqueuesize += dq->size;
761 void DrawQ_SetClipArea(float x, float y, float width, float height)
764 if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize)
766 Con_DPrint("DrawQueue full !\n");
769 dq = (drawqueue_t *) (r_refdef.drawqueue + r_refdef.drawqueuesize);
770 dq->size = sizeof(*dq);
771 dq->command = DRAWQUEUE_SETCLIP;
779 r_refdef.drawqueuesize += dq->size;
782 void DrawQ_ResetClipArea(void)
785 if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize)
787 Con_DPrint("DrawQueue full !\n");
790 dq = (drawqueue_t *) (r_refdef.drawqueue + r_refdef.drawqueuesize);
791 dq->size = sizeof(*dq);
792 dq->command = DRAWQUEUE_RESETCLIP;
800 r_refdef.drawqueuesize += dq->size;
808 void SCR_ScreenShot_f (void)
810 static int shotnumber;
811 static char oldname[MAX_QPATH];
812 char base[MAX_QPATH];
813 char filename[MAX_QPATH];
814 unsigned char *buffer1;
815 unsigned char *buffer2;
816 unsigned char *buffer3;
817 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
819 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
821 if (strcmp (oldname, scr_screenshot_name.string))
823 sprintf(oldname, "%s", scr_screenshot_name.string);
827 // find a file name to save it to
828 for (;shotnumber < 1000000;shotnumber++)
829 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
831 if (shotnumber >= 1000000)
833 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
837 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
839 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
840 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
841 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
843 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
844 Con_Printf("Wrote %s\n", filename);
846 Con_Printf("unable to write %s\n", filename);
855 typedef enum capturevideoformat_e
857 CAPTUREVIDEOFORMAT_TARGA,
858 CAPTUREVIDEOFORMAT_JPEG,
859 CAPTUREVIDEOFORMAT_RAWRGB,
860 CAPTUREVIDEOFORMAT_RAWYV12
862 capturevideoformat_t;
864 qboolean cl_capturevideo_active = false;
865 capturevideoformat_t cl_capturevideo_format;
866 static double cl_capturevideo_starttime = 0;
867 double cl_capturevideo_framerate = 0;
868 static int cl_capturevideo_soundrate = 0;
869 static int cl_capturevideo_frame = 0;
870 static unsigned char *cl_capturevideo_buffer = NULL;
871 static qfile_t *cl_capturevideo_videofile = NULL;
872 qfile_t *cl_capturevideo_soundfile = NULL;
873 static short cl_capturevideo_rgbtoyuvscaletable[3][3][256];
874 static unsigned char cl_capturevideo_yuvnormalizetable[3][256];
875 //static unsigned char cl_capturevideo_rgbgammatable[3][256];
877 void SCR_CaptureVideo_BeginVideo(void)
881 unsigned char out[44];
882 if (cl_capturevideo_active)
884 // soundrate is figured out on the first SoundFrame
885 cl_capturevideo_active = true;
886 cl_capturevideo_starttime = Sys_DoubleTime();
887 cl_capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
888 cl_capturevideo_soundrate = 0;
889 cl_capturevideo_frame = 0;
890 cl_capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
891 gamma = 1.0/scr_screenshot_gamma.value;
894 for (i = 0;i < 256;i++)
896 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
897 cl_capturevideo_rgbgammatable[0][i] = j;
898 cl_capturevideo_rgbgammatable[1][i] = j;
899 cl_capturevideo_rgbgammatable[2][i] = j;
903 R = Y + 1.4075 * (Cr - 128);
904 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
905 B = Y + 1.7790 * (Cb - 128);
906 Y = R * .299 + G * .587 + B * .114;
907 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
908 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
910 for (i = 0;i < 256;i++)
912 g = 255*pow(i/255.0, gamma);
913 // Y weights from RGB
914 cl_capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
915 cl_capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
916 cl_capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
917 // Cb weights from RGB
918 cl_capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
919 cl_capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
920 cl_capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
921 // Cr weights from RGB
922 cl_capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
923 cl_capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
924 cl_capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
925 // range reduction of YCbCr to valid signal range
926 cl_capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
927 cl_capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
928 cl_capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
931 if (cl_capturevideo_rawrgb.integer)
933 cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
934 cl_capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
936 else if (cl_capturevideo_rawyv12.integer)
938 cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
939 cl_capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
941 else if (scr_screenshot_jpeg.integer)
943 cl_capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
944 cl_capturevideo_videofile = NULL;
948 cl_capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
949 cl_capturevideo_videofile = NULL;
952 if (cl_capturevideo_sound.integer)
954 cl_capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
955 // wave header will be filled out when video ends
957 FS_Write (cl_capturevideo_soundfile, out, 44);
960 cl_capturevideo_soundfile = NULL;
963 void SCR_CaptureVideo_EndVideo(void)
966 unsigned char out[44];
967 if (!cl_capturevideo_active)
969 cl_capturevideo_active = false;
971 if (cl_capturevideo_videofile)
973 FS_Close(cl_capturevideo_videofile);
974 cl_capturevideo_videofile = NULL;
977 // finish the wave file
978 if (cl_capturevideo_soundfile)
980 i = (int)FS_Tell (cl_capturevideo_soundfile);
981 //"RIFF", (int) unknown (chunk size), "WAVE",
982 //"fmt ", (int) 16 (chunk size), (short) format 1 (uncompressed PCM), (short) 2 channels, (int) unknown rate, (int) unknown bytes per second, (short) 4 bytes per sample (channels * bytes per channel), (short) 16 bits per channel
983 //"data", (int) unknown (chunk size)
984 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
985 // the length of the whole RIFF chunk
988 out[5] = (n >> 8) & 0xFF;
989 out[6] = (n >> 16) & 0xFF;
990 out[7] = (n >> 24) & 0xFF;
992 n = cl_capturevideo_soundrate;
993 out[24] = (n) & 0xFF;
994 out[25] = (n >> 8) & 0xFF;
995 out[26] = (n >> 16) & 0xFF;
996 out[27] = (n >> 24) & 0xFF;
997 // bytes per second (rate * channels * bytes per channel)
998 n = cl_capturevideo_soundrate * 2 * 2;
999 out[28] = (n) & 0xFF;
1000 out[29] = (n >> 8) & 0xFF;
1001 out[30] = (n >> 16) & 0xFF;
1002 out[31] = (n >> 24) & 0xFF;
1003 // the length of the data chunk
1005 out[40] = (n) & 0xFF;
1006 out[41] = (n >> 8) & 0xFF;
1007 out[42] = (n >> 16) & 0xFF;
1008 out[43] = (n >> 24) & 0xFF;
1009 FS_Seek (cl_capturevideo_soundfile, 0, SEEK_SET);
1010 FS_Write (cl_capturevideo_soundfile, out, 44);
1011 FS_Close (cl_capturevideo_soundfile);
1012 cl_capturevideo_soundfile = NULL;
1015 if (cl_capturevideo_buffer)
1017 Mem_Free (cl_capturevideo_buffer);
1018 cl_capturevideo_buffer = NULL;
1021 cl_capturevideo_starttime = 0;
1022 cl_capturevideo_framerate = 0;
1023 cl_capturevideo_frame = 0;
1026 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
1028 int x = 0, y = 0, width = vid.width, height = vid.height;
1029 unsigned char *b, *out;
1031 int outoffset = (width/2)*(height/2);
1032 //return SCR_ScreenShot(filename, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.width * vid.height * 3, cl_capturevideo_buffer + vid.width * vid.height * 6, 0, 0, vid.width, vid.height, false, false, false, jpeg, true);
1033 // speed is critical here, so do saving as directly as possible
1034 switch (cl_capturevideo_format)
1036 case CAPTUREVIDEOFORMAT_RAWYV12:
1037 // FIXME: width/height must be multiple of 2, enforce this?
1038 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1040 // process one line at a time, and CbCr every other line at 2 pixel intervals
1041 for (y = 0;y < height;y++)
1044 for (b = cl_capturevideo_buffer + (height-1-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + y*width, x = 0;x < width;x++, b += 3, out++)
1045 *out = cl_capturevideo_yuvnormalizetable[0][cl_capturevideo_rgbtoyuvscaletable[0][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[0][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[0][2][b[2]]];
1048 // 2x2 Cb and Cr planes
1050 // low quality, no averaging
1051 for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
1054 out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[2][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[2][2][b[2]] + 128];
1056 out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[1][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[1][2][b[2]] + 128];
1059 // high quality, averaging
1060 int inpitch = width*3;
1061 for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
1063 int blockr, blockg, blockb;
1064 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
1065 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
1066 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
1068 out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[2][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[2][2][blockb] + 128];
1070 out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[1][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[1][2][blockb] + 128];
1075 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1076 if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
1079 case CAPTUREVIDEOFORMAT_RAWRGB:
1080 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1082 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1083 if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer, width*height*3))
1086 case CAPTUREVIDEOFORMAT_JPEG:
1087 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1089 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1091 sprintf(filename, "video/dp%06d.jpg", cl_capturevideo_frame);
1092 if (!JPEG_SaveImage_preflipped (filename, width, height, cl_capturevideo_buffer))
1096 case CAPTUREVIDEOFORMAT_TARGA:
1097 //return Image_WriteTGARGB_preflipped (filename, width, height, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.width * vid.height * 3, );
1098 memset (cl_capturevideo_buffer, 0, 18);
1099 cl_capturevideo_buffer[2] = 2; // uncompressed type
1100 cl_capturevideo_buffer[12] = (width >> 0) & 0xFF;
1101 cl_capturevideo_buffer[13] = (width >> 8) & 0xFF;
1102 cl_capturevideo_buffer[14] = (height >> 0) & 0xFF;
1103 cl_capturevideo_buffer[15] = (height >> 8) & 0xFF;
1104 cl_capturevideo_buffer[16] = 24; // pixel size
1105 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cl_capturevideo_buffer + 18);
1107 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1109 sprintf(filename, "video/dp%06d.tga", cl_capturevideo_frame);
1110 if (!FS_WriteFile (filename, cl_capturevideo_buffer, width*height*3 + 18))
1119 void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate)
1121 if (!cl_capturevideo_soundfile)
1123 cl_capturevideo_soundrate = rate;
1124 if (FS_Write (cl_capturevideo_soundfile, bufstereo16le, 4 * length) < (fs_offset_t)(4 * length))
1126 Cvar_SetValueQuick(&cl_capturevideo, 0);
1127 Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame);
1128 SCR_CaptureVideo_EndVideo();
1132 void SCR_CaptureVideo(void)
1135 if (cl_capturevideo.integer && r_render.integer)
1137 if (!cl_capturevideo_active)
1138 SCR_CaptureVideo_BeginVideo();
1139 if (cl_capturevideo_framerate != cl_capturevideo_fps.value)
1141 Con_Printf("You can not change the video framerate while recording a video.\n");
1142 Cvar_SetValueQuick(&cl_capturevideo_fps, cl_capturevideo_framerate);
1144 if (cl_capturevideo_soundfile)
1146 // preserve sound sync by duplicating frames when running slow
1147 newframenum = (Sys_DoubleTime() - cl_capturevideo_starttime) * cl_capturevideo_framerate;
1150 newframenum = cl_capturevideo_frame + 1;
1151 // if falling behind more than one second, stop
1152 if (newframenum - cl_capturevideo_frame > (int)ceil(cl_capturevideo_framerate))
1154 Cvar_SetValueQuick(&cl_capturevideo, 0);
1155 Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cl_capturevideo_frame);
1156 SCR_CaptureVideo_EndVideo();
1160 if (!SCR_CaptureVideo_VideoFrame(newframenum))
1162 Cvar_SetValueQuick(&cl_capturevideo, 0);
1163 Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame);
1164 SCR_CaptureVideo_EndVideo();
1167 else if (cl_capturevideo_active)
1168 SCR_CaptureVideo_EndVideo();
1175 Grab six views for environment mapping tests
1182 qboolean flipx, flipy, flipdiagonaly;
1186 {{ 0, 0, 0}, "rt", false, false, false},
1187 {{ 0, 270, 0}, "ft", false, false, false},
1188 {{ 0, 180, 0}, "lf", false, false, false},
1189 {{ 0, 90, 0}, "bk", false, false, false},
1190 {{-90, 180, 0}, "up", true, true, false},
1191 {{ 90, 180, 0}, "dn", true, true, false},
1193 {{ 0, 0, 0}, "px", true, true, true},
1194 {{ 0, 90, 0}, "py", false, true, false},
1195 {{ 0, 180, 0}, "nx", false, false, true},
1196 {{ 0, 270, 0}, "ny", true, false, false},
1197 {{-90, 180, 0}, "pz", false, false, true},
1198 {{ 90, 180, 0}, "nz", false, false, true}
1201 static void R_Envmap_f (void)
1204 char filename[MAX_QPATH], basename[MAX_QPATH];
1205 unsigned char *buffer1;
1206 unsigned char *buffer2;
1207 unsigned char *buffer3;
1209 if (Cmd_Argc() != 3)
1211 Con_Print("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
1215 strlcpy (basename, Cmd_Argv(1), sizeof (basename));
1216 size = atoi(Cmd_Argv(2));
1217 if (size != 128 && size != 256 && size != 512 && size != 1024)
1219 Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
1222 if (size > vid.width || size > vid.height)
1224 Con_Print("envmap: your resolution is not big enough to render that size\n");
1232 r_refdef.width = size;
1233 r_refdef.height = size;
1235 r_refdef.fov_x = 90;
1236 r_refdef.fov_y = 90;
1238 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
1239 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
1240 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3 + 18);
1242 for (j = 0;j < 12;j++)
1244 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1245 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
1250 SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_refdef.y + r_refdef.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
1260 //=============================================================================
1262 // LordHavoc: SHOWLMP stuff
1263 #define SHOWLMP_MAXLABELS 256
1264 typedef struct showlmp_s
1274 showlmp_t showlmp[SHOWLMP_MAXLABELS];
1276 void SHOWLMP_decodehide(void)
1280 lmplabel = MSG_ReadString();
1281 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1282 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
1284 showlmp[i].isactive = false;
1289 void SHOWLMP_decodeshow(void)
1292 char lmplabel[256], picname[256];
1294 strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
1295 strlcpy (picname, MSG_ReadString(), sizeof (picname));
1296 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
1303 x = MSG_ReadShort();
1304 y = MSG_ReadShort();
1307 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1308 if (showlmp[i].isactive)
1310 if (strcmp(showlmp[i].label, lmplabel) == 0)
1313 break; // drop out to replace it
1316 else if (k < 0) // find first empty one to replace
1319 return; // none found to replace
1320 // change existing one
1321 showlmp[k].isactive = true;
1322 strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label));
1323 strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic));
1328 void SHOWLMP_drawall(void)
1331 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1332 if (showlmp[i].isactive)
1333 DrawQ_Pic(showlmp[i].x, showlmp[i].y, showlmp[i].pic, 0, 0, 1, 1, 1, 1, 0);
1336 void SHOWLMP_clear(void)
1339 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1340 showlmp[i].isactive = false;
1343 void CL_SetupScreenSize(void)
1345 float conwidth, conheight;
1347 VID_UpdateGamma(false);
1349 conwidth = bound(320, vid_conwidth.value, 2048);
1350 conheight = bound(200, vid_conheight.value, 1536);
1351 if (vid_conwidth.value != conwidth)
1352 Cvar_SetValue("vid_conwidth", conwidth);
1353 if (vid_conheight.value != conheight)
1354 Cvar_SetValue("vid_conheight", conheight);
1356 vid_conwidth.integer = vid_conwidth.integer;
1357 vid_conheight.integer = vid_conheight.integer;
1359 SCR_SetUpToDrawConsole();
1362 extern void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1363 void CL_UpdateScreen(void)
1365 if (!scr_initialized || !con_initialized || vid_hidden)
1366 return; // not initialized yet
1368 // don't allow cheats in multiplayer
1369 if (!cl.islocalgame && cl.worldmodel)
1371 if (r_fullbright.integer != 0)
1372 Cvar_Set ("r_fullbright", "0");
1373 if (r_ambient.value != 0)
1374 Cvar_Set ("r_ambient", "0");
1378 if (scr_viewsize.value < 30)
1379 Cvar_Set ("viewsize","30");
1380 if (scr_viewsize.value > 120)
1381 Cvar_Set ("viewsize","120");
1383 // bound field of view
1384 if (scr_fov.value < 1)
1385 Cvar_Set ("fov","1");
1386 if (scr_fov.value > 170)
1387 Cvar_Set ("fov","170");
1389 // intermission is always full screen
1390 if (cl.intermission)
1394 if (scr_viewsize.value >= 120)
1395 sb_lines = 0; // no status bar at all
1396 else if (scr_viewsize.value >= 110)
1397 sb_lines = 24; // no inventory
1402 r_refdef.colormask[0] = 1;
1403 r_refdef.colormask[1] = 1;
1404 r_refdef.colormask[2] = 1;
1408 if (cls.signon == SIGNONS)
1409 R_TimeReport("other");
1411 CL_SetupScreenSize();
1415 if (cls.signon == SIGNONS)
1416 R_TimeReport("setup");
1418 //FIXME: force menu if nothing else to look at?
1419 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1421 if (cls.signon == SIGNONS)
1426 if (!r_letterbox.value)
1429 SCR_CheckDrawCenterString();
1435 if (cls.signon == SIGNONS)
1439 R_TimeReport_Start();
1441 R_Shadow_EditLights_DrawSelectedLightProperties();
1450 void CL_Screen_NewMap(void)