2006-03-28 15:44:01 +00:00
|
|
|
/* Emacs style mode select -*- C++ -*-
|
|
|
|
*-----------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* PrBoom a Doom port merged with LxDoom and LSDLDoom
|
|
|
|
* based on BOOM, a modified and improved DOOM engine
|
|
|
|
* Copyright (C) 1999 by
|
|
|
|
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
|
|
|
|
* Copyright (C) 1999-2000 by
|
|
|
|
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* DESCRIPTION:
|
|
|
|
* Gamma correction LUT stuff.
|
|
|
|
* Color range translation support
|
|
|
|
* Functions to draw patches (by post) directly to screen.
|
|
|
|
* Functions to blit a block to the screen.
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "r_main.h"
|
|
|
|
#include "r_draw.h"
|
|
|
|
#include "m_bbox.h"
|
|
|
|
#include "w_wad.h" /* needed for color translation lump lookup */
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "i_video.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "m_swap.h"
|
|
|
|
#include "rockmacros.h"
|
|
|
|
// Each screen is [SCREENWIDTH*SCREENHEIGHT];
|
2006-04-03 08:51:08 +00:00
|
|
|
byte *d_screens[6] IBSS_ATTR;
|
2006-03-28 15:44:01 +00:00
|
|
|
int dirtybox[4];
|
|
|
|
|
|
|
|
/* jff 4/24/98 initialize this at runtime */
|
|
|
|
const byte *colrngs[CR_LIMIT];
|
|
|
|
|
|
|
|
// Now where did these came from?
|
|
|
|
const byte gammatable[5][256] = // CPhipps - const
|
|
|
|
{
|
|
|
|
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
|
|
|
|
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
|
|
|
|
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
|
|
|
|
49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
|
|
|
|
65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
|
|
|
|
81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,
|
|
|
|
97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
|
|
|
|
113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
|
|
|
|
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
|
|
|
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
|
|
|
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
|
|
|
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
|
|
|
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
|
|
|
|
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
|
|
|
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
|
|
|
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255},
|
|
|
|
|
|
|
|
{2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23,24,25,26,27,29,30,31,
|
|
|
|
32,33,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,54,55,
|
|
|
|
56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,
|
|
|
|
78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,
|
|
|
|
99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
|
|
|
|
115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,129,
|
|
|
|
130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
|
|
|
|
146,147,148,148,149,150,151,152,153,154,155,156,157,158,159,160,
|
|
|
|
161,162,163,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
|
|
|
175,176,177,178,179,180,181,182,183,184,185,186,186,187,188,189,
|
|
|
|
190,191,192,193,194,195,196,196,197,198,199,200,201,202,203,204,
|
|
|
|
205,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,
|
|
|
|
219,220,221,222,222,223,224,225,226,227,228,229,230,230,231,232,
|
|
|
|
233,234,235,236,237,237,238,239,240,241,242,243,244,245,245,246,
|
|
|
|
247,248,249,250,251,252,252,253,254,255},
|
|
|
|
|
|
|
|
{4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32,33,35,36,38,39,40,42,
|
|
|
|
43,45,46,47,48,50,51,52,54,55,56,57,59,60,61,62,63,65,66,67,68,69,
|
|
|
|
70,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,
|
|
|
|
94,95,96,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,
|
|
|
|
113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
|
|
|
|
129,130,131,132,133,133,134,135,136,137,138,139,140,141,142,143,144,
|
|
|
|
144,145,146,147,148,149,150,151,152,153,153,154,155,156,157,158,159,
|
|
|
|
160,160,161,162,163,164,165,166,166,167,168,169,170,171,172,172,173,
|
|
|
|
174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,187,188,
|
|
|
|
188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,201,
|
|
|
|
202,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,
|
|
|
|
216,217,217,218,219,220,221,221,222,223,224,224,225,226,227,228,228,
|
|
|
|
229,230,231,231,232,233,234,235,235,236,237,238,238,239,240,241,241,
|
|
|
|
242,243,244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,
|
|
|
|
255},
|
|
|
|
|
|
|
|
{8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45,47,49,50,52,53,55,
|
|
|
|
57,58,60,61,63,64,65,67,68,70,71,72,74,75,76,77,79,80,81,82,84,85,
|
|
|
|
86,87,88,90,91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107,
|
|
|
|
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,
|
|
|
|
125,126,127,128,129,130,131,132,133,134,135,135,136,137,138,139,140,
|
|
|
|
141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,
|
|
|
|
155,156,157,158,159,160,160,161,162,163,164,165,165,166,167,168,169,
|
|
|
|
169,170,171,172,173,173,174,175,176,176,177,178,179,180,180,181,182,
|
|
|
|
183,183,184,185,186,186,187,188,189,189,190,191,192,192,193,194,195,
|
|
|
|
195,196,197,197,198,199,200,200,201,202,202,203,204,205,205,206,207,
|
|
|
|
207,208,209,210,210,211,212,212,213,214,214,215,216,216,217,218,219,
|
|
|
|
219,220,221,221,222,223,223,224,225,225,226,227,227,228,229,229,230,
|
|
|
|
231,231,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,
|
|
|
|
242,242,243,244,244,245,246,246,247,247,248,249,249,250,251,251,252,
|
|
|
|
253,253,254,254,255},
|
|
|
|
|
|
|
|
{16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64,66,68,69,71,73,75,76,
|
|
|
|
78,80,81,83,84,86,87,89,90,92,93,94,96,97,98,100,101,102,103,105,106,
|
|
|
|
107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,
|
|
|
|
125,126,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
|
|
|
|
142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,
|
|
|
|
156,157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169,
|
|
|
|
169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180,181,
|
|
|
|
182,182,183,184,184,185,186,187,187,188,189,189,190,191,191,192,193,
|
|
|
|
193,194,195,195,196,196,197,198,198,199,200,200,201,202,202,203,203,
|
|
|
|
204,205,205,206,207,207,208,208,209,210,210,211,211,212,213,213,214,
|
|
|
|
214,215,216,216,217,217,218,219,219,220,220,221,221,222,223,223,224,
|
|
|
|
224,225,225,226,227,227,228,228,229,229,230,230,231,232,232,233,233,
|
|
|
|
234,234,235,235,236,236,237,237,238,239,239,240,240,241,241,242,242,
|
|
|
|
243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,
|
|
|
|
251,252,252,253,254,254,255,255}
|
|
|
|
};
|
|
|
|
|
|
|
|
int usegamma;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* V_InitColorTranslation
|
|
|
|
*
|
|
|
|
* Loads the color translation tables from predefined lumps at game start
|
|
|
|
* No return
|
|
|
|
*
|
|
|
|
* Used for translating text colors from the red palette range
|
|
|
|
* to other colors. The first nine entries can be used to dynamically
|
|
|
|
* switch the output of text color thru the HUlib_drawText routine
|
|
|
|
* by embedding ESCn in the text to obtain color n. Symbols for n are
|
|
|
|
* provided in v_video.h.
|
|
|
|
*
|
|
|
|
* cphipps - constness of crdef_t stuff fixed
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
const byte **map;
|
|
|
|
} crdef_t;
|
|
|
|
|
|
|
|
// killough 5/2/98: table-driven approach
|
|
|
|
static const crdef_t crdefs[] = {
|
|
|
|
{"CRBRICK", &colrngs[CR_BRICK ]},
|
|
|
|
{"CRTAN", &colrngs[CR_TAN ]},
|
|
|
|
{"CRGRAY", &colrngs[CR_GRAY ]},
|
|
|
|
{"CRGREEN", &colrngs[CR_GREEN ]},
|
|
|
|
{"CRBROWN", &colrngs[CR_BROWN ]},
|
|
|
|
{"CRGOLD", &colrngs[CR_GOLD ]},
|
|
|
|
{"CRRED", &colrngs[CR_RED ]},
|
|
|
|
{"CRBLUE", &colrngs[CR_BLUE ]},
|
|
|
|
{"CRORANGE", &colrngs[CR_ORANGE]},
|
|
|
|
{"CRYELLOW", &colrngs[CR_YELLOW]},
|
|
|
|
{"CRBLUE2", &colrngs[CR_BLUE2]},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
// killough 5/2/98: tiny engine driven by table above
|
|
|
|
void V_InitColorTranslation(void)
|
|
|
|
{
|
|
|
|
register const crdef_t *p;
|
|
|
|
for (p=crdefs; p->name; p++)
|
|
|
|
*p->map = W_CacheLumpName(p->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_MarkRect
|
|
|
|
//
|
|
|
|
// Marks a rectangular portion of the screen specified by
|
|
|
|
// upper left origin and height and width dirty to minimize
|
|
|
|
// the amount of screen update necessary. No return.
|
|
|
|
//
|
|
|
|
void V_MarkRect(int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
M_AddToBox(dirtybox, x, y);
|
|
|
|
M_AddToBox(dirtybox, x+width-1, y+height-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_CopyRect
|
|
|
|
//
|
|
|
|
// Copies a source rectangle in a screen buffer to a destination
|
|
|
|
// rectangle in another screen buffer. Source origin in srcx,srcy,
|
|
|
|
// destination origin in destx,desty, common size in width and height.
|
|
|
|
// Source buffer specfified by srcscrn, destination buffer by destscrn.
|
|
|
|
//
|
|
|
|
// Marks the destination rectangle on the screen dirty.
|
|
|
|
//
|
|
|
|
// No return.
|
|
|
|
//
|
|
|
|
void V_CopyRect(int srcx, int srcy, int srcscrn, int width,
|
|
|
|
int height, int destx, int desty, int destscrn,
|
|
|
|
enum patch_translation_e flags)
|
|
|
|
{
|
|
|
|
byte *src;
|
|
|
|
byte *dest;
|
|
|
|
|
|
|
|
if (flags & VPT_STRETCH)
|
|
|
|
{
|
|
|
|
srcx=srcx*SCREENWIDTH/320;
|
|
|
|
srcy=srcy*SCREENHEIGHT/200;
|
|
|
|
width=width*SCREENWIDTH/320;
|
|
|
|
height=height*SCREENHEIGHT/200;
|
|
|
|
destx=destx*SCREENWIDTH/320;
|
|
|
|
desty=desty*SCREENHEIGHT/200;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (srcx<0
|
|
|
|
||srcx+width >SCREENWIDTH
|
|
|
|
|| srcy<0
|
|
|
|
|| srcy+height>SCREENHEIGHT
|
|
|
|
||destx<0||destx+width >SCREENWIDTH
|
|
|
|
|| desty<0
|
|
|
|
|| desty+height>SCREENHEIGHT)
|
|
|
|
I_Error ("V_CopyRect: Bad arguments");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
V_MarkRect (destx, desty, width, height);
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
src = d_screens[srcscrn]+SCREENWIDTH*srcy+srcx;
|
|
|
|
dest = d_screens[destscrn]+SCREENWIDTH*desty+destx;
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
for ( ; height>0 ; height--)
|
|
|
|
{
|
|
|
|
memcpy (dest, src, width);
|
|
|
|
src += SCREENWIDTH;
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DrawBlock
|
|
|
|
//
|
|
|
|
// Draw a linear block of pixels into the view buffer.
|
|
|
|
//
|
|
|
|
// The bytes at src are copied in linear order to the screen rectangle
|
|
|
|
// at x,y in screenbuffer scrn, with size width by height.
|
|
|
|
//
|
|
|
|
// The destination rectangle is marked dirty.
|
|
|
|
//
|
|
|
|
// No return.
|
|
|
|
//
|
|
|
|
// CPhipps - modified to take the patch translation flags. For now, only stretching is
|
|
|
|
// implemented, to support highres in the menus
|
|
|
|
//
|
|
|
|
void V_DrawBlock(int x, int y, int scrn, int width, int height,
|
|
|
|
const byte *src, enum patch_translation_e flags)
|
|
|
|
{
|
|
|
|
byte *dest;
|
|
|
|
|
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (x<0
|
|
|
|
||x+width >((flags & VPT_STRETCH) ? 320 : SCREENWIDTH)
|
|
|
|
|| y<0
|
|
|
|
|| y+height>((flags & VPT_STRETCH) ? 200 : SCREENHEIGHT))
|
|
|
|
I_Error ("V_DrawBlock: Bad V_DrawBlock");
|
|
|
|
|
|
|
|
if (flags & (VPT_TRANS | VPT_FLIP))
|
|
|
|
I_Error("V_DrawBlock: Unsupported flags (%u)", flags);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (flags & VPT_STRETCH) {
|
|
|
|
byte *dest;
|
|
|
|
int s_width;
|
|
|
|
fixed_t dx = (320 << FRACBITS) / SCREENWIDTH;
|
|
|
|
|
|
|
|
x = (x * SCREENWIDTH) / 320; y = (y * SCREENHEIGHT) / 200;
|
|
|
|
s_width = (width * SCREENWIDTH) / 320; height = (height * SCREENHEIGHT) / 200;
|
|
|
|
|
|
|
|
if (!scrn)
|
|
|
|
V_MarkRect (x, y, width, height);
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
dest = d_screens[scrn] + y*SCREENWIDTH+x;
|
2006-03-28 15:44:01 +00:00
|
|
|
// x & y no longer needed
|
|
|
|
|
|
|
|
while (height--) {
|
|
|
|
const byte *const src_row = src + width * ((height * 200) / SCREENHEIGHT);
|
|
|
|
byte *const dst_row = dest + SCREENWIDTH * height;
|
|
|
|
fixed_t tx;
|
|
|
|
|
|
|
|
for (x=0, tx=0; x<s_width; x++, tx+=dx)
|
|
|
|
dst_row[x] = src_row[tx >> FRACBITS];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
V_MarkRect (x, y, width, height);
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
dest = d_screens[scrn] + y*SCREENWIDTH+x;
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
while (height--) {
|
|
|
|
memcpy (dest, src, width);
|
|
|
|
src += width;
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* V_DrawBackground tiles a 64x64 patch over the entire screen, providing the
|
|
|
|
* background for the Help and Setup screens, and plot text betwen levels.
|
|
|
|
* cphipps - used to have M_DrawBackground, but that was used the framebuffer
|
|
|
|
* directly, so this is my code from the equivalent function in f_finale.c
|
|
|
|
*/
|
|
|
|
void V_DrawBackground(const char* flatname, int scrn)
|
|
|
|
{
|
|
|
|
/* erase the entire screen to a tiled background */
|
|
|
|
const byte *src;
|
|
|
|
int x,y;
|
|
|
|
int lump;
|
|
|
|
|
|
|
|
// killough 4/17/98:
|
|
|
|
src = W_CacheLumpNum(lump = firstflat + R_FlatNumForName(flatname));
|
|
|
|
|
|
|
|
V_DrawBlock(0, 0, scrn, 64, 64, src, 0);
|
|
|
|
|
|
|
|
for (y=0 ; y<SCREENHEIGHT ; y+=64)
|
|
|
|
for (x=y ? 0 : 64; x<SCREENWIDTH ; x+=64)
|
|
|
|
V_CopyRect(0, 0, scrn, ((SCREENWIDTH-x) < 64) ? (SCREENWIDTH-x) : 64,
|
|
|
|
((SCREENHEIGHT-y) < 64) ? (SCREENHEIGHT-y) : 64, x, y, scrn, VPT_NONE);
|
|
|
|
W_UnlockLumpNum(lump);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_GetBlock
|
|
|
|
//
|
|
|
|
// Gets a linear block of pixels from the view buffer.
|
|
|
|
//
|
|
|
|
// The pixels in the rectangle at x,y in screenbuffer scrn with size
|
|
|
|
// width by height are linearly packed into the buffer dest.
|
|
|
|
// No return
|
|
|
|
//
|
|
|
|
|
|
|
|
void V_GetBlock(int x, int y, int scrn, int width, int height, byte *dest)
|
|
|
|
{
|
|
|
|
byte *src;
|
|
|
|
|
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (x<0
|
|
|
|
||x+width >SCREENWIDTH
|
|
|
|
|| y<0
|
|
|
|
|| y+height>SCREENHEIGHT)
|
|
|
|
I_Error ("V_GetBlock: Bad arguments");
|
|
|
|
#endif
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
src = d_screens[scrn] + y*SCREENWIDTH+x;
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
while (height--)
|
|
|
|
{
|
|
|
|
memcpy (dest, src, width);
|
|
|
|
src += SCREENWIDTH;
|
|
|
|
dest += width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_Init
|
|
|
|
//
|
|
|
|
// Allocates the 4 full screen buffers in low DOS memory
|
|
|
|
// No return
|
|
|
|
//
|
|
|
|
|
|
|
|
void V_Init (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// CPhipps - allocate only 2 screens all the time, the rest can be allocated as and when needed
|
|
|
|
#define PREALLOCED_SCREENS 2
|
|
|
|
|
|
|
|
// CPhipps - no point in "stick these in low dos memory on PCs" anymore
|
2006-04-03 08:51:08 +00:00
|
|
|
// Allocate the screens individually, so I_InitGraphics can release d_screens[0]
|
2006-03-28 15:44:01 +00:00
|
|
|
// if e.g. it wants a MitSHM buffer instead
|
|
|
|
|
|
|
|
for (i=0 ; i<PREALLOCED_SCREENS ; i++)
|
2006-04-03 08:51:08 +00:00
|
|
|
d_screens[i] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
|
2006-03-28 15:44:01 +00:00
|
|
|
for (; i<4; i++) // Clear the rest (paranoia)
|
2006-04-03 08:51:08 +00:00
|
|
|
d_screens[i] = NULL;
|
2006-03-28 15:44:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DrawMemPatch
|
|
|
|
//
|
|
|
|
// CPhipps - unifying patch drawing routine, handles all cases and combinations
|
|
|
|
// of stretching, flipping and translating
|
|
|
|
//
|
|
|
|
// This function is big, hopefully not too big that gcc can't optimise it well.
|
|
|
|
// In fact it packs pretty well, there is no big performance lose for all this merging;
|
|
|
|
// the inner loops themselves are just the same as they always were
|
|
|
|
// (indeed, laziness of the people who wrote the 'clones' of the original V_DrawPatch
|
|
|
|
// means that their inner loops weren't so well optimised, so merging code may even speed them).
|
|
|
|
//
|
|
|
|
void V_DrawMemPatch(int x, int y, int scrn, const patch_t *patch,
|
|
|
|
int cm, enum patch_translation_e flags)
|
|
|
|
{
|
|
|
|
const byte *trans;
|
|
|
|
|
|
|
|
if (cm<CR_LIMIT)
|
|
|
|
trans=colrngs[cm];
|
|
|
|
else
|
|
|
|
trans=translationtables + 256*((cm-CR_LIMIT)-1);
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
|
2006-04-02 01:52:44 +00:00
|
|
|
// // CPhipps - auto-no-stretch if not high-res
|
|
|
|
// if (flags & VPT_STRETCH)
|
|
|
|
// if ((SCREENWIDTH==320) && (SCREENHEIGHT==200))
|
|
|
|
// flags &= ~VPT_STRETCH;
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
// CPhipps - null translation pointer => no translation
|
|
|
|
if (!trans)
|
|
|
|
flags &= ~VPT_TRANS;
|
|
|
|
|
2006-04-06 21:31:49 +00:00
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (x<0
|
|
|
|
||x+SHORT(patch->width) > ((flags & VPT_STRETCH) ? 320 : SCREENWIDTH)
|
|
|
|
|| y<0
|
|
|
|
|| y+SHORT(patch->height) > ((flags & VPT_STRETCH) ? 200 : SCREENHEIGHT))
|
|
|
|
// killough 1/19/98: improved error message:
|
|
|
|
I_Error("V_DrawMemPatch: Patch (%d,%d)-(%d,%d) exceeds LFB Bad V_DrawMemPatch (flags=%u)",
|
|
|
|
x, y, x+SHORT(patch->width), y+SHORT(patch->height), flags);
|
|
|
|
#endif
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
if (!(flags & VPT_STRETCH)) {
|
|
|
|
unsigned int col;
|
|
|
|
const column_t *column;
|
2006-04-03 08:51:08 +00:00
|
|
|
byte *desttop = d_screens[scrn]+y*SCREENWIDTH+x;
|
2006-03-28 15:44:01 +00:00
|
|
|
unsigned int w = SHORT(patch->width);
|
|
|
|
|
|
|
|
if (!scrn)
|
|
|
|
V_MarkRect (x, y, w, SHORT(patch->height));
|
|
|
|
|
|
|
|
w--; // CPhipps - note: w = width-1 now, speeds up flipping
|
|
|
|
|
|
|
|
for (col=0 ; (unsigned int)col<=w ; desttop++, col++) {
|
|
|
|
column = (column_t *)((byte *)patch +
|
|
|
|
LONG(patch->columnofs[(flags & VPT_FLIP) ? w-col : col]));
|
|
|
|
|
|
|
|
// step through the posts in a column
|
|
|
|
while (column->topdelta != 0xff ) {
|
|
|
|
// killough 2/21/98: Unrolled and performance-tuned
|
|
|
|
|
|
|
|
register const byte *source = (byte *)column + 3;
|
|
|
|
register byte *dest = desttop + column->topdelta*SCREENWIDTH;
|
|
|
|
register int count = column->length;
|
|
|
|
|
|
|
|
if (!(flags & VPT_TRANS)) {
|
|
|
|
if ((count-=4)>=0)
|
|
|
|
do {
|
|
|
|
register byte s0,s1;
|
|
|
|
s0 = source[0];
|
|
|
|
s1 = source[1];
|
|
|
|
dest[0] = s0;
|
|
|
|
dest[SCREENWIDTH] = s1;
|
|
|
|
dest += SCREENWIDTH*2;
|
|
|
|
s0 = source[2];
|
|
|
|
s1 = source[3];
|
|
|
|
source += 4;
|
|
|
|
dest[0] = s0;
|
|
|
|
dest[SCREENWIDTH] = s1;
|
|
|
|
dest += SCREENWIDTH*2;
|
|
|
|
} while ((count-=4)>=0);
|
|
|
|
if (count+=4)
|
|
|
|
do {
|
|
|
|
*dest = *source++;
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
} while (--count);
|
|
|
|
column = (column_t *)(source+1); //killough 2/21/98 even faster
|
|
|
|
} else {
|
|
|
|
// CPhipps - merged translation code here
|
|
|
|
if ((count-=4)>=0)
|
|
|
|
do {
|
|
|
|
register byte s0,s1;
|
|
|
|
s0 = source[0];
|
|
|
|
s1 = source[1];
|
|
|
|
s0 = trans[s0];
|
|
|
|
s1 = trans[s1];
|
|
|
|
dest[0] = s0;
|
|
|
|
dest[SCREENWIDTH] = s1;
|
|
|
|
dest += SCREENWIDTH*2;
|
|
|
|
s0 = source[2];
|
|
|
|
s1 = source[3];
|
|
|
|
s0 = trans[s0];
|
|
|
|
s1 = trans[s1];
|
|
|
|
source += 4;
|
|
|
|
dest[0] = s0;
|
|
|
|
dest[SCREENWIDTH] = s1;
|
|
|
|
dest += SCREENWIDTH*2;
|
|
|
|
} while ((count-=4)>=0);
|
|
|
|
if (count+=4)
|
|
|
|
do {
|
|
|
|
*dest = trans[*source++];
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
} while (--count);
|
|
|
|
column = (column_t *)(source+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// CPhipps - move stretched patch drawing code here
|
|
|
|
// - reformat initialisers, move variables into inner blocks
|
|
|
|
|
|
|
|
byte *desttop;
|
|
|
|
int col;
|
2006-04-05 06:37:37 +00:00
|
|
|
int w = (SHORT( patch->width ) << 16) -1; // CPhipps - -1 for faster flipping
|
2006-03-28 15:44:01 +00:00
|
|
|
int stretchx, stretchy;
|
|
|
|
int DX = (SCREENWIDTH<<16) / 320;
|
|
|
|
int DXI = (320<<16) / SCREENWIDTH;
|
|
|
|
int DY = (SCREENHEIGHT<<16) / 200;
|
|
|
|
register int DYI = (200<<16) / SCREENHEIGHT;
|
|
|
|
int DY2, DYI2;
|
|
|
|
|
|
|
|
stretchx = ( x * DX ) >> 16;
|
|
|
|
stretchy = ( y * DY ) >> 16;
|
|
|
|
DY2 = DY / 2;
|
|
|
|
DYI2 = DYI* 2;
|
|
|
|
|
|
|
|
if (!scrn)
|
|
|
|
V_MarkRect ( stretchx, stretchy, (SHORT( patch->width ) * DX ) >> 16,
|
|
|
|
(SHORT( patch->height) * DY ) >> 16 );
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
desttop = d_screens[scrn] + stretchy * SCREENWIDTH + stretchx;
|
2006-03-28 15:44:01 +00:00
|
|
|
|
2006-04-06 21:31:49 +00:00
|
|
|
// Clamp down the screenwidth
|
|
|
|
if(w>>16>=319)
|
|
|
|
w=(SCREENWIDTH-1)*DXI;
|
|
|
|
|
2006-03-28 15:44:01 +00:00
|
|
|
for ( col = 0; col <= w; x++, col+=DXI, desttop++ ) {
|
|
|
|
const column_t *column;
|
|
|
|
{
|
|
|
|
unsigned int d = patch->columnofs[(flags & VPT_FLIP) ? ((w - col)>>16): (col>>16)];
|
|
|
|
column = (column_t*)((byte*)patch + LONG(d));
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( column->topdelta != 0xff ) {
|
|
|
|
register const byte *source = ( byte* ) column + 3;
|
|
|
|
register byte *dest = desttop + (( column->topdelta * DY ) >> 16 ) * SCREENWIDTH;
|
|
|
|
register int count = ( column->length * DY ) >> 16;
|
|
|
|
register int srccol = 0x8000;
|
|
|
|
|
2006-04-05 06:37:37 +00:00
|
|
|
count = (count>SCREENHEIGHT)?SCREENHEIGHT:count; // Bounds checking allows those messed up
|
|
|
|
// GP32 mods to work (they're using patch->
|
|
|
|
// height values of 240, this code cuts off
|
|
|
|
// thier bottom few pixels
|
|
|
|
|
2006-03-28 15:44:01 +00:00
|
|
|
if (flags & VPT_TRANS)
|
|
|
|
while (count--) {
|
|
|
|
*dest = trans[source[srccol>>16]];
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
srccol+= DYI;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
while (count--) {
|
|
|
|
*dest = source[srccol>>16];
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
srccol+= DYI;
|
|
|
|
}
|
|
|
|
column = ( column_t* ) (( byte* ) column + ( column->length ) + 4 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CPhipps - some simple, useful wrappers for that function, for drawing patches from wads
|
|
|
|
|
|
|
|
// CPhipps - GNU C only suppresses generating a copy of a function if it is
|
|
|
|
// static inline; other compilers have different behaviour.
|
|
|
|
// This inline is _only_ for the function below
|
|
|
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
inline
|
|
|
|
#endif
|
|
|
|
void V_DrawNumPatch(int x, int y, int scrn, int lump,
|
|
|
|
int cm, enum patch_translation_e flags)
|
|
|
|
{
|
|
|
|
V_DrawMemPatch(x, y, scrn, (const patch_t*)W_CacheLumpNum(lump),
|
|
|
|
cm, flags);
|
|
|
|
W_UnlockLumpNum(lump);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* cph -
|
|
|
|
* V_NamePatchWidth - returns width of a patch.
|
|
|
|
* V_NamePatchHeight- returns height of a patch.
|
|
|
|
*
|
|
|
|
* Doesn't really belong here, but is often used in conjunction with
|
|
|
|
* this code.
|
|
|
|
* This is needed to reduce the number of patches being held locked
|
|
|
|
* in memory, since a lot of code was locking and holding pointers
|
|
|
|
* to graphics in order to get this info easily. Also, we do endian
|
|
|
|
* correction here, which reduces the chance of other code forgetting
|
|
|
|
* this.
|
|
|
|
*/
|
|
|
|
int V_NamePatchWidth(const char* name)
|
|
|
|
{
|
|
|
|
int lump = W_GetNumForName(name);
|
|
|
|
int w;
|
|
|
|
|
|
|
|
w = SHORT(((const patch_t*)W_CacheLumpNum(lump))->width);
|
|
|
|
W_UnlockLumpNum(lump);
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
int V_NamePatchHeight(const char* name)
|
|
|
|
{
|
|
|
|
int lump = W_GetNumForName(name);
|
|
|
|
int w;
|
|
|
|
|
|
|
|
w = SHORT(((const patch_t*)W_CacheLumpNum(lump))->height);
|
|
|
|
W_UnlockLumpNum(lump);
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CPhipps -
|
|
|
|
// V_PatchToBlock
|
|
|
|
//
|
|
|
|
// Returns a simple bitmap which contains the patch. See-through parts of the
|
|
|
|
// patch will be undefined (in fact black for now)
|
|
|
|
|
|
|
|
byte *V_PatchToBlock(const char* name, int cm,
|
|
|
|
enum patch_translation_e flags,
|
|
|
|
unsigned short* width, unsigned short* height)
|
|
|
|
{
|
2006-04-03 08:51:08 +00:00
|
|
|
byte *oldscr = d_screens[1];
|
2006-03-28 15:44:01 +00:00
|
|
|
byte *block;
|
|
|
|
const patch_t *patch;
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
d_screens[1] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
patch = W_CacheLumpName(name);
|
2006-04-06 21:31:49 +00:00
|
|
|
// One of those odd things that don't seem to have a purpose other then rangechecking
|
|
|
|
// On screens smaller than 320X200 this line causes problems.
|
|
|
|
// V_DrawMemPatch(SHORT(patch->leftoffset), SHORT(patch->topoffset),
|
|
|
|
// 1, patch, cm, flags);
|
2006-03-28 15:44:01 +00:00
|
|
|
|
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (flags & VPT_STRETCH)
|
|
|
|
I_Error("V_PatchToBlock: Stretching not supported");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*width = SHORT(patch->width); *height = SHORT(patch->height);
|
|
|
|
|
|
|
|
W_UnlockLumpName(name);
|
|
|
|
|
|
|
|
V_GetBlock(0, 0, 1, *width, *height,
|
|
|
|
block = malloc((long)(*width) * (*height)));
|
|
|
|
|
2006-04-03 08:51:08 +00:00
|
|
|
free(d_screens[1]);
|
|
|
|
d_screens[1] = oldscr;
|
2006-03-28 15:44:01 +00:00
|
|
|
return block;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_SetPalette
|
|
|
|
//
|
|
|
|
// CPhipps - New function to set the palette to palette number pal.
|
|
|
|
// Handles loading of PLAYPAL and calls I_SetPalette
|
|
|
|
|
|
|
|
void V_SetPalette(int pal)
|
|
|
|
{
|
|
|
|
I_SetPalette(pal);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_FillRect
|
|
|
|
//
|
|
|
|
// CPhipps - New function to fill a rectangle with a given colour
|
|
|
|
void V_FillRect(int scrn, int x, int y, int width, int height, byte colour)
|
|
|
|
{
|
2006-04-03 08:51:08 +00:00
|
|
|
byte* dest = d_screens[scrn] + x + y*SCREENWIDTH;
|
2006-03-28 15:44:01 +00:00
|
|
|
while (height--) {
|
|
|
|
memset(dest, colour, width);
|
|
|
|
dest += SCREENWIDTH;
|
|
|
|
}
|
|
|
|
}
|