Skip to content

Commit

Permalink
Heretic: add true color support (#1111)
Browse files Browse the repository at this point in the history
* Heretic: true color - initials

* Heretic: true color - V_DrawShadowedPatch now working

* Heretic: true color - fine tune patch shadows, better namings

Despite of here in V_ functions TINTTAB is used for shadows drawing, it's initial purpose is slightly different - it is a blending table, which is *also* used for shadows.

"drawtinttab" must be more clear in this context, and in case one day TC implementation will be done for Strife, XLA's function should be named "drawxlatab".

* Heretic: true color - fix V_DrawFullscreenRawOrPatch warning

* Heretic: true color - use COLORMAP lump for invulnerability effect

* Heretic: true color - simplify previous commit

Remove duplication of invul. colormap generation.

* Heretic: true color - remove redundant `sizeof` multipler for invul colormap handling

Raven Software's oversight, or attempt to reduce memory consumption?
https://github.com/OpenSourcedGames/Heretic/blob/master/Heretic%20Source/R_MAIN.C#L776

* Heretic: true color - remove redundant truecolor declarations

* Heretic: true color - add proper comment for removed sizeof()

* Heretic: true color - extend TINTTAB rendering functions

* Heretic: true color - translucent sprites

* Heretic: true color - no need for `V_LoadTintTable`

As not used in true color mode at all.

* Heretic: true color - proper palette for E2END pic

Fairly simple. We need only proper 256 colors for drawing E2END itself, but we also need to do a proper reset while switching back to normal palette, otherwise we'll get some wrong colors.

Suggestions for future:
- externalize gamma2table to i_video.h
- externalize R_InitColormaps and R_SetUnderwaterPalette to r_local.h

* Heretic: true color - better emulation of original Heretic's translucency

* Heretic: true color - add missing dc_translation to R_DrawTranslatedTLColumn

* Heretic: true color - small styling corrections

Also, "viewactive" is not needed. Despite of existing ovet the code, it's not doing anything. Using "setsizeneeded" wasn't optimal, it too expensive. All we need is:
- BorderNeedRefresh - updates screen border and bezel, including message area.
- SB_state - do a full redraw of whole status bar.

* Heretic: true color - use exclusively I_BlendOverTinttab for blending

* Heretic: true color - automap (line drawing)

This is, hopefully, as small diff as possible, which could be useful for custom COLORMAPs (but are there any existing?). Note that unlike Doom, REINDEX is using lesser color range to be as close to original smoothing as possible.

At this point, only background is not working on automap.

* fix status bar chain shading

* fix automap background drawing/parallaxing

* Externalize R_InitColormaps and R_SetUnderwaterPalette

Not sure if R_SetUnderwaterPalette needed to be guarded by a macro in header file, but probably this will make sence for better understanding about the nature of this function, i.e. it's "for true color only".

* Externalize I_SetGammaTable and gamma2table

No changes for Hexen and Strife needed, as these externals were made for true color render only.

* Allow R_SetUnderwaterPalette to accept any Hehacked-ed palette

Much neater and less macrocized now.
Thanks, Fabian!

* Remove unnecessary comment

* Update automap code

* Revert back pixel_t to byte for arrays of line colors. My typo made back in the time I was just started working on automap.

* Still use two arrays for normal and overlay mode. Idea of having "middle" color for walls drawing and array does not seems to be good enough, as we loose original color for both modes.

In theory, both arrays can be consolidated into one, but this is a bit tricky because we have to define "which color should be used for common walls drawing" w/o hitting if/else condition.

---------

Co-authored-by: Fabian Greffrath <fabian@greffrath.com>
  • Loading branch information
JNechaevsky and fabiangreffrath authored Nov 29, 2023
1 parent 50f49ed commit f9ddf41
Show file tree
Hide file tree
Showing 19 changed files with 373 additions and 48 deletions.
2 changes: 0 additions & 2 deletions src/doom/r_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -1172,12 +1172,10 @@ void R_InitColormaps (void)
byte *playpal;
int c, i, j = 0;
byte r, g, b;
extern byte **gamma2table;

// [crispy] intermediate gamma levels
if (!gamma2table)
{
extern void I_SetGammaTable (void);
I_SetGammaTable();
}

Expand Down
88 changes: 69 additions & 19 deletions src/heretic/am_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
vertex_t KeyPoints[NUM_KEY_TYPES];

#define NUMALIAS 3 // Number of antialiased lines.
// [crispy] precalculated color LUT for antialiased line drawing using COLORMAP
#define NUMSHADES 8

Check warning on line 37 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:37:9 [modernize-macro-to-enum]

macro 'NUMSHADES' defines an integral constant; prefer an enum instead
static pixel_t color_shades[NUMSHADES * 256];

Check warning on line 38 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:38:16 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'color_shades' is non-const and globally accessible, consider making it const

const char *LevelNames[] = {
// EPISODE 1 - THE CITY OF THE DAMNED
Expand Down Expand Up @@ -100,7 +103,7 @@ static int finit_height;// = SCREENHEIGHT - (42 << crispy->hires);
static int f_x, f_y; // location of window on screen
static int f_w, f_h; // size of window on screen
static int lightlev; // used for funky strobing effect
static byte *fb; // pseudo-frame buffer
static pixel_t *fb; // pseudo-frame buffer

Check warning on line 106 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:106:17 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'fb' is non-const and globally accessible, consider making it const

Check warning on line 106 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:106:17 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'fb' provides global access to a non-const object; consider making the pointed-to data 'const'

Check warning on line 106 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:106:17 [readability-identifier-length]

variable name 'fb' is too short, expected at least 3 characters
static int amclock;

static mpoint_t m_paninc; // how far the window pans each tic (map coords)
Expand Down Expand Up @@ -152,21 +155,17 @@ static char cheat_amap[] = { 'r', 'a', 'v', 'm', 'a', 'p' };

static byte cheatcount = 0;

// [crispy] gradient table for map normal mode
static byte antialias_normal[NUMALIAS][8] = {
{96, 97, 98, 99, 100, 101, 102, 103},
{110, 109, 108, 107, 106, 105, 104, 103},
{75, 76, 77, 78, 79, 80, 81, 103}
// [crispy] line colors for map normal mode
static byte antialias_normal[NUMALIAS] = {

Check warning on line 159 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:159:13 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'antialias_normal' is non-const and globally accessible, consider making it const
96, 110, 75
};

// [crispy] gradient table for map overlay mode
static byte antialias_overlay[NUMALIAS][8] = {
{100, 99, 98, 97, 96, 95, 95, 95},
{110, 109, 108, 105, 102, 99, 97, 95},
{75, 74, 73, 72, 71, 70, 69, 95}
// [crispy] line colors for map overlay mode
static byte antialias_overlay[NUMALIAS] = {

Check warning on line 164 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:164:13 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'antialias_overlay' is non-const and globally accessible, consider making it const
100, 110, 75
};

static byte (*antialias)[NUMALIAS][8]; // [crispy]
static byte (*antialias)[NUMALIAS]; // [crispy]

Check warning on line 168 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:168:15 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'antialias' is non-const and globally accessible, consider making it const

Check warning on line 168 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:168:15 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'antialias' provides global access to a non-const object; consider making the pointed-to data 'const'
/*
static byte *aliasmax[NUMALIAS] = {
&antialias[0][7], &antialias[1][7], &antialias[2][7]
Expand Down Expand Up @@ -197,7 +196,7 @@ extern fixed_t fractionaltic;

// Functions

void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor,
void DrawWuLine(int X0, int Y0, int X1, int Y1, int Color,

Check warning on line 199 in src/heretic/am_map.c

View workflow job for this annotation

GitHub Actions / cpp-linter (clang)

/src/heretic/am_map.c:199:21 [readability-identifier-length]

parameter name 'X0' is too short, expected at least 3 characters
int NumLevels, unsigned short IntensityBits);

// Calculates the slope and slope according to the x-axis of a line
Expand Down Expand Up @@ -543,6 +542,8 @@ void AM_LevelInit(boolean reinit)
{
// [crispy] Used for reinit
static int f_h_old;
// [crispy] Only need to precalculate color lookup tables once
static boolean precalc_once;

finit_width = SCREENWIDTH;
finit_height = SCREENHEIGHT - (42 << crispy->hires);
Expand Down Expand Up @@ -574,6 +575,26 @@ void AM_LevelInit(boolean reinit)
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);

f_h_old = f_h;

// [crispy] Precalculate color lookup tables for antialiased line drawing using COLORMAP
if (!precalc_once)
{
precalc_once = true;
for (int color = 0; color < 256; ++color)
{
#define REINDEX(I) (color + I * 256)
// Pick a range of shades for a steep gradient to keep lines thin
int shade_index[NUMSHADES] =
{
REINDEX(0), REINDEX(1), REINDEX(2), REINDEX(3), REINDEX(4), REINDEX(5), REINDEX(6), REINDEX(7),
};
#undef REINDEX
for (int shade = 0; shade < NUMSHADES; ++shade)
{
color_shades[color * NUMSHADES + shade] = colormaps[shade_index[shade]];
}
}
}
}

static boolean stopped = true;
Expand Down Expand Up @@ -1089,6 +1110,7 @@ void AM_clearFB(int color)

for (i = 0; i < finit_height; i++)
{
#ifndef CRISPY_TRUECOLOR
memcpy(I_VideoBuffer + i * finit_width,
maplump + j + (MAPBGROUNDWIDTH << crispy->hires) - x3, x3);

Expand All @@ -1097,7 +1119,30 @@ void AM_clearFB(int color)

memcpy(I_VideoBuffer + i * finit_width + x2 + x3,
maplump + j, x1);
#else
int z;
pixel_t *dest = I_VideoBuffer + i * finit_width;
byte *src = maplump + j + (MAPBGROUNDWIDTH << crispy->hires) - x3;

for (z = 0; z < x3; z++)
{
dest[z] = colormaps[src[z]];
}

dest += x3;
src += x3 - x2;
for (z = 0; z < x2; z++)
{
dest[z] = colormaps[src[z]];
}

dest += x2;
src = maplump + j;
for (z = 0; z < x1; z++)
{
dest[z] = colormaps[src[z]];
}
#endif
j += MAPBGROUNDWIDTH << crispy->hires;
if (j >= MAPBGROUNDHEIGHT * MAPBGROUNDWIDTH)
j = 0;
Expand Down Expand Up @@ -1227,15 +1272,15 @@ void AM_drawFline(fline_t * fl, int color)
switch (color)
{
case WALLCOLORS:
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &(*antialias)[0][0],
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, (*antialias)[0],
8, 3);
break;
case FDWALLCOLORS:
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &(*antialias)[1][0],
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, (*antialias)[1],
8, 3);
break;
case CDWALLCOLORS:
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &(*antialias)[2][0],
DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, (*antialias)[2],
8, 3);
break;
default:
Expand All @@ -1250,7 +1295,11 @@ void AM_drawFline(fline_t * fl, int color)
return;
}

#ifndef CRISPY_TRUECOLOR
#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO!
#else
#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(colormaps[cc])
#endif

dx = fl->b.x - fl->a.x;
ax = 2 * (dx < 0 ? -dx : dx);
Expand Down Expand Up @@ -1310,11 +1359,11 @@ void AM_drawFline(fline_t * fl, int color)
* IntensityBits = log base 2 of NumLevels; the # of bits used to describe
* the intensity of the drawing color. 2**IntensityBits==NumLevels
*/
void PUTDOT(short xx, short yy, byte * cc, byte * cm)
void PUTDOT(short xx, short yy, pixel_t * cc, pixel_t * cm)
{
static int oldyy;
static int oldyyshifted;
byte *oldcc = cc;
pixel_t *oldcc = cc;

if (xx < 32)
cc += 7 - (xx >> 2);
Expand Down Expand Up @@ -1354,12 +1403,13 @@ void PUTDOT(short xx, short yy, byte * cc, byte * cm)
// fb[(yy)*f_w+(xx)]=*(cc);
}

void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor,
void DrawWuLine(int X0, int Y0, int X1, int Y1, int Color,
int NumLevels, unsigned short IntensityBits)
{
unsigned short IntensityShift, ErrorAdj, ErrorAcc;
unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
short DeltaX, DeltaY, Temp, XDir;
pixel_t *BaseColor = &color_shades[Color * NUMSHADES];

/* Make sure the line runs top to bottom */
if (Y0 > Y1)
Expand Down
3 changes: 3 additions & 0 deletions src/heretic/d_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,9 @@ void D_BindVariables(void)
M_BindIntVariable("crispy_playercoords", &crispy->playercoords);
M_BindIntVariable("crispy_secretmessage", &crispy->secretmessage);
M_BindIntVariable("crispy_soundmono", &crispy->soundmono);
#ifdef CRISPY_TRUECOLOR
M_BindIntVariable("crispy_truecolor", &crispy->truecolor);
#endif
M_BindIntVariable("crispy_uncapped", &crispy->uncapped);
M_BindIntVariable("crispy_vsync", &crispy->vsync);
M_BindIntVariable("crispy_widescreen", &crispy->widescreen);
Expand Down
21 changes: 19 additions & 2 deletions src/heretic/f_finale.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ void F_Ticker(void)

void F_TextWrite(void)
{
byte *src, *dest;
byte *src;
pixel_t *dest;
int x, y;
int count;
const char *ch;
Expand All @@ -164,6 +165,7 @@ void F_TextWrite(void)
dest = I_VideoBuffer;
for (y = 0; y < SCREENHEIGHT; y++)
{
#ifndef CRISPY_TRUECOLOR
for (x = 0; x < SCREENWIDTH / 64; x++)
{
memcpy(dest, src + ((y & 63) << 6), 64);
Expand All @@ -174,6 +176,12 @@ void F_TextWrite(void)
memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
dest += (SCREENWIDTH & 63);
}
#else
for (x = 0; x < SCREENWIDTH; x++)
{
*dest++ = colormaps[src[((y & 63) << 6) + (x & 63)]];
}
#endif
}

// V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
Expand Down Expand Up @@ -220,7 +228,8 @@ void F_TextWrite(void)
void F_DrawPatchCol(int x, patch_t * patch, int col)
{
column_t *column;
byte *source, *dest, *desttop;
byte *source;
pixel_t *dest, *desttop;
int count;

column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col]));
Expand Down Expand Up @@ -342,7 +351,11 @@ void F_DrawUnderwater(void)
V_DrawFilledBox(0, 0, SCREENWIDTH, SCREENHEIGHT, 0);
lumpname = DEH_String("E2PAL");
palette = W_CacheLumpName(lumpname, PU_STATIC);
#ifndef CRISPY_TRUECOLOR
I_SetPalette(palette);
#else
R_SetUnderwaterPalette(palette);
#endif
W_ReleaseLumpName(lumpname);
V_DrawFullscreenRawOrPatch(W_GetNumForName(DEH_String("E2END")));
}
Expand All @@ -354,10 +367,14 @@ void F_DrawUnderwater(void)
case 2:
if (underwawa)
{
#ifndef CRISPY_TRUECOLOR
lumpname = DEH_String("PLAYPAL");
palette = W_CacheLumpName(lumpname, PU_STATIC);
I_SetPalette(palette);
W_ReleaseLumpName(lumpname);
#else
R_InitColormaps();
#endif
underwawa = false;
}
V_DrawFullscreenRawOrPatch(W_GetNumForName(DEH_String("TITLE")));
Expand Down
13 changes: 12 additions & 1 deletion src/heretic/in_lude.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ static const char *NameForMap(int map)

void IN_Start(void)
{
#ifndef CRISPY_TRUECOLOR
I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE));
#else
I_SetPalette(0);
#endif
IN_LoadPics();
IN_InitStats();
intermission = true;
Expand Down Expand Up @@ -618,13 +622,14 @@ void IN_DrawStatBack(void)
int y;

byte *src;
byte *dest;
pixel_t *dest;

src = W_CacheLumpName(DEH_String("FLOOR16"), PU_CACHE);
dest = I_VideoBuffer;

for (y = 0; y < SCREENHEIGHT; y++)
{
#ifndef CRISPY_TRUECOLOR
for (x = 0; x < SCREENWIDTH / 64; x++)
{
memcpy(dest, src + ((y & 63) << 6), 64);
Expand All @@ -635,6 +640,12 @@ void IN_DrawStatBack(void)
memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
dest += (SCREENWIDTH & 63);
}
#else
for (x = 0; x < SCREENWIDTH; x++)
{
*dest++ = colormaps[src[((y & 63) << 6) + (x & 63)]];
}
#endif
}
}

Expand Down
25 changes: 24 additions & 1 deletion src/heretic/mn_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1792,8 +1792,12 @@ boolean MN_Responder(event_t * event)
//set the msg to be cleared
players[consoleplayer].message = NULL;
paused = false;
#ifndef CRISPY_TRUECOLOR
I_SetPalette(W_CacheLumpName
("PLAYPAL", PU_CACHE));
#else
I_SetPalette(0);
#endif
D_StartTitle(); // go to intro/demo mode.
break;

Expand Down Expand Up @@ -2028,7 +2032,14 @@ boolean MN_Responder(event_t * event)
{
usegamma = 0;
}
#ifndef CRISPY_TRUECOLOR
I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE));
#else
I_SetPalette(0);
R_InitColormaps();
BorderNeedRefresh = true;
SB_state = -1;
#endif
return true;
}
// [crispy] those two can be considered as shortcuts for the ENGAGE cheat
Expand Down Expand Up @@ -2438,7 +2449,11 @@ void MN_DrawInfo(void)
{
lumpindex_t lumpindex; // [crispy]

#ifndef CRISPY_TRUECOLOR
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
#else
I_SetPalette(0);
#endif

// [crispy] Refactor to allow for use of V_DrawFullscreenRawOrPatch

Expand Down Expand Up @@ -2543,7 +2558,8 @@ static void DrawMouseMenu(void)

static void M_DrawCrispnessBackground(void)
{
byte *src, *dest;
byte *src;
pixel_t *dest;
int x, y;

if (gamemode == shareware)
Expand All @@ -2558,6 +2574,7 @@ static void M_DrawCrispnessBackground(void)

for (y = 0; y < SCREENHEIGHT; y++)
{
#ifndef CRISPY_TRUECOLOR
for (x = 0; x < SCREENWIDTH / 64; x++)
{
memcpy(dest, src + ((y & 63) << 6), 64);
Expand All @@ -2568,6 +2585,12 @@ static void M_DrawCrispnessBackground(void)
memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
dest += (SCREENWIDTH & 63);
}
#else
for (x = 0; x < SCREENWIDTH; x++)
{
*dest++ = colormaps[src[(y & 63) * 64 + (x & 63)]];
}
#endif
}

SB_state = -1;
Expand Down
Loading

0 comments on commit f9ddf41

Please sign in to comment.