2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
21 // draw.c -- this is the only file outside the refresh that touches the
34 static rectdesc_t r_rectdesc
;
36 byte
*draw_chars
; // 8*8 graphic characters
38 qpic_t
*draw_backtile
;
40 //=============================================================================
41 /* Support Routines */
43 typedef struct cachepic_s
49 #define MAX_CACHED_PICS 128
50 cachepic_t menu_cachepics
[MAX_CACHED_PICS
];
51 int menu_numcachepics
;
54 qpic_t
*Draw_PicFromWad (char *name
)
56 return W_GetLumpName (name
);
64 qpic_t
*Draw_CachePic (char *path
)
70 for (pic
=menu_cachepics
, i
=0 ; i
<menu_numcachepics
; pic
++, i
++)
71 if (!strcmp (path
, pic
->name
))
74 if (i
== menu_numcachepics
)
76 if (menu_numcachepics
== MAX_CACHED_PICS
)
77 Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
79 strcpy (pic
->name
, path
);
82 dat
= Cache_Check (&pic
->cache
);
88 // load the pic from disk
90 COM_LoadCacheFile (path
, &pic
->cache
);
92 dat
= (qpic_t
*)pic
->cache
.data
;
95 Sys_Error ("Draw_CachePic: failed to load %s", path
);
110 void Draw_Init (void)
112 draw_chars
= W_GetLumpName ("conchars");
113 draw_disc
= W_GetLumpName ("disc");
114 draw_backtile
= W_GetLumpName ("backtile");
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
;
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.
133 void Draw_Character (int x
, int y
, int num
)
137 unsigned short *pusdest
;
144 return; // totally off screen
147 if (y
> vid
.height
- 8 || x
< 0 || x
> vid
.width
- 8)
148 Sys_Error ("Con_DrawCharacter: (%i, %i)", x
, y
);
149 if (num
< 0 || num
> 255)
150 Sys_Error ("Con_DrawCharacter: char %i", num
);
155 source
= draw_chars
+ (row
<<10) + (col
<<3);
169 dest
= vid
.conbuffer
+ y
*vid
.conrowbytes
+ x
;
190 dest
+= vid
.conrowbytes
;
195 // FIXME: pre-expand to native format?
196 pusdest
= (unsigned short *)
197 ((byte
*)vid
.conbuffer
+ y
*vid
.conrowbytes
+ (x
<<1));
202 pusdest
[0] = d_8to16table
[source
[0]];
204 pusdest
[1] = d_8to16table
[source
[1]];
206 pusdest
[2] = d_8to16table
[source
[2]];
208 pusdest
[3] = d_8to16table
[source
[3]];
210 pusdest
[4] = d_8to16table
[source
[4]];
212 pusdest
[5] = d_8to16table
[source
[5]];
214 pusdest
[6] = d_8to16table
[source
[6]];
216 pusdest
[7] = d_8to16table
[source
[7]];
219 pusdest
+= (vid
.conrowbytes
>> 1);
229 void Draw_String (int x
, int y
, char *str
)
233 Draw_Character (x
, y
, *str
);
243 Draws a single character directly to the upper right corner of the screen.
244 This is for debugging lockups by drawing different chars in different parts
248 void Draw_DebugChar (char num
)
253 extern byte
*draw_chars
;
257 return; // don't have direct FB access, so no debugchars...
263 source
= draw_chars
+ (row
<<10) + (col
<<3);
265 dest
= vid
.direct
+ 312;
287 void Draw_Pic (int x
, int y
, qpic_t
*pic
)
290 unsigned short *pusdest
;
294 (x
+ pic
->width
> vid
.width
) ||
296 (y
+ pic
->height
> vid
.height
))
298 Sys_Error ("Draw_Pic: bad coordinates");
305 dest
= vid
.buffer
+ y
* vid
.rowbytes
+ x
;
307 for (v
=0 ; v
<pic
->height
; v
++)
309 Q_memcpy (dest
, source
, pic
->width
);
310 dest
+= vid
.rowbytes
;
311 source
+= pic
->width
;
316 // FIXME: pretranslate at load time?
317 pusdest
= (unsigned short *)vid
.buffer
+ y
* (vid
.rowbytes
>> 1) + x
;
319 for (v
=0 ; v
<pic
->height
; v
++)
321 for (u
=0 ; u
<pic
->width
; u
++)
323 pusdest
[u
] = d_8to16table
[source
[u
]];
326 pusdest
+= vid
.rowbytes
>> 1;
327 source
+= pic
->width
;
338 void Draw_TransPic (int x
, int y
, qpic_t
*pic
)
340 byte
*dest
, *source
, tbyte
;
341 unsigned short *pusdest
;
344 if (x
< 0 || (unsigned)(x
+ pic
->width
) > vid
.width
|| y
< 0 ||
345 (unsigned)(y
+ pic
->height
) > vid
.height
)
347 Sys_Error ("Draw_TransPic: bad coordinates");
354 dest
= vid
.buffer
+ y
* vid
.rowbytes
+ x
;
358 for (v
=0 ; v
<pic
->height
; v
++)
360 for (u
=0 ; u
<pic
->width
; u
++)
361 if ( (tbyte
=source
[u
]) != TRANSPARENT_COLOR
)
364 dest
+= vid
.rowbytes
;
365 source
+= pic
->width
;
370 for (v
=0 ; v
<pic
->height
; v
++)
372 for (u
=0 ; u
<pic
->width
; u
+=8)
374 if ( (tbyte
=source
[u
]) != TRANSPARENT_COLOR
)
376 if ( (tbyte
=source
[u
+1]) != TRANSPARENT_COLOR
)
378 if ( (tbyte
=source
[u
+2]) != TRANSPARENT_COLOR
)
380 if ( (tbyte
=source
[u
+3]) != TRANSPARENT_COLOR
)
382 if ( (tbyte
=source
[u
+4]) != TRANSPARENT_COLOR
)
384 if ( (tbyte
=source
[u
+5]) != TRANSPARENT_COLOR
)
386 if ( (tbyte
=source
[u
+6]) != TRANSPARENT_COLOR
)
388 if ( (tbyte
=source
[u
+7]) != TRANSPARENT_COLOR
)
391 dest
+= vid
.rowbytes
;
392 source
+= pic
->width
;
398 // FIXME: pretranslate at load time?
399 pusdest
= (unsigned short *)vid
.buffer
+ y
* (vid
.rowbytes
>> 1) + x
;
401 for (v
=0 ; v
<pic
->height
; v
++)
403 for (u
=0 ; u
<pic
->width
; u
++)
407 if (tbyte
!= TRANSPARENT_COLOR
)
409 pusdest
[u
] = d_8to16table
[tbyte
];
413 pusdest
+= vid
.rowbytes
>> 1;
414 source
+= pic
->width
;
422 Draw_TransPicTranslate
425 void Draw_TransPicTranslate (int x
, int y
, qpic_t
*pic
, byte
*translation
)
427 byte
*dest
, *source
, tbyte
;
428 unsigned short *pusdest
;
431 if (x
< 0 || (unsigned)(x
+ pic
->width
) > vid
.width
|| y
< 0 ||
432 (unsigned)(y
+ pic
->height
) > vid
.height
)
434 Sys_Error ("Draw_TransPic: bad coordinates");
441 dest
= vid
.buffer
+ y
* vid
.rowbytes
+ x
;
445 for (v
=0 ; v
<pic
->height
; v
++)
447 for (u
=0 ; u
<pic
->width
; u
++)
448 if ( (tbyte
=source
[u
]) != TRANSPARENT_COLOR
)
449 dest
[u
] = translation
[tbyte
];
451 dest
+= vid
.rowbytes
;
452 source
+= pic
->width
;
457 for (v
=0 ; v
<pic
->height
; v
++)
459 for (u
=0 ; u
<pic
->width
; u
+=8)
461 if ( (tbyte
=source
[u
]) != TRANSPARENT_COLOR
)
462 dest
[u
] = translation
[tbyte
];
463 if ( (tbyte
=source
[u
+1]) != TRANSPARENT_COLOR
)
464 dest
[u
+1] = translation
[tbyte
];
465 if ( (tbyte
=source
[u
+2]) != TRANSPARENT_COLOR
)
466 dest
[u
+2] = translation
[tbyte
];
467 if ( (tbyte
=source
[u
+3]) != TRANSPARENT_COLOR
)
468 dest
[u
+3] = translation
[tbyte
];
469 if ( (tbyte
=source
[u
+4]) != TRANSPARENT_COLOR
)
470 dest
[u
+4] = translation
[tbyte
];
471 if ( (tbyte
=source
[u
+5]) != TRANSPARENT_COLOR
)
472 dest
[u
+5] = translation
[tbyte
];
473 if ( (tbyte
=source
[u
+6]) != TRANSPARENT_COLOR
)
474 dest
[u
+6] = translation
[tbyte
];
475 if ( (tbyte
=source
[u
+7]) != TRANSPARENT_COLOR
)
476 dest
[u
+7] = translation
[tbyte
];
478 dest
+= vid
.rowbytes
;
479 source
+= pic
->width
;
485 // FIXME: pretranslate at load time?
486 pusdest
= (unsigned short *)vid
.buffer
+ y
* (vid
.rowbytes
>> 1) + x
;
488 for (v
=0 ; v
<pic
->height
; v
++)
490 for (u
=0 ; u
<pic
->width
; u
++)
494 if (tbyte
!= TRANSPARENT_COLOR
)
496 pusdest
[u
] = d_8to16table
[tbyte
];
500 pusdest
+= vid
.rowbytes
>> 1;
501 source
+= pic
->width
;
507 void Draw_CharToConback (int num
, byte
*dest
)
516 source
= draw_chars
+ (row
<<10) + (col
<<3);
522 for (x
=0 ; x
<8 ; x
++)
524 dest
[x
] = 0x60 + source
[x
];
533 Draw_ConsoleBackground
537 void Draw_ConsoleBackground (int lines
)
541 unsigned short *pusdest
;
546 conback
= Draw_CachePic ("gfx/conback.lmp");
548 // hack the version number directly into the pic
550 sprintf (ver
, "(WinQuake) %4.2f", (float)VERSION
);
551 dest
= conback
->data
+ 320*186 + 320 - 11 - 8*strlen(ver
);
553 sprintf (ver
, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION
, (float)VERSION
);
554 dest
= conback
->data
+ 320*186 + 320 - 11 - 8*strlen(ver
);
555 #elif defined(__linux__)
556 sprintf (ver
, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION
, (float)VERSION
);
557 dest
= conback
->data
+ 320*186 + 320 - 11 - 8*strlen(ver
);
559 dest
= conback
->data
+ 320 - 43 + 320*186;
560 sprintf (ver
, "%4.2f", VERSION
);
563 for (x
=0 ; x
<strlen(ver
) ; x
++)
564 Draw_CharToConback (ver
[x
], dest
+(x
<<3));
569 dest
= vid
.conbuffer
;
571 for (y
=0 ; y
<lines
; y
++, dest
+= vid
.conrowbytes
)
573 v
= (vid
.conheight
- lines
+ y
)*200/vid
.conheight
;
574 src
= conback
->data
+ v
*320;
575 if (vid
.conwidth
== 320)
576 memcpy (dest
, src
, vid
.conwidth
);
580 fstep
= 320*0x10000/vid
.conwidth
;
581 for (x
=0 ; x
<vid
.conwidth
; x
+=4)
583 dest
[x
] = src
[f
>>16];
585 dest
[x
+1] = src
[f
>>16];
587 dest
[x
+2] = src
[f
>>16];
589 dest
[x
+3] = src
[f
>>16];
597 pusdest
= (unsigned short *)vid
.conbuffer
;
599 for (y
=0 ; y
<lines
; y
++, pusdest
+= (vid
.conrowbytes
>> 1))
601 // FIXME: pre-expand to native format?
602 // FIXME: does the endian switching go away in production?
603 v
= (vid
.conheight
- lines
+ y
)*200/vid
.conheight
;
604 src
= conback
->data
+ v
*320;
606 fstep
= 320*0x10000/vid
.conwidth
;
607 for (x
=0 ; x
<vid
.conwidth
; x
+=4)
609 pusdest
[x
] = d_8to16table
[src
[f
>>16]];
611 pusdest
[x
+1] = d_8to16table
[src
[f
>>16]];
613 pusdest
[x
+2] = d_8to16table
[src
[f
>>16]];
615 pusdest
[x
+3] = d_8to16table
[src
[f
>>16]];
628 void R_DrawRect8 (vrect_t
*prect
, int rowbytes
, byte
*psrc
,
632 int i
, j
, srcdelta
, destdelta
;
635 pdest
= vid
.buffer
+ (prect
->y
* vid
.rowbytes
) + prect
->x
;
637 srcdelta
= rowbytes
- prect
->width
;
638 destdelta
= vid
.rowbytes
- prect
->width
;
642 for (i
=0 ; i
<prect
->height
; i
++)
644 for (j
=0 ; j
<prect
->width
; j
++)
647 if (t
!= TRANSPARENT_COLOR
)
662 for (i
=0 ; i
<prect
->height
; i
++)
664 memcpy (pdest
, psrc
, prect
->width
);
666 pdest
+= vid
.rowbytes
;
677 void R_DrawRect16 (vrect_t
*prect
, int rowbytes
, byte
*psrc
,
681 int i
, j
, srcdelta
, destdelta
;
682 unsigned short *pdest
;
684 // FIXME: would it be better to pre-expand native-format versions?
686 pdest
= (unsigned short *)vid
.buffer
+
687 (prect
->y
* (vid
.rowbytes
>> 1)) + prect
->x
;
689 srcdelta
= rowbytes
- prect
->width
;
690 destdelta
= (vid
.rowbytes
>> 1) - prect
->width
;
694 for (i
=0 ; i
<prect
->height
; i
++)
696 for (j
=0 ; j
<prect
->width
; j
++)
699 if (t
!= TRANSPARENT_COLOR
)
701 *pdest
= d_8to16table
[t
];
714 for (i
=0 ; i
<prect
->height
; i
++)
716 for (j
=0 ; j
<prect
->width
; j
++)
718 *pdest
= d_8to16table
[*psrc
];
734 This repeats a 64*64 tile graphic to fill the screen around a sized down
738 void Draw_TileClear (int x
, int y
, int w
, int h
)
740 int width
, height
, tileoffsetx
, tileoffsety
;
744 r_rectdesc
.rect
.x
= x
;
745 r_rectdesc
.rect
.y
= y
;
746 r_rectdesc
.rect
.width
= w
;
747 r_rectdesc
.rect
.height
= h
;
749 vr
.y
= r_rectdesc
.rect
.y
;
750 height
= r_rectdesc
.rect
.height
;
752 tileoffsety
= vr
.y
% r_rectdesc
.height
;
756 vr
.x
= r_rectdesc
.rect
.x
;
757 width
= r_rectdesc
.rect
.width
;
759 if (tileoffsety
!= 0)
760 vr
.height
= r_rectdesc
.height
- tileoffsety
;
762 vr
.height
= r_rectdesc
.height
;
764 if (vr
.height
> height
)
767 tileoffsetx
= vr
.x
% r_rectdesc
.width
;
771 if (tileoffsetx
!= 0)
772 vr
.width
= r_rectdesc
.width
- tileoffsetx
;
774 vr
.width
= r_rectdesc
.width
;
776 if (vr
.width
> width
)
779 psrc
= r_rectdesc
.ptexbytes
+
780 (tileoffsety
* r_rectdesc
.rowbytes
) + tileoffsetx
;
784 R_DrawRect8 (&vr
, r_rectdesc
.rowbytes
, psrc
, 0);
788 R_DrawRect16 (&vr
, r_rectdesc
.rowbytes
, psrc
, 0);
793 tileoffsetx
= 0; // only the left tile can be left-clipped
798 tileoffsety
= 0; // only the top tile can be top-clipped
807 Fills a box of pixels with a single color
810 void Draw_Fill (int x
, int y
, int w
, int h
, int c
)
813 unsigned short *pusdest
;
819 dest
= vid
.buffer
+ y
*vid
.rowbytes
+ x
;
820 for (v
=0 ; v
<h
; v
++, dest
+= vid
.rowbytes
)
821 for (u
=0 ; u
<w
; u
++)
826 uc
= d_8to16table
[c
];
828 pusdest
= (unsigned short *)vid
.buffer
+ y
* (vid
.rowbytes
>> 1) + x
;
829 for (v
=0 ; v
<h
; v
++, pusdest
+= (vid
.rowbytes
>> 1))
830 for (u
=0 ; u
<w
; u
++)
834 //=============================================================================
842 void Draw_FadeScreen (void)
851 for (y
=0 ; y
<vid
.height
; y
++)
855 pbuf
= (byte
*)(vid
.buffer
+ vid
.rowbytes
*y
);
858 for (x
=0 ; x
<vid
.width
; x
++)
876 void Draw_FadeScreen2 (void)
881 //=============================================================================
887 Draws the little blue disc in the corner of the screen.
888 Call before beginning any disc IO.
891 void Draw_BeginDisc (void)
894 D_BeginDirectRect (vid
.width
- 24, 0, draw_disc
->data
, 24, 24);
902 Erases the disc icon.
903 Call after completing any disc IO
906 void Draw_EndDisc (void)
909 D_EndDirectRect (vid
.width
- 24, 0, 24, 24);