1 line
13 KiB
C++
1 line
13 KiB
C++
// R_draw.c
|
|
|
|
#include "doomdef.h"
|
|
#include "r_local.h"
|
|
|
|
/*
|
|
|
|
All drawing to the view buffer is accomplished in this file. The other refresh
|
|
files only know about ccordinates, not the architecture of the frame buffer.
|
|
|
|
*/
|
|
|
|
byte *viewimage;
|
|
int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
|
|
byte *ylookup[MAXHEIGHT];
|
|
int columnofs[MAXWIDTH];
|
|
|
|
byte translations[3][256]; // color tables for different players
|
|
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= R_DrawColumn
|
|
=
|
|
= Source is the top of the column to scale
|
|
=
|
|
==================
|
|
*/
|
|
|
|
lighttable_t *dc_colormap;
|
|
int dc_x;
|
|
int dc_yl;
|
|
int dc_yh;
|
|
fixed_t dc_iscale;
|
|
fixed_t dc_texturemid;
|
|
byte *dc_source; // first pixel in a column (possibly virtual)
|
|
|
|
int dccount; // just for profiling
|
|
|
|
#if (!defined(USEASM) && !defined(__WATCOMC__) && !defined(__i386) && !defined(__m68k))
|
|
|
|
void R_DrawColumn (void)
|
|
{
|
|
int count;
|
|
byte *dest;
|
|
fixed_t frac, fracstep;
|
|
|
|
count = dc_yh - dc_yl;
|
|
if (count < 0)
|
|
return;
|
|
|
|
#ifdef RANGECHECK
|
|
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
|
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
|
#endif
|
|
|
|
dest = ylookup[dc_yl] + columnofs[dc_x];
|
|
|
|
fracstep = dc_iscale;
|
|
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
|
|
|
do
|
|
{
|
|
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
|
|
dest += SCREENWIDTH;
|
|
frac += fracstep;
|
|
} while (count--);
|
|
}
|
|
|
|
#if 0
|
|
void R_DrawColumn (void)
|
|
{
|
|
int count;
|
|
byte *source, *dest, *colormap;
|
|
unsigned frac, fracstep,fracstep2,fracstep3,fracstep4;
|
|
|
|
count = dc_yh - dc_yl + 1;
|
|
|
|
source = dc_source;
|
|
colormap = dc_colormap;
|
|
dest = ylookup[dc_yl] + columnofs[dc_x];
|
|
|
|
fracstep = dc_iscale<<9;
|
|
frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9;
|
|
|
|
fracstep2 = fracstep+fracstep;
|
|
fracstep3 = fracstep2+fracstep;
|
|
fracstep4 = fracstep3+fracstep;
|
|
|
|
while (count >= 8)
|
|
{
|
|
dest[0] = colormap[source[frac>>25]];
|
|
dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]];
|
|
dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]];
|
|
dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
|
|
frac += fracstep4;
|
|
dest[SCREENWIDTH*4] = colormap[source[frac>>25]];
|
|
dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]];
|
|
dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]];
|
|
dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]];
|
|
frac += fracstep4;
|
|
dest += SCREENWIDTH*8;
|
|
count -= 8;
|
|
}
|
|
|
|
while (count > 0)
|
|
{
|
|
*dest = colormap[source[frac>>25]];
|
|
dest += SCREENWIDTH;
|
|
frac += fracstep;
|
|
count--;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifndef __WATCOMC__
|
|
|
|
void R_DrawColumnLow (void)
|
|
{
|
|
int count;
|
|
byte *dest;
|
|
fixed_t frac, fracstep;
|
|
|
|
count = dc_yh - dc_yl;
|
|
if (count < 0)
|
|
return;
|
|
|
|
#ifdef RANGECHECK
|
|
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
|
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
|
// dccount++;
|
|
#endif
|
|
|
|
dest = ylookup[dc_yl] + columnofs[dc_x];
|
|
|
|
fracstep = dc_iscale;
|
|
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
|
|
|
do
|
|
{
|
|
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
|
|
dest += SCREENWIDTH;
|
|
frac += fracstep;
|
|
} while (count--);
|
|
}
|
|
|
|
#endif
|
|
|
|
#define FUZZTABLE 50
|
|
|
|
#ifdef __WATCOMC__
|
|
#define FUZZOFF (SCREENWIDTH/4)
|
|
#else
|
|
#define FUZZOFF (SCREENWIDTH)
|
|
#endif
|
|
int fuzzoffset[FUZZTABLE] = {
|
|
FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
|
|
};
|
|
int fuzzpos = 0;
|
|
|
|
void R_DrawFuzzColumn (void)
|
|
{
|
|
int count;
|
|
byte *dest;
|
|
fixed_t frac, fracstep;
|
|
|
|
if (!dc_yl)
|
|
dc_yl = 1;
|
|
if (dc_yh == viewheight-1)
|
|
dc_yh = viewheight - 2;
|
|
|
|
count = dc_yh - dc_yl;
|
|
if (count < 0)
|
|
return;
|
|
|
|
#ifdef RANGECHECK
|
|
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
|
I_Error ("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
if (detailshift)
|
|
{
|
|
if (dc_x & 1)
|
|
{
|
|
outpw (GC_INDEX,GC_READMAP+(2<<8) );
|
|
outp (SC_INDEX+1,12);
|
|
}
|
|
else
|
|
{
|
|
outpw (GC_INDEX,GC_READMAP);
|
|
outp (SC_INDEX+1,3);
|
|
}
|
|
dest = destview + dc_yl*80 + (dc_x>>1);
|
|
}
|
|
else
|
|
{
|
|
outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) );
|
|
outp (SC_INDEX+1,1<<(dc_x&3));
|
|
dest = destview + dc_yl*80 + (dc_x>>2);
|
|
}
|
|
#else
|
|
dest = ylookup[dc_yl] + columnofs[dc_x];
|
|
#endif
|
|
|
|
fracstep = dc_iscale;
|
|
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
|
|
|
do
|
|
{
|
|
*dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
|
|
if (++fuzzpos == FUZZTABLE)
|
|
fuzzpos = 0;
|
|
#ifdef __WATCOMC__
|
|
dest += SCREENWIDTH/4;
|
|
#else
|
|
dest += SCREENWIDTH;
|
|
#endif
|
|
frac += fracstep;
|
|
} while (count--);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
========================
|
|
=
|
|
= R_DrawTranslatedColumn
|
|
=
|
|
========================
|
|
*/
|
|
|
|
byte *dc_translation;
|
|
byte *translationtables;
|
|
|
|
void R_DrawTranslatedColumn (void)
|
|
{
|
|
int count;
|
|
byte *dest;
|
|
fixed_t frac, fracstep;
|
|
|
|
count = dc_yh - dc_yl;
|
|
if (count < 0)
|
|
return;
|
|
|
|
#ifdef RANGECHECK
|
|
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
|
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
if (detailshift)
|
|
{
|
|
if (dc_x & 1)
|
|
outp (SC_INDEX+1,12);
|
|
else
|
|
outp (SC_INDEX+1,3);
|
|
dest = destview + dc_yl*80 + (dc_x>>1);
|
|
}
|
|
else
|
|
{
|
|
outp (SC_INDEX+1,1<<(dc_x&3));
|
|
dest = destview + dc_yl*80 + (dc_x>>2);
|
|
}
|
|
#else
|
|
dest = ylookup[dc_yl] + columnofs[dc_x];
|
|
#endif
|
|
|
|
fracstep = dc_iscale;
|
|
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
|
|
|
do
|
|
{
|
|
*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
|
|
#ifdef __WATCOMC__
|
|
dest += SCREENWIDTH/4;
|
|
#else
|
|
dest += SCREENWIDTH;
|
|
#endif
|
|
frac += fracstep;
|
|
} while (count--);
|
|
}
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= R_InitTranslationTables
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void R_InitTranslationTables (void)
|
|
{
|
|
int i;
|
|
|
|
translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
|
|
translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
|
|
|
|
//
|
|
// translate just the 16 green colors
|
|
//
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
if (i >= 0x70 && i<= 0x7f)
|
|
{ // green, gray, brown, red
|
|
translationtables[i] = 0x60 + (i&0xf);
|
|
translationtables [i+256] = 0x40 + (i&0xf);
|
|
translationtables [i+512] = 0x20 + (i&0xf);
|
|
}
|
|
else
|
|
translationtables[i] = translationtables[i+256]
|
|
= translationtables[i+512] = i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= R_DrawSpan
|
|
=
|
|
================
|
|
*/
|
|
|
|
int ds_y;
|
|
int ds_x1;
|
|
int ds_x2;
|
|
lighttable_t *ds_colormap;
|
|
fixed_t ds_xfrac;
|
|
fixed_t ds_yfrac;
|
|
fixed_t ds_xstep;
|
|
fixed_t ds_ystep;
|
|
byte *ds_source; // start of a 64*64 tile image
|
|
|
|
int dscount; // just for profiling
|
|
|
|
#if (!defined(USEASM) && !defined(__WATCOMC__) && !defined(__i386) && !defined(__m68k))
|
|
void R_DrawSpan (void)
|
|
{
|
|
fixed_t xfrac, yfrac;
|
|
byte *dest;
|
|
int count, spot;
|
|
|
|
#ifdef RANGECHECK
|
|
if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH
|
|
|| (unsigned)ds_y>SCREENHEIGHT)
|
|
I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y);
|
|
// dscount++;
|
|
#endif
|
|
|
|
xfrac = ds_xfrac;
|
|
yfrac = ds_yfrac;
|
|
|
|
dest = ylookup[ds_y] + columnofs[ds_x1];
|
|
count = ds_x2 - ds_x1;
|
|
do
|
|
{
|
|
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
|
*dest++ = ds_colormap[ds_source[spot]];
|
|
xfrac += ds_xstep;
|
|
yfrac += ds_ystep;
|
|
} while (count--);
|
|
}
|
|
|
|
#if 0
|
|
void R_DrawSpan (void)
|
|
{
|
|
unsigned position, step;
|
|
byte *source,*colormap,*dest;
|
|
unsigned count, spot;
|
|
unsigned value, temp;
|
|
unsigned xtemp, ytemp;
|
|
|
|
position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
|
|
step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
|
|
|
|
source = ds_source;
|
|
colormap = ds_colormap;
|
|
dest = ylookup[ds_y] + columnofs[ds_x1];
|
|
count = ds_x2 - ds_x1 + 1;
|
|
|
|
while (count >= 4)
|
|
{
|
|
ytemp = position>>4;
|
|
ytemp = ytemp & 4032;
|
|
xtemp = position>>26;
|
|
spot = xtemp | ytemp;
|
|
position += step;
|
|
dest[0] = colormap[source[spot]];
|
|
ytemp = position>>4;
|
|
ytemp = ytemp & 4032;
|
|
xtemp = position>>26;
|
|
spot = xtemp | ytemp;
|
|
position += step;
|
|
dest[1] = colormap[source[spot]];
|
|
ytemp = position>>4;
|
|
ytemp = ytemp & 4032;
|
|
xtemp = position>>26;
|
|
spot = xtemp | ytemp;
|
|
position += step;
|
|
dest[2] = colormap[source[spot]];
|
|
ytemp = position>>4;
|
|
ytemp = ytemp & 4032;
|
|
xtemp = position>>26;
|
|
spot = xtemp | ytemp;
|
|
position += step;
|
|
dest[3] = colormap[source[spot]];
|
|
|
|
count -= 4;
|
|
dest += 4;
|
|
}
|
|
while (count > 0)
|
|
{
|
|
ytemp = position>>4;
|
|
ytemp = ytemp & 4032;
|
|
xtemp = position>>26;
|
|
spot = xtemp | ytemp;
|
|
position += step;
|
|
*dest++ = colormap[source[spot]];
|
|
count--;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifndef __WATCOMC__
|
|
|
|
void R_DrawSpanLow (void)
|
|
{
|
|
fixed_t xfrac, yfrac;
|
|
byte *dest;
|
|
int count, spot;
|
|
|
|
#ifdef RANGECHECK
|
|
if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH
|
|
|| (unsigned)ds_y>SCREENHEIGHT)
|
|
I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y);
|
|
// dscount++;
|
|
#endif
|
|
|
|
xfrac = ds_xfrac;
|
|
yfrac = ds_yfrac;
|
|
|
|
dest = ylookup[ds_y] + columnofs[ds_x1];
|
|
count = ds_x2 - ds_x1;
|
|
do
|
|
{
|
|
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
|
*dest++ = ds_colormap[ds_source[spot]];
|
|
xfrac += ds_xstep;
|
|
yfrac += ds_ystep;
|
|
} while (count--);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
================
|
|
=
|
|
= R_InitBuffer
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void R_InitBuffer (int width, int height)
|
|
{
|
|
int i;
|
|
|
|
viewwindowx = (SCREENWIDTH-width) >> 1;
|
|
for (i=0 ; i<width ; i++)
|
|
columnofs[i] = viewwindowx + i;
|
|
if (width == SCREENWIDTH)
|
|
viewwindowy = 0;
|
|
else
|
|
viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
|
|
for (i=0 ; i<height ; i++)
|
|
ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= R_FillBackScreen
|
|
=
|
|
= Fills the back screen with a pattern for variable screen sizes
|
|
= Also draws a beveled edge
|
|
==================
|
|
*/
|
|
|
|
void R_FillBackScreen (void)
|
|
{
|
|
byte *src, *dest;
|
|
int x,y;
|
|
patch_t *patch;
|
|
char name1[] = "FLOOR7_2"; // DOOM
|
|
char name2[] = "GRNROCK"; // DOOM II
|
|
char *name;
|
|
|
|
if (scaledviewwidth == 320)
|
|
return;
|
|
|
|
if (commercial)
|
|
name = name2;
|
|
else
|
|
name = name1;
|
|
src = W_CacheLumpName (name, PU_CACHE);
|
|
dest = screens[1];
|
|
|
|
for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
|
|
{
|
|
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
|
{
|
|
memcpy (dest, src+((y&63)<<6), 64);
|
|
dest += 64;
|
|
}
|
|
if (SCREENWIDTH&63)
|
|
{
|
|
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
|
dest += (SCREENWIDTH&63);
|
|
}
|
|
}
|
|
|
|
patch = W_CacheLumpName ("brdr_t",PU_CACHE);
|
|
for (x=0 ; x<scaledviewwidth ; x+=8)
|
|
V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
|
|
patch = W_CacheLumpName ("brdr_b",PU_CACHE);
|
|
for (x=0 ; x<scaledviewwidth ; x+=8)
|
|
V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
|
|
patch = W_CacheLumpName ("brdr_l",PU_CACHE);
|
|
for (y=0 ; y<viewheight ; y+=8)
|
|
V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
|
|
patch = W_CacheLumpName ("brdr_r",PU_CACHE);
|
|
for (y=0 ; y<viewheight ; y+=8)
|
|
V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
|
|
V_DrawPatch (viewwindowx-8,viewwindowy-8,1
|
|
, W_CacheLumpName ("brdr_tl",PU_CACHE));
|
|
V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy-8,1
|
|
, W_CacheLumpName ("brdr_tr",PU_CACHE));
|
|
V_DrawPatch (viewwindowx-8,viewwindowy+viewheight,1
|
|
, W_CacheLumpName ("brdr_bl",PU_CACHE));
|
|
V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+viewheight,1
|
|
, W_CacheLumpName ("brdr_br",PU_CACHE));
|
|
|
|
|
|
#ifdef __WATCOMC__
|
|
{
|
|
// copy the screen into VGA page 4
|
|
int p;
|
|
|
|
src = screens[1];
|
|
dest = (byte *)0xac000;
|
|
|
|
for (p=0 ; p<4 ; p++, src++)
|
|
{
|
|
outp (SC_INDEX,SC_MAPMASK);
|
|
outp (SC_INDEX+1,1<<p);
|
|
for (x=0 ; x<SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT)/4 ; x++)
|
|
dest[x] = src[x<<2];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void R_VideoErase (unsigned ofs, int count)
|
|
{
|
|
#ifdef __WATCOMC__
|
|
int i;
|
|
byte *src, *dest;
|
|
|
|
// write through all planes
|
|
outp (SC_INDEX,SC_MAPMASK);
|
|
outp (SC_INDEX+1,15);
|
|
// set write mode 1
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
|
|
|
|
src = (byte *)0xac000 + (ofs>>2);
|
|
dest = destscreen + (ofs>>2);
|
|
for (i=(count>>2)-1 ; i>=0 ; i--)
|
|
dest[i] = src[i];
|
|
|
|
// set write mode 0
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
|
|
|
|
#else
|
|
memcpy (screens[0]+ofs, screens[1]+ofs, count);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= R_DrawViewBorder
|
|
=
|
|
= Draws the border around the view for different size windows
|
|
==================
|
|
*/
|
|
|
|
void V_MarkRect (int x, int y, int width, int height);
|
|
|
|
void R_DrawViewBorder (void)
|
|
{
|
|
int top, side, ofs, i;
|
|
|
|
if (scaledviewwidth == SCREENWIDTH)
|
|
return;
|
|
|
|
top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2;
|
|
side = (SCREENWIDTH-scaledviewwidth)/2;
|
|
|
|
// copy top and one line of left side
|
|
R_VideoErase (0, top*SCREENWIDTH+side);
|
|
|
|
// copy one line of right side and bottom
|
|
ofs = (viewheight+top)*SCREENWIDTH-side;
|
|
R_VideoErase (ofs, top*SCREENWIDTH+side);
|
|
|
|
// copy sides using wraparound
|
|
ofs = top*SCREENWIDTH + SCREENWIDTH-side;
|
|
side <<= 1;
|
|
for (i=1 ; i<viewheight ; i++)
|
|
{
|
|
R_VideoErase (ofs, side);
|
|
ofs += SCREENWIDTH;
|
|
}
|
|
|
|
#ifndef __WATCOMC__
|
|
V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
|
|
#endif
|
|
}
|
|
|
|
|