mirror of
https://git.code.sf.net/p/quake/quakeforge-old
synced 2024-11-28 22:52:01 +00:00
d5217418ec
like adding a gratuitious feature, GL target users can crosshair 3 for a completely new crosshair and higher resolution crosshair (oooh!) Software renderer doesn't have it because...well look at Draw_Crosshair() in draw.c, it's truly a nightmare! You have to plot each pixel individually, makes you feel like you're coding in Applesoft BASIC. If you want it, figure out how to do it sanely.
990 lines
19 KiB
C
990 lines
19 KiB
C
/*
|
|
Copyright (C) 1996-1997 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 -- this is the only file outside the refresh that touches the
|
|
// vid buffer
|
|
|
|
#include "quakedef.h"
|
|
|
|
typedef struct {
|
|
vrect_t rect;
|
|
int width;
|
|
int height;
|
|
byte *ptexbytes;
|
|
int rowbytes;
|
|
} rectdesc_t;
|
|
|
|
static rectdesc_t r_rectdesc;
|
|
|
|
byte *draw_chars; // 8*8 graphic characters
|
|
qpic_t *draw_disc;
|
|
qpic_t *draw_backtile;
|
|
|
|
//=============================================================================
|
|
/* Support Routines */
|
|
|
|
typedef struct cachepic_s
|
|
{
|
|
char name[MAX_QPATH];
|
|
cache_user_t cache;
|
|
} cachepic_t;
|
|
|
|
#define MAX_CACHED_PICS 128
|
|
cachepic_t menu_cachepics[MAX_CACHED_PICS];
|
|
int menu_numcachepics;
|
|
|
|
|
|
qpic_t *Draw_PicFromWad (char *name)
|
|
{
|
|
return W_GetLumpName (name);
|
|
}
|
|
|
|
/*
|
|
================
|
|
Draw_CachePic
|
|
================
|
|
*/
|
|
qpic_t *Draw_CachePic (char *path)
|
|
{
|
|
cachepic_t *pic;
|
|
int i;
|
|
qpic_t *dat;
|
|
|
|
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
|
|
if (!strcmp (path, pic->name))
|
|
break;
|
|
|
|
if (i == menu_numcachepics)
|
|
{
|
|
if (menu_numcachepics == MAX_CACHED_PICS)
|
|
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
|
|
menu_numcachepics++;
|
|
strcpy (pic->name, path);
|
|
}
|
|
|
|
dat = Cache_Check (&pic->cache);
|
|
|
|
if (dat)
|
|
return dat;
|
|
|
|
//
|
|
// load the pic from disk
|
|
//
|
|
COM_LoadCacheFile (path, &pic->cache);
|
|
|
|
dat = (qpic_t *)pic->cache.data;
|
|
if (!dat)
|
|
{
|
|
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
|
}
|
|
|
|
SwapPic (dat);
|
|
|
|
return dat;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
Draw_Init
|
|
===============
|
|
*/
|
|
void Draw_Init (void)
|
|
{
|
|
draw_chars = W_GetLumpName ("conchars");
|
|
draw_disc = W_GetLumpName ("disc");
|
|
draw_backtile = W_GetLumpName ("backtile");
|
|
|
|
r_rectdesc.width = draw_backtile->width;
|
|
r_rectdesc.height = draw_backtile->height;
|
|
r_rectdesc.ptexbytes = draw_backtile->data;
|
|
r_rectdesc.rowbytes = draw_backtile->width;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
Draw_Character
|
|
|
|
Draws one 8*8 graphics character with 0 being transparent.
|
|
It can be clipped to the top of the screen to allow the console to be
|
|
smoothly scrolled off.
|
|
================
|
|
*/
|
|
void Draw_Character (int x, int y, int num)
|
|
{
|
|
byte *dest;
|
|
byte *source;
|
|
unsigned short *pusdest;
|
|
int drawline;
|
|
int row, col;
|
|
|
|
num &= 255;
|
|
|
|
if (y <= -8)
|
|
return; // totally off screen
|
|
|
|
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
|
|
return;
|
|
if (num < 0 || num > 255)
|
|
return;
|
|
|
|
row = num>>4;
|
|
col = num&15;
|
|
source = draw_chars + (row<<10) + (col<<3);
|
|
|
|
if (y < 0)
|
|
{ // clipped
|
|
drawline = 8 + y;
|
|
source -= 128*y;
|
|
y = 0;
|
|
}
|
|
else
|
|
drawline = 8;
|
|
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.conbuffer + y*vid.conrowbytes + x;
|
|
|
|
while (drawline--)
|
|
{
|
|
if (source[0])
|
|
dest[0] = source[0];
|
|
if (source[1])
|
|
dest[1] = source[1];
|
|
if (source[2])
|
|
dest[2] = source[2];
|
|
if (source[3])
|
|
dest[3] = source[3];
|
|
if (source[4])
|
|
dest[4] = source[4];
|
|
if (source[5])
|
|
dest[5] = source[5];
|
|
if (source[6])
|
|
dest[6] = source[6];
|
|
if (source[7])
|
|
dest[7] = source[7];
|
|
source += 128;
|
|
dest += vid.conrowbytes;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pre-expand to native format?
|
|
pusdest = (unsigned short *)
|
|
((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
|
|
|
|
while (drawline--)
|
|
{
|
|
if (source[0])
|
|
pusdest[0] = d_8to16table[source[0]];
|
|
if (source[1])
|
|
pusdest[1] = d_8to16table[source[1]];
|
|
if (source[2])
|
|
pusdest[2] = d_8to16table[source[2]];
|
|
if (source[3])
|
|
pusdest[3] = d_8to16table[source[3]];
|
|
if (source[4])
|
|
pusdest[4] = d_8to16table[source[4]];
|
|
if (source[5])
|
|
pusdest[5] = d_8to16table[source[5]];
|
|
if (source[6])
|
|
pusdest[6] = d_8to16table[source[6]];
|
|
if (source[7])
|
|
pusdest[7] = d_8to16table[source[7]];
|
|
|
|
source += 128;
|
|
pusdest += (vid.conrowbytes >> 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
Draw_String
|
|
================
|
|
*/
|
|
void Draw_String (int x, int y, char *str)
|
|
{
|
|
while (*str)
|
|
{
|
|
Draw_Character (x, y, *str);
|
|
str++;
|
|
x += 8;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
Draw_Alt_String
|
|
================
|
|
*/
|
|
void Draw_Alt_String (int x, int y, char *str)
|
|
{
|
|
while (*str)
|
|
{
|
|
Draw_Character (x, y, (*str) | 0x80);
|
|
str++;
|
|
x += 8;
|
|
}
|
|
}
|
|
|
|
void Draw_Pixel(int x, int y, byte color)
|
|
{
|
|
byte *dest;
|
|
unsigned short *pusdest;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.conbuffer + y*vid.conrowbytes + x;
|
|
*dest = color;
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pre-expand to native format?
|
|
pusdest = (unsigned short *)
|
|
((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
|
|
*pusdest = d_8to16table[color];
|
|
}
|
|
}
|
|
|
|
void Draw_Crosshair(void)
|
|
{
|
|
int x, y;
|
|
extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
|
|
extern vrect_t scr_vrect;
|
|
byte c = (byte)crosshaircolor.value;
|
|
|
|
if (crosshair.value == 2) {
|
|
x = scr_vrect.x + scr_vrect.width/2 + cl_crossx.value;
|
|
y = scr_vrect.y + scr_vrect.height/2 + cl_crossy.value;
|
|
// FIXME: Find a better way to do this...
|
|
Draw_Pixel(x - 1, y, c);
|
|
Draw_Pixel(x - 3, y, c);
|
|
Draw_Pixel(x + 1, y, c);
|
|
Draw_Pixel(x + 3, y, c);
|
|
Draw_Pixel(x, y - 1, c);
|
|
Draw_Pixel(x, y - 3, c);
|
|
Draw_Pixel(x, y + 1, c);
|
|
Draw_Pixel(x, y + 3, c);
|
|
} else if (crosshair.value)
|
|
Draw_Character (
|
|
scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value,
|
|
scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value,
|
|
'+');
|
|
}
|
|
|
|
/*
|
|
================
|
|
Draw_DebugChar
|
|
|
|
Draws a single character directly to the upper right corner of the screen.
|
|
This is for debugging lockups by drawing different chars in different parts
|
|
of the code.
|
|
================
|
|
*/
|
|
void Draw_DebugChar (char num)
|
|
{
|
|
byte *dest;
|
|
byte *source;
|
|
int drawline;
|
|
extern byte *draw_chars;
|
|
int row, col;
|
|
|
|
if (!vid.direct)
|
|
return; // don't have direct FB access, so no debugchars...
|
|
|
|
drawline = 8;
|
|
|
|
row = num>>4;
|
|
col = num&15;
|
|
source = draw_chars + (row<<10) + (col<<3);
|
|
|
|
dest = vid.direct + 312;
|
|
|
|
while (drawline--)
|
|
{
|
|
dest[0] = source[0];
|
|
dest[1] = source[1];
|
|
dest[2] = source[2];
|
|
dest[3] = source[3];
|
|
dest[4] = source[4];
|
|
dest[5] = source[5];
|
|
dest[6] = source[6];
|
|
dest[7] = source[7];
|
|
source += 128;
|
|
dest += 320;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=============
|
|
Draw_Pic
|
|
=============
|
|
*/
|
|
void Draw_Pic (int x, int y, qpic_t *pic)
|
|
{
|
|
byte *dest, *source;
|
|
unsigned short *pusdest;
|
|
int v, u;
|
|
|
|
if ((x < 0) ||
|
|
(x + pic->width > vid.width) ||
|
|
(y < 0) ||
|
|
(y + pic->height > vid.height))
|
|
{
|
|
Sys_Error ("Draw_Pic: bad coordinates");
|
|
}
|
|
|
|
source = pic->data;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.buffer + y * vid.rowbytes + x;
|
|
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
Q_memcpy (dest, source, pic->width);
|
|
dest += vid.rowbytes;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pretranslate at load time?
|
|
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
|
|
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
for (u=0 ; u<pic->width ; u++)
|
|
{
|
|
pusdest[u] = d_8to16table[source[u]];
|
|
}
|
|
|
|
pusdest += vid.rowbytes >> 1;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
Draw_SubPic
|
|
=============
|
|
*/
|
|
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
|
|
{
|
|
byte *dest, *source;
|
|
unsigned short *pusdest;
|
|
int v, u;
|
|
|
|
if ((x < 0) ||
|
|
(x + width > vid.width) ||
|
|
(y < 0) ||
|
|
(y + height > vid.height))
|
|
{
|
|
Sys_Error ("Draw_Pic: bad coordinates");
|
|
}
|
|
|
|
source = pic->data + srcy * pic->width + srcx;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.buffer + y * vid.rowbytes + x;
|
|
|
|
for (v=0 ; v<height ; v++)
|
|
{
|
|
Q_memcpy (dest, source, width);
|
|
dest += vid.rowbytes;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pretranslate at load time?
|
|
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
|
|
|
|
for (v=0 ; v<height ; v++)
|
|
{
|
|
for (u=srcx ; u<(srcx+width) ; u++)
|
|
{
|
|
pusdest[u] = d_8to16table[source[u]];
|
|
}
|
|
|
|
pusdest += vid.rowbytes >> 1;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
Draw_TransPic
|
|
=============
|
|
*/
|
|
void Draw_TransPic (int x, int y, qpic_t *pic)
|
|
{
|
|
byte *dest, *source, tbyte;
|
|
unsigned short *pusdest;
|
|
int v, u;
|
|
|
|
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
|
|
(unsigned)(y + pic->height) > vid.height)
|
|
{
|
|
Sys_Error ("Draw_TransPic: bad coordinates");
|
|
}
|
|
|
|
source = pic->data;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.buffer + y * vid.rowbytes + x;
|
|
|
|
if (pic->width & 7)
|
|
{ // general
|
|
for (v=0 ; v<pic->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<pic->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;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pretranslate at load time?
|
|
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
|
|
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
for (u=0 ; u<pic->width ; u++)
|
|
{
|
|
tbyte = source[u];
|
|
|
|
if (tbyte != TRANSPARENT_COLOR)
|
|
{
|
|
pusdest[u] = d_8to16table[tbyte];
|
|
}
|
|
}
|
|
|
|
pusdest += vid.rowbytes >> 1;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
Draw_TransPicTranslate
|
|
=============
|
|
*/
|
|
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
|
|
{
|
|
byte *dest, *source, tbyte;
|
|
unsigned short *pusdest;
|
|
int v, u;
|
|
|
|
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
|
|
(unsigned)(y + pic->height) > vid.height)
|
|
{
|
|
Sys_Error ("Draw_TransPic: bad coordinates");
|
|
}
|
|
|
|
source = pic->data;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.buffer + y * vid.rowbytes + x;
|
|
|
|
if (pic->width & 7)
|
|
{ // general
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
for (u=0 ; u<pic->width ; u++)
|
|
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
|
|
dest[u] = translation[tbyte];
|
|
|
|
dest += vid.rowbytes;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
else
|
|
{ // unwound
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
for (u=0 ; u<pic->width ; u+=8)
|
|
{
|
|
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
|
|
dest[u] = translation[tbyte];
|
|
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
|
|
dest[u+1] = translation[tbyte];
|
|
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
|
|
dest[u+2] = translation[tbyte];
|
|
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
|
|
dest[u+3] = translation[tbyte];
|
|
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
|
|
dest[u+4] = translation[tbyte];
|
|
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
|
|
dest[u+5] = translation[tbyte];
|
|
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
|
|
dest[u+6] = translation[tbyte];
|
|
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
|
|
dest[u+7] = translation[tbyte];
|
|
}
|
|
dest += vid.rowbytes;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: pretranslate at load time?
|
|
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
|
|
|
|
for (v=0 ; v<pic->height ; v++)
|
|
{
|
|
for (u=0 ; u<pic->width ; u++)
|
|
{
|
|
tbyte = source[u];
|
|
|
|
if (tbyte != TRANSPARENT_COLOR)
|
|
{
|
|
pusdest[u] = d_8to16table[tbyte];
|
|
}
|
|
}
|
|
|
|
pusdest += vid.rowbytes >> 1;
|
|
source += pic->width;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Draw_ConsoleBackground
|
|
|
|
================
|
|
*/
|
|
void Draw_ConsoleBackground (int lines)
|
|
{
|
|
int i, x, y, v;
|
|
byte *src, *dest;
|
|
unsigned short *pusdest;
|
|
int f, fstep;
|
|
qpic_t *conback;
|
|
static char saveback[320*8];
|
|
#ifdef QUAKEWORLD
|
|
char ver[] = "QuakeForge (Software QW) " VERSION;
|
|
#else
|
|
char ver[] = "QuakeForge (Software UQ) " VERSION;
|
|
#endif
|
|
|
|
conback = Draw_CachePic ("gfx/conback.lmp");
|
|
|
|
dest = conback->data + 320 - (strlen(ver)*8 + 11) + 320*186;
|
|
|
|
memcpy(saveback, conback->data + 320*186, 320*8);
|
|
|
|
// draw the pic
|
|
if (r_pixbytes == 1)
|
|
{
|
|
dest = vid.conbuffer;
|
|
|
|
for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
|
|
{
|
|
v = (vid.conheight - lines + y)*200/vid.conheight;
|
|
src = conback->data + v*320;
|
|
if (vid.conwidth == 320)
|
|
memcpy (dest, src, vid.conwidth);
|
|
else
|
|
{
|
|
f = 0;
|
|
fstep = 320*0x10000/vid.conwidth;
|
|
for (x=0 ; x<vid.conwidth ; x+=4)
|
|
{
|
|
dest[x] = src[f>>16];
|
|
f += fstep;
|
|
dest[x+1] = src[f>>16];
|
|
f += fstep;
|
|
dest[x+2] = src[f>>16];
|
|
f += fstep;
|
|
dest[x+3] = src[f>>16];
|
|
f += fstep;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pusdest = (unsigned short *)vid.conbuffer;
|
|
|
|
for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
|
|
{
|
|
// FIXME: pre-expand to native format?
|
|
// FIXME: does the endian switching go away in production?
|
|
v = (vid.conheight - lines + y)*200/vid.conheight;
|
|
src = conback->data + v*320;
|
|
f = 0;
|
|
fstep = 320*0x10000/vid.conwidth;
|
|
for (x=0 ; x<vid.conwidth ; x+=4)
|
|
{
|
|
pusdest[x] = d_8to16table[src[f>>16]];
|
|
f += fstep;
|
|
pusdest[x+1] = d_8to16table[src[f>>16]];
|
|
f += fstep;
|
|
pusdest[x+2] = d_8to16table[src[f>>16]];
|
|
f += fstep;
|
|
pusdest[x+3] = d_8to16table[src[f>>16]];
|
|
f += fstep;
|
|
}
|
|
}
|
|
}
|
|
// put it back
|
|
memcpy(conback->data + 320*186, saveback, 320*8);
|
|
|
|
y = lines-14;
|
|
x = vid.conwidth - (strlen(ver)*8 + 11);
|
|
for (i=0 ; i<strlen(ver) ; i++)
|
|
Draw_Character (x + i * 8, y, ver[i] | 0x80);
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
R_DrawRect8
|
|
==============
|
|
*/
|
|
void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
|
|
int transparent)
|
|
{
|
|
byte t;
|
|
int i, j, srcdelta, destdelta;
|
|
byte *pdest;
|
|
|
|
pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
|
|
|
|
srcdelta = rowbytes - prect->width;
|
|
destdelta = vid.rowbytes - prect->width;
|
|
|
|
if (transparent)
|
|
{
|
|
for (i=0 ; i<prect->height ; i++)
|
|
{
|
|
for (j=0 ; j<prect->width ; j++)
|
|
{
|
|
t = *psrc;
|
|
if (t != TRANSPARENT_COLOR)
|
|
{
|
|
*pdest = t;
|
|
}
|
|
|
|
psrc++;
|
|
pdest++;
|
|
}
|
|
|
|
psrc += srcdelta;
|
|
pdest += destdelta;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i=0 ; i<prect->height ; i++)
|
|
{
|
|
memcpy (pdest, psrc, prect->width);
|
|
psrc += rowbytes;
|
|
pdest += vid.rowbytes;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
R_DrawRect16
|
|
==============
|
|
*/
|
|
void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
|
|
int transparent)
|
|
{
|
|
byte t;
|
|
int i, j, srcdelta, destdelta;
|
|
unsigned short *pdest;
|
|
|
|
// FIXME: would it be better to pre-expand native-format versions?
|
|
|
|
pdest = (unsigned short *)vid.buffer +
|
|
(prect->y * (vid.rowbytes >> 1)) + prect->x;
|
|
|
|
srcdelta = rowbytes - prect->width;
|
|
destdelta = (vid.rowbytes >> 1) - prect->width;
|
|
|
|
if (transparent)
|
|
{
|
|
for (i=0 ; i<prect->height ; i++)
|
|
{
|
|
for (j=0 ; j<prect->width ; j++)
|
|
{
|
|
t = *psrc;
|
|
if (t != TRANSPARENT_COLOR)
|
|
{
|
|
*pdest = d_8to16table[t];
|
|
}
|
|
|
|
psrc++;
|
|
pdest++;
|
|
}
|
|
|
|
psrc += srcdelta;
|
|
pdest += destdelta;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i=0 ; i<prect->height ; i++)
|
|
{
|
|
for (j=0 ; j<prect->width ; j++)
|
|
{
|
|
*pdest = d_8to16table[*psrc];
|
|
psrc++;
|
|
pdest++;
|
|
}
|
|
|
|
psrc += srcdelta;
|
|
pdest += destdelta;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
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)
|
|
{
|
|
int width, height, tileoffsetx, tileoffsety;
|
|
byte *psrc;
|
|
vrect_t vr;
|
|
|
|
r_rectdesc.rect.x = x;
|
|
r_rectdesc.rect.y = y;
|
|
r_rectdesc.rect.width = w;
|
|
r_rectdesc.rect.height = h;
|
|
|
|
vr.y = r_rectdesc.rect.y;
|
|
height = r_rectdesc.rect.height;
|
|
|
|
tileoffsety = vr.y % r_rectdesc.height;
|
|
|
|
while (height > 0)
|
|
{
|
|
vr.x = r_rectdesc.rect.x;
|
|
width = r_rectdesc.rect.width;
|
|
|
|
if (tileoffsety != 0)
|
|
vr.height = r_rectdesc.height - tileoffsety;
|
|
else
|
|
vr.height = r_rectdesc.height;
|
|
|
|
if (vr.height > height)
|
|
vr.height = height;
|
|
|
|
tileoffsetx = vr.x % r_rectdesc.width;
|
|
|
|
while (width > 0)
|
|
{
|
|
if (tileoffsetx != 0)
|
|
vr.width = r_rectdesc.width - tileoffsetx;
|
|
else
|
|
vr.width = r_rectdesc.width;
|
|
|
|
if (vr.width > width)
|
|
vr.width = width;
|
|
|
|
psrc = r_rectdesc.ptexbytes +
|
|
(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
|
|
}
|
|
else
|
|
{
|
|
R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
|
|
}
|
|
|
|
vr.x += vr.width;
|
|
width -= vr.width;
|
|
tileoffsetx = 0; // only the left tile can be left-clipped
|
|
}
|
|
|
|
vr.y += vr.height;
|
|
height -= vr.height;
|
|
tileoffsety = 0; // only the top tile can be top-clipped
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
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;
|
|
unsigned short *pusdest;
|
|
unsigned uc;
|
|
int u, v;
|
|
|
|
if (x < 0 || x + w > vid.width ||
|
|
y < 0 || y + h > vid.height) {
|
|
Con_Printf("Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
|
|
x, y, w, h, c);
|
|
return;
|
|
}
|
|
|
|
if (r_pixbytes == 1)
|
|
{
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
uc = d_8to16table[c];
|
|
|
|
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
|
|
for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
|
|
for (u=0 ; u<w ; u++)
|
|
pusdest[u] = uc;
|
|
}
|
|
}
|
|
//=============================================================================
|
|
|
|
/*
|
|
================
|
|
Draw_FadeScreen
|
|
|
|
================
|
|
*/
|
|
void Draw_FadeScreen (void)
|
|
{
|
|
int x,y;
|
|
byte *pbuf;
|
|
|
|
VID_UnlockBuffer ();
|
|
S_ExtraUpdate ();
|
|
VID_LockBuffer ();
|
|
|
|
for (y=0 ; y<vid.height ; y++)
|
|
{
|
|
int t;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
VID_UnlockBuffer ();
|
|
S_ExtraUpdate ();
|
|
VID_LockBuffer ();
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
/*
|
|
================
|
|
Draw_BeginDisc
|
|
|
|
Draws the little blue disc in the corner of the screen.
|
|
Call before beginning any disc IO.
|
|
================
|
|
*/
|
|
void Draw_BeginDisc (void)
|
|
{
|
|
|
|
D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Draw_EndDisc
|
|
|
|
Erases the disc icon.
|
|
Call after completing any disc IO
|
|
================
|
|
*/
|
|
void Draw_EndDisc (void)
|
|
{
|
|
|
|
D_EndDirectRect (vid.width - 24, 0, 24, 24);
|
|
}
|
|
|