mirror of https://gitlab.com/nakst/essence
824 lines
18 KiB
C
824 lines
18 KiB
C
//
|
|
// Copyright(C) 1993-1996 Id Software, Inc.
|
|
// Copyright(C) 1993-2008 Raven Software
|
|
// Copyright(C) 2005-2014 Simon Howard
|
|
//
|
|
// 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.
|
|
//
|
|
// DESCRIPTION:
|
|
// Gamma correction LUT stuff.
|
|
// Functions to draw patches (by post) directly to screen.
|
|
// Functions to blit a block to the screen.
|
|
//
|
|
|
|
#include "essence/include.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "i_swap.h"
|
|
#include "i_video.h"
|
|
#include "m_bbox.h"
|
|
#include "m_misc.h"
|
|
#include "v_video.h"
|
|
#include "w_wad.h"
|
|
#include "z_zone.h"
|
|
|
|
// TODO: There are separate RANGECHECK defines for different games, but this
|
|
// is common code. Fix this.
|
|
#define RANGECHECK
|
|
|
|
// Blending table used for fuzzpatch, etc.
|
|
// Only used in Heretic/Hexen
|
|
|
|
byte *tinttable = NULL;
|
|
|
|
// villsa [STRIFE] Blending table used for Strife
|
|
byte *xlatab = NULL;
|
|
|
|
// The screen buffer that the v_video.c code draws to.
|
|
|
|
static byte *dest_screen = NULL;
|
|
|
|
int dirtybox[4];
|
|
|
|
// haleyjd 08/28/10: clipping callback function for patches.
|
|
// This is needed for Chocolate Strife, which clips patches to the screen.
|
|
static vpatchclipfunc_t patchclip_callback = NULL;
|
|
|
|
//
|
|
// V_MarkRect
|
|
//
|
|
void V_MarkRect(int x, int y, int width, int height)
|
|
{
|
|
// If we are temporarily using an alternate screen, do not
|
|
// affect the update box.
|
|
|
|
if (dest_screen == I_VideoBuffer)
|
|
{
|
|
M_AddToBox (dirtybox, x, y);
|
|
M_AddToBox (dirtybox, x + width-1, y + height-1);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// V_CopyRect
|
|
//
|
|
void V_CopyRect(int srcx, int srcy, byte *source,
|
|
int width, int height,
|
|
int destx, int desty)
|
|
{
|
|
byte *src;
|
|
byte *dest;
|
|
|
|
#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 ("Bad V_CopyRect");
|
|
}
|
|
#endif
|
|
|
|
V_MarkRect(destx, desty, width, height);
|
|
|
|
src = source + SCREENWIDTH * srcy + srcx;
|
|
dest = dest_screen + SCREENWIDTH * desty + destx;
|
|
|
|
for ( ; height>0 ; height--)
|
|
{
|
|
ES_memcpy(dest, src, width);
|
|
src += SCREENWIDTH;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
//
|
|
// V_SetPatchClipCallback
|
|
//
|
|
// haleyjd 08/28/10: Added for Strife support.
|
|
// By calling this function, you can setup runtime error checking for patch
|
|
// clipping. Strife never caused errors by drawing patches partway off-screen.
|
|
// Some versions of vanilla DOOM also behaved differently than the default
|
|
// implementation, so this could possibly be extended to those as well for
|
|
// accurate emulation.
|
|
//
|
|
void V_SetPatchClipCallback(vpatchclipfunc_t func)
|
|
{
|
|
patchclip_callback = func;
|
|
}
|
|
|
|
//
|
|
// V_DrawPatch
|
|
// Masks a column based masked pic to the screen.
|
|
//
|
|
|
|
void V_DrawPatch(int x, int y, patch_t *patch)
|
|
{
|
|
int count;
|
|
int col;
|
|
column_t *column;
|
|
byte *desttop;
|
|
byte *dest;
|
|
byte *source;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
// haleyjd 08/28/10: Strife needs silent error checking here.
|
|
if(patchclip_callback)
|
|
{
|
|
if(!patchclip_callback(patch, x, y))
|
|
return;
|
|
}
|
|
|
|
#ifdef RANGECHECK
|
|
if (x < 0
|
|
|| x + SHORT(patch->width) > SCREENWIDTH
|
|
|| y < 0
|
|
|| y + SHORT(patch->height) > SCREENHEIGHT)
|
|
{
|
|
I_Error("Bad V_DrawPatch x=%i y=%i patch.width=%i patch.height=%i topoffset=%i leftoffset=%i", x, y, patch->width, patch->height, patch->topoffset, patch->leftoffset);
|
|
}
|
|
#endif
|
|
|
|
V_MarkRect(x, y, SHORT(patch->width), SHORT(patch->height));
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
w = SHORT(patch->width);
|
|
|
|
for ( ; col<w ; x++, col++, desttop++)
|
|
{
|
|
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
|
|
|
|
// step through the posts in a column
|
|
while (column->topdelta != 0xff)
|
|
{
|
|
source = (byte *)column + 3;
|
|
dest = desttop + column->topdelta*SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while (count--)
|
|
{
|
|
*dest = *source++;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
column = (column_t *)((byte *)column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// V_DrawPatchFlipped
|
|
// Masks a column based masked pic to the screen.
|
|
// Flips horizontally, e.g. to mirror face.
|
|
//
|
|
|
|
void V_DrawPatchFlipped(int x, int y, patch_t *patch)
|
|
{
|
|
int count;
|
|
int col;
|
|
column_t *column;
|
|
byte *desttop;
|
|
byte *dest;
|
|
byte *source;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
// haleyjd 08/28/10: Strife needs silent error checking here.
|
|
if(patchclip_callback)
|
|
{
|
|
if(!patchclip_callback(patch, x, y))
|
|
return;
|
|
}
|
|
|
|
#ifdef RANGECHECK
|
|
if (x < 0
|
|
|| x + SHORT(patch->width) > SCREENWIDTH
|
|
|| y < 0
|
|
|| y + SHORT(patch->height) > SCREENHEIGHT)
|
|
{
|
|
I_Error("Bad V_DrawPatchFlipped");
|
|
}
|
|
#endif
|
|
|
|
V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height));
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
w = SHORT(patch->width);
|
|
|
|
for ( ; col<w ; x++, col++, desttop++)
|
|
{
|
|
column = (column_t *)((byte *)patch + LONG(patch->columnofs[w-1-col]));
|
|
|
|
// step through the posts in a column
|
|
while (column->topdelta != 0xff )
|
|
{
|
|
source = (byte *)column + 3;
|
|
dest = desttop + column->topdelta*SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while (count--)
|
|
{
|
|
*dest = *source++;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
column = (column_t *)((byte *)column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// V_DrawPatchDirect
|
|
// Draws directly to the screen on the pc.
|
|
//
|
|
|
|
void V_DrawPatchDirect(int x, int y, patch_t *patch)
|
|
{
|
|
V_DrawPatch(x, y, patch);
|
|
}
|
|
|
|
//
|
|
// V_DrawTLPatch
|
|
//
|
|
// Masks a column based translucent masked pic to the screen.
|
|
//
|
|
|
|
void V_DrawTLPatch(int x, int y, patch_t * patch)
|
|
{
|
|
int count, col;
|
|
column_t *column;
|
|
byte *desttop, *dest, *source;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
if (x < 0
|
|
|| x + SHORT(patch->width) > SCREENWIDTH
|
|
|| y < 0
|
|
|| y + SHORT(patch->height) > SCREENHEIGHT)
|
|
{
|
|
I_Error("Bad V_DrawTLPatch");
|
|
}
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
w = SHORT(patch->width);
|
|
for (; col < w; x++, col++, desttop++)
|
|
{
|
|
column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col]));
|
|
|
|
// step through the posts in a column
|
|
|
|
while (column->topdelta != 0xff)
|
|
{
|
|
source = (byte *) column + 3;
|
|
dest = desttop + column->topdelta * SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while (count--)
|
|
{
|
|
*dest = tinttable[((*dest) << 8) + *source++];
|
|
dest += SCREENWIDTH;
|
|
}
|
|
column = (column_t *) ((byte *) column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// V_DrawXlaPatch
|
|
//
|
|
// villsa [STRIFE] Masks a column based translucent masked pic to the screen.
|
|
//
|
|
|
|
void V_DrawXlaPatch(int x, int y, patch_t * patch)
|
|
{
|
|
int count, col;
|
|
column_t *column;
|
|
byte *desttop, *dest, *source;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
if(patchclip_callback)
|
|
{
|
|
if(!patchclip_callback(patch, x, y))
|
|
return;
|
|
}
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
w = SHORT(patch->width);
|
|
for(; col < w; x++, col++, desttop++)
|
|
{
|
|
column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col]));
|
|
|
|
// step through the posts in a column
|
|
|
|
while(column->topdelta != 0xff)
|
|
{
|
|
source = (byte *) column + 3;
|
|
dest = desttop + column->topdelta * SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while(count--)
|
|
{
|
|
*dest = xlatab[*dest + ((*source) << 8)];
|
|
source++;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
column = (column_t *) ((byte *) column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// V_DrawAltTLPatch
|
|
//
|
|
// Masks a column based translucent masked pic to the screen.
|
|
//
|
|
|
|
void V_DrawAltTLPatch(int x, int y, patch_t * patch)
|
|
{
|
|
int count, col;
|
|
column_t *column;
|
|
byte *desttop, *dest, *source;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
if (x < 0
|
|
|| x + SHORT(patch->width) > SCREENWIDTH
|
|
|| y < 0
|
|
|| y + SHORT(patch->height) > SCREENHEIGHT)
|
|
{
|
|
I_Error("Bad V_DrawAltTLPatch");
|
|
}
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
w = SHORT(patch->width);
|
|
for (; col < w; x++, col++, desttop++)
|
|
{
|
|
column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col]));
|
|
|
|
// step through the posts in a column
|
|
|
|
while (column->topdelta != 0xff)
|
|
{
|
|
source = (byte *) column + 3;
|
|
dest = desttop + column->topdelta * SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while (count--)
|
|
{
|
|
*dest = tinttable[((*dest) << 8) + *source++];
|
|
dest += SCREENWIDTH;
|
|
}
|
|
column = (column_t *) ((byte *) column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// V_DrawShadowedPatch
|
|
//
|
|
// Masks a column based masked pic to the screen.
|
|
//
|
|
|
|
void V_DrawShadowedPatch(int x, int y, patch_t *patch)
|
|
{
|
|
int count, col;
|
|
column_t *column;
|
|
byte *desttop, *dest, *source;
|
|
byte *desttop2, *dest2;
|
|
int w;
|
|
|
|
y -= SHORT(patch->topoffset);
|
|
x -= SHORT(patch->leftoffset);
|
|
|
|
if (x < 0
|
|
|| x + SHORT(patch->width) > SCREENWIDTH
|
|
|| y < 0
|
|
|| y + SHORT(patch->height) > SCREENHEIGHT)
|
|
{
|
|
I_Error("Bad V_DrawShadowedPatch");
|
|
}
|
|
|
|
col = 0;
|
|
desttop = dest_screen + y * SCREENWIDTH + x;
|
|
desttop2 = dest_screen + (y + 2) * SCREENWIDTH + x + 2;
|
|
|
|
w = SHORT(patch->width);
|
|
for (; col < w; x++, col++, desttop++, desttop2++)
|
|
{
|
|
column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col]));
|
|
|
|
// step through the posts in a column
|
|
|
|
while (column->topdelta != 0xff)
|
|
{
|
|
source = (byte *) column + 3;
|
|
dest = desttop + column->topdelta * SCREENWIDTH;
|
|
dest2 = desttop2 + column->topdelta * SCREENWIDTH;
|
|
count = column->length;
|
|
|
|
while (count--)
|
|
{
|
|
*dest2 = tinttable[((*dest2) << 8)];
|
|
dest2 += SCREENWIDTH;
|
|
*dest = *source++;
|
|
dest += SCREENWIDTH;
|
|
|
|
}
|
|
column = (column_t *) ((byte *) column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load tint table from TINTTAB lump.
|
|
//
|
|
|
|
void V_LoadTintTable(void)
|
|
{
|
|
tinttable = W_CacheLumpName("TINTTAB", PU_STATIC);
|
|
}
|
|
|
|
//
|
|
// V_LoadXlaTable
|
|
//
|
|
// villsa [STRIFE] Load xla table from XLATAB lump.
|
|
//
|
|
|
|
void V_LoadXlaTable(void)
|
|
{
|
|
xlatab = W_CacheLumpName("XLATAB", PU_STATIC);
|
|
}
|
|
|
|
//
|
|
// V_DrawBlock
|
|
// Draw a linear block of pixels into the view buffer.
|
|
//
|
|
|
|
void V_DrawBlock(int x, int y, int width, int height, byte *src)
|
|
{
|
|
byte *dest;
|
|
|
|
#ifdef RANGECHECK
|
|
if (x < 0
|
|
|| x + width >SCREENWIDTH
|
|
|| y < 0
|
|
|| y + height > SCREENHEIGHT)
|
|
{
|
|
I_Error ("Bad V_DrawBlock");
|
|
}
|
|
#endif
|
|
|
|
V_MarkRect (x, y, width, height);
|
|
|
|
dest = dest_screen + y * SCREENWIDTH + x;
|
|
|
|
while (height--)
|
|
{
|
|
ES_memcpy (dest, src, width);
|
|
src += width;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
void V_DrawFilledBox(int x, int y, int w, int h, int c)
|
|
{
|
|
uint8_t *buf, *buf1;
|
|
int x1, y1;
|
|
|
|
buf = I_VideoBuffer + SCREENWIDTH * y + x;
|
|
|
|
for (y1 = 0; y1 < h; ++y1)
|
|
{
|
|
buf1 = buf;
|
|
|
|
for (x1 = 0; x1 < w; ++x1)
|
|
{
|
|
*buf1++ = c;
|
|
}
|
|
|
|
buf += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
void V_DrawHorizLine(int x, int y, int w, int c)
|
|
{
|
|
uint8_t *buf;
|
|
int x1;
|
|
|
|
buf = I_VideoBuffer + SCREENWIDTH * y + x;
|
|
|
|
for (x1 = 0; x1 < w; ++x1)
|
|
{
|
|
*buf++ = c;
|
|
}
|
|
}
|
|
|
|
void V_DrawVertLine(int x, int y, int h, int c)
|
|
{
|
|
uint8_t *buf;
|
|
int y1;
|
|
|
|
buf = I_VideoBuffer + SCREENWIDTH * y + x;
|
|
|
|
for (y1 = 0; y1 < h; ++y1)
|
|
{
|
|
*buf = c;
|
|
buf += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
void V_DrawBox(int x, int y, int w, int h, int c)
|
|
{
|
|
V_DrawHorizLine(x, y, w, c);
|
|
V_DrawHorizLine(x, y+h-1, w, c);
|
|
V_DrawVertLine(x, y, h, c);
|
|
V_DrawVertLine(x+w-1, y, h, c);
|
|
}
|
|
|
|
//
|
|
// Draw a "raw" screen (lump containing raw data to blit directly
|
|
// to the screen)
|
|
//
|
|
|
|
void V_DrawRawScreen(byte *raw)
|
|
{
|
|
ES_memcpy(dest_screen, raw, SCREENWIDTH * SCREENHEIGHT);
|
|
}
|
|
|
|
//
|
|
// V_Init
|
|
//
|
|
void V_Init (void)
|
|
{
|
|
// no-op!
|
|
// There used to be separate screens that could be drawn to; these are
|
|
// now handled in the upper layers.
|
|
}
|
|
|
|
// Set the buffer that the code draws to.
|
|
|
|
void V_UseBuffer(byte *buffer)
|
|
{
|
|
dest_screen = buffer;
|
|
}
|
|
|
|
// Restore screen buffer to the i_video screen buffer.
|
|
|
|
void V_RestoreBuffer(void)
|
|
{
|
|
dest_screen = I_VideoBuffer;
|
|
}
|
|
|
|
//
|
|
// SCREEN SHOTS
|
|
//
|
|
|
|
typedef struct
|
|
{
|
|
char manufacturer;
|
|
char version;
|
|
char encoding;
|
|
char bits_per_pixel;
|
|
|
|
unsigned short xmin;
|
|
unsigned short ymin;
|
|
unsigned short xmax;
|
|
unsigned short ymax;
|
|
|
|
unsigned short hres;
|
|
unsigned short vres;
|
|
|
|
unsigned char palette[48];
|
|
|
|
char reserved;
|
|
char color_planes;
|
|
unsigned short bytes_per_line;
|
|
unsigned short palette_type;
|
|
|
|
char filler[58];
|
|
unsigned char data; // unbounded
|
|
} PACKEDATTR pcx_t;
|
|
|
|
|
|
//
|
|
// WritePCXfile
|
|
//
|
|
|
|
void WritePCXfile(char *filename, byte *data,
|
|
int width, int height,
|
|
byte *palette)
|
|
{
|
|
int i;
|
|
int length;
|
|
pcx_t* pcx;
|
|
byte* pack;
|
|
|
|
pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
|
|
|
|
pcx->manufacturer = 0x0a; // PCX id
|
|
pcx->version = 5; // 256 color
|
|
pcx->encoding = 1; // uncompressed
|
|
pcx->bits_per_pixel = 8; // 256 color
|
|
pcx->xmin = 0;
|
|
pcx->ymin = 0;
|
|
pcx->xmax = SHORT(width-1);
|
|
pcx->ymax = SHORT(height-1);
|
|
pcx->hres = SHORT(width);
|
|
pcx->vres = SHORT(height);
|
|
ES_memset (pcx->palette,0,sizeof(pcx->palette));
|
|
pcx->color_planes = 1; // chunky image
|
|
pcx->bytes_per_line = SHORT(width);
|
|
pcx->palette_type = SHORT(2); // not a grey scale
|
|
ES_memset (pcx->filler,0,sizeof(pcx->filler));
|
|
|
|
// pack the image
|
|
pack = &pcx->data;
|
|
|
|
for (i=0 ; i<width*height ; i++)
|
|
{
|
|
if ( (*data & 0xc0) != 0xc0)
|
|
*pack++ = *data++;
|
|
else
|
|
{
|
|
*pack++ = 0xc1;
|
|
*pack++ = *data++;
|
|
}
|
|
}
|
|
|
|
// write the palette
|
|
*pack++ = 0x0c; // palette ID byte
|
|
for (i=0 ; i<768 ; i++)
|
|
*pack++ = *palette++;
|
|
|
|
// write output file
|
|
length = pack - (byte *)pcx;
|
|
M_WriteFile (filename, pcx, length);
|
|
|
|
Z_Free (pcx);
|
|
}
|
|
|
|
//
|
|
// V_ScreenShot
|
|
//
|
|
|
|
void V_ScreenShot(char *format)
|
|
{
|
|
int i;
|
|
char lbmname[16]; // haleyjd 20110213: BUG FIX - 12 is too small!
|
|
char *ext;
|
|
|
|
// find a file name to save it to
|
|
ext = "pcx";
|
|
|
|
for (i=0; i<=99; i++)
|
|
{
|
|
M_snprintf(lbmname, sizeof(lbmname), format, i, ext);
|
|
|
|
if (!M_FileExists(lbmname))
|
|
{
|
|
break; // file doesn't exist
|
|
}
|
|
}
|
|
|
|
if (i == 100)
|
|
{
|
|
I_Error ("V_ScreenShot: Couldn't create a PCX");
|
|
}
|
|
|
|
// save the pcx file
|
|
WritePCXfile(lbmname, I_VideoBuffer,
|
|
SCREENWIDTH, SCREENHEIGHT,
|
|
W_CacheLumpName ("PLAYPAL", PU_CACHE));
|
|
}
|
|
|
|
#define MOUSE_SPEED_BOX_WIDTH 120
|
|
#define MOUSE_SPEED_BOX_HEIGHT 9
|
|
|
|
void V_DrawMouseSpeedBox(int speed)
|
|
{
|
|
extern int usemouse;
|
|
int bgcolor, bordercolor, red, black, white, yellow;
|
|
int box_x, box_y;
|
|
int original_speed;
|
|
int redline_x;
|
|
int linelen;
|
|
|
|
// Get palette indices for colors for widget. These depend on the
|
|
// palette of the game being played.
|
|
|
|
bgcolor = I_GetPaletteIndex(0x77, 0x77, 0x77);
|
|
bordercolor = I_GetPaletteIndex(0x55, 0x55, 0x55);
|
|
red = I_GetPaletteIndex(0xff, 0x00, 0x00);
|
|
black = I_GetPaletteIndex(0x00, 0x00, 0x00);
|
|
yellow = I_GetPaletteIndex(0xff, 0xff, 0x00);
|
|
white = I_GetPaletteIndex(0xff, 0xff, 0xff);
|
|
|
|
// If the mouse is turned off or acceleration is turned off, don't
|
|
// draw the box at all.
|
|
|
|
if (!usemouse || ES_fabs(mouse_acceleration - 1) < 0.01)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Calculate box position
|
|
|
|
box_x = SCREENWIDTH - MOUSE_SPEED_BOX_WIDTH - 10;
|
|
box_y = 15;
|
|
|
|
V_DrawFilledBox(box_x, box_y,
|
|
MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bgcolor);
|
|
V_DrawBox(box_x, box_y,
|
|
MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bordercolor);
|
|
|
|
// Calculate the position of the red line. This is 1/3 of the way
|
|
// along the box.
|
|
|
|
redline_x = MOUSE_SPEED_BOX_WIDTH / 3;
|
|
|
|
// Undo acceleration and get back the original mouse speed
|
|
|
|
if (speed < mouse_threshold)
|
|
{
|
|
original_speed = speed;
|
|
}
|
|
else
|
|
{
|
|
original_speed = speed - mouse_threshold;
|
|
original_speed = (int) (original_speed / mouse_acceleration);
|
|
original_speed += mouse_threshold;
|
|
}
|
|
|
|
// Calculate line length
|
|
|
|
linelen = (original_speed * redline_x) / mouse_threshold;
|
|
|
|
// Draw horizontal "thermometer"
|
|
|
|
if (linelen > MOUSE_SPEED_BOX_WIDTH - 1)
|
|
{
|
|
linelen = MOUSE_SPEED_BOX_WIDTH - 1;
|
|
}
|
|
|
|
V_DrawHorizLine(box_x + 1, box_y + 4, MOUSE_SPEED_BOX_WIDTH - 2, black);
|
|
|
|
if (linelen < redline_x)
|
|
{
|
|
V_DrawHorizLine(box_x + 1, box_y + MOUSE_SPEED_BOX_HEIGHT / 2,
|
|
linelen, white);
|
|
}
|
|
else
|
|
{
|
|
V_DrawHorizLine(box_x + 1, box_y + MOUSE_SPEED_BOX_HEIGHT / 2,
|
|
redline_x, white);
|
|
V_DrawHorizLine(box_x + redline_x, box_y + MOUSE_SPEED_BOX_HEIGHT / 2,
|
|
linelen - redline_x, yellow);
|
|
}
|
|
|
|
// Draw red line
|
|
|
|
V_DrawVertLine(box_x + redline_x, box_y + 1,
|
|
MOUSE_SPEED_BOX_HEIGHT - 2, red);
|
|
}
|
|
|