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