]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_screen.c
increased build number to 73
[divverent/darkplaces.git] / gl_screen.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 // screen.c -- master for refresh, status bar, console, chat, notify, etc
22
23 #include "quakedef.h"
24
25 /*
26
27 background clear
28 rendering
29 turtle/net/ram icons
30 sbar
31 centerprint / slow centerprint
32 notify lines
33 intermission / finale overlay
34 loading plaque
35 console
36 menu
37
38 required background clears
39 required update regions
40
41
42 syncronous draw mode or async
43 One off screen buffer, with updates either copied or xblited
44 Need to double buffer?
45
46
47 async draw will require the refresh area to be cleared, because it will be
48 xblited, but sync draw can just ignore it.
49
50 sync
51 draw
52
53 CenterPrint ()
54 SlowPrint ()
55 Screen_Update ();
56 Con_Printf ();
57
58 net 
59 turn off messages option
60
61 the refresh is allways rendered, unless the console is full screen
62
63
64 console is:
65         notify lines
66         half
67         full
68         
69
70 */
71
72
73 int                     glx, gly, glwidth, glheight;
74
75 // only the refresh window will be updated unless these variables are flagged 
76 int                     scr_copytop;
77 int                     scr_copyeverything;
78
79 float           scr_con_current;
80 float           scr_conlines;           // lines of console to display
81
82 float           oldscreensize, oldfov;
83 cvar_t          scr_viewsize = {"viewsize","100", true};
84 cvar_t          scr_fov = {"fov","90"}; // 10 - 170
85 cvar_t          scr_conspeed = {"scr_conspeed","300"};
86 cvar_t          scr_centertime = {"scr_centertime","2"};
87 cvar_t          scr_showram = {"showram","1"};
88 cvar_t          scr_showturtle = {"showturtle","0"};
89 cvar_t          scr_showpause = {"showpause","1"};
90 cvar_t          scr_printspeed = {"scr_printspeed","8"};
91 cvar_t          showfps = {"showfps", "0", true};
92
93 extern  cvar_t  crosshair;
94
95 qboolean        scr_initialized;                // ready to draw
96
97 qpic_t          *scr_ram;
98 qpic_t          *scr_net;
99 qpic_t          *scr_turtle;
100
101 int                     scr_fullupdate;
102
103 int                     clearconsole;
104 int                     clearnotify;
105
106 extern int                     sb_lines;
107
108 extern viddef_t        vid;                            // global video state
109
110 qboolean        scr_disabled_for_loading;
111 qboolean        scr_drawloading;
112 float           scr_disabled_time;
113
114 void SCR_ScreenShot_f (void);
115
116 /*
117 ===============================================================================
118
119 CENTER PRINTING
120
121 ===============================================================================
122 */
123
124 char            scr_centerstring[1024];
125 float           scr_centertime_start;   // for slow victory printing
126 float           scr_centertime_off;
127 int                     scr_center_lines;
128 int                     scr_erase_lines;
129 int                     scr_erase_center;
130
131 /*
132 ==============
133 SCR_CenterPrint
134
135 Called for important messages that should stay in the center of the screen
136 for a few moments
137 ==============
138 */
139 void SCR_CenterPrint (char *str)
140 {
141         strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
142         scr_centertime_off = scr_centertime.value;
143         scr_centertime_start = cl.time;
144
145 // count the number of lines for centering
146         scr_center_lines = 1;
147         while (*str)
148         {
149                 if (*str == '\n')
150                         scr_center_lines++;
151                 str++;
152         }
153 }
154
155
156 void SCR_DrawCenterString (void)
157 {
158         char    *start;
159         int             l;
160         int             x, y;
161         int             remaining;
162
163 // the finale prints the characters one at a time
164         if (cl.intermission)
165                 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
166         else
167                 remaining = 9999;
168
169         scr_erase_center = 0;
170         start = scr_centerstring;
171
172         if (scr_center_lines <= 4)
173                 y = vid.height*0.35;
174         else
175                 y = 48;
176
177         do      
178         {
179         // scan the width of the line
180                 for (l=0 ; l<40 ; l++)
181                         if (start[l] == '\n' || !start[l])
182                                 break;
183                 x = (vid.width - l*8)/2;
184                 // LordHavoc: speedup
185                 if (l > 0)
186                 {
187                         if (remaining < l)
188                                 l = remaining;
189                         Draw_String(x, y, start, l);
190                         remaining -= l;
191                         if (remaining <= 0)
192                                 return;
193                 }
194                 /*
195                 for (j=0 ; j<l ; j++, x+=8)
196                 {
197                         Draw_Character (x, y, start[j]);        
198                         if (!remaining--)
199                                 return;
200                 }
201                 */
202                         
203                 y += 8;
204
205                 while (*start && *start != '\n')
206                         start++;
207
208                 if (!*start)
209                         break;
210                 start++;                // skip the \n
211         } while (1);
212 }
213
214 void SCR_CheckDrawCenterString (void)
215 {
216         scr_copytop = 1;
217         if (scr_center_lines > scr_erase_lines)
218                 scr_erase_lines = scr_center_lines;
219
220         scr_centertime_off -= host_frametime;
221         
222         if (scr_centertime_off <= 0 && !cl.intermission)
223                 return;
224         if (key_dest != key_game)
225                 return;
226
227         SCR_DrawCenterString ();
228 }
229
230 //=============================================================================
231
232 /*
233 ====================
234 CalcFov
235 ====================
236 */
237 float CalcFov (float fov_x, float width, float height)
238 {
239         float   a;
240         float   x;
241
242         if (fov_x < 1 || fov_x > 179)
243                 Sys_Error ("Bad fov: %f", fov_x);
244
245         x = width/tan(fov_x/360*M_PI);
246
247         a = atan (height/x);
248
249         a = a*360/M_PI;
250
251         return a;
252 }
253
254 /*
255 =================
256 SCR_CalcRefdef
257
258 Must be called whenever vid changes
259 Internal use only
260 =================
261 */
262 static void SCR_CalcRefdef (void)
263 {
264         float           size;
265         int             h;
266         qboolean                full = false;
267
268
269         scr_fullupdate = 0;             // force a background redraw
270         vid.recalc_refdef = 0;
271
272 // force the status bar to redraw
273 //      Sbar_Changed ();
274
275 //========================================
276         
277 // bound viewsize
278         if (scr_viewsize.value < 30)
279                 Cvar_Set ("viewsize","30");
280         if (scr_viewsize.value > 120)
281                 Cvar_Set ("viewsize","120");
282
283 // bound field of view
284         if (scr_fov.value < 10)
285                 Cvar_Set ("fov","10");
286         if (scr_fov.value > 170)
287                 Cvar_Set ("fov","170");
288
289 // intermission is always full screen   
290         if (cl.intermission)
291                 size = 120;
292         else
293                 size = scr_viewsize.value;
294
295         if (size >= 120)
296                 sb_lines = 0;           // no status bar at all
297         else if (size >= 110)
298                 sb_lines = 24;          // no inventory
299         else
300                 sb_lines = 24+16+8;
301
302         if (scr_viewsize.value >= 100.0)
303         {
304                 full = true;
305                 size = 100.0;
306         }
307         else
308                 size = scr_viewsize.value;
309         if (cl.intermission)
310         {
311                 full = true;
312                 size = 100;
313                 sb_lines = 0;
314         }
315         size /= 100.0;
316
317         // LordHavoc: always fullyscreen rendering
318         h = vid.height/* - sb_lines*/;
319
320         r_refdef.vrect.width = vid.width * size;
321         if (r_refdef.vrect.width < 96)
322         {
323                 size = 96.0 / r_refdef.vrect.width;
324                 r_refdef.vrect.width = 96;      // min for icons
325         }
326
327         r_refdef.vrect.height = vid.height * size;
328         //if (r_refdef.vrect.height > vid.height - sb_lines)
329         //      r_refdef.vrect.height = vid.height - sb_lines;
330         if (r_refdef.vrect.height > (int) vid.height)
331                         r_refdef.vrect.height = vid.height;
332         r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
333         if (full)
334                 r_refdef.vrect.y = 0;
335         else 
336                 r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
337
338         r_refdef.fov_x = scr_fov.value;
339         r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
340 }
341
342
343 /*
344 =================
345 SCR_SizeUp_f
346
347 Keybinding command
348 =================
349 */
350 void SCR_SizeUp_f (void)
351 {
352         Cvar_SetValue ("viewsize",scr_viewsize.value+10);
353         vid.recalc_refdef = 1;
354 }
355
356
357 /*
358 =================
359 SCR_SizeDown_f
360
361 Keybinding command
362 =================
363 */
364 void SCR_SizeDown_f (void)
365 {
366         Cvar_SetValue ("viewsize",scr_viewsize.value-10);
367         vid.recalc_refdef = 1;
368 }
369
370 //============================================================================
371
372 /*
373 ==================
374 SCR_Init
375 ==================
376 */
377 void SCR_Init (void)
378 {
379
380         Cvar_RegisterVariable (&scr_fov);
381         Cvar_RegisterVariable (&scr_viewsize);
382         Cvar_RegisterVariable (&scr_conspeed);
383         Cvar_RegisterVariable (&scr_showram);
384         Cvar_RegisterVariable (&scr_showturtle);
385         Cvar_RegisterVariable (&scr_showpause);
386         Cvar_RegisterVariable (&scr_centertime);
387         Cvar_RegisterVariable (&scr_printspeed);
388         Cvar_RegisterVariable (&showfps);
389
390 //
391 // register our commands
392 //
393         Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
394         Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
395         Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
396
397         scr_ram = Draw_PicFromWad ("ram");
398         scr_net = Draw_PicFromWad ("net");
399         scr_turtle = Draw_PicFromWad ("turtle");
400
401         scr_initialized = true;
402 }
403
404
405
406 /*
407 ==============
408 SCR_DrawRam
409 ==============
410 */
411 void SCR_DrawRam (void)
412 {
413         if (!scr_showram.value)
414                 return;
415
416         if (!r_cache_thrash)
417                 return;
418
419         Draw_Pic (32, 0, scr_ram);
420 }
421
422 /*
423 ==============
424 SCR_DrawTurtle
425 ==============
426 */
427 void SCR_DrawTurtle (void)
428 {
429         static int      count;
430         
431         if (!scr_showturtle.value)
432                 return;
433
434         if (host_frametime < 0.1)
435         {
436                 count = 0;
437                 return;
438         }
439
440         count++;
441         if (count < 3)
442                 return;
443
444         Draw_Pic (0, 0, scr_turtle);
445 }
446
447 /*
448 ==============
449 SCR_DrawNet
450 ==============
451 */
452 void SCR_DrawNet (void)
453 {
454         if (realtime - cl.last_received_message < 0.3)
455                 return;
456         if (cls.demoplayback)
457                 return;
458
459         Draw_Pic (64, 0, scr_net);
460 }
461
462 /*
463 ==============
464 DrawPause
465 ==============
466 */
467 void SCR_DrawPause (void)
468 {
469         qpic_t  *pic;
470
471         if (!scr_showpause.value)               // turn off for screenshots
472                 return;
473
474         if (!cl.paused)
475                 return;
476
477         pic = Draw_CachePic ("gfx/pause.lmp");
478         Draw_Pic ( (vid.width - pic->width)/2, 
479                 (vid.height - 48 - pic->height)/2, pic);
480 }
481
482
483
484 /*
485 ==============
486 SCR_DrawLoading
487 ==============
488 */
489 void SCR_DrawLoading (void)
490 {
491         qpic_t  *pic;
492
493         if (!scr_drawloading)
494                 return;
495                 
496         pic = Draw_CachePic ("gfx/loading.lmp");
497         Draw_Pic ( (vid.width - pic->width)/2, 
498                 (vid.height - 48 - pic->height)/2, pic);
499 }
500
501
502
503 //=============================================================================
504
505
506 /*
507 ==================
508 SCR_SetUpToDrawConsole
509 ==================
510 */
511 void SCR_SetUpToDrawConsole (void)
512 {
513         Con_CheckResize ();
514         
515         //if (scr_drawloading)
516         //      return;         // never a console with loading plaque
517
518 // decide on the height of the console
519         con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
520
521         if (con_forcedup)
522         {
523                 scr_conlines = vid.height;              // full screen
524                 scr_con_current = scr_conlines;
525         }
526         else if (key_dest == key_console)
527                 scr_conlines = vid.height/2;    // half screen
528         else
529                 scr_conlines = 0;                               // none visible
530         
531         if (scr_conlines < scr_con_current)
532         {
533                 scr_con_current -= scr_conspeed.value*host_frametime;
534                 if (scr_conlines > scr_con_current)
535                         scr_con_current = scr_conlines;
536
537         }
538         else if (scr_conlines > scr_con_current)
539         {
540                 scr_con_current += scr_conspeed.value*host_frametime;
541                 if (scr_conlines < scr_con_current)
542                         scr_con_current = scr_conlines;
543         }
544 }
545         
546 /*
547 ==================
548 SCR_DrawConsole
549 ==================
550 */
551 void SCR_DrawConsole (void)
552 {
553         if (scr_con_current)
554         {
555                 scr_copyeverything = 1;
556                 Con_DrawConsole (scr_con_current, true);
557                 clearconsole = 0;
558         }
559         else
560         {
561                 if (key_dest == key_game || key_dest == key_message)
562                         Con_DrawNotify ();      // only draw notify in game
563         }
564 }
565
566
567 /* 
568 ============================================================================== 
569  
570                                                 SCREEN SHOTS 
571  
572 ============================================================================== 
573 */ 
574
575 typedef struct _TargaHeader {
576         unsigned char   id_length, colormap_type, image_type;
577         unsigned short  colormap_index, colormap_length;
578         unsigned char   colormap_size;
579         unsigned short  x_origin, y_origin, width, height;
580         unsigned char   pixel_size, attributes;
581 } TargaHeader;
582
583
584 /* 
585 ================== 
586 SCR_ScreenShot_f
587 ================== 
588 */  
589 void SCR_ScreenShot_f (void) 
590 {
591         byte            *buffer;
592         char            pcxname[80]; 
593         char            checkname[MAX_OSPATH];
594         int                     i, c, temp;
595 // 
596 // find a file name to save it to 
597 // 
598         strcpy(pcxname,"dp0000.tga");
599                 
600         for (i=0 ; i<=9999 ; i++) 
601         { 
602                 pcxname[2] = (i/1000)%10 + '0'; 
603                 pcxname[3] = (i/ 100)%10 + '0'; 
604                 pcxname[4] = (i/  10)%10 + '0'; 
605                 pcxname[5] = (i/   1)%10 + '0'; 
606                 sprintf (checkname, "%s/%s", com_gamedir, pcxname);
607                 if (Sys_FileTime(checkname) == -1)
608                         break;  // file doesn't exist
609         } 
610         if (i==10000)
611         {
612                 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); 
613                 return;
614         }
615
616
617         buffer = malloc(glwidth*glheight*3 + 18);
618         memset (buffer, 0, 18);
619         buffer[2] = 2;          // uncompressed type
620         buffer[12] = glwidth&255;
621         buffer[13] = glwidth>>8;
622         buffer[14] = glheight&255;
623         buffer[15] = glheight>>8;
624         buffer[16] = 24;        // pixel size
625
626         glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
627
628         // swap rgb to bgr
629         c = 18+glwidth*glheight*3;
630         for (i=18 ; i<c ; i+=3)
631         {
632                 temp = buffer[i];
633                 buffer[i] = buffer[i+2];
634                 buffer[i+2] = temp;
635         }
636         COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
637
638         free (buffer);
639         Con_Printf ("Wrote %s\n", pcxname);
640
641
642
643 //=============================================================================
644
645
646 /*
647 ===============
648 SCR_BeginLoadingPlaque
649
650 ================
651 */
652 void SCR_BeginLoadingPlaque (void)
653 {
654         S_StopAllSounds (true);
655
656         if (cls.state != ca_connected)
657                 return;
658         if (cls.signon != SIGNONS)
659                 return;
660         
661 // redraw with no console and the loading plaque
662         Con_ClearNotify ();
663         scr_centertime_off = 0;
664         scr_con_current = 0;
665
666         scr_drawloading = true;
667         scr_fullupdate = 0;
668 //      Sbar_Changed ();
669         SCR_UpdateScreen ();
670         scr_drawloading = false;
671
672         scr_disabled_for_loading = true;
673         scr_disabled_time = realtime;
674         scr_fullupdate = 0;
675 }
676
677 /*
678 ===============
679 SCR_EndLoadingPlaque
680
681 ================
682 */
683 void SCR_EndLoadingPlaque (void)
684 {
685         scr_disabled_for_loading = false;
686         scr_fullupdate = 0;
687         Con_ClearNotify ();
688 }
689
690 //=============================================================================
691
692 char    *scr_notifystring;
693 qboolean        scr_drawdialog;
694
695 void SCR_DrawNotifyString (void)
696 {
697         char    *start;
698         int             l;
699         int             x, y;
700
701         start = scr_notifystring;
702
703         y = vid.height*0.35;
704
705         do      
706         {
707         // scan the width of the line
708                 for (l=0 ; l<40 ; l++)
709                         if (start[l] == '\n' || !start[l])
710                                 break;
711                 x = (vid.width - l*8)/2;
712                 // LordHavoc: speedup
713 //              for (j=0 ; j<l ; j++, x+=8)
714 //                      Draw_Character (x, y, start[j]);        
715                 Draw_String (x, y, start, l);
716                         
717                 y += 8;
718
719                 while (*start && *start != '\n')
720                         start++;
721
722                 if (!*start)
723                         break;
724                 start++;                // skip the \n
725         } while (1);
726 }
727
728 /*
729 ==================
730 SCR_ModalMessage
731
732 Displays a text string in the center of the screen and waits for a Y or N
733 keypress.  
734 ==================
735 */
736 int SCR_ModalMessage (char *text)
737 {
738         if (cls.state == ca_dedicated)
739                 return true;
740
741         scr_notifystring = text;
742  
743 // draw a fresh screen
744         scr_fullupdate = 0;
745         scr_drawdialog = true;
746         SCR_UpdateScreen ();
747         scr_drawdialog = false;
748         
749         S_ClearBuffer ();               // so dma doesn't loop current sound
750
751         do
752         {
753                 key_count = -1;         // wait for a key down and up
754                 Sys_SendKeyEvents ();
755         } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
756
757         scr_fullupdate = 0;
758         SCR_UpdateScreen ();
759
760         return key_lastpress == 'y';
761 }
762
763
764 //=============================================================================
765
766 /*
767 ===============
768 SCR_BringDownConsole
769
770 Brings the console down and fades the palettes back to normal
771 ================
772 */
773 void SCR_BringDownConsole (void)
774 {
775         int             i;
776         
777         scr_centertime_off = 0;
778         
779         for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
780                 SCR_UpdateScreen ();
781
782         cl.cshifts[0].percent = 0;              // no area contents palette on next frame
783         VID_SetPalette (host_basepal);
784 }
785
786 void GL_Set2D (void);
787
788 extern void SHOWLMP_drawall();
789 extern cvar_t contrast;
790 extern cvar_t brightness;
791 extern cvar_t gl_lightmode;
792
793 void GL_BrightenScreen()
794 {
795         float f;
796         glDisable(GL_TEXTURE_2D);
797         glEnable(GL_BLEND);
798         f = brightness.value = bound(1.0f, brightness.value, 5.0f);
799         if (f >= 1.01f)
800         {
801                 glBlendFunc (GL_DST_COLOR, GL_ONE);
802                 glBegin (GL_TRIANGLES);
803                 while (f >= 1.01f)
804                 {
805                         if (f >= 2)
806                                 glColor3f (1, 1, 1);
807                         else
808                                 glColor3f (f-1, f-1, f-1);
809                         glVertex2f (-5000, -5000);
810                         glVertex2f (10000, -5000);
811                         glVertex2f (-5000, 10000);
812                         f *= 0.5;
813                 }
814                 glEnd ();
815         }
816         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
817         contrast.value = bound(0.2, contrast.value, 1.0);
818         if (contrast.value < 0.99f)
819         {
820                 glBegin (GL_TRIANGLES);
821                 glColor4f (1, 1, 1, 1-contrast.value);
822                 glVertex2f (-5000, -5000);
823                 glVertex2f (10000, -5000);
824                 glVertex2f (-5000, 10000);
825                 glEnd ();
826         }
827
828         glEnable (GL_CULL_FACE);
829         glEnable (GL_DEPTH_TEST);
830         glDisable(GL_BLEND);
831         glEnable(GL_TEXTURE_2D);
832 }
833
834 /*
835 ==================
836 SCR_UpdateScreen
837
838 This is called every frame, and can also be called explicitly to flush
839 text to the screen.
840
841 LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :)
842 ==================
843 */
844 extern cvar_t gl_vertexarrays;
845 extern qboolean gl_arrays;
846 void GL_Finish();
847 void SCR_UpdateScreen (void)
848 {
849         double  time1 = 0, time2;
850
851         if (r_speeds.value)
852                 time1 = Sys_FloatTime ();
853
854         if (!gl_arrays)
855                 gl_vertexarrays.value = 0;
856
857         scr_copytop = 0;
858         scr_copyeverything = 0;
859
860         if (scr_disabled_for_loading)
861         {
862                 if (realtime - scr_disabled_time > 60)
863                 {
864                         scr_disabled_for_loading = false;
865                         Con_Printf ("load failed.\n");
866                 }
867                 else
868                         return;
869         }
870
871         if (!scr_initialized || !con_initialized)
872                 return;                         // not initialized yet
873
874
875         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
876         
877         //
878         // determine size of refresh window
879         //
880         if (oldfov != scr_fov.value)
881         {
882                 oldfov = scr_fov.value;
883                 vid.recalc_refdef = true;
884         }
885
886         if (oldscreensize != scr_viewsize.value)
887         {
888                 oldscreensize = scr_viewsize.value;
889                 vid.recalc_refdef = true;
890         }
891
892         if (vid.recalc_refdef)
893                 SCR_CalcRefdef ();
894
895         glClearColor(1,0,0,0);
896         glClear (GL_COLOR_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
897
898 //
899 // do 3D refresh drawing, and then update the screen
900 //
901         SCR_SetUpToDrawConsole ();
902
903         V_RenderView ();
904
905         GL_Set2D ();
906
907         if (scr_drawdialog)
908         {
909                 Sbar_Draw ();
910 //              Draw_FadeScreen ();
911                 SCR_DrawNotifyString ();
912                 scr_copyeverything = true;
913         }
914         else if (scr_drawloading)
915         {
916                 SCR_DrawLoading ();
917                 Sbar_Draw ();
918         }
919         else if (cl.intermission == 1 && key_dest == key_game)
920         {
921                 Sbar_IntermissionOverlay ();
922         }
923         else if (cl.intermission == 2 && key_dest == key_game)
924         {
925                 Sbar_FinaleOverlay ();
926                 SCR_CheckDrawCenterString ();
927         }
928         else
929         {
930                 if (crosshair.value)
931                         Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
932                 
933                 SCR_DrawRam ();
934                 SCR_DrawNet ();
935                 SCR_DrawTurtle ();
936                 SCR_DrawPause ();
937                 SCR_CheckDrawCenterString ();
938                 Sbar_Draw ();
939                 SHOWLMP_drawall();
940                 SCR_DrawConsole ();     
941                 M_Draw ();
942         }
943
944         if (showfps.value)
945         {
946                 static double currtime;
947                 double newtime;
948                 char temp[32];
949                 int calc;
950                 newtime = Sys_FloatTime();
951                 calc = (int) (100.0 / (newtime - currtime));
952                 sprintf(temp, "% 4i.%02i fps", calc / 100, calc % 100);
953                 currtime = newtime;
954                 Draw_String(vid.width - (12*8), 0, temp, 9999);
955         }
956
957         V_UpdatePalette ();
958
959         GL_BrightenScreen();
960
961         GL_Finish();
962
963         if (r_speeds.value)
964         {
965                 time2 = Sys_FloatTime ();
966                 Con_Printf ("%3i ms  %4i wpoly %4i epoly %4i transpoly %4i lightpoly %4i BSPnodes %4i BSPleafs\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, currenttranspoly, c_light_polys, c_nodes, c_leafs);
967         }
968         GL_EndRendering ();
969 }
970
971 // for profiling, this is seperated
972 void GL_Finish()
973 {
974         glFinish ();
975 }
976