You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
445 lines
7.9 KiB
445 lines
7.9 KiB
/* |
|
Copyright (C) 1997-2001 Id Software, Inc. |
|
|
|
This program is free software; you can redistribute it and/or |
|
modify it under the terms of the GNU General Public License |
|
as published by the Free Software Foundation; either version 2 |
|
of the License, or (at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
|
|
See the GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program; if not, write to the Free Software |
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
|
|
*/ |
|
|
|
// draw.c |
|
|
|
#include "r_local.h" |
|
|
|
|
|
image_t *draw_chars; // 8*8 graphic characters |
|
|
|
//============================================================================= |
|
|
|
/* |
|
================ |
|
Draw_FindPic |
|
================ |
|
*/ |
|
image_t *Draw_FindPic (char *name) |
|
{ |
|
image_t *image; |
|
char fullname[MAX_QPATH]; |
|
|
|
if (name[0] != '/' && name[0] != '\\') |
|
{ |
|
Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name); |
|
image = R_FindImage (fullname, it_pic); |
|
} |
|
else |
|
image = R_FindImage (name+1, it_pic); |
|
|
|
return image; |
|
} |
|
|
|
|
|
|
|
/* |
|
=============== |
|
Draw_InitLocal |
|
=============== |
|
*/ |
|
void Draw_InitLocal (void) |
|
{ |
|
draw_chars = Draw_FindPic ("conchars"); |
|
} |
|
|
|
|
|
|
|
/* |
|
================ |
|
Draw_Char |
|
|
|
Draws one 8*8 graphics character |
|
It can be clipped to the top of the screen to allow the console to be |
|
smoothly scrolled off. |
|
================ |
|
*/ |
|
void Draw_Char (int x, int y, int num) |
|
{ |
|
byte *dest; |
|
byte *source; |
|
int drawline; |
|
int row, col; |
|
|
|
num &= 255; |
|
|
|
if (num == 32 || num == 32+128) |
|
return; |
|
|
|
if (y <= -8) |
|
return; // totally off screen |
|
|
|
// if ( ( y + 8 ) >= vid.height ) |
|
if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw... |
|
return; |
|
|
|
#ifdef PARANOID |
|
if (y > vid.height - 8 || x < 0 || x > vid.width - 8) |
|
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y); |
|
if (num < 0 || num > 255) |
|
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num); |
|
#endif |
|
|
|
row = num>>4; |
|
col = num&15; |
|
source = draw_chars->pixels[0] + (row<<10) + (col<<3); |
|
|
|
if (y < 0) |
|
{ // clipped |
|
drawline = 8 + y; |
|
source -= 128*y; |
|
y = 0; |
|
} |
|
else |
|
drawline = 8; |
|
|
|
|
|
dest = vid.buffer + y*vid.rowbytes + x; |
|
|
|
while (drawline--) |
|
{ |
|
if (source[0] != TRANSPARENT_COLOR) |
|
dest[0] = source[0]; |
|
if (source[1] != TRANSPARENT_COLOR) |
|
dest[1] = source[1]; |
|
if (source[2] != TRANSPARENT_COLOR) |
|
dest[2] = source[2]; |
|
if (source[3] != TRANSPARENT_COLOR) |
|
dest[3] = source[3]; |
|
if (source[4] != TRANSPARENT_COLOR) |
|
dest[4] = source[4]; |
|
if (source[5] != TRANSPARENT_COLOR) |
|
dest[5] = source[5]; |
|
if (source[6] != TRANSPARENT_COLOR) |
|
dest[6] = source[6]; |
|
if (source[7] != TRANSPARENT_COLOR) |
|
dest[7] = source[7]; |
|
source += 128; |
|
dest += vid.rowbytes; |
|
} |
|
} |
|
|
|
/* |
|
============= |
|
Draw_GetPicSize |
|
============= |
|
*/ |
|
void Draw_GetPicSize (int *w, int *h, char *pic) |
|
{ |
|
image_t *gl; |
|
|
|
gl = Draw_FindPic (pic); |
|
if (!gl) |
|
{ |
|
*w = *h = -1; |
|
return; |
|
} |
|
*w = gl->width; |
|
*h = gl->height; |
|
} |
|
|
|
/* |
|
============= |
|
Draw_StretchPicImplementation |
|
============= |
|
*/ |
|
void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic) |
|
{ |
|
byte *dest, *source; |
|
int v, u, sv; |
|
int height; |
|
int f, fstep; |
|
int skip; |
|
|
|
if ((x < 0) || |
|
(x + w > vid.width) || |
|
(y + h > vid.height)) |
|
{ |
|
ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates"); |
|
} |
|
|
|
height = h; |
|
if (y < 0) |
|
{ |
|
skip = -y; |
|
height += y; |
|
y = 0; |
|
} |
|
else |
|
skip = 0; |
|
|
|
dest = vid.buffer + y * vid.rowbytes + x; |
|
|
|
for (v=0 ; v<height ; v++, dest += vid.rowbytes) |
|
{ |
|
sv = (skip + v)*pic->height/h; |
|
source = pic->pixels[0] + sv*pic->width; |
|
if (w == pic->width) |
|
memcpy (dest, source, w); |
|
else |
|
{ |
|
f = 0; |
|
fstep = pic->width*0x10000/w; |
|
for (u=0 ; u<w ; u+=4) |
|
{ |
|
dest[u] = source[f>>16]; |
|
f += fstep; |
|
dest[u+1] = source[f>>16]; |
|
f += fstep; |
|
dest[u+2] = source[f>>16]; |
|
f += fstep; |
|
dest[u+3] = source[f>>16]; |
|
f += fstep; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
============= |
|
Draw_StretchPic |
|
============= |
|
*/ |
|
void Draw_StretchPic (int x, int y, int w, int h, char *name) |
|
{ |
|
image_t *pic; |
|
|
|
pic = Draw_FindPic (name); |
|
if (!pic) |
|
{ |
|
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); |
|
return; |
|
} |
|
Draw_StretchPicImplementation (x, y, w, h, pic); |
|
} |
|
|
|
/* |
|
============= |
|
Draw_StretchRaw |
|
============= |
|
*/ |
|
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data) |
|
{ |
|
image_t pic; |
|
|
|
pic.pixels[0] = data; |
|
pic.width = cols; |
|
pic.height = rows; |
|
Draw_StretchPicImplementation (x, y, w, h, &pic); |
|
} |
|
|
|
/* |
|
============= |
|
Draw_Pic |
|
============= |
|
*/ |
|
void Draw_Pic (int x, int y, char *name) |
|
{ |
|
image_t *pic; |
|
byte *dest, *source; |
|
int v, u; |
|
int tbyte; |
|
int height; |
|
|
|
pic = Draw_FindPic (name); |
|
if (!pic) |
|
{ |
|
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); |
|
return; |
|
} |
|
|
|
if ((x < 0) || |
|
(x + pic->width > vid.width) || |
|
(y + pic->height > vid.height)) |
|
return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates"); |
|
|
|
height = pic->height; |
|
source = pic->pixels[0]; |
|
if (y < 0) |
|
{ |
|
height += y; |
|
source += pic->width*-y; |
|
y = 0; |
|
} |
|
|
|
dest = vid.buffer + y * vid.rowbytes + x; |
|
|
|
if (!pic->transparent) |
|
{ |
|
for (v=0 ; v<height ; v++) |
|
{ |
|
memcpy (dest, source, pic->width); |
|
dest += vid.rowbytes; |
|
source += pic->width; |
|
} |
|
} |
|
else |
|
{ |
|
if (pic->width & 7) |
|
{ // general |
|
for (v=0 ; v<height ; v++) |
|
{ |
|
for (u=0 ; u<pic->width ; u++) |
|
if ( (tbyte=source[u]) != TRANSPARENT_COLOR) |
|
dest[u] = tbyte; |
|
|
|
dest += vid.rowbytes; |
|
source += pic->width; |
|
} |
|
} |
|
else |
|
{ // unwound |
|
for (v=0 ; v<height ; v++) |
|
{ |
|
for (u=0 ; u<pic->width ; u+=8) |
|
{ |
|
if ( (tbyte=source[u]) != TRANSPARENT_COLOR) |
|
dest[u] = tbyte; |
|
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) |
|
dest[u+1] = tbyte; |
|
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) |
|
dest[u+2] = tbyte; |
|
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) |
|
dest[u+3] = tbyte; |
|
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) |
|
dest[u+4] = tbyte; |
|
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) |
|
dest[u+5] = tbyte; |
|
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) |
|
dest[u+6] = tbyte; |
|
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) |
|
dest[u+7] = tbyte; |
|
} |
|
dest += vid.rowbytes; |
|
source += pic->width; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
============= |
|
Draw_TileClear |
|
|
|
This repeats a 64*64 tile graphic to fill the screen around a sized down |
|
refresh window. |
|
============= |
|
*/ |
|
void Draw_TileClear (int x, int y, int w, int h, char *name) |
|
{ |
|
int i, j; |
|
byte *psrc; |
|
byte *pdest; |
|
image_t *pic; |
|
int x2; |
|
|
|
if (x < 0) |
|
{ |
|
w += x; |
|
x = 0; |
|
} |
|
if (y < 0) |
|
{ |
|
h += y; |
|
y = 0; |
|
} |
|
if (x + w > vid.width) |
|
w = vid.width - x; |
|
if (y + h > vid.height) |
|
h = vid.height - y; |
|
if (w <= 0 || h <= 0) |
|
return; |
|
|
|
pic = Draw_FindPic (name); |
|
if (!pic) |
|
{ |
|
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); |
|
return; |
|
} |
|
x2 = x + w; |
|
pdest = vid.buffer + y*vid.rowbytes; |
|
for (i=0 ; i<h ; i++, pdest += vid.rowbytes) |
|
{ |
|
psrc = pic->pixels[0] + pic->width * ((i+y)&63); |
|
for (j=x ; j<x2 ; j++) |
|
pdest[j] = psrc[j&63]; |
|
} |
|
} |
|
|
|
|
|
/* |
|
============= |
|
Draw_Fill |
|
|
|
Fills a box of pixels with a single color |
|
============= |
|
*/ |
|
void Draw_Fill (int x, int y, int w, int h, int c) |
|
{ |
|
byte *dest; |
|
int u, v; |
|
|
|
if (x+w > vid.width) |
|
w = vid.width - x; |
|
if (y+h > vid.height) |
|
h = vid.height - y; |
|
if (x < 0) |
|
{ |
|
w += x; |
|
x = 0; |
|
} |
|
if (y < 0) |
|
{ |
|
h += y; |
|
y = 0; |
|
} |
|
if (w < 0 || h < 0) |
|
return; |
|
dest = vid.buffer + y*vid.rowbytes + x; |
|
for (v=0 ; v<h ; v++, dest += vid.rowbytes) |
|
for (u=0 ; u<w ; u++) |
|
dest[u] = c; |
|
} |
|
//============================================================================= |
|
|
|
/* |
|
================ |
|
Draw_FadeScreen |
|
|
|
================ |
|
*/ |
|
void Draw_FadeScreen (void) |
|
{ |
|
int x,y; |
|
byte *pbuf; |
|
int t; |
|
|
|
for (y=0 ; y<vid.height ; y++) |
|
{ |
|
pbuf = (byte *)(vid.buffer + vid.rowbytes*y); |
|
t = (y & 1) << 1; |
|
|
|
for (x=0 ; x<vid.width ; x++) |
|
{ |
|
if ((x & 3) != t) |
|
pbuf[x] = 0; |
|
} |
|
} |
|
}
|
|
|