|
|
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:
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: draw_chars = W_GetLumpName ("conchars");
113: draw_disc = W_GetLumpName ("disc");
114: draw_backtile = W_GetLumpName ("backtile");
115:
116: r_rectdesc.width = draw_backtile->width;
117: r_rectdesc.height = draw_backtile->height;
118: r_rectdesc.ptexbytes = draw_backtile->data;
119: r_rectdesc.rowbytes = draw_backtile->width;
120: }
121:
122:
123:
124: /*
125: ================
126: Draw_Character
127:
128: Draws one 8*8 graphics character with 0 being transparent.
129: It can be clipped to the top of the screen to allow the console to be
130: smoothly scrolled off.
131: ================
132: */
133: void Draw_Character (int x, int y, int num)
134: {
135: byte *dest;
136: byte *source;
137: unsigned short *pusdest;
138: int drawline;
139: int row, col;
140:
141: num &= 255;
142:
143: if (y <= -8)
144: return; // totally off screen
145:
146: if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
147: return;
148: if (num < 0 || num > 255)
149: return;
150:
151: row = num>>4;
152: col = num&15;
153: source = draw_chars + (row<<10) + (col<<3);
154:
155: if (y < 0)
156: { // clipped
157: drawline = 8 + y;
158: source -= 128*y;
159: y = 0;
160: }
161: else
162: drawline = 8;
163:
164:
165: if (r_pixbytes == 1)
166: {
167: dest = vid.conbuffer + y*vid.conrowbytes + x;
168:
169: while (drawline--)
170: {
171: if (source[0])
172: dest[0] = source[0];
173: if (source[1])
174: dest[1] = source[1];
175: if (source[2])
176: dest[2] = source[2];
177: if (source[3])
178: dest[3] = source[3];
179: if (source[4])
180: dest[4] = source[4];
181: if (source[5])
182: dest[5] = source[5];
183: if (source[6])
184: dest[6] = source[6];
185: if (source[7])
186: dest[7] = source[7];
187: source += 128;
188: dest += vid.conrowbytes;
189: }
190: }
191: else
192: {
193: // FIXME: pre-expand to native format?
194: pusdest = (unsigned short *)
195: ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
196:
197: while (drawline--)
198: {
199: if (source[0])
200: pusdest[0] = d_8to16table[source[0]];
201: if (source[1])
202: pusdest[1] = d_8to16table[source[1]];
203: if (source[2])
204: pusdest[2] = d_8to16table[source[2]];
205: if (source[3])
206: pusdest[3] = d_8to16table[source[3]];
207: if (source[4])
208: pusdest[4] = d_8to16table[source[4]];
209: if (source[5])
210: pusdest[5] = d_8to16table[source[5]];
211: if (source[6])
212: pusdest[6] = d_8to16table[source[6]];
213: if (source[7])
214: pusdest[7] = d_8to16table[source[7]];
215:
216: source += 128;
217: pusdest += (vid.conrowbytes >> 1);
218: }
219: }
220: }
221:
222: /*
223: ================
224: Draw_String
225: ================
226: */
227: void Draw_String (int x, int y, char *str)
228: {
229: while (*str)
230: {
231: Draw_Character (x, y, *str);
232: str++;
233: x += 8;
234: }
235: }
236:
237: /*
238: ================
239: Draw_Alt_String
240: ================
241: */
242: void Draw_Alt_String (int x, int y, char *str)
243: {
244: while (*str)
245: {
246: Draw_Character (x, y, (*str) | 0x80);
247: str++;
248: x += 8;
249: }
250: }
251:
252: void Draw_Pixel(int x, int y, byte color)
253: {
254: byte *dest;
255: unsigned short *pusdest;
256:
257: if (r_pixbytes == 1)
258: {
259: dest = vid.conbuffer + y*vid.conrowbytes + x;
260: *dest = color;
261: }
262: else
263: {
264: // FIXME: pre-expand to native format?
265: pusdest = (unsigned short *)
266: ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
267: *pusdest = d_8to16table[color];
268: }
269: }
270:
271: void Draw_Crosshair(void)
272: {
273: int x, y;
274: extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
275: extern vrect_t scr_vrect;
276: byte c = (byte)crosshaircolor.value;
277:
278: if (crosshair.value == 2) {
279: x = scr_vrect.x + scr_vrect.width/2 + cl_crossx.value;
280: y = scr_vrect.y + scr_vrect.height/2 + cl_crossy.value;
281: Draw_Pixel(x - 1, y, c);
282: Draw_Pixel(x - 3, y, c);
283: Draw_Pixel(x + 1, y, c);
284: Draw_Pixel(x + 3, y, c);
285: Draw_Pixel(x, y - 1, c);
286: Draw_Pixel(x, y - 3, c);
287: Draw_Pixel(x, y + 1, c);
288: Draw_Pixel(x, y + 3, c);
289: } else if (crosshair.value)
290: Draw_Character (
291: scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value,
292: scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value,
293: '+');
294: }
295:
296: /*
297: ================
298: Draw_DebugChar
299:
300: Draws a single character directly to the upper right corner of the screen.
301: This is for debugging lockups by drawing different chars in different parts
302: of the code.
303: ================
304: */
305: void Draw_DebugChar (char num)
306: {
307: byte *dest;
308: byte *source;
309: int drawline;
310: extern byte *draw_chars;
311: int row, col;
312:
313: if (!vid.direct)
314: return; // don't have direct FB access, so no debugchars...
315:
316: drawline = 8;
317:
318: row = num>>4;
319: col = num&15;
320: source = draw_chars + (row<<10) + (col<<3);
321:
322: dest = vid.direct + 312;
323:
324: while (drawline--)
325: {
326: dest[0] = source[0];
327: dest[1] = source[1];
328: dest[2] = source[2];
329: dest[3] = source[3];
330: dest[4] = source[4];
331: dest[5] = source[5];
332: dest[6] = source[6];
333: dest[7] = source[7];
334: source += 128;
335: dest += 320;
336: }
337: }
338:
339: /*
340: =============
341: Draw_Pic
342: =============
343: */
344: void Draw_Pic (int x, int y, qpic_t *pic)
345: {
346: byte *dest, *source;
347: unsigned short *pusdest;
348: int v, u;
349:
350: if ((x < 0) ||
351: (x + pic->width > vid.width) ||
352: (y < 0) ||
353: (y + pic->height > vid.height))
354: {
355: Sys_Error ("Draw_Pic: bad coordinates");
356: }
357:
358: source = pic->data;
359:
360: if (r_pixbytes == 1)
361: {
362: dest = vid.buffer + y * vid.rowbytes + x;
363:
364: for (v=0 ; v<pic->height ; v++)
365: {
366: Q_memcpy (dest, source, pic->width);
367: dest += vid.rowbytes;
368: source += pic->width;
369: }
370: }
371: else
372: {
373: // FIXME: pretranslate at load time?
374: pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
375:
376: for (v=0 ; v<pic->height ; v++)
377: {
378: for (u=0 ; u<pic->width ; u++)
379: {
380: pusdest[u] = d_8to16table[source[u]];
381: }
382:
383: pusdest += vid.rowbytes >> 1;
384: source += pic->width;
385: }
386: }
387: }
388:
389:
390: /*
391: =============
392: Draw_SubPic
393: =============
394: */
395: void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
396: {
397: byte *dest, *source;
398: unsigned short *pusdest;
399: int v, u;
400:
401: if ((x < 0) ||
402: (x + width > vid.width) ||
403: (y < 0) ||
404: (y + height > vid.height))
405: {
406: Sys_Error ("Draw_Pic: bad coordinates");
407: }
408:
409: source = pic->data + srcy * pic->width + srcx;
410:
411: if (r_pixbytes == 1)
412: {
413: dest = vid.buffer + y * vid.rowbytes + x;
414:
415: for (v=0 ; v<height ; v++)
416: {
417: Q_memcpy (dest, source, width);
418: dest += vid.rowbytes;
419: source += pic->width;
420: }
421: }
422: else
423: {
424: // FIXME: pretranslate at load time?
425: pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
426:
427: for (v=0 ; v<height ; v++)
428: {
429: for (u=srcx ; u<(srcx+width) ; u++)
430: {
431: pusdest[u] = d_8to16table[source[u]];
432: }
433:
434: pusdest += vid.rowbytes >> 1;
435: source += pic->width;
436: }
437: }
438: }
439:
440:
441: /*
442: =============
443: Draw_TransPic
444: =============
445: */
446: void Draw_TransPic (int x, int y, qpic_t *pic)
447: {
448: byte *dest, *source, tbyte;
449: unsigned short *pusdest;
450: int v, u;
451:
452: if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
453: (unsigned)(y + pic->height) > vid.height)
454: {
455: Sys_Error ("Draw_TransPic: bad coordinates");
456: }
457:
458: source = pic->data;
459:
460: if (r_pixbytes == 1)
461: {
462: dest = vid.buffer + y * vid.rowbytes + x;
463:
464: if (pic->width & 7)
465: { // general
466: for (v=0 ; v<pic->height ; v++)
467: {
468: for (u=0 ; u<pic->width ; u++)
469: if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
470: dest[u] = tbyte;
471:
472: dest += vid.rowbytes;
473: source += pic->width;
474: }
475: }
476: else
477: { // unwound
478: for (v=0 ; v<pic->height ; v++)
479: {
480: for (u=0 ; u<pic->width ; u+=8)
481: {
482: if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
483: dest[u] = tbyte;
484: if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
485: dest[u+1] = tbyte;
486: if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
487: dest[u+2] = tbyte;
488: if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
489: dest[u+3] = tbyte;
490: if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
491: dest[u+4] = tbyte;
492: if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
493: dest[u+5] = tbyte;
494: if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
495: dest[u+6] = tbyte;
496: if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
497: dest[u+7] = tbyte;
498: }
499: dest += vid.rowbytes;
500: source += pic->width;
501: }
502: }
503: }
504: else
505: {
506: // FIXME: pretranslate at load time?
507: pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
508:
509: for (v=0 ; v<pic->height ; v++)
510: {
511: for (u=0 ; u<pic->width ; u++)
512: {
513: tbyte = source[u];
514:
515: if (tbyte != TRANSPARENT_COLOR)
516: {
517: pusdest[u] = d_8to16table[tbyte];
518: }
519: }
520:
521: pusdest += vid.rowbytes >> 1;
522: source += pic->width;
523: }
524: }
525: }
526:
527:
528: /*
529: =============
530: Draw_TransPicTranslate
531: =============
532: */
533: void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
534: {
535: byte *dest, *source, tbyte;
536: unsigned short *pusdest;
537: int v, u;
538:
539: if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
540: (unsigned)(y + pic->height) > vid.height)
541: {
542: Sys_Error ("Draw_TransPic: bad coordinates");
543: }
544:
545: source = pic->data;
546:
547: if (r_pixbytes == 1)
548: {
549: dest = vid.buffer + y * vid.rowbytes + x;
550:
551: if (pic->width & 7)
552: { // general
553: for (v=0 ; v<pic->height ; v++)
554: {
555: for (u=0 ; u<pic->width ; u++)
556: if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
557: dest[u] = translation[tbyte];
558:
559: dest += vid.rowbytes;
560: source += pic->width;
561: }
562: }
563: else
564: { // unwound
565: for (v=0 ; v<pic->height ; v++)
566: {
567: for (u=0 ; u<pic->width ; u+=8)
568: {
569: if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
570: dest[u] = translation[tbyte];
571: if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
572: dest[u+1] = translation[tbyte];
573: if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
574: dest[u+2] = translation[tbyte];
575: if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
576: dest[u+3] = translation[tbyte];
577: if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
578: dest[u+4] = translation[tbyte];
579: if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
580: dest[u+5] = translation[tbyte];
581: if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
582: dest[u+6] = translation[tbyte];
583: if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
584: dest[u+7] = translation[tbyte];
585: }
586: dest += vid.rowbytes;
587: source += pic->width;
588: }
589: }
590: }
591: else
592: {
593: // FIXME: pretranslate at load time?
594: pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
595:
596: for (v=0 ; v<pic->height ; v++)
597: {
598: for (u=0 ; u<pic->width ; u++)
599: {
600: tbyte = source[u];
601:
602: if (tbyte != TRANSPARENT_COLOR)
603: {
604: pusdest[u] = d_8to16table[tbyte];
605: }
606: }
607:
608: pusdest += vid.rowbytes >> 1;
609: source += pic->width;
610: }
611: }
612: }
613:
614:
615: void Draw_CharToConback (int num, byte *dest)
616: {
617: int row, col;
618: byte *source;
619: int drawline;
620: int x;
621:
622: row = num>>4;
623: col = num&15;
624: source = draw_chars + (row<<10) + (col<<3);
625:
626: drawline = 8;
627:
628: while (drawline--)
629: {
630: for (x=0 ; x<8 ; x++)
631: if (source[x])
632: dest[x] = 0x60 + source[x];
633: source += 128;
634: dest += 320;
635: }
636:
637: }
638:
639: /*
640: ================
641: Draw_ConsoleBackground
642:
643: ================
644: */
645: void Draw_ConsoleBackground (int lines)
646: {
647: int x, y, v;
648: byte *src, *dest;
649: unsigned short *pusdest;
650: int f, fstep;
651: qpic_t *conback;
652: char ver[100];
653: static char saveback[320*8];
654:
655: conback = Draw_CachePic ("gfx/conback.lmp");
656:
657: // hack the version number directly into the pic
658:
659: //sprintf (ver, "start commands with a \\ character %4.2f", VERSION);
660:
661: if (cls.download) {
662: sprintf (ver, "%4.2f", VERSION);
663: dest = conback->data + 320 + 320*186 - 11 - 8*strlen(ver);
664: } else {
665: #if defined(__linux__)
666: sprintf (ver, "Linux (%4.2f) QuakeWorld %4.2f", LINUX_VERSION, VERSION);
667: #else
668: sprintf (ver, "QuakeWorld %4.2f", VERSION);
669: #endif
670: dest = conback->data + 320 - (strlen(ver)*8 + 11) + 320*186;
671: }
672:
673: memcpy(saveback, conback->data + 320*186, 320*8);
674: for (x=0 ; x<strlen(ver) ; x++)
675: Draw_CharToConback (ver[x], dest+(x<<3));
676:
677: // draw the pic
678: if (r_pixbytes == 1)
679: {
680: dest = vid.conbuffer;
681:
682: for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
683: {
684: v = (vid.conheight - lines + y)*200/vid.conheight;
685: src = conback->data + v*320;
686: if (vid.conwidth == 320)
687: memcpy (dest, src, vid.conwidth);
688: else
689: {
690: f = 0;
691: fstep = 320*0x10000/vid.conwidth;
692: for (x=0 ; x<vid.conwidth ; x+=4)
693: {
694: dest[x] = src[f>>16];
695: f += fstep;
696: dest[x+1] = src[f>>16];
697: f += fstep;
698: dest[x+2] = src[f>>16];
699: f += fstep;
700: dest[x+3] = src[f>>16];
701: f += fstep;
702: }
703: }
704: }
705: }
706: else
707: {
708: pusdest = (unsigned short *)vid.conbuffer;
709:
710: for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
711: {
712: // FIXME: pre-expand to native format?
713: // FIXME: does the endian switching go away in production?
714: v = (vid.conheight - lines + y)*200/vid.conheight;
715: src = conback->data + v*320;
716: f = 0;
717: fstep = 320*0x10000/vid.conwidth;
718: for (x=0 ; x<vid.conwidth ; x+=4)
719: {
720: pusdest[x] = d_8to16table[src[f>>16]];
721: f += fstep;
722: pusdest[x+1] = d_8to16table[src[f>>16]];
723: f += fstep;
724: pusdest[x+2] = d_8to16table[src[f>>16]];
725: f += fstep;
726: pusdest[x+3] = d_8to16table[src[f>>16]];
727: f += fstep;
728: }
729: }
730: }
731: // put it back
732: memcpy(conback->data + 320*186, saveback, 320*8);
733: }
734:
735:
736: /*
737: ==============
738: R_DrawRect8
739: ==============
740: */
741: void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
742: int transparent)
743: {
744: byte t;
745: int i, j, srcdelta, destdelta;
746: byte *pdest;
747:
748: pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
749:
750: srcdelta = rowbytes - prect->width;
751: destdelta = vid.rowbytes - prect->width;
752:
753: if (transparent)
754: {
755: for (i=0 ; i<prect->height ; i++)
756: {
757: for (j=0 ; j<prect->width ; j++)
758: {
759: t = *psrc;
760: if (t != TRANSPARENT_COLOR)
761: {
762: *pdest = t;
763: }
764:
765: psrc++;
766: pdest++;
767: }
768:
769: psrc += srcdelta;
770: pdest += destdelta;
771: }
772: }
773: else
774: {
775: for (i=0 ; i<prect->height ; i++)
776: {
777: memcpy (pdest, psrc, prect->width);
778: psrc += rowbytes;
779: pdest += vid.rowbytes;
780: }
781: }
782: }
783:
784:
785: /*
786: ==============
787: R_DrawRect16
788: ==============
789: */
790: void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
791: int transparent)
792: {
793: byte t;
794: int i, j, srcdelta, destdelta;
795: unsigned short *pdest;
796:
797: // FIXME: would it be better to pre-expand native-format versions?
798:
799: pdest = (unsigned short *)vid.buffer +
800: (prect->y * (vid.rowbytes >> 1)) + prect->x;
801:
802: srcdelta = rowbytes - prect->width;
803: destdelta = (vid.rowbytes >> 1) - prect->width;
804:
805: if (transparent)
806: {
807: for (i=0 ; i<prect->height ; i++)
808: {
809: for (j=0 ; j<prect->width ; j++)
810: {
811: t = *psrc;
812: if (t != TRANSPARENT_COLOR)
813: {
814: *pdest = d_8to16table[t];
815: }
816:
817: psrc++;
818: pdest++;
819: }
820:
821: psrc += srcdelta;
822: pdest += destdelta;
823: }
824: }
825: else
826: {
827: for (i=0 ; i<prect->height ; i++)
828: {
829: for (j=0 ; j<prect->width ; j++)
830: {
831: *pdest = d_8to16table[*psrc];
832: psrc++;
833: pdest++;
834: }
835:
836: psrc += srcdelta;
837: pdest += destdelta;
838: }
839: }
840: }
841:
842:
843: /*
844: =============
845: Draw_TileClear
846:
847: This repeats a 64*64 tile graphic to fill the screen around a sized down
848: refresh window.
849: =============
850: */
851: void Draw_TileClear (int x, int y, int w, int h)
852: {
853: int width, height, tileoffsetx, tileoffsety;
854: byte *psrc;
855: vrect_t vr;
856:
857: r_rectdesc.rect.x = x;
858: r_rectdesc.rect.y = y;
859: r_rectdesc.rect.width = w;
860: r_rectdesc.rect.height = h;
861:
862: vr.y = r_rectdesc.rect.y;
863: height = r_rectdesc.rect.height;
864:
865: tileoffsety = vr.y % r_rectdesc.height;
866:
867: while (height > 0)
868: {
869: vr.x = r_rectdesc.rect.x;
870: width = r_rectdesc.rect.width;
871:
872: if (tileoffsety != 0)
873: vr.height = r_rectdesc.height - tileoffsety;
874: else
875: vr.height = r_rectdesc.height;
876:
877: if (vr.height > height)
878: vr.height = height;
879:
880: tileoffsetx = vr.x % r_rectdesc.width;
881:
882: while (width > 0)
883: {
884: if (tileoffsetx != 0)
885: vr.width = r_rectdesc.width - tileoffsetx;
886: else
887: vr.width = r_rectdesc.width;
888:
889: if (vr.width > width)
890: vr.width = width;
891:
892: psrc = r_rectdesc.ptexbytes +
893: (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
894:
895: if (r_pixbytes == 1)
896: {
897: R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
898: }
899: else
900: {
901: R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
902: }
903:
904: vr.x += vr.width;
905: width -= vr.width;
906: tileoffsetx = 0; // only the left tile can be left-clipped
907: }
908:
909: vr.y += vr.height;
910: height -= vr.height;
911: tileoffsety = 0; // only the top tile can be top-clipped
912: }
913: }
914:
915:
916: /*
917: =============
918: Draw_Fill
919:
920: Fills a box of pixels with a single color
921: =============
922: */
923: void Draw_Fill (int x, int y, int w, int h, int c)
924: {
925: byte *dest;
926: unsigned short *pusdest;
927: unsigned uc;
928: int u, v;
929:
930: if (x < 0 || x + w > vid.width ||
931: y < 0 || y + h > vid.height) {
932: Con_Printf("Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
933: x, y, w, h, c);
934: return;
935: }
936:
937: if (r_pixbytes == 1)
938: {
939: dest = vid.buffer + y*vid.rowbytes + x;
940: for (v=0 ; v<h ; v++, dest += vid.rowbytes)
941: for (u=0 ; u<w ; u++)
942: dest[u] = c;
943: }
944: else
945: {
946: uc = d_8to16table[c];
947:
948: pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
949: for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
950: for (u=0 ; u<w ; u++)
951: pusdest[u] = uc;
952: }
953: }
954: //=============================================================================
955:
956: /*
957: ================
958: Draw_FadeScreen
959:
960: ================
961: */
962: void Draw_FadeScreen (void)
963: {
964: int x,y;
965: byte *pbuf;
966:
967: VID_UnlockBuffer ();
968: S_ExtraUpdate ();
969: VID_LockBuffer ();
970:
971: for (y=0 ; y<vid.height ; y++)
972: {
973: int t;
974:
975: pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
976: t = (y & 1) << 1;
977:
978: for (x=0 ; x<vid.width ; x++)
979: {
980: if ((x & 3) != t)
981: pbuf[x] = 0;
982: }
983: }
984:
985: VID_UnlockBuffer ();
986: S_ExtraUpdate ();
987: VID_LockBuffer ();
988: }
989:
990: //=============================================================================
991:
992: /*
993: ================
994: Draw_BeginDisc
995:
996: Draws the little blue disc in the corner of the screen.
997: Call before beginning any disc IO.
998: ================
999: */
1000: void Draw_BeginDisc (void)
1001: {
1002:
1003: D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
1004: }
1005:
1006:
1007: /*
1008: ================
1009: Draw_EndDisc
1010:
1011: Erases the disc icon.
1012: Call after completing any disc IO
1013: ================
1014: */
1015: void Draw_EndDisc (void)
1016: {
1017:
1018: D_EndDirectRect (vid.width - 24, 0, 24, 24);
1019: }
1020:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.