home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-28  |  18.5 KB  |  903 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. // draw.c -- this is the only file outside the refresh that touches the
  22. // vid buffer
  23.  
  24. #include "quakedef.h"
  25.  
  26. typedef struct {
  27.   vrect_t rect;
  28.   int   width;
  29.   int   height;
  30.   byte  *ptexbytes;
  31.   int   rowbytes;
  32. } rectdesc_t;
  33.  
  34. static rectdesc_t r_rectdesc;
  35.  
  36. byte    *draw_chars;        // 8*8 graphic characters
  37. qpic_t    *draw_disc;
  38. qpic_t    *draw_backtile;
  39.  
  40. //=============================================================================
  41. /* Support Routines */
  42.  
  43. typedef struct cachepic_s
  44. {
  45.   char    name[MAX_QPATH];
  46.   cache_user_t  cache;
  47. } cachepic_t;
  48.  
  49. #define MAX_CACHED_PICS   128
  50. cachepic_t  menu_cachepics[MAX_CACHED_PICS];
  51. int     menu_numcachepics;
  52.  
  53.  
  54. qpic_t  *Draw_PicFromWad (char *name)
  55. {
  56.   return W_GetLumpName (name);
  57. }
  58.  
  59. /*
  60. ================
  61. Draw_CachePic
  62. ================
  63. */
  64. qpic_t  *Draw_CachePic (char *path)
  65. {
  66.   cachepic_t  *pic;
  67.   int     i;
  68.   qpic_t    *dat;
  69.   
  70.   for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
  71.     if (!strcmp (path, pic->name))
  72.       break;
  73.  
  74.   if (i == menu_numcachepics)
  75.   {
  76.     if (menu_numcachepics == MAX_CACHED_PICS)
  77.       Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
  78.     menu_numcachepics++;
  79.     strcpy (pic->name, path);
  80.   }
  81.  
  82.   dat = Cache_Check (&pic->cache);
  83.  
  84.   if (dat)
  85.     return dat;
  86.  
  87. //
  88. // load the pic from disk
  89. //
  90.   COM_LoadCacheFile (path, &pic->cache);
  91.   
  92.   dat = (qpic_t *)pic->cache.data;
  93.   if (!dat)
  94.   {
  95.     Sys_Error ("Draw_CachePic: failed to load %s", path);
  96.   }
  97.  
  98.   SwapPic (dat);
  99.  
  100.   return dat;
  101. }
  102.  
  103.  
  104.  
  105. /*
  106. ===============
  107. Draw_Init
  108. ===============
  109. */
  110. void Draw_Init (void)
  111. {
  112.   int   i;
  113.  
  114.   draw_chars = W_GetLumpName ("conchars");
  115.   draw_disc = W_GetLumpName ("disc");
  116.   draw_backtile = W_GetLumpName ("backtile");
  117.  
  118.   r_rectdesc.width = draw_backtile->width;
  119.   r_rectdesc.height = draw_backtile->height;
  120.   r_rectdesc.ptexbytes = draw_backtile->data;
  121.   r_rectdesc.rowbytes = draw_backtile->width;
  122. }
  123.  
  124.  
  125.  
  126. /*
  127. ================
  128. Draw_Character
  129.  
  130. Draws one 8*8 graphics character with 0 being transparent.
  131. It can be clipped to the top of the screen to allow the console to be
  132. smoothly scrolled off.
  133. ================
  134. */
  135. void Draw_Character (int x, int y, int num)
  136. {
  137.   byte      *dest;
  138.   byte      *source;
  139.   unsigned short  *pusdest;
  140.   int       drawline; 
  141.   int       row, col;
  142.  
  143.   num &= 255;
  144.   
  145.   if (y <= -8)
  146.     return;     // totally off screen
  147.  
  148. #ifdef PARANOID
  149.   if (y > (int)(vid.height - 8) || x < 0 || x > (int)(vid.width - 8)) /*phx*/
  150.     Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
  151.   if (num < 0 || num > 255)
  152.     Sys_Error ("Con_DrawCharacter: char %i", num);
  153. #endif
  154.  
  155.   row = num>>4;
  156.   col = num&15;
  157.   source = draw_chars + (row<<10) + (col<<3);
  158.  
  159.   if (y < 0)
  160.   { // clipped
  161.     drawline = 8 + y;
  162.     source -= 128*y;
  163.     y = 0;
  164.   }
  165.   else
  166.     drawline = 8;
  167.  
  168.  
  169.   if (r_pixbytes == 1)
  170.   {
  171.     dest = vid.conbuffer + y*vid.conrowbytes + x;
  172.   
  173.     while (drawline--)
  174.     {
  175.       if (source[0])
  176.         dest[0] = source[0];
  177.       if (source[1])
  178.         dest[1] = source[1];
  179.       if (source[2])
  180.         dest[2] = source[2];
  181.       if (source[3])
  182.         dest[3] = source[3];
  183.       if (source[4])
  184.         dest[4] = source[4];
  185.       if (source[5])
  186.         dest[5] = source[5];
  187.       if (source[6])
  188.         dest[6] = source[6];
  189.       if (source[7])
  190.         dest[7] = source[7];
  191.       source += 128;
  192.       dest += vid.conrowbytes;
  193.     }
  194.   }
  195.   else
  196.   {
  197.   // FIXME: pre-expand to native format?
  198.     pusdest = (unsigned short *)
  199.         ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
  200.  
  201.     while (drawline--)
  202.     {
  203.       if (source[0])
  204.         pusdest[0] = d_8to16table[source[0]];
  205.       if (source[1])
  206.         pusdest[1] = d_8to16table[source[1]];
  207.       if (source[2])
  208.         pusdest[2] = d_8to16table[source[2]];
  209.       if (source[3])
  210.         pusdest[3] = d_8to16table[source[3]];
  211.       if (source[4])
  212.         pusdest[4] = d_8to16table[source[4]];
  213.       if (source[5])
  214.         pusdest[5] = d_8to16table[source[5]];
  215.       if (source[6])
  216.         pusdest[6] = d_8to16table[source[6]];
  217.       if (source[7])
  218.         pusdest[7] = d_8to16table[source[7]];
  219.  
  220.       source += 128;
  221.       pusdest += (vid.conrowbytes >> 1);
  222.     }
  223.   }
  224. }
  225.  
  226. /*
  227. ================
  228. Draw_String
  229. ================
  230. */
  231. void Draw_String (int x, int y, char *str)
  232. {
  233.   while (*str)
  234.   {
  235.     Draw_Character (x, y, *str);
  236.     str++;
  237.     x += 8;
  238.   }
  239. }
  240.  
  241. /*
  242. ================
  243. Draw_DebugChar
  244.  
  245. Draws a single character directly to the upper right corner of the screen.
  246. This is for debugging lockups by drawing different chars in different parts
  247. of the code.
  248. ================
  249. */
  250. void Draw_DebugChar (char num)
  251. {
  252.   byte      *dest;
  253.   byte      *source;
  254.   int       drawline; 
  255.   extern byte   *draw_chars;
  256.   int       row, col;
  257.  
  258.   if (!vid.direct)
  259.     return;   // don't have direct FB access, so no debugchars...
  260.  
  261.   drawline = 8;
  262.  
  263.   row = num>>4;
  264.   col = num&15;
  265.   source = draw_chars + (row<<10) + (col<<3);
  266.  
  267.   dest = vid.direct + 312;
  268.  
  269.   while (drawline--)
  270.   {
  271.     dest[0] = source[0];
  272.     dest[1] = source[1];
  273.     dest[2] = source[2];
  274.     dest[3] = source[3];
  275.     dest[4] = source[4];
  276.     dest[5] = source[5];
  277.     dest[6] = source[6];
  278.     dest[7] = source[7];
  279.     source += 128;
  280.     dest += 320;
  281.   }
  282. }
  283.  
  284. /*
  285. =============
  286. Draw_Pic
  287. =============
  288. */
  289. void Draw_Pic (int x, int y, qpic_t *pic)
  290. {
  291.   byte      *dest, *source;
  292.   unsigned short  *pusdest;
  293.   int       v, u;
  294.  
  295.   if ((x < 0) ||
  296.     (x + pic->width > vid.width) ||
  297.     (y < 0) ||
  298.     (y + pic->height > vid.height))
  299.   {
  300.     Sys_Error ("Draw_Pic: bad coordinates");
  301.   }
  302.  
  303.   source = pic->data;
  304.  
  305.   if (r_pixbytes == 1)
  306.   {
  307.     dest = vid.buffer + y * vid.rowbytes + x;
  308.  
  309.     for (v=0 ; v<pic->height ; v++)
  310.     {
  311.       Q_memcpy (dest, source, pic->width);
  312.       dest += vid.rowbytes;
  313.       source += pic->width;
  314.     }
  315.   }
  316.   else
  317.   {
  318.   // FIXME: pretranslate at load time?
  319.     pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  320.  
  321.     for (v=0 ; v<pic->height ; v++)
  322.     {
  323.       for (u=0 ; u<pic->width ; u++)
  324.       {
  325.         pusdest[u] = d_8to16table[source[u]];
  326.       }
  327.  
  328.       pusdest += vid.rowbytes >> 1;
  329.       source += pic->width;
  330.     }
  331.   }
  332. }
  333.  
  334.  
  335. /*
  336. =============
  337. Draw_TransPic
  338. =============
  339. */
  340. void Draw_TransPic (int x, int y, qpic_t *pic)
  341. {
  342.   byte  *dest, *source, tbyte;
  343.   unsigned short  *pusdest;
  344.   int       v, u;
  345.  
  346.   if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  347.      (unsigned)(y + pic->height) > vid.height)
  348.   {
  349.     Sys_Error ("Draw_TransPic: bad coordinates");
  350.   }
  351.     
  352.   source = pic->data;
  353.  
  354.   if (r_pixbytes == 1)
  355.   {
  356.     dest = vid.buffer + y * vid.rowbytes + x;
  357.  
  358.     if (pic->width & 7)
  359.     { // general
  360.       for (v=0 ; v<pic->height ; v++)
  361.       {
  362.         for (u=0 ; u<pic->width ; u++)
  363.           if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  364.             dest[u] = tbyte;
  365.   
  366.         dest += vid.rowbytes;
  367.         source += pic->width;
  368.       }
  369.     }
  370.     else
  371.     { // unwound
  372.       for (v=0 ; v<pic->height ; v++)
  373.       {
  374.         for (u=0 ; u<pic->width ; u+=8)
  375.         {
  376.           if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  377.             dest[u] = tbyte;
  378.           if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  379.             dest[u+1] = tbyte;
  380.           if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  381.             dest[u+2] = tbyte;
  382.           if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  383.             dest[u+3] = tbyte;
  384.           if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  385.             dest[u+4] = tbyte;
  386.           if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  387.             dest[u+5] = tbyte;
  388.           if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  389.             dest[u+6] = tbyte;
  390.           if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  391.             dest[u+7] = tbyte;
  392.         }
  393.         dest += vid.rowbytes;
  394.         source += pic->width;
  395.       }
  396.     }
  397.   }
  398.   else
  399.   {
  400.   // FIXME: pretranslate at load time?
  401.     pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  402.  
  403.     for (v=0 ; v<pic->height ; v++)
  404.     {
  405.       for (u=0 ; u<pic->width ; u++)
  406.       {
  407.         tbyte = source[u];
  408.  
  409.         if (tbyte != TRANSPARENT_COLOR)
  410.         {
  411.           pusdest[u] = d_8to16table[tbyte];
  412.         }
  413.       }
  414.  
  415.       pusdest += vid.rowbytes >> 1;
  416.       source += pic->width;
  417.     }
  418.   }
  419. }
  420.  
  421.  
  422. /*
  423. =============
  424. Draw_TransPicTranslate
  425. =============
  426. */
  427. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  428. {
  429.   byte  *dest, *source, tbyte;
  430.   unsigned short  *pusdest;
  431.   int       v, u;
  432.  
  433.   if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  434.      (unsigned)(y + pic->height) > vid.height)
  435.   {
  436.     Sys_Error ("Draw_TransPic: bad coordinates");
  437.   }
  438.     
  439.   source = pic->data;
  440.  
  441.   if (r_pixbytes == 1)
  442.   {
  443.     dest = vid.buffer + y * vid.rowbytes + x;
  444.  
  445.     if (pic->width & 7)
  446.     { // general
  447.       for (v=0 ; v<pic->height ; v++)
  448.       {
  449.         for (u=0 ; u<pic->width ; u++)
  450.           if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  451.             dest[u] = translation[tbyte];
  452.  
  453.         dest += vid.rowbytes;
  454.         source += pic->width;
  455.       }
  456.     }
  457.     else
  458.     { // unwound
  459.       for (v=0 ; v<pic->height ; v++)
  460.       {
  461.         for (u=0 ; u<pic->width ; u+=8)
  462.         {
  463.           if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  464.             dest[u] = translation[tbyte];
  465.           if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  466.             dest[u+1] = translation[tbyte];
  467.           if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  468.             dest[u+2] = translation[tbyte];
  469.           if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  470.             dest[u+3] = translation[tbyte];
  471.           if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  472.             dest[u+4] = translation[tbyte];
  473.           if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  474.             dest[u+5] = translation[tbyte];
  475.           if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  476.             dest[u+6] = translation[tbyte];
  477.           if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  478.             dest[u+7] = translation[tbyte];
  479.         }
  480.         dest += vid.rowbytes;
  481.         source += pic->width;
  482.       }
  483.     }
  484.   }
  485.   else
  486.   {
  487.   // FIXME: pretranslate at load time?
  488.     pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  489.  
  490.     for (v=0 ; v<pic->height ; v++)
  491.     {
  492.       for (u=0 ; u<pic->width ; u++)
  493.       {
  494.         tbyte = source[u];
  495.  
  496.         if (tbyte != TRANSPARENT_COLOR)
  497.         {
  498.           pusdest[u] = d_8to16table[tbyte];
  499.         }
  500.       }
  501.  
  502.       pusdest += vid.rowbytes >> 1;
  503.       source += pic->width;
  504.     }
  505.   }
  506. }
  507.  
  508.  
  509. void Draw_CharToConback (int num, byte *dest)
  510. {
  511.   int   row, col;
  512.   byte  *source;
  513.   int   drawline;
  514.   int   x;
  515.  
  516.   row = num>>4;
  517.   col = num&15;
  518.   source = draw_chars + (row<<10) + (col<<3);
  519.  
  520.   drawline = 8;
  521.  
  522.   while (drawline--)
  523.   {
  524.     for (x=0 ; x<8 ; x++)
  525.       if (source[x])
  526.         dest[x] = 0x60 + source[x];
  527.     source += 128;
  528.     dest += 320;
  529.   }
  530.  
  531. }
  532.  
  533. /*
  534. ================
  535. Draw_ConsoleBackground
  536.  
  537. ================
  538. */
  539. void Draw_ConsoleBackground (int lines)
  540. {
  541.   int       x, y, v;
  542.   byte      *src, *dest;
  543.   unsigned short  *pusdest;
  544.   int       f, fstep;
  545.   qpic_t      *conback;
  546.   char      ver[100];
  547.  
  548.   conback = Draw_CachePic ("gfx/conback.lmp");
  549.  
  550. // hack the version number directly into the pic
  551. #ifdef _WIN32
  552.   sprintf (ver, "(WinQuake) %4.2f", (float)VERSION);
  553.   dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  554. #elif defined(X11)
  555.   sprintf (ver, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION, (float)VERSION);
  556.   dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  557. #elif defined(__linux__)
  558.   sprintf (ver, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION, (float)VERSION);
  559.   dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  560. #else
  561.   dest = conback->data + 320 - 43 + 320*186;
  562.   sprintf (ver, "%4.2f", VERSION);
  563. #endif
  564.  
  565.   for (x=0 ; x<strlen(ver) ; x++)
  566.     Draw_CharToConback (ver[x], dest+(x<<3));
  567.   
  568. // draw the pic
  569.   if (r_pixbytes == 1)
  570.   {
  571.     dest = vid.conbuffer;
  572.  
  573.     for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
  574.     {
  575.       v = (vid.conheight - lines + y)*200/vid.conheight;
  576.       src = conback->data + v*320;
  577.       if (vid.conwidth == 320)
  578.         memcpy (dest, src, vid.conwidth);
  579.       else
  580.       {
  581.         f = 0;
  582.         fstep = 320*0x10000/vid.conwidth;
  583.         for (x=0 ; x<vid.conwidth ; x+=4)
  584.         {
  585.           dest[x] = src[f>>16];
  586.           f += fstep;
  587.           dest[x+1] = src[f>>16];
  588.           f += fstep;
  589.           dest[x+2] = src[f>>16];
  590.           f += fstep;
  591.           dest[x+3] = src[f>>16];
  592.           f += fstep;
  593.         }
  594.       }
  595.     }
  596.   }
  597.   else
  598.   {
  599.     pusdest = (unsigned short *)vid.conbuffer;
  600.  
  601.     for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
  602.     {
  603.     // FIXME: pre-expand to native format?
  604.     // FIXME: does the endian switching go away in production?
  605.       v = (vid.conheight - lines + y)*200/vid.conheight;
  606.       src = conback->data + v*320;
  607.       f = 0;
  608.       fstep = 320*0x10000/vid.conwidth;
  609.       for (x=0 ; x<vid.conwidth ; x+=4)
  610.       {
  611.         pusdest[x] = d_8to16table[src[f>>16]];
  612.         f += fstep;
  613.         pusdest[x+1] = d_8to16table[src[f>>16]];
  614.         f += fstep;
  615.         pusdest[x+2] = d_8to16table[src[f>>16]];
  616.         f += fstep;
  617.         pusdest[x+3] = d_8to16table[src[f>>16]];
  618.         f += fstep;
  619.       }
  620.     }
  621.   }
  622. }
  623.  
  624.  
  625. /*
  626. ==============
  627. R_DrawRect8
  628. ==============
  629. */
  630. void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
  631.   int transparent)
  632. {
  633.   byte  t;
  634.   int   i, j, srcdelta, destdelta;
  635.   byte  *pdest;
  636.  
  637.   pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
  638.  
  639.   srcdelta = rowbytes - prect->width;
  640.   destdelta = vid.rowbytes - prect->width;
  641.  
  642.   if (transparent)
  643.   {
  644.     for (i=0 ; i<prect->height ; i++)
  645.     {
  646.       for (j=0 ; j<prect->width ; j++)
  647.       {
  648.         t = *psrc;
  649.         if (t != TRANSPARENT_COLOR)
  650.         {
  651.           *pdest = t;
  652.         }
  653.  
  654.         psrc++;
  655.         pdest++;
  656.       }
  657.  
  658.       psrc += srcdelta;
  659.       pdest += destdelta;
  660.     }
  661.   }
  662.   else
  663.   {
  664.     for (i=0 ; i<prect->height ; i++)
  665.     {
  666.       memcpy (pdest, psrc, prect->width);
  667.       psrc += rowbytes;
  668.       pdest += vid.rowbytes;
  669.     }
  670.   }
  671. }
  672.  
  673.  
  674. /*
  675. ==============
  676. R_DrawRect16
  677. ==============
  678. */
  679. void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
  680.   int transparent)
  681. {
  682.   byte      t;
  683.   int       i, j, srcdelta, destdelta;
  684.   unsigned short  *pdest;
  685.  
  686. // FIXME: would it be better to pre-expand native-format versions?
  687.  
  688.   pdest = (unsigned short *)vid.buffer +
  689.       (prect->y * (vid.rowbytes >> 1)) + prect->x;
  690.  
  691.   srcdelta = rowbytes - prect->width;
  692.   destdelta = (vid.rowbytes >> 1) - prect->width;
  693.  
  694.   if (transparent)
  695.   {
  696.     for (i=0 ; i<prect->height ; i++)
  697.     {
  698.       for (j=0 ; j<prect->width ; j++)
  699.       {
  700.         t = *psrc;
  701.         if (t != TRANSPARENT_COLOR)
  702.         {
  703.           *pdest = d_8to16table[t];
  704.         }
  705.  
  706.         psrc++;
  707.         pdest++;
  708.       }
  709.  
  710.       psrc += srcdelta;
  711.       pdest += destdelta;
  712.     }
  713.   }
  714.   else
  715.   {
  716.     for (i=0 ; i<prect->height ; i++)
  717.     {
  718.       for (j=0 ; j<prect->width ; j++)
  719.       {
  720.         *pdest = d_8to16table[*psrc];
  721.         psrc++;
  722.         pdest++;
  723.       }
  724.  
  725.       psrc += srcdelta;
  726.       pdest += destdelta;
  727.     }
  728.   }
  729. }
  730.  
  731.  
  732. /*
  733. =============
  734. Draw_TileClear
  735.  
  736. This repeats a 64*64 tile graphic to fill the screen around a sized down
  737. refresh window.
  738. =============
  739. */
  740. void Draw_TileClear (int x, int y, int w, int h)
  741. {
  742.   int       width, height, tileoffsetx, tileoffsety;
  743.   byte      *psrc;
  744.   vrect_t     vr;
  745.  
  746.   r_rectdesc.rect.x = x;
  747.   r_rectdesc.rect.y = y;
  748.   r_rectdesc.rect.width = w;
  749.   r_rectdesc.rect.height = h;
  750.  
  751.   vr.y = r_rectdesc.rect.y;
  752.   height = r_rectdesc.rect.height;
  753.  
  754.   tileoffsety = vr.y % r_rectdesc.height;
  755.  
  756.   while (height > 0)
  757.   {
  758.     vr.x = r_rectdesc.rect.x;
  759.     width = r_rectdesc.rect.width;
  760.  
  761.     if (tileoffsety != 0)
  762.       vr.height = r_rectdesc.height - tileoffsety;
  763.     else
  764.       vr.height = r_rectdesc.height;
  765.  
  766.     if (vr.height > height)
  767.       vr.height = height;
  768.  
  769.     tileoffsetx = vr.x % r_rectdesc.width;
  770.  
  771.     while (width > 0)
  772.     {
  773.       if (tileoffsetx != 0)
  774.         vr.width = r_rectdesc.width - tileoffsetx;
  775.       else
  776.         vr.width = r_rectdesc.width;
  777.  
  778.       if (vr.width > width)
  779.         vr.width = width;
  780.  
  781.       psrc = r_rectdesc.ptexbytes +
  782.           (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
  783.  
  784.       if (r_pixbytes == 1)
  785.       {
  786.         R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
  787.       }
  788.       else
  789.       {
  790.         R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
  791.       }
  792.  
  793.       vr.x += vr.width;
  794.       width -= vr.width;
  795.       tileoffsetx = 0;  // only the left tile can be left-clipped
  796.     }
  797.  
  798.     vr.y += vr.height;
  799.     height -= vr.height;
  800.     tileoffsety = 0;    // only the top tile can be top-clipped
  801.   }
  802. }
  803.  
  804.  
  805. /*
  806. =============
  807. Draw_Fill
  808.  
  809. Fills a box of pixels with a single color
  810. =============
  811. */
  812. void Draw_Fill (int x, int y, int w, int h, int c)
  813. {
  814.   byte      *dest;
  815.   unsigned short  *pusdest;
  816.   unsigned    uc;
  817.   int       u, v;
  818.  
  819.   if (r_pixbytes == 1)
  820.   {
  821.     dest = vid.buffer + y*vid.rowbytes + x;
  822.     for (v=0 ; v<h ; v++, dest += vid.rowbytes)
  823.       for (u=0 ; u<w ; u++)
  824.         dest[u] = c;
  825.   }
  826.   else
  827.   {
  828.     uc = d_8to16table[c];
  829.  
  830.     pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  831.     for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
  832.       for (u=0 ; u<w ; u++)
  833.         pusdest[u] = uc;
  834.   }
  835. }
  836. //=============================================================================
  837.  
  838. /*
  839. ================
  840. Draw_FadeScreen
  841.  
  842. ================
  843. */
  844. void Draw_FadeScreen (void)
  845. {
  846.   int     x,y;
  847.   byte    *pbuf;
  848.  
  849.   VID_UnlockBuffer ();
  850.   S_ExtraUpdate ();
  851.   VID_LockBuffer ();
  852.  
  853.   for (y=0 ; y<vid.height ; y++)
  854.   {
  855.     int t;
  856.  
  857.     pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
  858.     t = (y & 1) << 1;
  859.  
  860.     for (x=0 ; x<vid.width ; x++)
  861.     {
  862.       if ((x & 3) != t)
  863.         pbuf[x] = 0;
  864.     }
  865.   }
  866.  
  867.   VID_UnlockBuffer ();
  868.   S_ExtraUpdate ();
  869.   VID_LockBuffer ();
  870. }
  871.  
  872. //=============================================================================
  873.  
  874. /*
  875. ================
  876. Draw_BeginDisc
  877.  
  878. Draws the little blue disc in the corner of the screen.
  879. Call before beginning any disc IO.
  880. ================
  881. */
  882. void Draw_BeginDisc (void)
  883. {
  884.  
  885.   D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
  886. }
  887.  
  888.  
  889. /*
  890. ================
  891. Draw_EndDisc
  892.  
  893. Erases the disc icon.
  894. Call after completing any disc IO
  895. ================
  896. */
  897. void Draw_EndDisc (void)
  898. {
  899.  
  900.   D_EndDirectRect (vid.width - 24, 0, 24, 24);
  901. }
  902.  
  903.