123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035 |
- /* 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
- * Copyright 2005, 2006 by
- * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
- *
- * 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 "r_filter.h"
- #include "lprintf.h"
- // Each screen is [SCREENWIDTH*SCREENHEIGHT];
- screeninfo_t screens[NUM_SCREENS];
- /* jff 4/24/98 initialize this at runtime */
- const byte *colrngs[CR_LIMIT];
- 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_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.
- //
- static void FUNC_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
- src = screens[srcscrn].data+screens[srcscrn].byte_pitch*srcy+srcx*V_GetPixelDepth();
- dest = screens[destscrn].data+screens[destscrn].byte_pitch*desty+destx*V_GetPixelDepth();
- for ( ; height>0 ; height--)
- {
- memcpy (dest, src, width*V_GetPixelDepth());
- src += screens[srcscrn].byte_pitch;
- dest += screens[destscrn].byte_pitch;
- }
- }
- /*
- * 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
- */
- static void FUNC_V_DrawBackground(const char* flatname, int scrn)
- {
- /* erase the entire screen to a tiled background */
- const byte *src;
- int x,y;
- int width,height;
- int lump;
- // killough 4/17/98:
- src = W_CacheLumpNum(lump = firstflat + R_FlatNumForName(flatname));
- /* V_DrawBlock(0, 0, scrn, 64, 64, src, 0); */
- width = height = 64;
- if (V_GetMode() == VID_MODE8) {
- byte *dest = screens[scrn].data;
- while (height--) {
- memcpy (dest, src, width);
- src += width;
- dest += screens[scrn].byte_pitch;
- }
- } else if (V_GetMode() == VID_MODE15) {
- unsigned short *dest = (unsigned short *)screens[scrn].data;
- while (height--) {
- int i;
- for (i=0; i<width; i++) {
- dest[i] = VID_PAL15(src[i], VID_COLORWEIGHTMASK);
- }
- src += width;
- dest += screens[scrn].short_pitch;
- }
- } else if (V_GetMode() == VID_MODE16) {
- unsigned short *dest = (unsigned short *)screens[scrn].data;
- while (height--) {
- int i;
- for (i=0; i<width; i++) {
- dest[i] = VID_PAL16(src[i], VID_COLORWEIGHTMASK);
- }
- src += width;
- dest += screens[scrn].short_pitch;
- }
- } else if (V_GetMode() == VID_MODE32) {
- unsigned int *dest = (unsigned int *)screens[scrn].data;
- while (height--) {
- int i;
- for (i=0; i<width; i++) {
- dest[i] = VID_PAL32(src[i], VID_COLORWEIGHTMASK);
- }
- src += width;
- dest += screens[scrn].int_pitch;
- }
- }
- /* end V_DrawBlock */
- 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_Init
- //
- // Allocates the 4 full screen buffers in low DOS memory
- // No return
- //
- void V_Init (void)
- {
- int i;
- // reset the all
- for (i = 0; i<NUM_SCREENS; i++) {
- screens[i].data = NULL;
- screens[i].not_on_heap = false;
- screens[i].width = 0;
- screens[i].height = 0;
- screens[i].byte_pitch = 0;
- screens[i].short_pitch = 0;
- screens[i].int_pitch = 0;
- }
- }
- //
- // 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).
- //
- static void V_DrawMemPatch(int x, int y, int scrn, const rpatch_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 -= patch->topoffset;
- x -= patch->leftoffset;
- // CPhipps - auto-no-stretch if not high-res
- if (flags & VPT_STRETCH)
- if ((SCREENWIDTH==320) && (SCREENHEIGHT==200))
- flags &= ~VPT_STRETCH;
- // CPhipps - null translation pointer => no translation
- if (!trans)
- flags &= ~VPT_TRANS;
- if (V_GetMode() == VID_MODE8 && !(flags & VPT_STRETCH)) {
- int col;
- byte *desttop = screens[scrn].data+y*screens[scrn].byte_pitch+x*V_GetPixelDepth();
- unsigned int w = patch->width;
- if (y<0 || y+patch->height > ((flags & VPT_STRETCH) ? 200 : SCREENHEIGHT)) {
- // killough 1/19/98: improved error message:
- lprintf(LO_WARN, "V_DrawMemPatch8: Patch (%d,%d)-(%d,%d) exceeds LFB in vertical direction (horizontal is clipped)\n"
- "Bad V_DrawMemPatch8 (flags=%u)", x, y, x+patch->width, y+patch->height, flags);
- return;
- }
- w--; // CPhipps - note: w = width-1 now, speeds up flipping
- for (col=0 ; (unsigned int)col<=w ; desttop++, col++, x++) {
- int i;
- const int colindex = (flags & VPT_FLIP) ? (w - col) : (col);
- const rcolumn_t *column = R_GetPatchColumn(patch, colindex);
- if (x < 0)
- continue;
- if (x >= SCREENWIDTH)
- break;
- // step through the posts in a column
- for (i=0; i<column->numPosts; i++) {
- const rpost_t *post = &column->posts[i];
- // killough 2/21/98: Unrolled and performance-tuned
- const byte *source = column->pixels + post->topdelta;
- byte *dest = desttop + post->topdelta*screens[scrn].byte_pitch;
- int count = post->length;
- if (!(flags & VPT_TRANS)) {
- if ((count-=4)>=0)
- do {
- register byte s0,s1;
- s0 = source[0];
- s1 = source[1];
- dest[0] = s0;
- dest[screens[scrn].byte_pitch] = s1;
- dest += screens[scrn].byte_pitch*2;
- s0 = source[2];
- s1 = source[3];
- source += 4;
- dest[0] = s0;
- dest[screens[scrn].byte_pitch] = s1;
- dest += screens[scrn].byte_pitch*2;
- } while ((count-=4)>=0);
- if (count+=4)
- do {
- *dest = *source++;
- dest += screens[scrn].byte_pitch;
- } while (--count);
- } 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[screens[scrn].byte_pitch] = s1;
- dest += screens[scrn].byte_pitch*2;
- s0 = source[2];
- s1 = source[3];
- s0 = trans[s0];
- s1 = trans[s1];
- source += 4;
- dest[0] = s0;
- dest[screens[scrn].byte_pitch] = s1;
- dest += screens[scrn].byte_pitch*2;
- } while ((count-=4)>=0);
- if (count+=4)
- do {
- *dest = trans[*source++];
- dest += screens[scrn].byte_pitch;
- } while (--count);
- }
- }
- }
- }
- else {
- // CPhipps - move stretched patch drawing code here
- // - reformat initialisers, move variables into inner blocks
- int col;
- int w = (patch->width << 16) - 1; // CPhipps - -1 for faster flipping
- int left, right, top, bottom;
- int DX = (SCREENWIDTH<<16) / 320;
- int DXI = (320<<16) / SCREENWIDTH;
- int DY = (SCREENHEIGHT<<16) / 200;
- int DYI = (200<<16) / SCREENHEIGHT;
- R_DrawColumn_f colfunc;
- draw_column_vars_t dcvars;
- draw_vars_t olddrawvars = drawvars;
- R_SetDefaultDrawColumnVars(&dcvars);
- drawvars.byte_topleft = screens[scrn].data;
- drawvars.short_topleft = (unsigned short *)screens[scrn].data;
- drawvars.int_topleft = (unsigned int *)screens[scrn].data;
- drawvars.byte_pitch = screens[scrn].byte_pitch;
- drawvars.short_pitch = screens[scrn].short_pitch;
- drawvars.int_pitch = screens[scrn].int_pitch;
- if (!(flags & VPT_STRETCH)) {
- DX = 1 << 16;
- DXI = 1 << 16;
- DY = 1 << 16;
- DYI = 1 << 16;
- }
- if (flags & VPT_TRANS) {
- colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_TRANSLATED, drawvars.filterpatch, RDRAW_FILTER_NONE);
- dcvars.translation = trans;
- } else {
- colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterpatch, RDRAW_FILTER_NONE);
- }
- left = ( x * DX ) >> FRACBITS;
- top = ( y * DY ) >> FRACBITS;
- right = ( (x + patch->width) * DX ) >> FRACBITS;
- bottom = ( (y + patch->height) * DY ) >> FRACBITS;
- dcvars.texheight = patch->height;
- dcvars.iscale = DYI;
- dcvars.drawingmasked = MAX(patch->width, patch->height) > 8;
- dcvars.edgetype = drawvars.patch_edges;
- if (drawvars.filterpatch == RDRAW_FILTER_LINEAR) {
- // bias the texture u coordinate
- if (patch->isNotTileable)
- col = -(FRACUNIT>>1);
- else
- col = (patch->width<<FRACBITS)-(FRACUNIT>>1);
- }
- else {
- col = 0;
- }
- for (dcvars.x=left; dcvars.x<right; dcvars.x++, col+=DXI) {
- int i;
- const int colindex = (flags & VPT_FLIP) ? ((w - col)>>16): (col>>16);
- const rcolumn_t *column = R_GetPatchColumn(patch, colindex);
- const rcolumn_t *prevcolumn = R_GetPatchColumn(patch, colindex-1);
- const rcolumn_t *nextcolumn = R_GetPatchColumn(patch, colindex+1);
- // ignore this column if it's to the left of our clampRect
- if (dcvars.x < 0)
- continue;
- if (dcvars.x >= SCREENWIDTH)
- break;
- dcvars.texu = ((flags & VPT_FLIP) ? ((patch->width<<FRACBITS)-col) : col) % (patch->width<<FRACBITS);
- // step through the posts in a column
- for (i=0; i<column->numPosts; i++) {
- const rpost_t *post = &column->posts[i];
- int yoffset = 0;
- dcvars.yl = (((y + post->topdelta) * DY)>>FRACBITS);
- dcvars.yh = (((y + post->topdelta + post->length) * DY - (FRACUNIT>>1))>>FRACBITS);
- dcvars.edgeslope = post->slope;
- if ((dcvars.yh < 0) || (dcvars.yh < top))
- continue;
- if ((dcvars.yl >= SCREENHEIGHT) || (dcvars.yl >= bottom))
- continue;
- if (dcvars.yh >= bottom) {
- dcvars.yh = bottom-1;
- dcvars.edgeslope &= ~RDRAW_EDGESLOPE_BOT_MASK;
- }
- if (dcvars.yh >= SCREENHEIGHT) {
- dcvars.yh = SCREENHEIGHT-1;
- dcvars.edgeslope &= ~RDRAW_EDGESLOPE_BOT_MASK;
- }
- if (dcvars.yl < 0) {
- yoffset = 0-dcvars.yl;
- dcvars.yl = 0;
- dcvars.edgeslope &= ~RDRAW_EDGESLOPE_TOP_MASK;
- }
- if (dcvars.yl < top) {
- yoffset = top-dcvars.yl;
- dcvars.yl = top;
- dcvars.edgeslope &= ~RDRAW_EDGESLOPE_TOP_MASK;
- }
- dcvars.source = column->pixels + post->topdelta + yoffset;
- dcvars.prevsource = prevcolumn ? prevcolumn->pixels + post->topdelta + yoffset: dcvars.source;
- dcvars.nextsource = nextcolumn ? nextcolumn->pixels + post->topdelta + yoffset: dcvars.source;
- dcvars.texturemid = -((dcvars.yl-centery)*dcvars.iscale);
- colfunc(&dcvars);
- }
- }
- R_ResetColumnBuffer();
- drawvars = olddrawvars;
- }
- }
- // 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
- static void FUNC_V_DrawNumPatch(int x, int y, int scrn, int lump,
- int cm, enum patch_translation_e flags)
- {
- V_DrawMemPatch(x, y, scrn, R_CachePatchNum(lump), cm, flags);
- R_UnlockPatchNum(lump);
- }
- unsigned short *V_Palette15 = NULL;
- unsigned short *V_Palette16 = NULL;
- unsigned int *V_Palette32 = NULL;
- static unsigned short *Palettes15 = NULL;
- static unsigned short *Palettes16 = NULL;
- static unsigned int *Palettes32 = NULL;
- static int currentPaletteIndex = 0;
- //
- // V_UpdateTrueColorPalette
- //
- void V_UpdateTrueColorPalette(video_mode_t mode) {
- int i, w, p;
- byte r,g,b;
- int nr,ng,nb;
- float t;
- int paletteNum = (V_GetMode() == VID_MODEGL ? 0 : currentPaletteIndex);
- static int usegammaOnLastPaletteGeneration = -1;
-
- int pplump = W_GetNumForName("PLAYPAL");
- int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom);
- const byte *pal = W_CacheLumpNum(pplump);
- // opengl doesn't use the gamma
- const byte *const gtable =
- (const byte *)W_CacheLumpNum(gtlump) +
- (V_GetMode() == VID_MODEGL ? 0 : 256*(usegamma))
- ;
- int numPals = W_LumpLength(pplump) / (3*256);
- const float dontRoundAbove = 220;
- float roundUpR, roundUpG, roundUpB;
-
- if (usegammaOnLastPaletteGeneration != usegamma) {
- if (Palettes15) free(Palettes15);
- if (Palettes16) free(Palettes16);
- if (Palettes32) free(Palettes32);
- Palettes15 = NULL;
- Palettes16 = NULL;
- Palettes32 = NULL;
- usegammaOnLastPaletteGeneration = usegamma;
- }
-
- if (mode == VID_MODE32) {
- if (!Palettes32) {
- // set int palette
- Palettes32 = (unsigned int*)malloc(numPals*256*sizeof(unsigned int)*VID_NUMCOLORWEIGHTS);
- for (p=0; p<numPals; p++) {
- for (i=0; i<256; i++) {
- r = gtable[pal[(256*p+i)*3+0]];
- g = gtable[pal[(256*p+i)*3+1]];
- b = gtable[pal[(256*p+i)*3+2]];
-
- // ideally, we should always round up, but very bright colors
- // overflow the blending adds, so they don't get rounded.
- roundUpR = (r > dontRoundAbove) ? 0 : 0.5f;
- roundUpG = (g > dontRoundAbove) ? 0 : 0.5f;
- roundUpB = (b > dontRoundAbove) ? 0 : 0.5f;
-
- for (w=0; w<VID_NUMCOLORWEIGHTS; w++) {
- t = (float)(w)/(float)(VID_NUMCOLORWEIGHTS-1);
- nr = (int)(r*t+roundUpR);
- ng = (int)(g*t+roundUpG);
- nb = (int)(b*t+roundUpB);
- Palettes32[((p*256+i)*VID_NUMCOLORWEIGHTS)+w] = (
- (nr<<16) | (ng<<8) | nb
- );
- }
- }
- }
- }
- V_Palette32 = Palettes32 + paletteNum*256*VID_NUMCOLORWEIGHTS;
- }
- else if (mode == VID_MODE16) {
- if (!Palettes16) {
- // set short palette
- Palettes16 = (unsigned short*)malloc(numPals*256*sizeof(unsigned short)*VID_NUMCOLORWEIGHTS);
- for (p=0; p<numPals; p++) {
- for (i=0; i<256; i++) {
- r = gtable[pal[(256*p+i)*3+0]];
- g = gtable[pal[(256*p+i)*3+1]];
- b = gtable[pal[(256*p+i)*3+2]];
-
- // ideally, we should always round up, but very bright colors
- // overflow the blending adds, so they don't get rounded.
- roundUpR = (r > dontRoundAbove) ? 0 : 0.5f;
- roundUpG = (g > dontRoundAbove) ? 0 : 0.5f;
- roundUpB = (b > dontRoundAbove) ? 0 : 0.5f;
-
- for (w=0; w<VID_NUMCOLORWEIGHTS; w++) {
- t = (float)(w)/(float)(VID_NUMCOLORWEIGHTS-1);
- nr = (int)((r>>3)*t+roundUpR);
- ng = (int)((g>>2)*t+roundUpG);
- nb = (int)((b>>3)*t+roundUpB);
- Palettes16[((p*256+i)*VID_NUMCOLORWEIGHTS)+w] = (
- (nr<<11) | (ng<<5) | nb
- );
- }
- }
- }
- }
- V_Palette16 = Palettes16 + paletteNum*256*VID_NUMCOLORWEIGHTS;
- }
- else if (mode == VID_MODE15) {
- if (!Palettes15) {
- // set short palette
- Palettes15 = (unsigned short*)malloc(numPals*256*sizeof(unsigned short)*VID_NUMCOLORWEIGHTS);
- for (p=0; p<numPals; p++) {
- for (i=0; i<256; i++) {
- r = gtable[pal[(256*p+i)*3+0]];
- g = gtable[pal[(256*p+i)*3+1]];
- b = gtable[pal[(256*p+i)*3+2]];
-
- // ideally, we should always round up, but very bright colors
- // overflow the blending adds, so they don't get rounded.
- roundUpR = (r > dontRoundAbove) ? 0 : 0.5f;
- roundUpG = (g > dontRoundAbove) ? 0 : 0.5f;
- roundUpB = (b > dontRoundAbove) ? 0 : 0.5f;
-
- for (w=0; w<VID_NUMCOLORWEIGHTS; w++) {
- t = (float)(w)/(float)(VID_NUMCOLORWEIGHTS-1);
- nr = (int)((r>>3)*t+roundUpR);
- ng = (int)((g>>3)*t+roundUpG);
- nb = (int)((b>>3)*t+roundUpB);
- Palettes15[((p*256+i)*VID_NUMCOLORWEIGHTS)+w] = (
- (nr<<10) | (ng<<5) | nb
- );
- }
- }
- }
- }
- V_Palette15 = Palettes15 + paletteNum*256*VID_NUMCOLORWEIGHTS;
- }
-
- W_UnlockLumpNum(pplump);
- W_UnlockLumpNum(gtlump);
- }
- //---------------------------------------------------------------------------
- // V_DestroyTrueColorPalette
- //---------------------------------------------------------------------------
- static void V_DestroyTrueColorPalette(video_mode_t mode) {
- if (mode == VID_MODE15) {
- if (Palettes15) free(Palettes15);
- Palettes15 = NULL;
- V_Palette15 = NULL;
- }
- if (mode == VID_MODE16) {
- if (Palettes16) free(Palettes16);
- Palettes16 = NULL;
- V_Palette16 = NULL;
- }
- if (mode == VID_MODE32) {
- if (Palettes32) free(Palettes32);
- Palettes32 = NULL;
- V_Palette32 = NULL;
- }
- }
- void V_DestroyUnusedTrueColorPalettes(void) {
- if (V_GetMode() != VID_MODE15) V_DestroyTrueColorPalette(VID_MODE15);
- if (V_GetMode() != VID_MODE16) V_DestroyTrueColorPalette(VID_MODE16);
- if (V_GetMode() != VID_MODE32) V_DestroyTrueColorPalette(VID_MODE32);
- }
- //
- // 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)
- {
- currentPaletteIndex = pal;
- if (V_GetMode() == VID_MODEGL) {
- #ifdef GL_DOOM
- gld_SetPalette(pal);
- #endif
- } else {
- I_SetPalette(pal);
- if (V_GetMode() == VID_MODE15 || V_GetMode() == VID_MODE16 || V_GetMode() == VID_MODE32) {
- // V_SetPalette can be called as part of the gamma setting before
- // we've loaded any wads, which prevents us from reading the palette - POPE
- if (W_CheckNumForName("PLAYPAL") >= 0) {
- V_UpdateTrueColorPalette(V_GetMode());
- }
- }
- }
- }
- //
- // V_FillRect
- //
- // CPhipps - New function to fill a rectangle with a given colour
- static void V_FillRect8(int scrn, int x, int y, int width, int height, byte colour)
- {
- byte* dest = screens[scrn].data + x + y*screens[scrn].byte_pitch;
- while (height--) {
- memset(dest, colour, width);
- dest += screens[scrn].byte_pitch;
- }
- }
- static void V_FillRect15(int scrn, int x, int y, int width, int height, byte colour)
- {
- unsigned short* dest = (unsigned short *)screens[scrn].data + x + y*screens[scrn].short_pitch;
- int w;
- short c = VID_PAL15(colour, VID_COLORWEIGHTMASK);
- while (height--) {
- for (w=0; w<width; w++) {
- dest[w] = c;
- }
- dest += screens[scrn].short_pitch;
- }
- }
- static void V_FillRect16(int scrn, int x, int y, int width, int height, byte colour)
- {
- unsigned short* dest = (unsigned short *)screens[scrn].data + x + y*screens[scrn].short_pitch;
- int w;
- short c = VID_PAL16(colour, VID_COLORWEIGHTMASK);
- while (height--) {
- for (w=0; w<width; w++) {
- dest[w] = c;
- }
- dest += screens[scrn].short_pitch;
- }
- }
- static void V_FillRect32(int scrn, int x, int y, int width, int height, byte colour)
- {
- unsigned int* dest = (unsigned int *)screens[scrn].data + x + y*screens[scrn].int_pitch;
- int w;
- int c = VID_PAL32(colour, VID_COLORWEIGHTMASK);
- while (height--) {
- for (w=0; w<width; w++) {
- dest[w] = c;
- }
- dest += screens[scrn].int_pitch;
- }
- }
- static void WRAP_V_DrawLine(fline_t* fl, int color);
- static void V_PlotPixel8(int scrn, int x, int y, byte color);
- static void V_PlotPixel15(int scrn, int x, int y, byte color);
- static void V_PlotPixel16(int scrn, int x, int y, byte color);
- static void V_PlotPixel32(int scrn, int x, int y, byte color);
- #ifdef GL_DOOM
- static void WRAP_gld_FillRect(int scrn, int x, int y, int width, int height, byte colour)
- {
- gld_FillBlock(x,y,width,height,colour);
- }
- static void WRAP_gld_CopyRect(int srcx, int srcy, int srcscrn, int width, int height, int destx, int desty, int destscrn, enum patch_translation_e flags)
- {
- }
- static void WRAP_gld_DrawBackground(const char *flatname, int n)
- {
- gld_DrawBackground(flatname);
- }
- static void WRAP_gld_DrawNumPatch(int x, int y, int scrn, int lump, int cm, enum patch_translation_e flags)
- {
- gld_DrawNumPatch(x,y,lump,cm,flags);
- }
- static void V_PlotPixelGL(int scrn, int x, int y, byte color) {
- gld_DrawLine(x-1, y, x+1, y, color);
- gld_DrawLine(x, y-1, x, y+1, color);
- }
- static void WRAP_gld_DrawLine(fline_t* fl, int color)
- {
- gld_DrawLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, color);
- }
- #endif
- static void NULL_FillRect(int scrn, int x, int y, int width, int height, byte colour) {}
- static void NULL_CopyRect(int srcx, int srcy, int srcscrn, int width, int height, int destx, int desty, int destscrn, enum patch_translation_e flags) {}
- static void NULL_DrawBackground(const char *flatname, int n) {}
- static void NULL_DrawNumPatch(int x, int y, int scrn, int lump, int cm, enum patch_translation_e flags) {}
- static void NULL_PlotPixel(int scrn, int x, int y, byte color) {}
- static void NULL_DrawLine(fline_t* fl, int color) {}
- const char *default_videomode;
- static video_mode_t current_videomode = VID_MODE8;
- V_CopyRect_f V_CopyRect = NULL_CopyRect;
- V_FillRect_f V_FillRect = NULL_FillRect;
- V_DrawNumPatch_f V_DrawNumPatch = NULL_DrawNumPatch;
- V_DrawBackground_f V_DrawBackground = NULL_DrawBackground;
- V_PlotPixel_f V_PlotPixel = NULL_PlotPixel;
- V_DrawLine_f V_DrawLine = NULL_DrawLine;
- //
- // V_InitMode
- //
- void V_InitMode(video_mode_t mode) {
- #ifndef GL_DOOM
- if (mode == VID_MODEGL)
- mode = VID_MODE8;
- #endif
- switch (mode) {
- case VID_MODE8:
- lprintf(LO_INFO, "V_InitMode: using 8 bit video mode\n");
- V_CopyRect = FUNC_V_CopyRect;
- V_FillRect = V_FillRect8;
- V_DrawNumPatch = FUNC_V_DrawNumPatch;
- V_DrawBackground = FUNC_V_DrawBackground;
- V_PlotPixel = V_PlotPixel8;
- V_DrawLine = WRAP_V_DrawLine;
- current_videomode = VID_MODE8;
- break;
- case VID_MODE15:
- lprintf(LO_INFO, "V_InitMode: using 15 bit video mode\n");
- V_CopyRect = FUNC_V_CopyRect;
- V_FillRect = V_FillRect15;
- V_DrawNumPatch = FUNC_V_DrawNumPatch;
- V_DrawBackground = FUNC_V_DrawBackground;
- V_PlotPixel = V_PlotPixel15;
- V_DrawLine = WRAP_V_DrawLine;
- current_videomode = VID_MODE15;
- break;
- case VID_MODE16:
- lprintf(LO_INFO, "V_InitMode: using 16 bit video mode\n");
- V_CopyRect = FUNC_V_CopyRect;
- V_FillRect = V_FillRect16;
- V_DrawNumPatch = FUNC_V_DrawNumPatch;
- V_DrawBackground = FUNC_V_DrawBackground;
- V_PlotPixel = V_PlotPixel16;
- V_DrawLine = WRAP_V_DrawLine;
- current_videomode = VID_MODE16;
- break;
- case VID_MODE32:
- lprintf(LO_INFO, "V_InitMode: using 32 bit video mode\n");
- V_CopyRect = FUNC_V_CopyRect;
- V_FillRect = V_FillRect32;
- V_DrawNumPatch = FUNC_V_DrawNumPatch;
- V_DrawBackground = FUNC_V_DrawBackground;
- V_PlotPixel = V_PlotPixel32;
- V_DrawLine = WRAP_V_DrawLine;
- current_videomode = VID_MODE32;
- break;
- #ifdef GL_DOOM
- case VID_MODEGL:
- lprintf(LO_INFO, "V_InitMode: using OpenGL video mode\n");
- V_CopyRect = WRAP_gld_CopyRect;
- V_FillRect = WRAP_gld_FillRect;
- V_DrawNumPatch = WRAP_gld_DrawNumPatch;
- V_DrawBackground = WRAP_gld_DrawBackground;
- V_PlotPixel = V_PlotPixelGL;
- V_DrawLine = WRAP_gld_DrawLine;
- current_videomode = VID_MODEGL;
- break;
- #endif
- default: break;
- }
- R_FilterInit();
- }
- //
- // V_GetMode
- //
- video_mode_t V_GetMode(void) {
- return current_videomode;
- }
- //
- // V_GetModePixelDepth
- //
- int V_GetModePixelDepth(video_mode_t mode) {
- switch (mode) {
- case VID_MODE8: return 1;
- case VID_MODE15: return 2;
- case VID_MODE16: return 2;
- case VID_MODE32: return 4;
- default: return 0;
- }
- }
- //
- // V_GetNumPixelBits
- //
- int V_GetNumPixelBits(void) {
- switch (current_videomode) {
- case VID_MODE8: return 8;
- case VID_MODE15: return 15;
- case VID_MODE16: return 16;
- case VID_MODE32: return 32;
- default: return 0;
- }
- }
- //
- // V_GetPixelDepth
- //
- int V_GetPixelDepth(void) {
- return V_GetModePixelDepth(current_videomode);
- }
- //
- // V_AllocScreen
- //
- void V_AllocScreen(screeninfo_t *scrn) {
- if (!scrn->not_on_heap)
- if ((scrn->byte_pitch * scrn->height) > 0)
- scrn->data = malloc(scrn->byte_pitch*scrn->height);
- }
- //
- // V_AllocScreens
- //
- void V_AllocScreens(void) {
- int i;
- for (i=0; i<NUM_SCREENS; i++)
- V_AllocScreen(&screens[i]);
- }
- //
- // V_FreeScreen
- //
- void V_FreeScreen(screeninfo_t *scrn) {
- if (!scrn->not_on_heap) {
- free(scrn->data);
- scrn->data = NULL;
- }
- }
- //
- // V_FreeScreens
- //
- void V_FreeScreens(void) {
- int i;
- for (i=0; i<NUM_SCREENS; i++)
- V_FreeScreen(&screens[i]);
- }
- static void V_PlotPixel8(int scrn, int x, int y, byte color) {
- screens[scrn].data[x+screens[scrn].byte_pitch*y] = color;
- }
- static void V_PlotPixel15(int scrn, int x, int y, byte color) {
- ((unsigned short *)screens[scrn].data)[x+screens[scrn].short_pitch*y] = VID_PAL15(color, VID_COLORWEIGHTMASK);
- }
- static void V_PlotPixel16(int scrn, int x, int y, byte color) {
- ((unsigned short *)screens[scrn].data)[x+screens[scrn].short_pitch*y] = VID_PAL16(color, VID_COLORWEIGHTMASK);
- }
- static void V_PlotPixel32(int scrn, int x, int y, byte color) {
- ((unsigned int *)screens[scrn].data)[x+screens[scrn].int_pitch*y] = VID_PAL32(color, VID_COLORWEIGHTMASK);
- }
- //
- // WRAP_V_DrawLine()
- //
- // Draw a line in the frame buffer.
- // Classic Bresenham w/ whatever optimizations needed for speed
- //
- // Passed the frame coordinates of line, and the color to be drawn
- // Returns nothing
- //
- static void WRAP_V_DrawLine(fline_t* fl, int color)
- {
- register int x;
- register int y;
- register int dx;
- register int dy;
- register int sx;
- register int sy;
- register int ax;
- register int ay;
- register int d;
- #ifdef RANGECHECK // killough 2/22/98
- static int fuck = 0;
- // For debugging only
- if
- (
- fl->a.x < 0 || fl->a.x >= SCREENWIDTH
- || fl->a.y < 0 || fl->a.y >= SCREENHEIGHT
- || fl->b.x < 0 || fl->b.x >= SCREENWIDTH
- || fl->b.y < 0 || fl->b.y >= SCREENHEIGHT
- )
- {
- //jff 8/3/98 use logical output routine
- lprintf(LO_DEBUG, "fuck %d \r", fuck++);
- return;
- }
- #endif
- #define PUTDOT(xx,yy,cc) V_PlotPixel(0,xx,yy,(byte)cc)
- dx = fl->b.x - fl->a.x;
- ax = 2 * (dx<0 ? -dx : dx);
- sx = dx<0 ? -1 : 1;
- dy = fl->b.y - fl->a.y;
- ay = 2 * (dy<0 ? -dy : dy);
- sy = dy<0 ? -1 : 1;
- x = fl->a.x;
- y = fl->a.y;
- if (ax > ay)
- {
- d = ay - ax/2;
- while (1)
- {
- PUTDOT(x,y,color);
- if (x == fl->b.x) return;
- if (d>=0)
- {
- y += sy;
- d -= ax;
- }
- x += sx;
- d += ay;
- }
- }
- else
- {
- d = ax - ay/2;
- while (1)
- {
- PUTDOT(x, y, color);
- if (y == fl->b.y) return;
- if (d >= 0)
- {
- x += sx;
- d -= ay;
- }
- y += sy;
- d += ax;
- }
- }
- }
|