|
|
1.1 ! root 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: // screen.c -- master for refresh, status bar, console, chat, notify, etc ! 21: ! 22: #include "quakedef.h" ! 23: #include "r_local.h" ! 24: ! 25: #include <time.h> ! 26: ! 27: /* ! 28: ! 29: background clear ! 30: rendering ! 31: turtle/net/ram icons ! 32: sbar ! 33: centerprint / slow centerprint ! 34: notify lines ! 35: intermission / finale overlay ! 36: loading plaque ! 37: console ! 38: menu ! 39: ! 40: required background clears ! 41: required update regions ! 42: ! 43: ! 44: syncronous draw mode or async ! 45: One off screen buffer, with updates either copied or xblited ! 46: Need to double buffer? ! 47: ! 48: ! 49: async draw will require the refresh area to be cleared, because it will be ! 50: xblited, but sync draw can just ignore it. ! 51: ! 52: sync ! 53: draw ! 54: ! 55: CenterPrint () ! 56: SlowPrint () ! 57: Screen_Update (); ! 58: Con_Printf (); ! 59: ! 60: net ! 61: turn off messages option ! 62: ! 63: the refresh is allways rendered, unless the console is full screen ! 64: ! 65: ! 66: console is: ! 67: notify lines ! 68: half ! 69: full ! 70: ! 71: ! 72: */ ! 73: ! 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: float oldsbar; ! 84: cvar_t scr_viewsize = {"viewsize","100", true}; ! 85: cvar_t scr_fov = {"fov","90"}; // 10 - 170 ! 86: cvar_t scr_conspeed = {"scr_conspeed","300"}; ! 87: cvar_t scr_centertime = {"scr_centertime","2"}; ! 88: cvar_t scr_showram = {"showram","1"}; ! 89: cvar_t scr_showturtle = {"showturtle","0"}; ! 90: cvar_t scr_showpause = {"showpause","1"}; ! 91: cvar_t scr_printspeed = {"scr_printspeed","8"}; ! 92: cvar_t scr_allowsnap = {"scr_allowsnap", "1"}; ! 93: ! 94: qboolean scr_initialized; // ready to draw ! 95: ! 96: qpic_t *scr_ram; ! 97: qpic_t *scr_net; ! 98: qpic_t *scr_turtle; ! 99: ! 100: int scr_fullupdate; ! 101: ! 102: int clearconsole; ! 103: int clearnotify; ! 104: ! 105: int sb_lines; ! 106: ! 107: viddef_t vid; // global video state ! 108: ! 109: vrect_t *pconupdate; ! 110: vrect_t scr_vrect; ! 111: ! 112: qboolean scr_disabled_for_loading; ! 113: ! 114: qboolean scr_skipupdate; ! 115: ! 116: qboolean block_drawing; ! 117: ! 118: void SCR_ScreenShot_f (void); ! 119: void SCR_RSShot_f (void); ! 120: ! 121: /* ! 122: =============================================================================== ! 123: ! 124: CENTER PRINTING ! 125: ! 126: =============================================================================== ! 127: */ ! 128: ! 129: char scr_centerstring[1024]; ! 130: float scr_centertime_start; // for slow victory printing ! 131: float scr_centertime_off; ! 132: int scr_center_lines; ! 133: int scr_erase_lines; ! 134: int scr_erase_center; ! 135: ! 136: /* ! 137: ============== ! 138: SCR_CenterPrint ! 139: ! 140: Called for important messages that should stay in the center of the screen ! 141: for a few moments ! 142: ============== ! 143: */ ! 144: void SCR_CenterPrint (char *str) ! 145: { ! 146: strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); ! 147: scr_centertime_off = scr_centertime.value; ! 148: scr_centertime_start = cl.time; ! 149: ! 150: // count the number of lines for centering ! 151: scr_center_lines = 1; ! 152: while (*str) ! 153: { ! 154: if (*str == '\n') ! 155: scr_center_lines++; ! 156: str++; ! 157: } ! 158: } ! 159: ! 160: void SCR_EraseCenterString (void) ! 161: { ! 162: int y; ! 163: ! 164: if (scr_erase_center++ > vid.numpages) ! 165: { ! 166: scr_erase_lines = 0; ! 167: return; ! 168: } ! 169: ! 170: if (scr_center_lines <= 4) ! 171: y = vid.height*0.35; ! 172: else ! 173: y = 48; ! 174: ! 175: scr_copytop = 1; ! 176: Draw_TileClear (0, y, vid.width, min(8*scr_erase_lines, vid.height - y - 1)); ! 177: } ! 178: ! 179: void SCR_DrawCenterString (void) ! 180: { ! 181: char *start; ! 182: int l; ! 183: int j; ! 184: int x, y; ! 185: int remaining; ! 186: ! 187: // the finale prints the characters one at a time ! 188: if (cl.intermission) ! 189: remaining = scr_printspeed.value * (cl.time - scr_centertime_start); ! 190: else ! 191: remaining = 9999; ! 192: ! 193: scr_erase_center = 0; ! 194: start = scr_centerstring; ! 195: ! 196: if (scr_center_lines <= 4) ! 197: y = vid.height*0.35; ! 198: else ! 199: y = 48; ! 200: ! 201: do ! 202: { ! 203: // scan the width of the line ! 204: for (l=0 ; l<40 ; l++) ! 205: if (start[l] == '\n' || !start[l]) ! 206: break; ! 207: x = (vid.width - l*8)/2; ! 208: for (j=0 ; j<l ; j++, x+=8) ! 209: { ! 210: Draw_Character (x, y, start[j]); ! 211: if (!remaining--) ! 212: return; ! 213: } ! 214: ! 215: y += 8; ! 216: ! 217: while (*start && *start != '\n') ! 218: start++; ! 219: ! 220: if (!*start) ! 221: break; ! 222: start++; // skip the \n ! 223: } while (1); ! 224: } ! 225: ! 226: void SCR_CheckDrawCenterString (void) ! 227: { ! 228: scr_copytop = 1; ! 229: if (scr_center_lines > scr_erase_lines) ! 230: scr_erase_lines = scr_center_lines; ! 231: ! 232: scr_centertime_off -= host_frametime; ! 233: ! 234: if (scr_centertime_off <= 0 && !cl.intermission) ! 235: return; ! 236: if (key_dest != key_game) ! 237: return; ! 238: ! 239: SCR_DrawCenterString (); ! 240: } ! 241: ! 242: //============================================================================= ! 243: ! 244: /* ! 245: ==================== ! 246: CalcFov ! 247: ==================== ! 248: */ ! 249: float CalcFov (float fov_x, float width, float height) ! 250: { ! 251: float a; ! 252: float x; ! 253: ! 254: if (fov_x < 1 || fov_x > 179) ! 255: Sys_Error ("Bad fov: %f", fov_x); ! 256: ! 257: x = width/tan(fov_x/360*M_PI); ! 258: ! 259: a = atan (height/x); ! 260: ! 261: a = a*360/M_PI; ! 262: ! 263: return a; ! 264: } ! 265: ! 266: /* ! 267: ================= ! 268: SCR_CalcRefdef ! 269: ! 270: Must be called whenever vid changes ! 271: Internal use only ! 272: ================= ! 273: */ ! 274: static void SCR_CalcRefdef (void) ! 275: { ! 276: vrect_t vrect; ! 277: float size; ! 278: ! 279: scr_fullupdate = 0; // force a background redraw ! 280: vid.recalc_refdef = 0; ! 281: ! 282: // force the status bar to redraw ! 283: Sbar_Changed (); ! 284: ! 285: //======================================== ! 286: ! 287: // bound viewsize ! 288: if (scr_viewsize.value < 30) ! 289: Cvar_Set ("viewsize","30"); ! 290: if (scr_viewsize.value > 120) ! 291: Cvar_Set ("viewsize","120"); ! 292: ! 293: // bound field of view ! 294: if (scr_fov.value < 10) ! 295: Cvar_Set ("fov","10"); ! 296: if (scr_fov.value > 170) ! 297: Cvar_Set ("fov","170"); ! 298: ! 299: r_refdef.fov_x = scr_fov.value; ! 300: r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); ! 301: ! 302: // intermission is always full screen ! 303: if (cl.intermission) ! 304: size = 120; ! 305: else ! 306: size = scr_viewsize.value; ! 307: ! 308: if (size >= 120) ! 309: sb_lines = 0; // no status bar at all ! 310: else if (size >= 110) ! 311: sb_lines = 24; // no inventory ! 312: else ! 313: sb_lines = 24+16+8; ! 314: ! 315: // these calculations mirror those in R_Init() for r_refdef, but take no ! 316: // account of water warping ! 317: vrect.x = 0; ! 318: vrect.y = 0; ! 319: vrect.width = vid.width; ! 320: vrect.height = vid.height; ! 321: ! 322: R_SetVrect (&vrect, &scr_vrect, sb_lines); ! 323: ! 324: // guard against going from one mode to another that's less than half the ! 325: // vertical resolution ! 326: if (scr_con_current > vid.height) ! 327: scr_con_current = vid.height; ! 328: ! 329: // notify the refresh of the change ! 330: R_ViewChanged (&vrect, sb_lines, vid.aspect); ! 331: } ! 332: ! 333: ! 334: /* ! 335: ================= ! 336: SCR_SizeUp_f ! 337: ! 338: Keybinding command ! 339: ================= ! 340: */ ! 341: void SCR_SizeUp_f (void) ! 342: { ! 343: if (scr_viewsize.value < 120) { ! 344: Cvar_SetValue ("viewsize",scr_viewsize.value+10); ! 345: vid.recalc_refdef = 1; ! 346: } ! 347: } ! 348: ! 349: ! 350: /* ! 351: ================= ! 352: SCR_SizeDown_f ! 353: ! 354: Keybinding command ! 355: ================= ! 356: */ ! 357: void SCR_SizeDown_f (void) ! 358: { ! 359: Cvar_SetValue ("viewsize",scr_viewsize.value-10); ! 360: vid.recalc_refdef = 1; ! 361: } ! 362: ! 363: //============================================================================ ! 364: ! 365: /* ! 366: ================== ! 367: SCR_Init ! 368: ================== ! 369: */ ! 370: void SCR_Init (void) ! 371: { ! 372: Cvar_RegisterVariable (&scr_fov); ! 373: Cvar_RegisterVariable (&scr_viewsize); ! 374: Cvar_RegisterVariable (&scr_conspeed); ! 375: Cvar_RegisterVariable (&scr_showram); ! 376: Cvar_RegisterVariable (&scr_showturtle); ! 377: Cvar_RegisterVariable (&scr_showpause); ! 378: Cvar_RegisterVariable (&scr_centertime); ! 379: Cvar_RegisterVariable (&scr_printspeed); ! 380: Cvar_RegisterVariable (&scr_allowsnap); ! 381: ! 382: // ! 383: // register our commands ! 384: // ! 385: Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); ! 386: Cmd_AddCommand ("snap",SCR_RSShot_f); ! 387: Cmd_AddCommand ("sizeup",SCR_SizeUp_f); ! 388: Cmd_AddCommand ("sizedown",SCR_SizeDown_f); ! 389: ! 390: scr_ram = W_GetLumpName ("ram"); ! 391: scr_net = W_GetLumpName ("net"); ! 392: scr_turtle = W_GetLumpName ("turtle"); ! 393: ! 394: scr_initialized = true; ! 395: } ! 396: ! 397: ! 398: ! 399: /* ! 400: ============== ! 401: SCR_DrawRam ! 402: ============== ! 403: */ ! 404: void SCR_DrawRam (void) ! 405: { ! 406: if (!scr_showram.value) ! 407: return; ! 408: ! 409: if (!r_cache_thrash) ! 410: return; ! 411: ! 412: Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); ! 413: } ! 414: ! 415: /* ! 416: ============== ! 417: SCR_DrawTurtle ! 418: ============== ! 419: */ ! 420: void SCR_DrawTurtle (void) ! 421: { ! 422: static int count; ! 423: ! 424: if (!scr_showturtle.value) ! 425: return; ! 426: ! 427: if (host_frametime < 0.1) ! 428: { ! 429: count = 0; ! 430: return; ! 431: } ! 432: ! 433: count++; ! 434: if (count < 3) ! 435: return; ! 436: ! 437: Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); ! 438: } ! 439: ! 440: /* ! 441: ============== ! 442: SCR_DrawNet ! 443: ============== ! 444: */ ! 445: void SCR_DrawNet (void) ! 446: { ! 447: if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) ! 448: return; ! 449: if (cls.demoplayback) ! 450: return; ! 451: ! 452: Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); ! 453: } ! 454: ! 455: void SCR_DrawFPS (void) ! 456: { ! 457: extern cvar_t show_fps; ! 458: static double lastframetime; ! 459: double t; ! 460: extern int fps_count; ! 461: static lastfps; ! 462: int x, y; ! 463: char st[80]; ! 464: ! 465: if (!show_fps.value) ! 466: return; ! 467: ! 468: t = Sys_DoubleTime(); ! 469: if ((t - lastframetime) >= 1.0) { ! 470: lastfps = fps_count; ! 471: fps_count = 0; ! 472: lastframetime = t; ! 473: } ! 474: ! 475: sprintf(st, "%3d FPS", lastfps); ! 476: x = vid.width - strlen(st) * 8 - 8; ! 477: y = vid.height - sb_lines - 8; ! 478: // Draw_TileClear(x, y, strlen(st) * 8, 8); ! 479: Draw_String(x, y, st); ! 480: } ! 481: ! 482: /* ! 483: ============== ! 484: DrawPause ! 485: ============== ! 486: */ ! 487: void SCR_DrawPause (void) ! 488: { ! 489: qpic_t *pic; ! 490: ! 491: if (!scr_showpause.value) // turn off for screenshots ! 492: return; ! 493: ! 494: if (!cl.paused) ! 495: return; ! 496: ! 497: pic = Draw_CachePic ("gfx/pause.lmp"); ! 498: Draw_Pic ( (vid.width - pic->width)/2, ! 499: (vid.height - 48 - pic->height)/2, pic); ! 500: } ! 501: ! 502: ! 503: //============================================================================= ! 504: ! 505: ! 506: /* ! 507: ================== ! 508: SCR_SetUpToDrawConsole ! 509: ================== ! 510: */ ! 511: void SCR_SetUpToDrawConsole (void) ! 512: { ! 513: Con_CheckResize (); ! 514: ! 515: // decide on the height of the console ! 516: if (cls.state != ca_active) ! 517: { ! 518: scr_conlines = vid.height; // full screen ! 519: scr_con_current = scr_conlines; ! 520: } ! 521: else if (key_dest == key_console) ! 522: scr_conlines = vid.height/2; // half screen ! 523: else ! 524: scr_conlines = 0; // none visible ! 525: ! 526: if (scr_conlines < scr_con_current) ! 527: { ! 528: scr_con_current -= scr_conspeed.value*host_frametime; ! 529: if (scr_conlines > scr_con_current) ! 530: scr_con_current = scr_conlines; ! 531: ! 532: } ! 533: else if (scr_conlines > scr_con_current) ! 534: { ! 535: scr_con_current += scr_conspeed.value*host_frametime; ! 536: if (scr_conlines < scr_con_current) ! 537: scr_con_current = scr_conlines; ! 538: } ! 539: ! 540: if (clearconsole++ < vid.numpages) ! 541: { ! 542: scr_copytop = 1; ! 543: Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); ! 544: Sbar_Changed (); ! 545: } ! 546: else if (clearnotify++ < vid.numpages) ! 547: { ! 548: scr_copytop = 1; ! 549: Draw_TileClear (0,0,vid.width, con_notifylines); ! 550: } ! 551: else ! 552: con_notifylines = 0; ! 553: } ! 554: ! 555: /* ! 556: ================== ! 557: SCR_DrawConsole ! 558: ================== ! 559: */ ! 560: void SCR_DrawConsole (void) ! 561: { ! 562: if (scr_con_current) ! 563: { ! 564: scr_copyeverything = 1; ! 565: Con_DrawConsole (scr_con_current); ! 566: clearconsole = 0; ! 567: } ! 568: else ! 569: { ! 570: if (key_dest == key_game || key_dest == key_message) ! 571: Con_DrawNotify (); // only draw notify in game ! 572: } ! 573: } ! 574: ! 575: ! 576: /* ! 577: ============================================================================== ! 578: ! 579: SCREEN SHOTS ! 580: ! 581: ============================================================================== ! 582: */ ! 583: ! 584: ! 585: /* ! 586: ============== ! 587: WritePCXfile ! 588: ============== ! 589: */ ! 590: void WritePCXfile (char *filename, byte *data, int width, int height, ! 591: int rowbytes, byte *palette, qboolean upload) ! 592: { ! 593: int i, j, length; ! 594: pcx_t *pcx; ! 595: byte *pack; ! 596: ! 597: pcx = Hunk_TempAlloc (width*height*2+1000); ! 598: if (pcx == NULL) ! 599: { ! 600: Con_Printf("SCR_ScreenShot_f: not enough memory\n"); ! 601: return; ! 602: } ! 603: ! 604: pcx->manufacturer = 0x0a; // PCX id ! 605: pcx->version = 5; // 256 color ! 606: pcx->encoding = 1; // uncompressed ! 607: pcx->bits_per_pixel = 8; // 256 color ! 608: pcx->xmin = 0; ! 609: pcx->ymin = 0; ! 610: pcx->xmax = LittleShort((short)(width-1)); ! 611: pcx->ymax = LittleShort((short)(height-1)); ! 612: pcx->hres = LittleShort((short)width); ! 613: pcx->vres = LittleShort((short)height); ! 614: Q_memset (pcx->palette,0,sizeof(pcx->palette)); ! 615: pcx->color_planes = 1; // chunky image ! 616: pcx->bytes_per_line = LittleShort((short)width); ! 617: pcx->palette_type = LittleShort(2); // not a grey scale ! 618: Q_memset (pcx->filler,0,sizeof(pcx->filler)); ! 619: ! 620: // pack the image ! 621: pack = &pcx->data; ! 622: ! 623: for (i=0 ; i<height ; i++) ! 624: { ! 625: for (j=0 ; j<width ; j++) ! 626: { ! 627: if ( (*data & 0xc0) != 0xc0) ! 628: *pack++ = *data++; ! 629: else ! 630: { ! 631: *pack++ = 0xc1; ! 632: *pack++ = *data++; ! 633: } ! 634: } ! 635: ! 636: data += rowbytes - width; ! 637: } ! 638: ! 639: // write the palette ! 640: *pack++ = 0x0c; // palette ID byte ! 641: for (i=0 ; i<768 ; i++) ! 642: *pack++ = *palette++; ! 643: ! 644: // write output file ! 645: length = pack - (byte *)pcx; ! 646: if (upload) ! 647: CL_StartUpload((void *)pcx, length); ! 648: else ! 649: COM_WriteFile (filename, pcx, length); ! 650: } ! 651: ! 652: ! 653: ! 654: /* ! 655: ================== ! 656: SCR_ScreenShot_f ! 657: ================== ! 658: */ ! 659: void SCR_ScreenShot_f (void) ! 660: { ! 661: int i; ! 662: char pcxname[80]; ! 663: char checkname[MAX_OSPATH]; ! 664: ! 665: // ! 666: // find a file name to save it to ! 667: // ! 668: strcpy(pcxname,"quake00.pcx"); ! 669: ! 670: for (i=0 ; i<=99 ; i++) ! 671: { ! 672: pcxname[5] = i/10 + '0'; ! 673: pcxname[6] = i%10 + '0'; ! 674: sprintf (checkname, "%s/%s", com_gamedir, pcxname); ! 675: if (Sys_FileTime(checkname) == -1) ! 676: break; // file doesn't exist ! 677: } ! 678: if (i==100) ! 679: { ! 680: Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); ! 681: return; ! 682: } ! 683: ! 684: // ! 685: // save the pcx file ! 686: // ! 687: D_EnableBackBufferAccess (); // enable direct drawing of console to back ! 688: // buffer ! 689: ! 690: WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes, ! 691: host_basepal, false); ! 692: ! 693: D_DisableBackBufferAccess (); // for adapters that can't stay mapped in ! 694: // for linear writes all the time ! 695: ! 696: Con_Printf ("Wrote %s\n", pcxname); ! 697: } ! 698: ! 699: /* ! 700: Find closest color in the palette for named color ! 701: */ ! 702: int MipColor(int r, int g, int b) ! 703: { ! 704: int i; ! 705: float dist; ! 706: int best; ! 707: float bestdist; ! 708: int r1, g1, b1; ! 709: static int lr = -1, lg = -1, lb = -1; ! 710: static int lastbest; ! 711: ! 712: if (r == lr && g == lg && b == lb) ! 713: return lastbest; ! 714: ! 715: bestdist = 256*256*3; ! 716: ! 717: for (i = 0; i < 256; i++) { ! 718: r1 = host_basepal[i*3] - r; ! 719: g1 = host_basepal[i*3+1] - g; ! 720: b1 = host_basepal[i*3+2] - b; ! 721: dist = r1*r1 + g1*g1 + b1*b1; ! 722: if (dist < bestdist) { ! 723: bestdist = dist; ! 724: best = i; ! 725: } ! 726: } ! 727: lr = r; lg = g; lb = b; ! 728: lastbest = best; ! 729: return best; ! 730: } ! 731: ! 732: // in draw.c ! 733: extern byte *draw_chars; // 8*8 graphic characters ! 734: ! 735: void SCR_DrawCharToSnap (int num, byte *dest, int width) ! 736: { ! 737: int row, col; ! 738: byte *source; ! 739: int drawline; ! 740: int x; ! 741: ! 742: row = num>>4; ! 743: col = num&15; ! 744: source = draw_chars + (row<<10) + (col<<3); ! 745: ! 746: drawline = 8; ! 747: ! 748: while (drawline--) ! 749: { ! 750: for (x=0 ; x<8 ; x++) ! 751: if (source[x]) ! 752: dest[x] = source[x]; ! 753: else ! 754: dest[x] = 98; ! 755: source += 128; ! 756: dest += width; ! 757: } ! 758: ! 759: } ! 760: ! 761: void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width) ! 762: { ! 763: byte *dest; ! 764: const unsigned char *p; ! 765: ! 766: dest = buf + ((y * width) + x); ! 767: ! 768: p = (const unsigned char *)s; ! 769: while (*p) { ! 770: SCR_DrawCharToSnap(*p++, dest, width); ! 771: dest += 8; ! 772: } ! 773: } ! 774: ! 775: ! 776: /* ! 777: ================== ! 778: SCR_RSShot_f ! 779: ================== ! 780: */ ! 781: void SCR_RSShot_f (void) ! 782: { ! 783: int i, x, y; ! 784: unsigned char *src, *dest; ! 785: char pcxname[80]; ! 786: char checkname[MAX_OSPATH]; ! 787: unsigned char *newbuf, *srcbuf; ! 788: int srcrowbytes; ! 789: int w, h; ! 790: int dx, dy, dex, dey, nx; ! 791: int r, b, g; ! 792: int count; ! 793: float fracw, frach; ! 794: char st[80]; ! 795: time_t now; ! 796: ! 797: if (CL_IsUploading()) ! 798: return; // already one pending ! 799: ! 800: if (cls.state < ca_onserver) ! 801: return; // gotta be connected ! 802: ! 803: if (!scr_allowsnap.value) { ! 804: MSG_WriteByte (&cls.netchan.message, clc_stringcmd); ! 805: SZ_Print (&cls.netchan.message, "snap\n"); ! 806: Con_Printf("Refusing remote screen shot request.\n"); ! 807: return; ! 808: } ! 809: ! 810: Con_Printf("Remote screen shot requested.\n"); ! 811: ! 812: #if 0 ! 813: // ! 814: // find a file name to save it to ! 815: // ! 816: strcpy(pcxname,"mquake00.pcx"); ! 817: ! 818: for (i=0 ; i<=99 ; i++) ! 819: { ! 820: pcxname[6] = i/10 + '0'; ! 821: pcxname[7] = i%10 + '0'; ! 822: sprintf (checkname, "%s/%s", com_gamedir, pcxname); ! 823: if (Sys_FileTime(checkname) == -1) ! 824: break; // file doesn't exist ! 825: } ! 826: if (i==100) ! 827: { ! 828: Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); ! 829: return; ! 830: } ! 831: #endif ! 832: ! 833: // ! 834: // save the pcx file ! 835: // ! 836: D_EnableBackBufferAccess (); // enable direct drawing of console to back ! 837: // buffer ! 838: ! 839: w = (vid.width < RSSHOT_WIDTH) ? vid.width : RSSHOT_WIDTH; ! 840: h = (vid.height < RSSHOT_HEIGHT) ? vid.height : RSSHOT_HEIGHT; ! 841: ! 842: fracw = (float)vid.width / (float)w; ! 843: frach = (float)vid.height / (float)h; ! 844: ! 845: newbuf = malloc(w*h); ! 846: ! 847: for (y = 0; y < h; y++) { ! 848: dest = newbuf + (w * y); ! 849: ! 850: for (x = 0; x < w; x++) { ! 851: r = g = b = 0; ! 852: ! 853: dx = x * fracw; ! 854: dex = (x + 1) * fracw; ! 855: if (dex == dx) dex++; // at least one ! 856: dy = y * frach; ! 857: dey = (y + 1) * frach; ! 858: if (dey == dy) dey++; // at least one ! 859: ! 860: count = 0; ! 861: for (/* */; dy < dey; dy++) { ! 862: src = vid.buffer + (vid.rowbytes * dy) + dx; ! 863: for (nx = dx; nx < dex; nx++) { ! 864: r += host_basepal[*src * 3]; ! 865: g += host_basepal[*src * 3+1]; ! 866: b += host_basepal[*src * 3+2]; ! 867: src++; ! 868: count++; ! 869: } ! 870: } ! 871: r /= count; ! 872: g /= count; ! 873: b /= count; ! 874: *dest++ = MipColor(r, g, b); ! 875: } ! 876: } ! 877: ! 878: time(&now); ! 879: strcpy(st, ctime(&now)); ! 880: st[strlen(st) - 1] = 0; ! 881: SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 0, w); ! 882: ! 883: strncpy(st, cls.servername, sizeof(st)); ! 884: st[sizeof(st) - 1] = 0; ! 885: SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 10, w); ! 886: ! 887: strncpy(st, name.string, sizeof(st)); ! 888: st[sizeof(st) - 1] = 0; ! 889: SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 20, w); ! 890: ! 891: WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true); ! 892: ! 893: free(newbuf); ! 894: ! 895: D_DisableBackBufferAccess (); // for adapters that can't stay mapped in ! 896: // for linear writes all the time ! 897: ! 898: // Con_Printf ("Wrote %s\n", pcxname); ! 899: Con_Printf ("Sending shot to server...\n"); ! 900: } ! 901: ! 902: ! 903: //============================================================================= ! 904: ! 905: char *scr_notifystring; ! 906: qboolean scr_drawdialog; ! 907: ! 908: void SCR_DrawNotifyString (void) ! 909: { ! 910: char *start; ! 911: int l; ! 912: int j; ! 913: int x, y; ! 914: ! 915: start = scr_notifystring; ! 916: ! 917: y = vid.height*0.35; ! 918: ! 919: do ! 920: { ! 921: // scan the width of the line ! 922: for (l=0 ; l<40 ; l++) ! 923: if (start[l] == '\n' || !start[l]) ! 924: break; ! 925: x = (vid.width - l*8)/2; ! 926: for (j=0 ; j<l ; j++, x+=8) ! 927: Draw_Character (x, y, start[j]); ! 928: ! 929: y += 8; ! 930: ! 931: while (*start && *start != '\n') ! 932: start++; ! 933: ! 934: if (!*start) ! 935: break; ! 936: start++; // skip the \n ! 937: } while (1); ! 938: } ! 939: ! 940: /* ! 941: ================== ! 942: SCR_ModalMessage ! 943: ! 944: Displays a text string in the center of the screen and waits for a Y or N ! 945: keypress. ! 946: ================== ! 947: */ ! 948: int SCR_ModalMessage (char *text) ! 949: { ! 950: scr_notifystring = text; ! 951: ! 952: // draw a fresh screen ! 953: scr_fullupdate = 0; ! 954: scr_drawdialog = true; ! 955: SCR_UpdateScreen (); ! 956: scr_drawdialog = false; ! 957: ! 958: S_ClearBuffer (); // so dma doesn't loop current sound ! 959: ! 960: do ! 961: { ! 962: key_count = -1; // wait for a key down and up ! 963: Sys_SendKeyEvents (); ! 964: } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE); ! 965: ! 966: scr_fullupdate = 0; ! 967: SCR_UpdateScreen (); ! 968: ! 969: return key_lastpress == 'y'; ! 970: } ! 971: ! 972: ! 973: //============================================================================= ! 974: ! 975: /* ! 976: =============== ! 977: SCR_BringDownConsole ! 978: ! 979: Brings the console down and fades the palettes back to normal ! 980: ================ ! 981: */ ! 982: void SCR_BringDownConsole (void) ! 983: { ! 984: int i; ! 985: ! 986: scr_centertime_off = 0; ! 987: ! 988: for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++) ! 989: SCR_UpdateScreen (); ! 990: ! 991: cl.cshifts[0].percent = 0; // no area contents palette on next frame ! 992: VID_SetPalette (host_basepal); ! 993: } ! 994: ! 995: ! 996: /* ! 997: ================== ! 998: SCR_UpdateScreen ! 999: ! 1000: This is called every frame, and can also be called explicitly to flush ! 1001: text to the screen. ! 1002: ! 1003: WARNING: be very careful calling this from elsewhere, because the refresh ! 1004: needs almost the entire 256k of stack space! ! 1005: ================== ! 1006: */ ! 1007: void SCR_UpdateScreen (void) ! 1008: { ! 1009: static float oldscr_viewsize; ! 1010: vrect_t vrect; ! 1011: ! 1012: if (scr_skipupdate || block_drawing) ! 1013: return; ! 1014: ! 1015: if (scr_disabled_for_loading) ! 1016: return; ! 1017: ! 1018: #ifdef _WIN32 ! 1019: { // don't suck up any cpu if minimized ! 1020: extern int Minimized; ! 1021: ! 1022: if (Minimized) ! 1023: return; ! 1024: } ! 1025: #endif ! 1026: ! 1027: scr_copytop = 0; ! 1028: scr_copyeverything = 0; ! 1029: ! 1030: if (!scr_initialized || !con_initialized) ! 1031: return; // not initialized yet ! 1032: ! 1033: if (scr_viewsize.value != oldscr_viewsize) ! 1034: { ! 1035: oldscr_viewsize = scr_viewsize.value; ! 1036: vid.recalc_refdef = 1; ! 1037: } ! 1038: ! 1039: // ! 1040: // check for vid changes ! 1041: // ! 1042: if (oldfov != scr_fov.value) ! 1043: { ! 1044: oldfov = scr_fov.value; ! 1045: vid.recalc_refdef = true; ! 1046: } ! 1047: ! 1048: if (oldscreensize != scr_viewsize.value) ! 1049: { ! 1050: oldscreensize = scr_viewsize.value; ! 1051: vid.recalc_refdef = true; ! 1052: } ! 1053: ! 1054: if (oldsbar != cl_sbar.value) ! 1055: { ! 1056: oldsbar = cl_sbar.value; ! 1057: vid.recalc_refdef = true; ! 1058: } ! 1059: ! 1060: if (vid.recalc_refdef) ! 1061: { ! 1062: // something changed, so reorder the screen ! 1063: SCR_CalcRefdef (); ! 1064: } ! 1065: ! 1066: // ! 1067: // do 3D refresh drawing, and then update the screen ! 1068: // ! 1069: D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly ! 1070: ! 1071: if (scr_fullupdate++ < vid.numpages) ! 1072: { // clear the entire screen ! 1073: scr_copyeverything = 1; ! 1074: Draw_TileClear (0,0,vid.width,vid.height); ! 1075: Sbar_Changed (); ! 1076: } ! 1077: ! 1078: pconupdate = NULL; ! 1079: ! 1080: ! 1081: SCR_SetUpToDrawConsole (); ! 1082: SCR_EraseCenterString (); ! 1083: ! 1084: D_DisableBackBufferAccess (); // for adapters that can't stay mapped in ! 1085: // for linear writes all the time ! 1086: ! 1087: VID_LockBuffer (); ! 1088: V_RenderView (); ! 1089: VID_UnlockBuffer (); ! 1090: ! 1091: D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly ! 1092: ! 1093: if (scr_drawdialog) ! 1094: { ! 1095: Sbar_Draw (); ! 1096: Draw_FadeScreen (); ! 1097: SCR_DrawNotifyString (); ! 1098: scr_copyeverything = true; ! 1099: } ! 1100: else if (cl.intermission == 1 && key_dest == key_game) ! 1101: { ! 1102: Sbar_IntermissionOverlay (); ! 1103: } ! 1104: else if (cl.intermission == 2 && key_dest == key_game) ! 1105: { ! 1106: Sbar_FinaleOverlay (); ! 1107: SCR_CheckDrawCenterString (); ! 1108: } ! 1109: else ! 1110: { ! 1111: SCR_DrawRam (); ! 1112: SCR_DrawNet (); ! 1113: SCR_DrawTurtle (); ! 1114: SCR_DrawPause (); ! 1115: SCR_DrawFPS (); ! 1116: SCR_CheckDrawCenterString (); ! 1117: Sbar_Draw (); ! 1118: SCR_DrawConsole (); ! 1119: M_Draw (); ! 1120: } ! 1121: ! 1122: ! 1123: D_DisableBackBufferAccess (); // for adapters that can't stay mapped in ! 1124: // for linear writes all the time ! 1125: if (pconupdate) ! 1126: { ! 1127: D_UpdateRects (pconupdate); ! 1128: } ! 1129: ! 1130: V_UpdatePalette (); ! 1131: ! 1132: // ! 1133: // update one of three areas ! 1134: // ! 1135: if (scr_copyeverything) ! 1136: { ! 1137: vrect.x = 0; ! 1138: vrect.y = 0; ! 1139: vrect.width = vid.width; ! 1140: vrect.height = vid.height; ! 1141: vrect.pnext = 0; ! 1142: ! 1143: VID_Update (&vrect); ! 1144: } ! 1145: else if (scr_copytop) ! 1146: { ! 1147: vrect.x = 0; ! 1148: vrect.y = 0; ! 1149: vrect.width = vid.width; ! 1150: vrect.height = vid.height - sb_lines; ! 1151: vrect.pnext = 0; ! 1152: ! 1153: VID_Update (&vrect); ! 1154: } ! 1155: else ! 1156: { ! 1157: vrect.x = scr_vrect.x; ! 1158: vrect.y = scr_vrect.y; ! 1159: vrect.width = scr_vrect.width; ! 1160: vrect.height = scr_vrect.height; ! 1161: vrect.pnext = 0; ! 1162: ! 1163: VID_Update (&vrect); ! 1164: } ! 1165: } ! 1166: ! 1167: /* ! 1168: ================== ! 1169: SCR_UpdateWholeScreen ! 1170: ================== ! 1171: */ ! 1172: void SCR_UpdateWholeScreen (void) ! 1173: { ! 1174: scr_fullupdate = 0; ! 1175: SCR_UpdateScreen (); ! 1176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.