1 /*
2 draw.c
3
4 this is the only file outside the refresh that touches the vid buffer
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #define NH_DEFINE
32 #include "namehack.h"
33
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40
41 #include <stdlib.h>
42
43 #include "QF/cvar.h"
44 #include "QF/draw.h"
45 #include "QF/quakefs.h"
46 #include "QF/sound.h"
47 #include "QF/sys.h"
48
49 #include "d_iface.h"
50 #include "r_internal.h"
51 #include "vid_internal.h"
52
53 typedef struct {
54 vrect_t rect;
55 int width;
56 int height;
57 byte *ptexbytes;
58 int rowbytes;
59 } rectdesc_t;
60
61 static rectdesc_t r_rectdesc;
62
63 static qpic_t *draw_disc;
64 static qpic_t *draw_backtile;
65
66
67 /* Support Routines */
68
69 typedef struct cachepic_s {
70 char name[MAX_QPATH];
71 cache_user_t cache;
72 } cachepic_t;
73
74 #define MAX_CACHED_PICS 128
75 static cachepic_t cachepics[MAX_CACHED_PICS];
76 static int numcachepics;
77
78 #define CLIP(x,y,w,h,mw,mh) \
79 do { \
80 if (y < 0) { \
81 h += y; \
82 y = 0; \
83 } \
84 if (y + h > mh) \
85 h = mh - y; \
86 if (h <= 0) \
87 return; \
88 if (x < 0) { \
89 w += x; \
90 x = 0; \
91 } \
92 if (x + w > mw) \
93 w = mw - x; \
94 if (w <= 0) \
95 return; \
96 } while (0)
97
98
99 qpic_t *
sw32_Draw_MakePic(int width,int height,const byte * data)100 sw32_Draw_MakePic (int width, int height, const byte *data)
101 {
102 qpic_t *pic;
103 int size = width * height;
104
105 pic = malloc (field_offset (qpic_t, data[size]));
106 pic->width = width;
107 pic->height = height;
108 memcpy (pic->data, data, size);
109 return pic;
110 }
111
112 void
sw32_Draw_DestroyPic(qpic_t * pic)113 sw32_Draw_DestroyPic (qpic_t *pic)
114 {
115 free (pic);
116 }
117
118 qpic_t *
sw32_Draw_PicFromWad(const char * name)119 sw32_Draw_PicFromWad (const char *name)
120 {
121 return W_GetLumpName (name);
122 }
123
124
125 qpic_t *
sw32_Draw_CachePic(const char * path,qboolean alpha)126 sw32_Draw_CachePic (const char *path, qboolean alpha)
127 {
128 cachepic_t *pic;
129 int i;
130 qpic_t *dat;
131
132 for (pic = cachepics, i = 0; i < numcachepics; pic++, i++)
133 if (!strcmp (path, pic->name))
134 break;
135
136 if (i == numcachepics) {
137 for (pic = cachepics, i = 0; i < numcachepics; pic++, i++)
138 if (!pic->name[0])
139 break;
140 if (i == numcachepics) {
141 if (numcachepics == MAX_CACHED_PICS)
142 Sys_Error ("numcachepics == MAX_CACHED_PICS");
143 numcachepics++;
144 }
145 strcpy (pic->name, path);
146 }
147
148 dat = Cache_Check (&pic->cache);
149
150 if (dat)
151 return dat;
152
153 // load the pic from disk
154 QFS_LoadCacheFile (path, &pic->cache);
155
156 dat = (qpic_t *) pic->cache.data;
157 if (!dat) {
158 Sys_Error ("Draw_CachePic: failed to load %s", path);
159 }
160
161 SwapPic (dat);
162
163 return dat;
164 }
165
166 void
sw32_Draw_UncachePic(const char * path)167 sw32_Draw_UncachePic (const char *path)
168 {
169 cachepic_t *pic;
170 int i;
171
172 for (pic = cachepics, i = 0; i < numcachepics; pic++, i++) {
173 if (!strcmp (path, pic->name)) {
174 Cache_Release (&pic->cache);
175 pic->name[0] = 0;
176 break;
177 }
178 }
179 }
180
181
182 void
sw32_Draw_TextBox(int x,int y,int width,int lines,byte alpha)183 sw32_Draw_TextBox (int x, int y, int width, int lines, byte alpha)
184 {
185 qpic_t *p;
186 int cx, cy;
187 int n;
188
189 // draw left side
190 cx = x;
191 cy = y;
192 p = sw32_Draw_CachePic ("gfx/box_tl.lmp", true);
193 sw32_Draw_Pic (cx, cy, p);
194 p = sw32_Draw_CachePic ("gfx/box_ml.lmp", true);
195 for (n = 0; n < lines; n++) {
196 cy += 8;
197 sw32_Draw_Pic (cx, cy, p);
198 }
199 p = sw32_Draw_CachePic ("gfx/box_bl.lmp", true);
200 sw32_Draw_Pic (cx, cy + 8, p);
201
202 // draw middle
203 cx += 8;
204 while (width > 0) {
205 cy = y;
206 p = sw32_Draw_CachePic ("gfx/box_tm.lmp", true);
207 sw32_Draw_Pic (cx, cy, p);
208 p = sw32_Draw_CachePic ("gfx/box_mm.lmp", true);
209 for (n = 0; n < lines; n++) {
210 cy += 8;
211 if (n == 1)
212 p = sw32_Draw_CachePic ("gfx/box_mm2.lmp", true);
213 sw32_Draw_Pic (cx, cy, p);
214 }
215 p = sw32_Draw_CachePic ("gfx/box_bm.lmp", true);
216 sw32_Draw_Pic (cx, cy + 8, p);
217 width -= 2;
218 cx += 16;
219 }
220
221 // draw right side
222 cy = y;
223 p = sw32_Draw_CachePic ("gfx/box_tr.lmp", true);
224 sw32_Draw_Pic (cx, cy, p);
225 p = sw32_Draw_CachePic ("gfx/box_mr.lmp", true);
226 for (n = 0; n < lines; n++) {
227 cy += 8;
228 sw32_Draw_Pic (cx, cy, p);
229 }
230 p = sw32_Draw_CachePic ("gfx/box_br.lmp", true);
231 sw32_Draw_Pic (cx, cy + 8, p);
232 }
233
234
235 void
sw32_Draw_Init(void)236 sw32_Draw_Init (void)
237 {
238 draw_chars = W_GetLumpName ("conchars");
239 draw_disc = W_GetLumpName ("disc");
240 draw_backtile = W_GetLumpName ("backtile");
241
242 r_rectdesc.width = draw_backtile->width;
243 r_rectdesc.height = draw_backtile->height;
244 r_rectdesc.ptexbytes = draw_backtile->data;
245 r_rectdesc.rowbytes = draw_backtile->width;
246 }
247
248
249 /*
250 Draw_Character
251
252 Draws one 8*8 graphics character with 0 being transparent.
253 It can be clipped to the top of the screen to allow the console to be
254 smoothly scrolled off.
255 */
256 void
sw32_Draw_Character(int x,int y,unsigned int chr)257 sw32_Draw_Character (int x, int y, unsigned int chr)
258 {
259 byte *source;
260 int drawline;
261 int row, col;
262
263 chr &= 255;
264
265 if (y <= -8)
266 return; // totally off screen
267
268 if (y > vid.conheight - 8 || x < 0 || x > vid.conwidth - 8)
269 return;
270 if (chr > 255)
271 return;
272
273 row = chr >> 4;
274 col = chr & 15;
275 source = draw_chars + (row << 10) + (col << 3);
276
277 if (y < 0) { // clipped
278 drawline = 8 + y;
279 source -= 128 * y;
280 y = 0;
281 } else
282 drawline = 8;
283
284
285 switch(sw32_r_pixbytes) {
286 case 1:
287 {
288 byte *dest = (byte *) vid.conbuffer + y * vid.conrowbytes + x;
289
290 while (drawline--) {
291 if (source[0])
292 dest[0] = source[0];
293 if (source[1])
294 dest[1] = source[1];
295 if (source[2])
296 dest[2] = source[2];
297 if (source[3])
298 dest[3] = source[3];
299 if (source[4])
300 dest[4] = source[4];
301 if (source[5])
302 dest[5] = source[5];
303 if (source[6])
304 dest[6] = source[6];
305 if (source[7])
306 dest[7] = source[7];
307 source += 128;
308 dest += vid.conrowbytes;
309 }
310 }
311 break;
312 case 2:
313 {
314 unsigned short *dest = (unsigned short *) vid.conbuffer + y *
315 (vid.conrowbytes >> 1) + x;
316
317 while (drawline--) {
318 if (source[0])
319 dest[0] = sw32_8to16table[source[0]];
320 if (source[1])
321 dest[1] = sw32_8to16table[source[1]];
322 if (source[2])
323 dest[2] = sw32_8to16table[source[2]];
324 if (source[3])
325 dest[3] = sw32_8to16table[source[3]];
326 if (source[4])
327 dest[4] = sw32_8to16table[source[4]];
328 if (source[5])
329 dest[5] = sw32_8to16table[source[5]];
330 if (source[6])
331 dest[6] = sw32_8to16table[source[6]];
332 if (source[7])
333 dest[7] = sw32_8to16table[source[7]];
334
335 source += 128;
336 dest += (vid.conrowbytes >> 1);
337 }
338 }
339 break;
340 case 4:
341 {
342 unsigned int *dest = (unsigned int *) vid.conbuffer + y *
343 (vid.conrowbytes >> 2) + x;
344
345 while (drawline--) {
346 if (source[0])
347 dest[0] = d_8to24table[source[0]];
348 if (source[1])
349 dest[1] = d_8to24table[source[1]];
350 if (source[2])
351 dest[2] = d_8to24table[source[2]];
352 if (source[3])
353 dest[3] = d_8to24table[source[3]];
354 if (source[4])
355 dest[4] = d_8to24table[source[4]];
356 if (source[5])
357 dest[5] = d_8to24table[source[5]];
358 if (source[6])
359 dest[6] = d_8to24table[source[6]];
360 if (source[7])
361 dest[7] = d_8to24table[source[7]];
362
363 source += 128;
364 dest += (vid.conrowbytes >> 2);
365 }
366 }
367 break;
368 default:
369 Sys_Error("Draw_Character: unsupported r_pixbytes %i", sw32_r_pixbytes);
370 }
371 }
372
373 void
sw32_Draw_String(int x,int y,const char * str)374 sw32_Draw_String (int x, int y, const char *str)
375 {
376 while (*str) {
377 sw32_Draw_Character (x, y, *str++);
378 x += 8;
379 }
380 }
381
382 void
sw32_Draw_nString(int x,int y,const char * str,int count)383 sw32_Draw_nString (int x, int y, const char *str, int count)
384 {
385 while (count-- && *str) {
386 sw32_Draw_Character (x, y, *str++);
387 x += 8;
388 }
389 }
390
391
392 void
sw32_Draw_AltString(int x,int y,const char * str)393 sw32_Draw_AltString (int x, int y, const char *str)
394 {
395 while (*str) {
396 sw32_Draw_Character (x, y, (*str++) | 0x80);
397 x += 8;
398 }
399 }
400
401
402 static void
Draw_Pixel(int x,int y,byte color)403 Draw_Pixel (int x, int y, byte color)
404 {
405 switch(sw32_r_pixbytes)
406 {
407 case 1:
408 ((byte *) vid.conbuffer)[y * vid.conrowbytes + x] = color;
409 break;
410 case 2:
411 ((unsigned short *) vid.conbuffer)[y * (vid.conrowbytes >> 1) + x] =
412 sw32_8to16table[color];
413 break;
414 case 4:
415 ((unsigned int *) vid.conbuffer)[y * (vid.conrowbytes >> 2) + x] =
416 d_8to24table[color];
417 break;
418 default:
419 Sys_Error("Draw_Pixel: unsupported r_pixbytes %i", sw32_r_pixbytes);
420 }
421 }
422
423 static void
crosshair_1(int x,int y)424 crosshair_1 (int x, int y)
425 {
426 sw32_Draw_Character (x - 4, y - 4, '+');
427 }
428
429 static void
crosshair_2(int x,int y)430 crosshair_2 (int x, int y)
431 {
432 byte c = crosshaircolor->int_val;
433
434 Draw_Pixel (x - 1, y, c);
435 Draw_Pixel (x - 3, y, c);
436 Draw_Pixel (x + 1, y, c);
437 Draw_Pixel (x + 3, y, c);
438 Draw_Pixel (x, y - 1, c);
439 Draw_Pixel (x, y - 3, c);
440 Draw_Pixel (x, y + 1, c);
441 Draw_Pixel (x, y + 3, c);
442 }
443
444 static void
crosshair_3(int x,int y)445 crosshair_3 (int x, int y)
446 {
447 byte c = crosshaircolor->int_val;
448
449 Draw_Pixel (x - 3, y - 3, c);
450 Draw_Pixel (x + 3, y - 3, c);
451 Draw_Pixel (x - 2, y - 2, c);
452 Draw_Pixel (x + 2, y - 2, c);
453 Draw_Pixel (x - 3, y + 3, c);
454 Draw_Pixel (x + 2, y + 2, c);
455 Draw_Pixel (x - 2, y + 2, c);
456 Draw_Pixel (x + 3, y + 3, c);
457 }
458
459 static void
crosshair_4(int x,int y)460 crosshair_4 (int x, int y)
461 {
462 //byte c = crosshaircolor->int_val;
463
464 Draw_Pixel (x, y - 2, 8);
465 Draw_Pixel (x + 1, y - 2, 9);
466
467 Draw_Pixel (x, y - 1, 6);
468 Draw_Pixel (x + 1, y - 1, 8);
469 Draw_Pixel (x + 2, y - 1, 2);
470
471 Draw_Pixel (x - 2, y, 6);
472 Draw_Pixel (x - 1, y, 8);
473 Draw_Pixel (x, y, 8);
474 Draw_Pixel (x + 1, y, 6);
475 Draw_Pixel (x + 2, y, 8);
476 Draw_Pixel (x + 3, y, 8);
477
478 Draw_Pixel (x - 1, y + 1, 2);
479 Draw_Pixel (x, y + 1, 8);
480 Draw_Pixel (x + 1, y + 1, 8);
481 Draw_Pixel (x + 2, y + 1, 2);
482 Draw_Pixel (x + 3, y + 1, 2);
483 Draw_Pixel (x + 4, y + 1, 2);
484
485 Draw_Pixel (x, y + 2, 7);
486 Draw_Pixel (x + 1, y + 2, 8);
487 Draw_Pixel (x + 2, y + 2, 2);
488
489 Draw_Pixel (x + 1, y + 3, 2);
490 Draw_Pixel (x + 2, y + 3, 2);
491 }
492
493 static void
crosshair_5(int x,int y)494 crosshair_5 (int x, int y)
495 {
496 byte c = crosshaircolor->int_val;
497
498 Draw_Pixel (x - 1, y - 3, c);
499 Draw_Pixel (x + 0, y - 3, c);
500 Draw_Pixel (x + 1, y - 3, c);
501
502 Draw_Pixel (x - 2, y - 2, c);
503 Draw_Pixel (x + 2, y - 2, c);
504
505 Draw_Pixel (x - 3, y - 1, c);
506 Draw_Pixel (x + 3, y - 1, c);
507
508 Draw_Pixel (x - 3, y, c);
509 Draw_Pixel (x, y, c);
510 Draw_Pixel (x + 3, y, c);
511
512 Draw_Pixel (x - 3, y + 1, c);
513 Draw_Pixel (x + 3, y + 1, c);
514
515 Draw_Pixel (x - 2, y + 2, c);
516 Draw_Pixel (x + 2, y + 2, c);
517
518 Draw_Pixel (x - 1, y + 3, c);
519 Draw_Pixel (x + 0, y + 3, c);
520 Draw_Pixel (x + 1, y + 3, c);
521 }
522
523 static void (*crosshair_func[]) (int x, int y) = {
524 crosshair_1,
525 crosshair_2,
526 crosshair_3,
527 crosshair_4,
528 crosshair_5,
529 };
530
531 void
sw32_Draw_Crosshair(void)532 sw32_Draw_Crosshair (void)
533 {
534 int x, y;
535 int ch;
536
537 ch = crosshair->int_val - 1;
538 if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0]))
539 return;
540
541 x = vid.conwidth / 2 + cl_crossx->int_val;
542 y = vid.conheight / 2 + cl_crossy->int_val;
543
544 crosshair_func[ch] (x, y);
545 }
546
547 void
sw32_Draw_CrosshairAt(int ch,int x,int y)548 sw32_Draw_CrosshairAt (int ch, int x, int y)
549 {
550 ch -= 1;
551 if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0]))
552 return;
553
554 crosshair_func[ch] (x, y);
555 }
556
557 void
sw32_Draw_Pic(int x,int y,qpic_t * pic)558 sw32_Draw_Pic (int x, int y, qpic_t *pic)
559 {
560 byte *source, tbyte;
561 int v, u;
562
563 if (x < 0 || (x + pic->width) > vid.conwidth
564 || y < 0 || (y + pic->height) > vid.conheight) {
565 Sys_MaskPrintf (SYS_VID, "Draw_Pic: bad coordinates");
566 sw32_Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height);
567 return;
568 }
569
570 source = pic->data;
571
572 switch(sw32_r_pixbytes) {
573 case 1:
574 {
575 byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x;
576
577 if (pic->width & 7) { // general
578 for (v = 0; v < pic->height; v++) {
579 for (u = 0; u < pic->width; u++)
580 if ((tbyte = source[u]) != TRANSPARENT_COLOR)
581 dest[u] = tbyte;
582
583 dest += vid.rowbytes;
584 source += pic->width;
585 }
586 } else { // unwound
587 for (v = 0; v < pic->height; v++) {
588 for (u = 0; u < pic->width; u += 8) {
589 if ((tbyte = source[u]) != TRANSPARENT_COLOR)
590 dest[u] = tbyte;
591 if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR)
592 dest[u + 1] = tbyte;
593 if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR)
594 dest[u + 2] = tbyte;
595 if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR)
596 dest[u + 3] = tbyte;
597 if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR)
598 dest[u + 4] = tbyte;
599 if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR)
600 dest[u + 5] = tbyte;
601 if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR)
602 dest[u + 6] = tbyte;
603 if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR)
604 dest[u + 7] = tbyte;
605 }
606 dest += vid.rowbytes;
607 source += pic->width;
608 }
609 }
610 }
611 break;
612 case 2:
613 {
614 unsigned short *dest = (unsigned short *) vid.buffer + y *
615 (vid.rowbytes >> 1) + x;
616
617 for (v = 0; v < pic->height; v++) {
618 for (u = 0; u < pic->width; u++) {
619 tbyte = source[u];
620 if (tbyte != TRANSPARENT_COLOR)
621 dest[u] = sw32_8to16table[tbyte];
622 }
623
624 dest += vid.rowbytes >> 1;
625 source += pic->width;
626 }
627 }
628 break;
629 case 4:
630 {
631 unsigned int *dest = (unsigned int *) vid.buffer + y *
632 (vid.rowbytes >> 2) + x;
633 for (v = 0; v < pic->height; v++) {
634 for (u = 0; u < pic->width; u++) {
635 tbyte = source[u];
636 if (tbyte != TRANSPARENT_COLOR)
637 dest[u] = d_8to24table[tbyte];
638 }
639 dest += vid.rowbytes >> 2;
640 source += pic->width;
641 }
642 }
643 break;
644 default:
645 Sys_Error("Draw_Pic: unsupported r_pixbytes %i", sw32_r_pixbytes);
646 }
647 }
648
649 void
sw32_Draw_Picf(float x,float y,qpic_t * pic)650 sw32_Draw_Picf (float x, float y, qpic_t *pic)
651 {
652 sw32_Draw_Pic (x, y, pic);
653 }
654
655 void
sw32_Draw_SubPic(int x,int y,qpic_t * pic,int srcx,int srcy,int width,int height)656 sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
657 int height)
658 {
659 byte *source, tbyte;
660 int v, u;
661
662 if ((x < 0) || (x + width > vid.conwidth)
663 || (y < 0) || (y + height > vid.conheight)) {
664 Sys_MaskPrintf (SYS_VID, "Draw_SubPic: bad coordinates");
665 }
666 // first, clip to screen
667 if (x < 0) {
668 srcx += x;
669 width += x;
670 x = 0;
671 }
672 if (x + width > vid.width)
673 width = vid.width - x;
674 if (width <= 0)
675 return;
676 if (y < 0) {
677 srcy += y;
678 height += y;
679 y = 0;
680 }
681 if (y + height > vid.height)
682 height = vid.height - y;
683 if (height <= 0)
684 return;
685 // next, clip to pic
686 CLIP (srcx, srcy, width, height, pic->width, pic->height);
687
688 source = pic->data + srcy * pic->width + srcx;
689
690 switch (sw32_r_pixbytes) {
691 case 1:
692 {
693 byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x;
694
695 for (v = 0; v < height; v++) {
696 for (u = 0; u < width; u++)
697 if ((tbyte = source[u]) != TRANSPARENT_COLOR)
698 dest[u] = tbyte;
699 dest += vid.rowbytes;
700 source += pic->width;
701 }
702 }
703 break;
704 case 2:
705 {
706 unsigned short *dest = (unsigned short *) vid.buffer + y *
707 (vid.rowbytes >> 1) + x;
708 for (v = 0; v < height; v++, dest += vid.rowbytes >> 1,
709 source += pic->width)
710 for (u = 0; u < width; u++)
711 if ((tbyte = source[u]) != TRANSPARENT_COLOR)
712 dest[u] = sw32_8to16table[tbyte];
713 }
714 break;
715 case 4:
716 {
717 unsigned int *dest = (unsigned int *) vid.buffer + y *
718 (vid.rowbytes >> 2) + x;
719 for (v = 0; v < height; v++, dest += vid.rowbytes >> 2,
720 source += pic->width)
721 for (u = 0; u < width; u++)
722 if ((tbyte = source[u]) != TRANSPARENT_COLOR)
723 dest[u] = d_8to24table[tbyte];
724 }
725 break;
726 default:
727 Sys_Error("Draw_SubPic: unsupported r_pixbytes %i", sw32_r_pixbytes);
728 }
729 }
730
731
732 void
sw32_Draw_ConsoleBackground(int lines,byte alpha)733 sw32_Draw_ConsoleBackground (int lines, byte alpha)
734 {
735 int x, y, v;
736 byte *src;
737 int f, fstep;
738 qpic_t *conback;
739
740 conback = sw32_Draw_CachePic ("gfx/conback.lmp", true);
741
742 // draw the pic
743 switch(sw32_r_pixbytes) {
744 case 1:
745 {
746 byte *dest = vid.conbuffer;
747
748 for (y = 0; y < lines; y++, dest += vid.conrowbytes) {
749 v = (vid.conheight - lines + y) * 200 / vid.conheight;
750 src = conback->data + v * 320;
751 if (vid.conwidth == 320)
752 memcpy (dest, src, vid.conwidth);
753 else {
754 f = 0;
755 fstep = 320 * 0x10000 / vid.conwidth;
756 for (x = 0; x < vid.conwidth; x += 4) {
757 dest[x] = src[f >> 16];
758 f += fstep;
759 dest[x + 1] = src[f >> 16];
760 f += fstep;
761 dest[x + 2] = src[f >> 16];
762 f += fstep;
763 dest[x + 3] = src[f >> 16];
764 f += fstep;
765 }
766 }
767 }
768 }
769 break;
770 case 2:
771 {
772 unsigned short *dest = (unsigned short *) vid.conbuffer;
773
774 for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 1)) {
775 // FIXME: pre-expand to native format?
776 // FIXME: does the endian switching go away in production?
777 v = (vid.conheight - lines + y) * 200 / vid.conheight;
778 src = conback->data + v * 320;
779 f = 0;
780 fstep = 320 * 0x10000 / vid.conwidth;
781 for (x = 0; x < vid.conwidth; x += 4) {
782 dest[x] = sw32_8to16table[src[f >> 16]];
783 f += fstep;
784 dest[x + 1] = sw32_8to16table[src[f >> 16]];
785 f += fstep;
786 dest[x + 2] = sw32_8to16table[src[f >> 16]];
787 f += fstep;
788 dest[x + 3] = sw32_8to16table[src[f >> 16]];
789 f += fstep;
790 }
791 }
792 }
793 break;
794 case 4:
795 {
796 unsigned int *dest = (unsigned int *) vid.conbuffer;
797 for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 2)) {
798 v = (vid.conheight - lines + y) * 200 / vid.conheight;
799 src = conback->data + v * 320;
800 f = 0;
801 fstep = 320 * 0x10000 / vid.conwidth;
802 for (x = 0; x < vid.conwidth; x += 4) {
803 dest[x ] = d_8to24table[src[f >> 16]];f += fstep;
804 dest[x + 1] = d_8to24table[src[f >> 16]];f += fstep;
805 dest[x + 2] = d_8to24table[src[f >> 16]];f += fstep;
806 dest[x + 3] = d_8to24table[src[f >> 16]];f += fstep;
807 }
808 }
809 }
810 break;
811
812 default:
813 Sys_Error("Draw_ConsoleBackground: unsupported r_pixbytes %i",
814 sw32_r_pixbytes);
815 }
816
817 // if (!cls.download)
818 sw32_Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
819 lines - 14, cl_verstring->string);
820 }
821
822 static void
R_DrawRect(vrect_t * prect,int rowbytes,byte * psrc,int transparent)823 R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
824 {
825 switch(sw32_r_pixbytes) {
826 case 1:
827 {
828 byte t;
829 int i, j, srcdelta, destdelta;
830 byte *pdest;
831
832 pdest = (byte *) vid.buffer + prect->y * vid.rowbytes + prect->x;
833
834 srcdelta = rowbytes - prect->width;
835 destdelta = vid.rowbytes - prect->width;
836
837 if (transparent)
838 {
839 for (i = 0; i < prect->height; i++)
840 {
841 for (j = 0; j < prect->width; j++)
842 {
843 t = *psrc;
844 if (t != TRANSPARENT_COLOR)
845 *pdest = t;
846 psrc++;
847 pdest++;
848 }
849
850 psrc += srcdelta;
851 pdest += destdelta;
852 }
853 }
854 else
855 {
856 for (i = 0; i < prect->height; i++)
857 {
858 memcpy (pdest, psrc, prect->width);
859 psrc += rowbytes;
860 pdest += vid.rowbytes;
861 }
862 }
863 }
864 break;
865 case 2:
866 {
867 int i, j, srcdelta, destdelta;
868 unsigned short *pdest;
869
870 pdest = (unsigned short *) vid.buffer +
871 (prect->y * (vid.rowbytes >> 1)) + prect->x;
872
873 srcdelta = rowbytes - prect->width;
874 destdelta = (vid.rowbytes >> 1) - prect->width;
875
876 if (transparent) {
877 for (i = 0; i < prect->height; i++)
878 {
879 j = prect->width;
880 while(j >= 8)
881 {
882 j -= 8;
883 if (psrc[0] != TRANSPARENT_COLOR)
884 pdest[0] = sw32_8to16table[psrc[0]];
885 if (psrc[1] != TRANSPARENT_COLOR)
886 pdest[1] = sw32_8to16table[psrc[1]];
887 if (psrc[2] != TRANSPARENT_COLOR)
888 pdest[2] = sw32_8to16table[psrc[2]];
889 if (psrc[3] != TRANSPARENT_COLOR)
890 pdest[3] = sw32_8to16table[psrc[3]];
891 if (psrc[4] != TRANSPARENT_COLOR)
892 pdest[4] = sw32_8to16table[psrc[4]];
893 if (psrc[5] != TRANSPARENT_COLOR)
894 pdest[5] = sw32_8to16table[psrc[5]];
895 if (psrc[6] != TRANSPARENT_COLOR)
896 pdest[6] = sw32_8to16table[psrc[6]];
897 if (psrc[7] != TRANSPARENT_COLOR)
898 pdest[7] = sw32_8to16table[psrc[7]];
899 psrc += 8;
900 pdest += 8;
901 }
902 if (j & 4)
903 {
904 if (psrc[0] != TRANSPARENT_COLOR)
905 pdest[0] = sw32_8to16table[psrc[0]];
906 if (psrc[1] != TRANSPARENT_COLOR)
907 pdest[1] = sw32_8to16table[psrc[1]];
908 if (psrc[2] != TRANSPARENT_COLOR)
909 pdest[2] = sw32_8to16table[psrc[2]];
910 if (psrc[3] != TRANSPARENT_COLOR)
911 pdest[3] = sw32_8to16table[psrc[3]];
912 psrc += 4;
913 pdest += 4;
914 }
915 if (j & 2)
916 {
917 if (psrc[0] != TRANSPARENT_COLOR)
918 pdest[0] = sw32_8to16table[psrc[0]];
919 if (psrc[1] != TRANSPARENT_COLOR)
920 pdest[1] = sw32_8to16table[psrc[1]];
921 psrc += 2;
922 pdest += 2;
923 }
924 if (j & 1)
925 {
926 if (psrc[0] != TRANSPARENT_COLOR)
927 pdest[0] = sw32_8to16table[psrc[0]];
928 psrc++;
929 pdest++;
930 }
931
932 psrc += srcdelta;
933 pdest += destdelta;
934 }
935 } else {
936 for (i = 0; i < prect->height; i++, psrc += srcdelta,
937 pdest += destdelta)
938 {
939 j = prect->width;
940 while(j >= 8)
941 {
942 j -= 8;
943 pdest[0] = sw32_8to16table[psrc[0]];
944 pdest[1] = sw32_8to16table[psrc[1]];
945 pdest[2] = sw32_8to16table[psrc[2]];
946 pdest[3] = sw32_8to16table[psrc[3]];
947 pdest[4] = sw32_8to16table[psrc[4]];
948 pdest[5] = sw32_8to16table[psrc[5]];
949 pdest[6] = sw32_8to16table[psrc[6]];
950 pdest[7] = sw32_8to16table[psrc[7]];
951 psrc += 8;
952 pdest += 8;
953 }
954 if (j & 4)
955 {
956 pdest[0] = sw32_8to16table[psrc[0]];
957 pdest[1] = sw32_8to16table[psrc[1]];
958 pdest[2] = sw32_8to16table[psrc[2]];
959 pdest[3] = sw32_8to16table[psrc[3]];
960 psrc += 4;
961 pdest += 4;
962 }
963 if (j & 2)
964 {
965 pdest[0] = sw32_8to16table[psrc[0]];
966 pdest[1] = sw32_8to16table[psrc[1]];
967 psrc += 2;
968 pdest += 2;
969 }
970 if (j & 1)
971 {
972 pdest[0] = sw32_8to16table[psrc[0]];
973 psrc++;
974 pdest++;
975 }
976 }
977 }
978 }
979 break;
980 case 4:
981 {
982 int i, j, srcdelta, destdelta;
983 int *pdest;
984
985 pdest = (int *) vid.buffer + prect->y * (vid.rowbytes >> 2) + prect->x;
986
987 srcdelta = rowbytes - prect->width;
988 destdelta = (vid.rowbytes >> 2) - prect->width;
989
990 if (transparent)
991 {
992 for (i = 0; i < prect->height; i++)
993 {
994 j = prect->width;
995 while(j >= 8)
996 {
997 j -= 8;
998 if (psrc[0] != TRANSPARENT_COLOR)
999 pdest[0] = d_8to24table[psrc[0]];
1000 if (psrc[1] != TRANSPARENT_COLOR)
1001 pdest[1] = d_8to24table[psrc[1]];
1002 if (psrc[2] != TRANSPARENT_COLOR)
1003 pdest[2] = d_8to24table[psrc[2]];
1004 if (psrc[3] != TRANSPARENT_COLOR)
1005 pdest[3] = d_8to24table[psrc[3]];
1006 if (psrc[4] != TRANSPARENT_COLOR)
1007 pdest[4] = d_8to24table[psrc[4]];
1008 if (psrc[5] != TRANSPARENT_COLOR)
1009 pdest[5] = d_8to24table[psrc[5]];
1010 if (psrc[6] != TRANSPARENT_COLOR)
1011 pdest[6] = d_8to24table[psrc[6]];
1012 if (psrc[7] != TRANSPARENT_COLOR)
1013 pdest[7] = d_8to24table[psrc[7]];
1014 psrc += 8;
1015 pdest += 8;
1016 }
1017 if (j & 4)
1018 {
1019 if (psrc[0] != TRANSPARENT_COLOR)
1020 pdest[0] = d_8to24table[psrc[0]];
1021 if (psrc[1] != TRANSPARENT_COLOR)
1022 pdest[1] = d_8to24table[psrc[1]];
1023 if (psrc[2] != TRANSPARENT_COLOR)
1024 pdest[2] = d_8to24table[psrc[2]];
1025 if (psrc[3] != TRANSPARENT_COLOR)
1026 pdest[3] = d_8to24table[psrc[3]];
1027 psrc += 4;
1028 pdest += 4;
1029 }
1030 if (j & 2)
1031 {
1032 if (psrc[0] != TRANSPARENT_COLOR)
1033 pdest[0] = d_8to24table[psrc[0]];
1034 if (psrc[1] != TRANSPARENT_COLOR)
1035 pdest[1] = d_8to24table[psrc[1]];
1036 psrc += 2;
1037 pdest += 2;
1038 }
1039 if (j & 1)
1040 {
1041 if (psrc[0] != TRANSPARENT_COLOR)
1042 pdest[0] = d_8to24table[psrc[0]];
1043 psrc++;
1044 pdest++;
1045 }
1046
1047 psrc += srcdelta;
1048 pdest += destdelta;
1049 }
1050 }
1051 else
1052 {
1053 for (i = 0; i < prect->height; i++, psrc += srcdelta,
1054 pdest += destdelta)
1055 {
1056 j = prect->width;
1057 while(j >= 8)
1058 {
1059 j -= 8;
1060 pdest[0] = d_8to24table[psrc[0]];
1061 pdest[1] = d_8to24table[psrc[1]];
1062 pdest[2] = d_8to24table[psrc[2]];
1063 pdest[3] = d_8to24table[psrc[3]];
1064 pdest[4] = d_8to24table[psrc[4]];
1065 pdest[5] = d_8to24table[psrc[5]];
1066 pdest[6] = d_8to24table[psrc[6]];
1067 pdest[7] = d_8to24table[psrc[7]];
1068 psrc += 8;
1069 pdest += 8;
1070 }
1071 if (j & 4)
1072 {
1073 pdest[0] = d_8to24table[psrc[0]];
1074 pdest[1] = d_8to24table[psrc[1]];
1075 pdest[2] = d_8to24table[psrc[2]];
1076 pdest[3] = d_8to24table[psrc[3]];
1077 psrc += 4;
1078 pdest += 4;
1079 }
1080 if (j & 2)
1081 {
1082 pdest[0] = d_8to24table[psrc[0]];
1083 pdest[1] = d_8to24table[psrc[1]];
1084 psrc += 2;
1085 pdest += 2;
1086 }
1087 if (j & 1)
1088 {
1089 pdest[0] = d_8to24table[psrc[0]];
1090 psrc++;
1091 pdest++;
1092 }
1093 }
1094 }
1095 }
1096 break;
1097 default:
1098 Sys_Error("R_DrawRect: unsupported r_pixbytes %i", sw32_r_pixbytes);
1099 }
1100 }
1101
1102 /*
1103 Draw_TileClear
1104
1105 This repeats a 64*64 tile graphic to fill the screen around a sized down
1106 refresh window.
1107 */
1108 void
sw32_Draw_TileClear(int x,int y,int w,int h)1109 sw32_Draw_TileClear (int x, int y, int w, int h)
1110 {
1111 int width, height, tileoffsetx, tileoffsety;
1112 byte *psrc;
1113 vrect_t vr;
1114
1115 CLIP (x, y, w, h, vid.width, vid.height);
1116
1117 r_rectdesc.rect.x = x;
1118 r_rectdesc.rect.y = y;
1119 r_rectdesc.rect.width = w;
1120 r_rectdesc.rect.height = h;
1121
1122 vr.y = r_rectdesc.rect.y;
1123 height = r_rectdesc.rect.height;
1124
1125 tileoffsety = vr.y % r_rectdesc.height;
1126
1127 while (height > 0) {
1128 vr.x = r_rectdesc.rect.x;
1129 width = r_rectdesc.rect.width;
1130
1131 if (tileoffsety != 0)
1132 vr.height = r_rectdesc.height - tileoffsety;
1133 else
1134 vr.height = r_rectdesc.height;
1135
1136 if (vr.height > height)
1137 vr.height = height;
1138
1139 tileoffsetx = vr.x % r_rectdesc.width;
1140
1141 while (width > 0) {
1142 if (tileoffsetx != 0)
1143 vr.width = r_rectdesc.width - tileoffsetx;
1144 else
1145 vr.width = r_rectdesc.width;
1146
1147 if (vr.width > width)
1148 vr.width = width;
1149
1150 psrc = r_rectdesc.ptexbytes +
1151 (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
1152
1153 R_DrawRect (&vr, r_rectdesc.rowbytes, psrc, 0);
1154
1155 vr.x += vr.width;
1156 width -= vr.width;
1157 tileoffsetx = 0; // only the left tile can be left-clipped
1158 }
1159
1160 vr.y += vr.height;
1161 height -= vr.height;
1162 tileoffsety = 0; // only the top tile can be top-clipped
1163 }
1164 }
1165
1166
1167 /*
1168 Draw_Fill
1169
1170 Fills a box of pixels with a single color
1171 */
1172 void
sw32_Draw_Fill(int x,int y,int w,int h,int c)1173 sw32_Draw_Fill (int x, int y, int w, int h, int c)
1174 {
1175 int u, v;
1176
1177 if (x < 0 || x + w > vid.conwidth
1178 || y < 0 || y + h > vid.conheight) {
1179 Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
1180 x, y, w, h, c);
1181 }
1182 CLIP (x, y, w, h, vid.width, vid.height);
1183
1184 switch (sw32_r_pixbytes) {
1185 case 1:
1186 {
1187 byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x;
1188 for (v = 0; v < h; v++, dest += vid.rowbytes)
1189 for (u = 0; u < w; u++)
1190 dest[u] = c;
1191 }
1192 break;
1193 case 2:
1194 {
1195 unsigned short *dest = (unsigned short *) vid.buffer + y *
1196 (vid.rowbytes >> 1) + x;
1197 c = sw32_8to16table[c];
1198 for (v = 0; v < h; v++, dest += (vid.rowbytes >> 1))
1199 for (u = 0; u < w; u++)
1200 dest[u] = c;
1201 }
1202 break;
1203 case 4:
1204 {
1205 unsigned int *dest = (unsigned int *) vid.buffer + y *
1206 (vid.rowbytes >> 2) + x;
1207 c = d_8to24table[c];
1208 for (v = 0; v < h; v++, dest += (vid.rowbytes >> 2))
1209 for (u = 0; u < w; u++)
1210 dest[u] = c;
1211 }
1212 break;
1213 default:
1214 Sys_Error("Draw_Fill: unsupported r_pixbytes %i", sw32_r_pixbytes);
1215 }
1216 }
1217
1218
1219 void
sw32_Draw_FadeScreen(void)1220 sw32_Draw_FadeScreen (void)
1221 {
1222 int x, y;
1223
1224 VID_UnlockBuffer ();
1225 S_ExtraUpdate ();
1226 VID_LockBuffer ();
1227
1228 switch(sw32_r_pixbytes) {
1229 case 1:
1230 {
1231 for (y = 0; y < vid.conheight; y++) {
1232 unsigned int t;
1233 byte *pbuf = (byte *) ((byte *) vid.buffer + vid.rowbytes * y);
1234 t = (y & 1) << 1;
1235
1236 for (x = 0; x < vid.conwidth; x++) {
1237 if ((x & 3) != t)
1238 pbuf[x] = 0;
1239 }
1240 }
1241 }
1242 break;
1243 case 2:
1244 {
1245 for (y = 0; y < vid.conheight; y++) {
1246 unsigned short *pbuf = (unsigned short *)
1247 ((byte *) vid.buffer + vid.rowbytes * y);
1248 pbuf = (unsigned short *) vid.buffer + (vid.rowbytes >> 1) * y;
1249 for (x = 0; x < vid.conwidth; x++)
1250 pbuf[x] = (pbuf[x] >> 1) & 0x7BEF;
1251 }
1252 }
1253 break;
1254 case 4:
1255 {
1256 for (y = 0; y < vid.conheight; y++) {
1257 unsigned int *pbuf = (unsigned int *)
1258 ((byte *) vid.buffer + vid.rowbytes * y);
1259 for (x = 0; x < vid.conwidth; x++)
1260 pbuf[x] = (pbuf[x] >> 1) & 0x7F7F7F7F;
1261 }
1262 }
1263 break;
1264 default:
1265 Sys_Error("Draw_FadeScreen: unsupported r_pixbytes %i", sw32_r_pixbytes);
1266 }
1267 vr_data.scr_copyeverything = 1;
1268
1269 VID_UnlockBuffer ();
1270 S_ExtraUpdate ();
1271 VID_LockBuffer ();
1272 }
1273
1274 void
sw32_Draw_BlendScreen(quat_t color)1275 sw32_Draw_BlendScreen (quat_t color)
1276 {
1277 int r, g, b, i;
1278 byte *basepal, *newpal;
1279 byte pal[768];
1280
1281 switch(sw32_r_pixbytes) {
1282 case 1:
1283 {
1284 basepal = vid.basepal;
1285 newpal = pal;
1286
1287 for (i = 0; i < 256; i++) {
1288 r = basepal[0];
1289 g = basepal[1];
1290 b = basepal[2];
1291 basepal += 3;
1292
1293 r += (int) (color[3] * (color[0] * 256 - r));
1294 g += (int) (color[3] * (color[1] * 256 - g));
1295 b += (int) (color[3] * (color[2] * 256 - b));
1296
1297 newpal[0] = vid.gammatable[r];
1298 newpal[1] = vid.gammatable[g];
1299 newpal[2] = vid.gammatable[b];
1300 newpal += 3;
1301 }
1302 vid.set_palette (pal);
1303 }
1304 break;
1305 case 2:
1306 {
1307 int g1, g2, x, y;
1308 unsigned short rramp[32], gramp[64], bramp[32], *temp;
1309 for (i = 0; i < 32; i++) {
1310 r = i << 3;
1311 g1 = i << 3;
1312 g2 = g1 + 4;
1313 b = i << 3;
1314
1315 r += (int) (color[3] * (color[0] * 256 - r));
1316 g1 += (int) (color[3] * (color[1] - g1));
1317 g2 += (int) (color[3] * (color[1] - g2));
1318 b += (int) (color[3] * (color[2] - b));
1319
1320 rramp[i] = (vid.gammatable[r] << 8) & 0xF800;
1321 gramp[i*2+0] = (vid.gammatable[g1] << 3) & 0x07E0;
1322 gramp[i*2+1] = (vid.gammatable[g2] << 3) & 0x07E0;
1323 bramp[i] = (vid.gammatable[b] >> 3) & 0x001F;
1324 }
1325 temp = vid.buffer;
1326 for (y = 0;y < vid.height;y++, temp += (vid.rowbytes >> 1))
1327 for (x = 0;x < vid.width;x++)
1328 temp[x] = rramp[(temp[x] & 0xF800) >> 11]
1329 + gramp[(temp[x] & 0x07E0) >> 5] + bramp[temp[x] & 0x001F];
1330 }
1331 break;
1332 case 4:
1333 {
1334 int x, y;
1335
1336 byte ramp[256][4], *temp;
1337 for (i = 0; i < 256; i++) {
1338 r = i;
1339 g = i;
1340 b = i;
1341
1342 r += (int) (color[3] * (color[0] * 256 - r));
1343 g += (int) (color[3] * (color[1] * 256 - g));
1344 b += (int) (color[3] * (color[2] * 256 - b));
1345
1346 ramp[i][0] = vid.gammatable[r];
1347 ramp[i][1] = vid.gammatable[g];
1348 ramp[i][2] = vid.gammatable[b];
1349 ramp[i][3] = 0;
1350 }
1351 temp = vid.buffer;
1352 for (y = 0; y < vid.height; y++, temp += vid.rowbytes)
1353 {
1354 for (x = 0;x < vid.width;x++)
1355 {
1356 temp[x*4+0] = ramp[temp[x*4+0]][0];
1357 temp[x*4+1] = ramp[temp[x*4+1]][1];
1358 temp[x*4+2] = ramp[temp[x*4+2]][2];
1359 temp[x*4+3] = 0;
1360 }
1361 }
1362 }
1363 break;
1364 default:
1365 Sys_Error("V_UpdatePalette: unsupported r_pixbytes %i", sw32_r_pixbytes);
1366 }
1367 }
1368