/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // screen.c -- master for refresh, status bar, console, chat, notify, etc #include "quakedef.h" #include "r_local.h" // only the refresh window will be updated unless these variables are flagged int scr_copytop; int scr_copyeverything; int reflectavailable; float scr_con_current; float scr_conlines; // lines of console to display float oldsbar; float oldscreensize, oldfov; cvar_t *scr_viewsize; cvar_t *scr_fov; // 10 - 170 cvar_t *scr_fovadapt;// "Hor+" scaling cvar_t *scr_conspeed; cvar_t *scr_centertime; cvar_t *scr_showram; cvar_t *scr_showturtle; cvar_t *scr_showpause; cvar_t *scr_printspeed; cvar_t *scr_conheight; // 2000-01-12 Variable console height by Fett cvar_t *scr_scale; // leilei cvar_t *scr_retroscale; // leilei cvar_t *scr_aspectmode; // leilei qboolean scr_initialized; // ready to draw qpic_t *scr_ram; qpic_t *scr_net; qpic_t *scr_turtle; int sb_what_lines; // leilei - refdef sbar scale hack int scr_fullupdate; extern int vidmodetweak; // leilei - 0: normal resolution // 1: 16:10= 4:3 (320x200, 640x400) // 2: 2:3 = 4:3 (320x480 Tweaked) // 3: 8:10 = 4:3 (320x400 Tweaked) int clearconsole; int clearnotify; int retroscalefactor; // leilei viddef_t vid; // global video state vrect_t *pconupdate; vrect_t scr_vrect; qboolean scr_disabled_for_loading; qboolean scr_drawloading; float scr_disabled_time; qboolean scr_skipupdate; qboolean block_drawing; void SCR_ScreenShot_f (void); /* =============================================================================== CENTER PRINTING =============================================================================== */ char scr_centerstring[1024]; float scr_centertime_start; // for slow victory printing float scr_centertime_off; int scr_center_lines; int scr_erase_lines; int scr_erase_center; /* ============== SCR_CenterPrint Called for important messages that should stay in the center of the screen for a few moments ============== */ void SCR_CenterPrint (char *str) { strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); scr_centertime_off = scr_centertime->value; scr_centertime_start = cl.time; // count the number of lines for centering scr_center_lines = 1; while (*str) { if (*str == '\n') scr_center_lines++; str++; } } void SCR_EraseCenterString (void) { int y; if (scr_erase_center++ > vid.numpages) { scr_erase_lines = 0; return; } if (scr_center_lines <= 4) y = vid.height*0.35; else y = 48; scr_copytop = 1; Draw_TileClear (0, y,vid.width, 8*scr_erase_lines); } void SCR_DrawCenterString (void) { char *start; int l; int j; int x, y; int remaining; // the finale prints the characters one at a time if (cl.intermission) remaining = scr_printspeed->value * (cl.time - scr_centertime_start); else remaining = 9999; #ifdef SCALED2D scr_erase_center = 0; start = scr_centerstring; if (scr_center_lines <= 4) y = vid.vconheight*0.35; else y = 48; do { // scan the width of the line for (l=0 ; l<40 ; l++) if (start[l] == '\n' || !start[l]) break; x = (vid.vconwidth - l*8)/2; for (j=0 ; j scr_erase_lines) scr_erase_lines = scr_center_lines; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes start // scr_centertime_off -= host_frametime; scr_centertime_off -= host_cpu_frametime; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes end if (scr_centertime_off <= 0 && !cl.intermission) return; if (key_dest != key_game) return; SCR_DrawCenterString (); } //============================================================================= float scalefactor; float scalefactorv; // QUAKESPASM CODE BY SEZERO START /* ==================== AdaptFovx Adapt a 4:3 horizontal FOV to the current screen size using the "Hor+" scaling: 2.0 * atan(width / height * 3.0 / 4.0 * tan(fov_x / 2.0)) ==================== */ extern cvar_t *temp2; float AdaptFovx (float fov_x, float width, float height) { float a, x; float ferv; if (cl_sbar->value) ferv = 0.15 * ((float)sb_lines * 0.02083333); // leilei - fudge around the size of fov else ferv = 0; if (fov_x < 1 || fov_x > 179) fov_x = 90; // fallback to 90 if we fail... // Sys_Error ("Bad fov: %f", fov_x); #ifndef _WIN32 if (vid.aspect > 1.10f) return fov_x; // there's no such thing as a widescreen dos machine #endif // if (!scr_fov_adapt.value) // return fov_x; if ((x = height / width) == 0.75) return fov_x; a = atan((0.75 - ferv)/ x * tan(fov_x / 360 * M_PI)); a = a * 360 / M_PI; return a; } /* ==================== CalcFovy ==================== */ float CalcFovy (float fov_x, float width, float height) { float a, x; if (fov_x < 1 || fov_x > 179) fov_x = 90; // fallback to 90 if we fail... // Sys_Error ("Bad fov: %f", fov_x); x = width / tan(fov_x / 360 * M_PI); a = atan(height / x); a = a * 360 / M_PI; return a; } // QUAKESPASM CODE BY SEZERO END // leilei - i am a dirty bitch for not figuring this out on my own .-_-. /* ==================== CalcFov ==================== */ float CalcFov (float fov_x, float width, float height) { /* float a; float x; if (fov_x < 1 || fov_x > 179){ fov_x = 179; // leilei - don't crash. } // Sys_Error ("Bad fov: %f", fov_x); x = width/tan(fov_x/360*M_PI); a = atan (height/x); a = a*360/M_PI; return a; */ float x; x = width / tan(fov_x / 360 * M_PI); return atan (height / x) * 360 / M_PI; } // MH's correct thing float SCR_CalcFovX (float fov_y, float width, float height) { // bound, don't crash if (fov_y < 1) fov_y = 1; if (fov_y > 179) fov_y = 179; return (atan (width / (height / tan ((fov_y * M_PI) / 360.0f))) * 360.0f) / M_PI; } float SCR_CalcFovY (float fov_x, float width, float height) { // bound, don't crash if (fov_x < 1) fov_x = 1; if (fov_x > 179) fov_x = 179; return (atan (height / (width / tan ((fov_x * M_PI) / 360.0f))) * 360.0f) / M_PI; } void SCR_SetFOV (float fovvar, int width, int height) { float aspect = (float) height / (float) width; float BASELINE_W, BASELINE_H; BASELINE_W = 640.0f; BASELINE_H = 480.0f - (24 * scalefactor); // leilei - new baseline // horizontalFov = atan (tan (verticalFov) * aspectratio) // verticalFov = atan (tan (horizontalFov) / aspectratio) if (aspect > (BASELINE_H / BASELINE_W)) { // use the same calculation as GLQuake did (horizontal is constant, vertical varies) r_refdef.fov_x = fovvar; r_refdef.fov_y = SCR_CalcFovY (r_refdef.fov_x, width, height); } else { // alternate calculation (vertical is constant, horizontal varies) r_refdef.fov_y = SCR_CalcFovY (fovvar, BASELINE_W, BASELINE_H); r_refdef.fov_x = SCR_CalcFovX (r_refdef.fov_y, width, height); } } float CalcFovOld (float fov_x, float width, float height) { float a; float x; if (fov_x < 1 || fov_x > 179) Sys_Error ("Bad fov: %f", fov_x); x = width/tan(fov_x/360*M_PI); a = atan (height/x); a = a*360/M_PI; return a; } int yeahimconsoled; int screenfake; // leilei - forcing 320x200 metrics in any resolution no matter what (HACK HACK HACK!) void SCR_StretchInit (void) { int i; float eh; if ((i = COM_CheckParm("-conwidth")) != 0){ vid.vconwidth = Q_atoi(com_argv[i+1]); scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; // vid.vconwidth = vid.width / scalefactor; // vid.vconheight = vid.height / scalefactor; // leilei - variable height doesn't work right now. yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged } else if ((i = COM_CheckParm("-youpickedupaclip")) != 0){ vid.vconwidth = 32; vid.vconheight = 32; scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / 32; // vid.vconwidth = vid.width / scalefactor; // vid.vconheight = vid.height / scalefactor; // leilei - variable height doesn't work right now. yeahimconsoled = 0; sb_scaled = 1; menu_scaled = 0; console_scaled = 0; // currently bugged } else if ((i = COM_CheckParm("-conheight")) != 0){ vid.vconheight = Q_atoi(com_argv[i+1]); scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; // vid.vconwidth = vid.width / scalefactor; // vid.vconheight = vid.height / scalefactor; // leilei - variable height doesn't work right now. yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged } else{ scalefactor = 0; // we don't stretch. } if (scalefactor > (vid.height / 200)) scalefactor = vid.height / 200; // scr_scale->value = scalefactor + scalefactorv / 2; // transfer are cvar's ovar. /* int i; float eh; if ((i = COM_CheckParm("-conwidth")) != 0){ vid.vconwidth = Q_atoi(com_argv[i+1]); eh = vid.width / vid.vconwidth; vid.vconwidth = vid.width / eh; vid.vconheight = vid.height / eh; // leilei - variable height doesn't work right now. yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 0; // currently bugged } else vid.vconwidth = vid.width; */ /* if (yeahimconsoled){ vid.vconwidth &= 0xfff8; // make it a multiple of eight // pick a conheight that matches with correct aspect // vid.vconheight = vid.vconwidth*3 / 4; if ((i = COM_CheckParm("-conheight")) != 0) // vid.vconheight = Q_atoi(com_argv[i+1]); vid.vconheight = vid.height / (vid.width / vid.vconwidth); // leilei - variable height doesn't work right now. if (vid.vconheight < 200) vid.vconheight = 200; } else { vid.vconwidth = vid.width; vid.vconheight = vid.height; } */ // if (vid.vconheight > vid.height) // vid.vconheight = 200; // clamping it crashes, so fall back to 320x200 anyway // if (yeahimconsoled) // vid.vconheight = vid.height / (vid.width / vid.vconwidth); // leilei - variable height doesn't work right now. }; void SCR_CvarCheck (void) { scalefactor = scr_scale->value; scalefactorv = scr_scale->value; if (scr_retroscale->value){ scalefactorv = vid.height / 200; // force old metrics etc!! scalefactor = scalefactorv; retroscalefactor = 1; } else retroscalefactor = 0; if (scalefactorv > (vid.height / 200)) scalefactorv = vid.height / 200; // if we go beyond 320x200, then clamp! // if (scalefactor > (vid.width / 320)) // scalefactor = vid.width / 320; // if we go beyond 320x200, then clamp! if (scalefactor < 1) scalefactor = 1; if (scalefactorv < 1) scalefactorv = 1; SCR_StretchRefresh(); }; void SCR_StretchRefresh (void) { int i; float eh; if (!scalefactor) return; // don't even try if (!scalefactorv) return; // don't even try screenfake = 0; if (screenfake == 1){ vid.vconwidth = 320; vid.vconheight = 200; scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged vid.recalc_refdef = 1; // yeah return; } if (screenfake == 2){ vid.vconwidth = 320; vid.vconheight = 400; scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged vid.recalc_refdef = 1; // yeah return; } if (screenfake == 3){ vid.vconwidth = 360; vid.vconheight = 480; scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged vid.recalc_refdef = 1; // yeah return; } if (screenfake == 4){ vid.vconwidth = 640; vid.vconheight = 400; scalefactor = vid.width / vid.vconwidth; scalefactorv = vid.height / vid.vconheight; yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 1; // currently bugged vid.recalc_refdef = 1; // yeah return; } if (scalefactorv < 1){ vid.vconheight = vid.height; yeahimconsoled = 0; sb_scaled = 0; menu_scaled = 0; console_scaled = 0; // currently bugged } if (scalefactor < 1){ vid.vconwidth = vid.width; yeahimconsoled = 0; sb_scaled = 0; menu_scaled = 0; console_scaled = 0; // currently bugged return; // avoid div0 at all costs } // if (scalefactor > (vid.height / 200)) // scalefactor = vid.height / 200; // if (scalefactor < (vid.vconheight / vid.height)) // scalefactor = vid.vconheight / vid.height; vid.vconwidth = vid.width / scalefactor; vid.vconheight = vid.height / scalefactorv; // leilei - variable height doesn't work right now. yeahimconsoled = 1; sb_scaled = 1; menu_scaled = 1; console_scaled = 0; // currently bugged // minimum safeguards so we don't make a size too small to enter // the evil land of crash city if (vid.vconwidth < 320) vid.vconwidth = 320; if (vid.vconheight < 200) vid.vconheight = 200; if (vid.vconwidth > vid.width && vid.vconheight > vid.height){ vid.vconwidth = vid.width; vid.vconheight = vid.height; yeahimconsoled = 0; sb_scaled = 0; menu_scaled = 0; console_scaled = 0; scalefactor = 1; scalefactorv = 1; } vid.recalc_refdef = 1; // yeah }; /* ================= SCR_CalcRefdef Must be called whenever vid changes Internal use only ================= */ static void SCR_CalcRefdef (void) { vrect_t vrect; float size; float stretchf = 1; scr_fullupdate = 0; // force a background redraw vid.recalc_refdef = 0; if (vid.stretched == 2) stretchf = 2; else if (vid.stretched == 3) stretchf = 0.5; if (vid.width < 800 && vid.aspect > 1.6) { stretchf *= 0.8; // try to fix it for 320x200.... } // force the status bar to redraw Sbar_Changed (); //======================================== // bound viewsize if (scr_viewsize->value < 30) Cvar_Set (scr_viewsize, "30"); if (scr_viewsize->value > 120) Cvar_Set (scr_viewsize, "120"); // bound field of view if (scr_fov->value < 10) Cvar_Set (scr_fov,"10"); // if (scr_fov->value > 90) // Cvar_Set (scr_fov,"90"); // cheaters can eat crap if (scr_fov->value > 199) Cvar_Set (scr_fov,"199"); // cheaters can eat crap // leilei - Removed this because it breaks the 'tear gars' in swatteam // intermission is always full screen if (cl.intermission) size = 120; else size = scr_viewsize->value; #ifdef SCALED2D if(sb_scaled){ if (size >= 120) sb_lines = 0; // no status bar at all else if (size >= 110) sb_lines = 24; // no inventory else sb_lines = 24+16+8; } else #endif { if (size >= 120) sb_lines = 0; // no status bar at all else if (size >= 110) sb_lines = 24; // no inventory else sb_lines = 24+16+8; } #ifdef SCALED2D if (sb_scaled) // sb_what_lines = sb_lines * (vid.vconheight / vid.height); // leilei - refdef hack fix sb_what_lines = sb_lines * (scalefactorv); // leilei - refdef hack fix else #endif sb_what_lines = sb_lines; // these calculations mirror those in R_Init() for r_refdef, but take no // account of water warping vrect.x = 0; vrect.y = 0; vrect.width = vid.width; vrect.height = vid.height; R_SetVrect (&vrect, &scr_vrect, sb_what_lines); r_refdef.vrect = scr_vrect; //r_refdef.fov_x = AdaptFovx (scr_fov->value, r_refdef.vrect.width, r_refdef.vrect.height); //r_refdef.fov_y = CalcFovy (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); //r_refdef.fov_y = CalcFovy (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); // quakespasm if (scr_aspectmode->value == 1){ r_refdef.fov_x = AdaptFovx (scr_fov->value, r_refdef.vrect.width * stretchf, r_refdef.vrect.height); r_refdef.fov_y = CalcFovy (r_refdef.fov_x, r_refdef.vrect.width * stretchf, r_refdef.vrect.height); } // mh's "Quakespasm is wrong" post, a bit re-adapted else if (scr_aspectmode->value == 2){ SCR_SetFOV(scr_fov->value, r_refdef.vrect.width * stretchf, r_refdef.vrect.height); } else // crappy old fov where we lose vert. just like Q3A! { r_refdef.fov_x = scr_fov->value; r_refdef.fov_y = CalcFovOld (r_refdef.fov_x, r_refdef.vrect.width * stretchf, r_refdef.vrect.height); } // guard against going from one mode to another that's less than half the // vertical resolution if (scr_con_current > vid.height) scr_con_current = vid.height; // notify the refresh of the change R_ViewChanged (&vrect, sb_what_lines, vid.aspect); // R_ViewChanged (vid.aspect); } /* ================= SCR_SizeUp_f Keybinding command ================= */ void SCR_SizeUp_f (void) { Cvar_SetValue (scr_viewsize, scr_viewsize->value+10); vid.recalc_refdef = 1; } /* ================= SCR_SizeDown_f Keybinding command ================= */ void SCR_SizeDown_f (void) { Cvar_SetValue (scr_viewsize, scr_viewsize->value-10); vid.recalc_refdef = 1; } //============================================================================ extern cvar_t *cl_bobmodel; extern cvar_t *r_shading; extern cvar_t *s_oldspatial; // 2001-09-18 New cvar system by Maddes (Init) start /* ================== SCR_Init_Cvars ================== */ cvar_t *scr_fov_adapt; void SCR_Init_Cvars (void) { scr_fov = Cvar_Get ("fov", "90", CVAR_ORIGINAL); scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE|CVAR_ORIGINAL); scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_ORIGINAL); scr_showram = Cvar_Get ("showram", "1", CVAR_ORIGINAL); scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_ORIGINAL); scr_showpause = Cvar_Get ("showpause", "1", CVAR_ORIGINAL); scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_ORIGINAL); scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_ORIGINAL); scr_fov_adapt = Cvar_Get ("scr_fov_adapt", "1", CVAR_ARCHIVE | CVAR_ORIGINAL); // 2000-01-12 Variable console height by Fett start scr_conheight = Cvar_Get ("scr_conheight", "0.5", CVAR_ARCHIVE); Cvar_SetRangecheck (scr_conheight, Cvar_RangecheckFloat, 0, 1); Cvar_Set(scr_conheight, scr_conheight->string); // do rangecheck // 2000-01-12 Variable console height by Fett end scr_scale = Cvar_Get ("scr_scale", "2", CVAR_ARCHIVE | CVAR_ORIGINAL); // leilei - default to 2 scr_retroscale = Cvar_Get ("scr_retroscale", "1", CVAR_ARCHIVE | CVAR_ORIGINAL); // leilei - default to 1 since it's fast now..... scr_aspectmode = Cvar_Get ("scr_aspectmode", "1", CVAR_ARCHIVE | CVAR_ORIGINAL); } // 2001-09-18 New cvar system by Maddes (Init) end /* ================== SCR_Init ================== */ void SCR_Init (void) { // 2001-09-18 New cvar system by Maddes (Init) end // // register our commands // Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); Cmd_AddCommand ("sizeup",SCR_SizeUp_f); Cmd_AddCommand ("sizedown",SCR_SizeDown_f); scr_ram = Draw_PicFromWad ("ram"); scr_net = Draw_PicFromWad ("net"); scr_turtle = Draw_PicFromWad ("turtle"); scr_initialized = true; } /* ============== SCR_DrawRam ============== */ void SCR_DrawRam (void) { if (!scr_showram->value) return; if (!r_cache_thrash) return; if (menu_scaled) Draw_Pic_Scaled (scr_vrect.x+32, scr_vrect.y, scr_ram); else Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); } /* ============== SCR_DrawTurtle ============== */ void SCR_DrawTurtle (void) { static int count; if (!scr_showturtle->value) return; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes start // if (host_frametime < 0.1) if (host_cpu_frametime < 0.1) // 2001-10-20 TIMESCALE extension by Tomaz/Maddes end { count = 0; return; } count++; if (count < 3) return; if (menu_scaled) Draw_Pic_Scaled (scr_vrect.x, scr_vrect.y, scr_turtle); else Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); } /* ============== SCR_DrawNet ============== */ void SCR_DrawNet (void) { if (realtime - cl.last_received_message < 0.3) return; if (cls.demoplayback) return; if (menu_scaled) Draw_Pic_Scaled (scr_vrect.x+64, scr_vrect.y, scr_net); else Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); } // 2001-11-31 FPS display by QuakeForge/Muff start /* ============== SCR_DrawFPS ============== */ //muff - hacked out of SourceForge implementation + modified void SCR_DrawFPS (void) { static double lastframetime; double t; static int lastfps; int x, y; char st[80]; if (!cl_showfps->value) return; t = Sys_FloatTime (); if ((t - lastframetime) >= 1.0) { lastfps = fps_count; fps_count = 0; lastframetime = t; } sprintf(st, "%3d FPS", lastfps); #ifdef SCALED2D if (sb_scaled) x = vid.vconwidth - strlen(st) * 16 - 16; else #endif x = vid.width - strlen(st) * 16 - 16; y = 0 ; #ifdef SCALED2D if (sb_scaled) Draw_String_Scaled(x, y, st); else #endif Draw_String(x, y, st); } // 2001-11-31 FPS display by QuakeForge/Muff end /* ============== DrawPause ============== */ void SCR_DrawPause (void) { qpic_t *pic; if (!scr_showpause->value) // turn off for screenshots return; if (!cl.paused) return; pic = Draw_CachePic ("gfx/pause.lmp"); if (menu_scaled) Draw_Pic_Scaled ( (vid.vconwidth - pic->width)/2, (vid.vconheight - 48 - pic->height)/2, pic); else Draw_Pic ( (vid.width - pic->width)/2, (vid.height - 48 - pic->height)/2, pic); } /* ============== SCR_DrawLoading ============== */ void SCR_DrawLoading (void) { qpic_t *pic; if (!scr_drawloading) return; pic = Draw_CachePic ("gfx/loading.lmp"); if (menu_scaled) Draw_Pic_Scaled ( (vid.vconwidth - pic->width)/2, (vid.vconheight - 48 - pic->height)/2, pic); else Draw_Pic ( (vid.width - pic->width)/2, (vid.height - 48 - pic->height)/2, pic); } //============================================================================= /* ================== SCR_SetUpToDrawConsole ================== */ extern cvar_t *con_alpha; // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes void SCR_SetUpToDrawConsole (void) { Con_CheckResize (); if (scr_drawloading) return; // never a console with loading plaque // decide on the height of the console con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; if (con_forcedup) { scr_conlines = vid.height; // full screen scr_con_current = scr_conlines; } else if (key_dest == key_console) // 2000-01-12 Variable console height by Fett/Maddes start { scr_conlines = vid.height/2; // half screen #ifdef SCALED2D if (console_scaled) // scr_conlines = vid.vconheight/2; // half screen scr_conlines = vid.vconheight*scr_conheight->value; // in-game console else #endif scr_conlines = vid.height*scr_conheight->value; // in-game console if (scr_conlines < (3*8+8+8)) // always leave three lines visible (plus command line and border) { scr_conlines = (3*8+8+8); } if (scr_conlines >= vid.height) { #ifdef SCALED2D if (console_scaled) scr_conlines = vid.vconheight - 1; // maximum is full screen else #endif scr_conlines = vid.height - 1; // maximum is full screen } } // 2000-01-12 Variable console height by Fett/Maddes end else scr_conlines = 0; // none visible if (scr_conlines < scr_con_current) { // 2001-10-20 TIMESCALE extension by Tomaz/Maddes start // scr_con_current -= scr_conspeed->value*host_frametime; if (console_scaled) scr_con_current -= scr_conspeed->value*host_cpu_frametime * vid.height / vid.vconheight; else scr_con_current -= scr_conspeed->value*host_cpu_frametime; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes end if (scr_conlines > scr_con_current) scr_con_current = scr_conlines; } else if (scr_conlines > scr_con_current) { // 2001-10-20 TIMESCALE extension by Tomaz/Maddes start // scr_con_current += scr_conspeed->value*host_frametime; if (console_scaled) scr_con_current += scr_conspeed->value*host_cpu_frametime * vid.height / vid.vconheight; else scr_con_current += scr_conspeed->value*host_cpu_frametime; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes end if (scr_conlines < scr_con_current) scr_con_current = scr_conlines; } if (clearconsole++ < vid.numpages) { scr_copytop = 1; // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes start if (con_alpha->value == 1.0) { // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes end Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes start } else { // Draw full valid screen Draw_TileClear (0, 0, vid.width, vid.height ); } // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes end Sbar_Changed (); } else if (clearnotify++ < vid.numpages) { scr_copytop = 1; Draw_TileClear (0,0,vid.width, con_notifylines); } else con_notifylines = 0; } /* ================== SCR_DrawConsole ================== */ void SCR_DrawConsole (void) { if (scr_con_current) { scr_copyeverything = 1; Con_DrawConsole (scr_con_current, true); clearconsole = 0; } else { if (key_dest == key_game || key_dest == key_message) Con_DrawNotify (); // only draw notify in game } } /* ============================================================================== SCREEN SHOTS ============================================================================== */ typedef struct { char manufacturer; char version; char encoding; char bits_per_pixel; unsigned short xmin,ymin,xmax,ymax; unsigned short hres,vres; unsigned char palette[48]; char reserved; char color_planes; unsigned short bytes_per_line; unsigned short palette_type; char filler[58]; unsigned char data; // unbounded } pcx_t; /* ============== WritePCXfile ============== */ void WritePCXfile (char *filename, byte *data, int width, int height, int rowbytes, byte *palette) { int i, j, length; pcx_t *pcx; byte *pack; pcx = Hunk_TempAlloc (width*height*2+1000); if (pcx == NULL) { Con_Printf("SCR_ScreenShot_f: not enough memory\n"); return; } pcx->manufacturer = 0x0a; // PCX id pcx->version = 5; // 256 color pcx->encoding = 1; // uncompressed pcx->bits_per_pixel = 8; // 256 color pcx->xmin = 0; pcx->ymin = 0; pcx->xmax = LittleShort((short)(width-1)); pcx->ymax = LittleShort((short)(height-1)); pcx->hres = LittleShort((short)width); pcx->vres = LittleShort((short)height); Q_memset (pcx->palette,0,sizeof(pcx->palette)); pcx->color_planes = 1; // chunky image pcx->bytes_per_line = LittleShort((short)width); pcx->palette_type = LittleShort(2); // not a grey scale Q_memset (pcx->filler,0,sizeof(pcx->filler)); // pack the image pack = &pcx->data; for (i=0 ; ivalue > 1 && !r_dowarp && !r_docrap){ reflectpass = 1; V_RenderView (); reflectpass = 0; V_RenderView (); } else { reflectpass = 0; V_RenderView (); } #else reflectpass = 0; V_RenderView (); #endif }; int dontevendraw; void SCR_UpdateScreen (void) { static float oldscr_viewsize; static float oldlcd_x; static float oldv_detail; vrect_t vrect; if (scr_skipupdate || block_drawing) return; scr_copytop = 0; scr_copyeverything = 0; if (fogenabled && r_fogquality->value){ foguse2 = 0;foguse = 2;} else if (fogenabled && !r_fogquality->value){ foguse = 1;foguse2 = 0;} else if (!fogenabled){ foguse = 0; foguse2 = 0;} if (scr_disabled_for_loading) { if (realtime - scr_disabled_time > 60) { scr_disabled_for_loading = false; Con_Printf ("load failed.\n"); } else return; } if (cls.state == ca_dedicated) return; // stdout only if (!scr_initialized || !con_initialized) return; // not initialized yet if (scr_viewsize->value != oldscr_viewsize) { oldscr_viewsize = scr_viewsize->value; vid.recalc_refdef = 1; } // // check for vid changes // if (oldfov != scr_fov->value) { oldfov = scr_fov->value; vid.recalc_refdef = true; } if (oldlcd_x != lcd_x->value) { oldlcd_x = lcd_x->value; vid.recalc_refdef = true; } if (oldv_detail != v_detail->value) { oldv_detail = v_detail->value; vid.recalc_refdef = true; } if (oldscreensize != scr_viewsize->value) { oldscreensize = scr_viewsize->value; vid.recalc_refdef = true; } if (oldsbar != cl_sbar->value) { oldsbar = cl_sbar->value; vid.recalc_refdef = true; } if (!reflectpass){ if (vid.recalc_refdef) { // something changed, so reorder the screen SCR_CalcRefdef (); } // // do 3D refresh drawing, and then update the screen // D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly if (scr_fullupdate++ < vid.numpages) { // clear the entire screen scr_copyeverything = 1; Draw_TileClear (0,0,vid.width,vid.height); Sbar_Changed (); } pconupdate = NULL; } SCR_SetUpToDrawConsole (); SCR_EraseCenterString (); D_DisableBackBufferAccess (); // for adapters that can't stay mapped in // for linear writes all the time // Draw_FadeScreen (); VID_LockBuffer (); // Draw_GetShroomedPT1(); // leilei - water reflections need two passes // we all start it here! // TODO- mirror chain splitpass = 0; if (!dontevendraw) SCR_ReallyRender(); if(splitmeup){ client_t oldcle; client_state_t oldcl; //*oldcl = cl; oldcl = cl; //cl = clsplit; splitpass = 1; if (!dontevendraw) SCR_ReallyRender(); } VID_UnlockBuffer (); D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly // stupid place to put this //if(oldwateralpha != newwateralpha){ // oldwateralpha = newwateralpha = r_wateralpha->value; // if(newwateralpha < 1) WaterTableGet(); //} // leilei - make a new alpha tables. if (!nolookups){ if(oldwateralpha != r_wateralpha->value || (oldtranquality != (int)r_tranquality->value) || (oldwaterblend != (int)r_waterblend->value)){ oldtranquality = r_tranquality->value; oldwateralpha = r_wateralpha->value; oldwaterblend = r_waterblend->value; WaterTableGet(); } } if(retroscalefactor != scr_retroscale->value){ SCR_CvarCheck(); } else if(scalefactor != scr_scale->value && !scr_retroscale->value){ SCR_CvarCheck(); } if (dyncolor != r_coloreddyns->value){ dyncolor = r_coloreddyns->value; } if (shadowhack != r_shadowhack->value){ shadowhack = r_shadowhack->value; } if (r_dynamic->value) dynlightenabled = 1; else dynlightenabled = 0; // Draw_GetShroomedPT2(); if (r_tinge->value == 3) Draw_DudeScreen (); else if (r_tinge->value == 2) Draw_DudeScreen66 (); else if (r_tinge->value == 1) Draw_DudeScreen33 (); else if (r_tinge->value == -1) Draw_DudeScreen33A (); else if (r_tinge->value == -2) Draw_DudeScreen66A (); //Draw_Bloom (); /*if (cl.paused || scr_drawloading || scr_drawdialog){ dontevendraw = 1; Draw_Something (); Sbar_Draw (); } else dontevendraw = 0; */ if (scr_drawdialog) { Sbar_Draw (); Draw_FadeScreen (); SCR_DrawNotifyString (); scr_copyeverything = true; } else if (scr_drawloading) { //Draw_FadeScreen (); // this WAS cool, but... i'll have to make a whole transition thing first SCR_DrawLoading (); Sbar_Draw (); } else if (cl.intermission == 1 && key_dest == key_game) { Sbar_IntermissionOverlay (); } else if (cl.intermission == 2 && key_dest == key_game) { Sbar_FinaleOverlay (); SCR_CheckDrawCenterString (); } else if (cl.intermission == 3 && key_dest == key_game) { SCR_CheckDrawCenterString (); } else { SCR_DrawRam (); SCR_DrawNet (); SCR_DrawTurtle (); SCR_DrawFPS (); // 2001-11-31 FPS display by QuakeForge/Muff SCR_DrawPause (); SCR_CheckDrawCenterString (); Sbar_Draw (); SCR_DrawConsole (); M_Draw (); } D_DisableBackBufferAccess (); // for adapters that can't stay mapped in // for linear writes all the time if (pconupdate) { D_UpdateRects (pconupdate); } V_UpdatePalette (); // // update one of three areas // #ifdef SCALED2D if (sb_scaled) sb_what_lines = sb_lines * (vid.height / vid.vconheight); // leilei - refdef hack fix else #endif // if (!reflectpass) sb_what_lines = sb_lines; // else // sb_what_lines = 0; if (scr_copyeverything) { vrect.x = 0; vrect.y = 0; vrect.width = vid.width; vrect.height = vid.height; vrect.pnext = 0; VID_Update (&vrect); } else if (scr_copytop) { vrect.x = 0; vrect.y = 0; vrect.width = vid.width; vrect.height = vid.height - sb_lines; vrect.pnext = 0; VID_Update (&vrect); } else { vrect.x = scr_vrect.x; vrect.y = scr_vrect.y; vrect.width = scr_vrect.width; vrect.height = scr_vrect.height; vrect.pnext = 0; VID_Update (&vrect); } } /* ================== SCR_UpdateWholeScreen ================== */ void SCR_UpdateWholeScreen (void) { scr_fullupdate = 0; SCR_UpdateScreen (); }