Annotation of quakeworld/client/screen.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.