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