2014-03-15 16:59:03 +00:00
|
|
|
// SONIC ROBO BLAST 2
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
2022-03-03 19:24:46 +00:00
|
|
|
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// This program is free software distributed under the
|
|
|
|
// terms of the GNU General Public License, version 2.
|
|
|
|
// See the 'LICENSE' file for more details.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/// \file v_video.c
|
|
|
|
/// \brief Gamma correction LUT stuff
|
|
|
|
/// Functions to draw patches (by post) directly to screen.
|
|
|
|
/// Functions to blit a block to the screen.
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "r_local.h"
|
2018-01-20 22:14:24 +00:00
|
|
|
#include "p_local.h" // stplyr
|
|
|
|
#include "g_game.h" // players
|
2014-03-15 16:59:03 +00:00
|
|
|
#include "v_video.h"
|
2019-11-18 14:39:54 +00:00
|
|
|
#include "st_stuff.h"
|
2014-03-15 16:59:03 +00:00
|
|
|
#include "hu_stuff.h"
|
2019-11-23 21:15:09 +00:00
|
|
|
#include "f_finale.h"
|
2014-03-15 16:59:03 +00:00
|
|
|
#include "r_draw.h"
|
|
|
|
#include "console.h"
|
|
|
|
|
|
|
|
#include "i_video.h" // rendermode
|
|
|
|
#include "z_zone.h"
|
|
|
|
#include "m_misc.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
#include "hardware/hw_glob.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Each screen is [vid.width*vid.height];
|
|
|
|
UINT8 *screens[5];
|
|
|
|
// screens[0] = main display window
|
|
|
|
// screens[1] = back screen, alternative blitting
|
|
|
|
// screens[2] = screenshot buffer, gif movie buffer
|
|
|
|
// screens[3] = fade screen start
|
|
|
|
// screens[4] = fade screen end, postimage tempoarary buffer
|
|
|
|
|
2020-05-08 13:40:50 +00:00
|
|
|
static CV_PossibleValue_t ticrate_cons_t[] = {{0, "No"}, {1, "Full"}, {2, "Compact"}, {0, NULL}};
|
2020-10-07 06:04:23 +00:00
|
|
|
consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", CV_SAVE, ticrate_cons_t, NULL);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2017-04-19 21:24:28 +00:00
|
|
|
static void CV_palette_OnChange(void);
|
|
|
|
|
|
|
|
static CV_PossibleValue_t gamma_cons_t[] = {{-15, "MIN"}, {5, "MAX"}, {0, NULL}};
|
2020-10-07 06:04:23 +00:00
|
|
|
consvar_t cv_globalgamma = CVAR_INIT ("gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2017-04-18 22:21:10 +00:00
|
|
|
static CV_PossibleValue_t saturation_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
|
2020-10-07 06:04:23 +00:00
|
|
|
consvar_t cv_globalsaturation = CVAR_INIT ("saturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
2017-04-19 21:24:28 +00:00
|
|
|
|
|
|
|
#define huecoloursteps 4
|
|
|
|
|
|
|
|
static CV_PossibleValue_t hue_cons_t[] = {{0, "MIN"}, {(huecoloursteps*6)-1, "MAX"}, {0, NULL}};
|
2020-10-07 06:04:23 +00:00
|
|
|
consvar_t cv_rhue = CVAR_INIT ("rhue", "0", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_yhue = CVAR_INIT ("yhue", "4", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_ghue = CVAR_INIT ("ghue", "8", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_chue = CVAR_INIT ("chue", "12", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_bhue = CVAR_INIT ("bhue", "16", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_mhue = CVAR_INIT ("mhue", "20", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange);
|
|
|
|
|
|
|
|
consvar_t cv_rgamma = CVAR_INIT ("rgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_ygamma = CVAR_INIT ("ygamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_ggamma = CVAR_INIT ("ggamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_cgamma = CVAR_INIT ("cgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_bgamma = CVAR_INIT ("bgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_mgamma = CVAR_INIT ("mgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange);
|
|
|
|
|
|
|
|
consvar_t cv_rsaturation = CVAR_INIT ("rsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_ysaturation = CVAR_INIT ("ysaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_gsaturation = CVAR_INIT ("gsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_csaturation = CVAR_INIT ("csaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_bsaturation = CVAR_INIT ("bsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
|
|
|
consvar_t cv_msaturation = CVAR_INIT ("msaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
static CV_PossibleValue_t constextsize_cons_t[] = {
|
|
|
|
{V_NOSCALEPATCH, "Small"}, {V_SMALLSCALEPATCH, "Medium"}, {V_MEDSCALEPATCH, "Large"}, {0, "Huge"},
|
|
|
|
{0, NULL}};
|
|
|
|
static void CV_constextsize_OnChange(void);
|
2020-10-07 06:04:23 +00:00
|
|
|
consvar_t cv_constextsize = CVAR_INIT ("con_textsize", "Medium", CV_SAVE|CV_CALL, constextsize_cons_t, CV_constextsize_OnChange);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// local copy of the palette for V_GetColor()
|
|
|
|
RGBA_t *pLocalPalette = NULL;
|
2017-04-29 15:40:07 +00:00
|
|
|
RGBA_t *pMasterPalette = NULL;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2017-04-18 22:21:10 +00:00
|
|
|
/*
|
|
|
|
The following was an extremely helpful resource when developing my Colour Cube LUT.
|
|
|
|
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html
|
|
|
|
Please check it out if you're trying to maintain this.
|
|
|
|
toast 18/04/17
|
|
|
|
*/
|
|
|
|
float Cubepal[2][2][2][3];
|
2019-12-13 02:18:39 +00:00
|
|
|
boolean Cubeapply = false;
|
2017-04-18 22:21:10 +00:00
|
|
|
|
|
|
|
// returns whether to apply cube, selectively avoiding expensive operations
|
|
|
|
static boolean InitCube(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2017-04-18 22:21:10 +00:00
|
|
|
boolean apply = false;
|
|
|
|
UINT8 q;
|
|
|
|
float working[2][2][2][3] = // the initial positions of the corners of the colour cube!
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{0.0, 0.0, 0.0}, // black corner
|
2017-04-18 22:38:38 +00:00
|
|
|
{0.0, 0.0, 1.0} // blue corner
|
2017-04-18 22:21:10 +00:00
|
|
|
},
|
|
|
|
{
|
2017-04-18 22:40:57 +00:00
|
|
|
{0.0, 1.0, 0.0}, // green corner
|
2017-04-18 22:38:38 +00:00
|
|
|
{0.0, 1.0, 1.0} // cyan corner
|
2017-04-18 22:21:10 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
2017-04-18 22:38:38 +00:00
|
|
|
{1.0, 0.0, 0.0}, // red corner
|
2017-04-18 22:21:10 +00:00
|
|
|
{1.0, 0.0, 1.0} // magenta corner
|
|
|
|
},
|
|
|
|
{
|
2017-04-18 22:38:38 +00:00
|
|
|
{1.0, 1.0, 0.0}, // yellow corner
|
2017-04-18 22:21:10 +00:00
|
|
|
{1.0, 1.0, 1.0} // white corner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2017-04-19 21:24:28 +00:00
|
|
|
float desatur[3]; // grey
|
|
|
|
float globalgammamul, globalgammaoffs;
|
|
|
|
boolean doinggamma;
|
|
|
|
|
|
|
|
#define diffcons(cv) (cv.value != atoi(cv.defaultvalue))
|
|
|
|
|
|
|
|
doinggamma = diffcons(cv_globalgamma);
|
2017-04-18 22:21:10 +00:00
|
|
|
|
|
|
|
#define gammascale 8
|
2017-04-19 21:24:28 +00:00
|
|
|
globalgammamul = (cv_globalgamma.value ? ((255 - (gammascale*abs(cv_globalgamma.value)))/255.0) : 1.0);
|
|
|
|
globalgammaoffs = ((cv_globalgamma.value > 0) ? ((gammascale*cv_globalgamma.value)/255.0) : 0.0);
|
|
|
|
desatur[0] = desatur[1] = desatur[2] = globalgammaoffs + (0.33*globalgammamul);
|
|
|
|
|
|
|
|
if (doinggamma
|
|
|
|
|| diffcons(cv_rhue)
|
|
|
|
|| diffcons(cv_yhue)
|
|
|
|
|| diffcons(cv_ghue)
|
|
|
|
|| diffcons(cv_chue)
|
|
|
|
|| diffcons(cv_bhue)
|
|
|
|
|| diffcons(cv_mhue)
|
|
|
|
|| diffcons(cv_rgamma)
|
|
|
|
|| diffcons(cv_ygamma)
|
|
|
|
|| diffcons(cv_ggamma)
|
|
|
|
|| diffcons(cv_cgamma)
|
|
|
|
|| diffcons(cv_bgamma)
|
2017-04-20 12:15:32 +00:00
|
|
|
|| diffcons(cv_mgamma)) // set the gamma'd/hued positions (saturation is done later)
|
2017-04-19 21:24:28 +00:00
|
|
|
{
|
|
|
|
float mod, tempgammamul, tempgammaoffs;
|
2017-04-18 22:21:10 +00:00
|
|
|
|
|
|
|
apply = true;
|
|
|
|
|
2017-04-19 21:24:28 +00:00
|
|
|
working[0][0][0][0] = working[0][0][0][1] = working[0][0][0][2] = globalgammaoffs;
|
|
|
|
working[1][1][1][0] = working[1][1][1][1] = working[1][1][1][2] = globalgammaoffs+globalgammamul;
|
|
|
|
|
|
|
|
#define dohue(hue, gamma, loc) \
|
|
|
|
tempgammamul = (gamma ? ((255 - (gammascale*abs(gamma)))/255.0)*globalgammamul : globalgammamul);\
|
|
|
|
tempgammaoffs = ((gamma > 0) ? ((gammascale*gamma)/255.0) + globalgammaoffs : globalgammaoffs);\
|
|
|
|
mod = ((hue % huecoloursteps)*(tempgammamul)/huecoloursteps);\
|
|
|
|
switch (hue/huecoloursteps)\
|
|
|
|
{\
|
|
|
|
case 0:\
|
|
|
|
default:\
|
|
|
|
loc[0] = tempgammaoffs+tempgammamul;\
|
|
|
|
loc[1] = tempgammaoffs+mod;\
|
|
|
|
loc[2] = tempgammaoffs;\
|
|
|
|
break;\
|
|
|
|
case 1:\
|
|
|
|
loc[0] = tempgammaoffs+tempgammamul-mod;\
|
|
|
|
loc[1] = tempgammaoffs+tempgammamul;\
|
|
|
|
loc[2] = tempgammaoffs;\
|
|
|
|
break;\
|
|
|
|
case 2:\
|
|
|
|
loc[0] = tempgammaoffs;\
|
|
|
|
loc[1] = tempgammaoffs+tempgammamul;\
|
|
|
|
loc[2] = tempgammaoffs+mod;\
|
|
|
|
break;\
|
|
|
|
case 3:\
|
|
|
|
loc[0] = tempgammaoffs;\
|
|
|
|
loc[1] = tempgammaoffs+tempgammamul-mod;\
|
|
|
|
loc[2] = tempgammaoffs+tempgammamul;\
|
|
|
|
break;\
|
|
|
|
case 4:\
|
|
|
|
loc[0] = tempgammaoffs+mod;\
|
|
|
|
loc[1] = tempgammaoffs;\
|
|
|
|
loc[2] = tempgammaoffs+tempgammamul;\
|
|
|
|
break;\
|
|
|
|
case 5:\
|
|
|
|
loc[0] = tempgammaoffs+tempgammamul;\
|
|
|
|
loc[1] = tempgammaoffs;\
|
|
|
|
loc[2] = tempgammaoffs+tempgammamul-mod;\
|
|
|
|
break;\
|
2017-04-18 22:21:10 +00:00
|
|
|
}
|
2017-04-19 21:24:28 +00:00
|
|
|
dohue(cv_rhue.value, cv_rgamma.value, working[1][0][0]);
|
|
|
|
dohue(cv_yhue.value, cv_ygamma.value, working[1][1][0]);
|
|
|
|
dohue(cv_ghue.value, cv_ggamma.value, working[0][1][0]);
|
|
|
|
dohue(cv_chue.value, cv_cgamma.value, working[0][1][1]);
|
|
|
|
dohue(cv_bhue.value, cv_bgamma.value, working[0][0][1]);
|
|
|
|
dohue(cv_mhue.value, cv_mgamma.value, working[1][0][1]);
|
|
|
|
#undef dohue
|
2017-04-18 22:21:10 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 21:24:28 +00:00
|
|
|
#define dosaturation(a, e) a = ((1 - work)*e + work*a)
|
|
|
|
#define docvsat(cv_sat, hue, gamma, r, g, b) \
|
|
|
|
if diffcons(cv_sat)\
|
|
|
|
{\
|
|
|
|
float work, mod, tempgammamul, tempgammaoffs;\
|
|
|
|
apply = true;\
|
|
|
|
work = (cv_sat.value/10.0);\
|
|
|
|
mod = ((hue % huecoloursteps)*(1.0)/huecoloursteps);\
|
|
|
|
if (hue & huecoloursteps)\
|
|
|
|
mod = 2-mod;\
|
|
|
|
else\
|
|
|
|
mod += 1;\
|
|
|
|
tempgammamul = (gamma ? ((255 - (gammascale*abs(gamma)))/255.0)*globalgammamul : globalgammamul);\
|
|
|
|
tempgammaoffs = ((gamma > 0) ? ((gammascale*gamma)/255.0) + globalgammaoffs : globalgammaoffs);\
|
|
|
|
for (q = 0; q < 3; q++)\
|
|
|
|
dosaturation(working[r][g][b][q], (tempgammaoffs+(desatur[q]*mod*tempgammamul)));\
|
|
|
|
}
|
|
|
|
|
|
|
|
docvsat(cv_rsaturation, cv_rhue.value, cv_rgamma.value, 1, 0, 0);
|
|
|
|
docvsat(cv_ysaturation, cv_yhue.value, cv_ygamma.value, 1, 1, 0);
|
|
|
|
docvsat(cv_gsaturation, cv_ghue.value, cv_ggamma.value, 0, 1, 0);
|
|
|
|
docvsat(cv_csaturation, cv_chue.value, cv_cgamma.value, 0, 1, 1);
|
|
|
|
docvsat(cv_bsaturation, cv_bhue.value, cv_bgamma.value, 0, 0, 1);
|
|
|
|
docvsat(cv_msaturation, cv_mhue.value, cv_mgamma.value, 1, 0, 1);
|
|
|
|
|
|
|
|
#undef gammascale
|
|
|
|
|
|
|
|
if diffcons(cv_globalsaturation)
|
2017-04-18 22:21:10 +00:00
|
|
|
{
|
2017-04-19 21:24:28 +00:00
|
|
|
float work = (cv_globalsaturation.value/10.0);
|
2017-04-18 22:21:10 +00:00
|
|
|
|
|
|
|
apply = true;
|
|
|
|
|
|
|
|
for (q = 0; q < 3; q++)
|
|
|
|
{
|
|
|
|
dosaturation(working[1][0][0][q], desatur[q]);
|
2017-04-19 21:24:28 +00:00
|
|
|
dosaturation(working[0][1][0][q], desatur[q]);
|
|
|
|
dosaturation(working[0][0][1][q], desatur[q]);
|
2017-04-18 22:21:10 +00:00
|
|
|
|
|
|
|
dosaturation(working[1][1][0][q], 2*desatur[q]);
|
|
|
|
dosaturation(working[0][1][1][q], 2*desatur[q]);
|
2017-04-19 21:24:28 +00:00
|
|
|
dosaturation(working[1][0][1][q], 2*desatur[q]);
|
2017-04-18 22:21:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-19 21:24:28 +00:00
|
|
|
#undef dosaturation
|
|
|
|
|
|
|
|
#undef diffcons
|
|
|
|
|
2017-04-18 22:21:10 +00:00
|
|
|
if (!apply)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
#define dowork(i, j, k, l) \
|
|
|
|
if (working[i][j][k][l] > 1.0)\
|
|
|
|
working[i][j][k][l] = 1.0;\
|
|
|
|
else if (working[i][j][k][l] < 0.0)\
|
|
|
|
working[i][j][k][l] = 0.0;\
|
|
|
|
Cubepal[i][j][k][l] = working[i][j][k][l]
|
|
|
|
for (q = 0; q < 3; q++)
|
|
|
|
{
|
|
|
|
dowork(0, 0, 0, q);
|
|
|
|
dowork(1, 0, 0, q);
|
|
|
|
dowork(0, 1, 0, q);
|
|
|
|
dowork(1, 1, 0, q);
|
|
|
|
dowork(0, 0, 1, q);
|
|
|
|
dowork(1, 0, 1, q);
|
|
|
|
dowork(0, 1, 1, q);
|
|
|
|
dowork(1, 1, 1, q);
|
|
|
|
}
|
|
|
|
#undef dowork
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
#ifdef BACKWARDSCOMPATCORRECTION
|
2017-04-20 12:15:32 +00:00
|
|
|
/*
|
|
|
|
So it turns out that the way gamma was implemented previously, the default
|
|
|
|
colour profile of the game was messed up. Since this bad decision has been
|
|
|
|
around for a long time, and the intent is to keep the base game looking the
|
|
|
|
same, I'm not gonna be the one to remove this base modification.
|
|
|
|
toast 20/04/17
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
... welp yes i am (27/07/19, see the ifdef around it)
|
2017-04-20 12:15:32 +00:00
|
|
|
*/
|
|
|
|
const UINT8 correctiontable[256] =
|
2014-03-15 16:59:03 +00:00
|
|
|
{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,
|
2017-04-20 12:15:32 +00:00
|
|
|
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
#endif
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// keep a copy of the palette so that we can get the RGB value for a color index at any time.
|
|
|
|
static void LoadPalette(const char *lumpname)
|
|
|
|
{
|
|
|
|
lumpnum_t lumpnum = W_GetNumForName(lumpname);
|
|
|
|
size_t i, palsize = W_LumpLength(lumpnum)/3;
|
|
|
|
UINT8 *pal;
|
|
|
|
|
2019-12-14 20:55:11 +00:00
|
|
|
Cubeapply = InitCube();
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
Z_Free(pLocalPalette);
|
2017-04-29 15:40:07 +00:00
|
|
|
Z_Free(pMasterPalette);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
pLocalPalette = Z_Malloc(sizeof (*pLocalPalette)*palsize, PU_STATIC, NULL);
|
2017-04-29 15:40:07 +00:00
|
|
|
pMasterPalette = Z_Malloc(sizeof (*pMasterPalette)*palsize, PU_STATIC, NULL);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
pal = W_CacheLumpNum(lumpnum, PU_CACHE);
|
|
|
|
for (i = 0; i < palsize; i++)
|
|
|
|
{
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
#ifdef BACKWARDSCOMPATCORRECTION
|
2017-04-29 15:40:07 +00:00
|
|
|
pMasterPalette[i].s.red = pLocalPalette[i].s.red = correctiontable[*pal++];
|
|
|
|
pMasterPalette[i].s.green = pLocalPalette[i].s.green = correctiontable[*pal++];
|
|
|
|
pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = correctiontable[*pal++];
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
#else
|
|
|
|
pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++;
|
|
|
|
pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++;
|
|
|
|
pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++;
|
|
|
|
#endif
|
2017-04-29 15:40:07 +00:00
|
|
|
pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF;
|
2017-04-18 22:21:10 +00:00
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
// lerp of colour cubing! if you want, make it smoother yourself
|
2019-12-13 02:30:09 +00:00
|
|
|
if (Cubeapply)
|
|
|
|
V_CubeApply(&pLocalPalette[i].s.red, &pLocalPalette[i].s.green, &pLocalPalette[i].s.blue);
|
2019-12-13 02:18:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue)
|
|
|
|
{
|
|
|
|
float working[4][3];
|
|
|
|
float linear;
|
|
|
|
UINT8 q;
|
2017-04-18 22:21:10 +00:00
|
|
|
|
2019-12-13 02:18:39 +00:00
|
|
|
if (!Cubeapply)
|
|
|
|
return;
|
|
|
|
|
|
|
|
linear = (*red/255.0);
|
2017-04-18 22:21:10 +00:00
|
|
|
#define dolerp(e1, e2) ((1 - linear)*e1 + linear*e2)
|
2019-12-13 02:18:39 +00:00
|
|
|
for (q = 0; q < 3; q++)
|
|
|
|
{
|
|
|
|
working[0][q] = dolerp(Cubepal[0][0][0][q], Cubepal[1][0][0][q]);
|
|
|
|
working[1][q] = dolerp(Cubepal[0][1][0][q], Cubepal[1][1][0][q]);
|
|
|
|
working[2][q] = dolerp(Cubepal[0][0][1][q], Cubepal[1][0][1][q]);
|
|
|
|
working[3][q] = dolerp(Cubepal[0][1][1][q], Cubepal[1][1][1][q]);
|
|
|
|
}
|
|
|
|
linear = (*green/255.0);
|
|
|
|
for (q = 0; q < 3; q++)
|
|
|
|
{
|
|
|
|
working[0][q] = dolerp(working[0][q], working[1][q]);
|
|
|
|
working[1][q] = dolerp(working[2][q], working[3][q]);
|
|
|
|
}
|
|
|
|
linear = (*blue/255.0);
|
|
|
|
for (q = 0; q < 3; q++)
|
|
|
|
{
|
|
|
|
working[0][q] = 255*dolerp(working[0][q], working[1][q]);
|
|
|
|
if (working[0][q] > 255.0)
|
|
|
|
working[0][q] = 255.0;
|
|
|
|
else if (working[0][q] < 0.0)
|
|
|
|
working[0][q] = 0.0;
|
|
|
|
}
|
2017-04-29 15:40:07 +00:00
|
|
|
#undef dolerp
|
2017-04-18 22:21:10 +00:00
|
|
|
|
2019-12-13 02:18:39 +00:00
|
|
|
*red = (UINT8)(working[0][0]);
|
|
|
|
*green = (UINT8)(working[0][1]);
|
|
|
|
*blue = (UINT8)(working[0][2]);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *R_GetPalname(UINT16 num)
|
|
|
|
{
|
|
|
|
static char palname[9];
|
|
|
|
char newpal[9] = "PLAYPAL";
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
if (num > 0 && num <= 10000)
|
2014-03-15 16:59:03 +00:00
|
|
|
snprintf(newpal, 8, "PAL%04u", num-1);
|
|
|
|
|
|
|
|
strncpy(palname, newpal, 8);
|
|
|
|
return palname;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *GetPalette(void)
|
|
|
|
{
|
|
|
|
if (gamestate == GS_LEVEL)
|
|
|
|
return R_GetPalname(mapheaderinfo[gamemap-1]->palette);
|
|
|
|
return "PLAYPAL";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void LoadMapPalette(void)
|
|
|
|
{
|
|
|
|
LoadPalette(GetPalette());
|
|
|
|
}
|
|
|
|
|
|
|
|
// -------------+
|
|
|
|
// V_SetPalette : Set the current palette to use for palettized graphics
|
|
|
|
// :
|
|
|
|
// -------------+
|
|
|
|
void V_SetPalette(INT32 palettenum)
|
|
|
|
{
|
|
|
|
if (!pLocalPalette)
|
|
|
|
LoadMapPalette();
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
HWR_SetPalette(&pLocalPalette[palettenum*256]);
|
2021-03-30 18:27:10 +00:00
|
|
|
#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
if (rendermode != render_none)
|
|
|
|
I_SetPalette(&pLocalPalette[palettenum*256]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void V_SetPaletteLump(const char *pal)
|
|
|
|
{
|
|
|
|
LoadPalette(pal);
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
HWR_SetPalette(pLocalPalette);
|
2021-03-30 18:27:10 +00:00
|
|
|
#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
if (rendermode != render_none)
|
|
|
|
I_SetPalette(pLocalPalette);
|
|
|
|
}
|
|
|
|
|
2017-04-19 21:24:28 +00:00
|
|
|
static void CV_palette_OnChange(void)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
// reload palette
|
|
|
|
LoadMapPalette();
|
|
|
|
V_SetPalette(0);
|
|
|
|
}
|
|
|
|
|
2017-01-06 20:26:10 +00:00
|
|
|
#if defined (__GNUC__) && defined (__i386__) && !defined (NOASM) && !defined (__APPLE__) && !defined (NORUSEASM)
|
2014-03-15 16:59:03 +00:00
|
|
|
void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes,
|
|
|
|
size_t destrowbytes);
|
|
|
|
#define HAVE_VIDCOPY
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void CV_constextsize_OnChange(void)
|
|
|
|
{
|
2021-05-02 05:03:35 +00:00
|
|
|
if (!con_refresh)
|
|
|
|
con_recalc = true;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Copy a rectangular area from one bitmap to another (8bpp)
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes,
|
|
|
|
size_t destrowbytes)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_VIDCOPY
|
|
|
|
VID_BlitLinearScreen_ASM(srcptr,destptr,width,height,srcrowbytes,destrowbytes);
|
|
|
|
#else
|
|
|
|
if (srcrowbytes == destrowbytes)
|
|
|
|
M_Memcpy(destptr, srcptr, srcrowbytes * height);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (height--)
|
|
|
|
{
|
|
|
|
M_Memcpy(destptr, srcptr, width);
|
|
|
|
|
|
|
|
destptr += destrowbytes;
|
|
|
|
srcptr += srcrowbytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0};
|
|
|
|
static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5};
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
static const UINT8 *v_colormap = NULL;
|
|
|
|
static const UINT8 *v_translevel = NULL;
|
|
|
|
|
|
|
|
static inline UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
|
|
|
|
{
|
|
|
|
(void)dest; return source[ofs>>FRACBITS];
|
|
|
|
}
|
|
|
|
static inline UINT8 mappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
|
|
|
|
{
|
|
|
|
(void)dest; return *(v_colormap + source[ofs>>FRACBITS]);
|
|
|
|
}
|
|
|
|
static inline UINT8 translucentpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
|
|
|
|
{
|
|
|
|
return *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff));
|
|
|
|
}
|
|
|
|
static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
|
|
|
|
{
|
|
|
|
return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff));
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
// Draws a patch scaled to arbitrary size.
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
2021-11-15 18:07:20 +00:00
|
|
|
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
|
|
|
|
UINT32 blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT);
|
2014-03-21 18:42:55 +00:00
|
|
|
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
fixed_t col, ofs, colfrac, rowfrac, fdup, vdup;
|
2014-03-15 16:59:03 +00:00
|
|
|
INT32 dupx, dupy;
|
|
|
|
const column_t *column;
|
|
|
|
UINT8 *desttop, *dest, *deststart, *destend;
|
|
|
|
const UINT8 *source, *deststop;
|
2016-03-25 20:04:49 +00:00
|
|
|
fixed_t pwidth; // patch width
|
|
|
|
fixed_t offx = 0; // x offset
|
2014-03-21 18:42:55 +00:00
|
|
|
|
2018-04-06 13:42:49 +00:00
|
|
|
UINT8 perplayershuffle = 0;
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2018-11-10 18:56:13 +00:00
|
|
|
//if (rendermode != render_soft && !con_startup) // Why?
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-21 18:42:55 +00:00
|
|
|
{
|
2020-08-08 08:16:47 +00:00
|
|
|
HWR_DrawStretchyFixedPatch(patch, x, y, pscale, vscale, scrn, colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
return;
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
#endif
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
patchdrawfunc = standardpdraw;
|
|
|
|
|
|
|
|
v_translevel = NULL;
|
2022-01-19 09:09:57 +00:00
|
|
|
if (alphalevel || blendmode)
|
2014-03-21 18:42:55 +00:00
|
|
|
{
|
2022-01-19 12:17:57 +00:00
|
|
|
if (alphalevel == 10) // V_HUDTRANSHALF
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudminusalpha[st_translucency];
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 11) // V_HUDTRANS
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = 10 - st_translucency;
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudplusalpha[st_translucency];
|
2014-03-21 18:42:55 +00:00
|
|
|
|
|
|
|
if (alphalevel >= 10)
|
|
|
|
return; // invis
|
2017-10-25 15:40:21 +00:00
|
|
|
|
2022-01-19 12:17:57 +00:00
|
|
|
if (alphalevel || blendmode)
|
|
|
|
{
|
2022-01-19 09:09:57 +00:00
|
|
|
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
2017-02-10 23:24:06 +00:00
|
|
|
patchdrawfunc = translucentpdraw;
|
2022-01-19 12:17:57 +00:00
|
|
|
}
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
v_colormap = NULL;
|
|
|
|
if (colormap)
|
|
|
|
{
|
|
|
|
v_colormap = colormap;
|
|
|
|
patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
|
|
|
|
}
|
|
|
|
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT)
|
|
|
|
{
|
|
|
|
case 1: // V_NOSCALEPATCH
|
|
|
|
dupx = dupy = 1;
|
|
|
|
break;
|
|
|
|
case 2: // V_SMALLSCALEPATCH
|
|
|
|
dupx = vid.smalldupx;
|
|
|
|
dupy = vid.smalldupy;
|
|
|
|
break;
|
|
|
|
case 3: // V_MEDSCALEPATCH
|
|
|
|
dupx = vid.meddupx;
|
|
|
|
dupy = vid.meddupy;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only use one dup, to avoid stretching (har har)
|
|
|
|
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
fdup = vdup = FixedMul(dupx<<FRACBITS, pscale);
|
|
|
|
if (vscale != pscale)
|
|
|
|
vdup = FixedMul(dupx<<FRACBITS, vscale);
|
2014-03-15 16:59:03 +00:00
|
|
|
colfrac = FixedDiv(FRACUNIT, fdup);
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
rowfrac = FixedDiv(FRACUNIT, vdup);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
{
|
2018-10-29 12:06:22 +00:00
|
|
|
fixed_t offsetx = 0, offsety = 0;
|
2014-03-21 18:42:55 +00:00
|
|
|
|
2018-10-29 12:06:22 +00:00
|
|
|
// left offset
|
2014-03-21 18:42:55 +00:00
|
|
|
if (scrn & V_FLIP)
|
2020-11-22 23:02:47 +00:00
|
|
|
offsetx = FixedMul((patch->width - patch->leftoffset)<<FRACBITS, pscale) + 1;
|
2014-03-21 18:42:55 +00:00
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
offsetx = FixedMul(patch->leftoffset<<FRACBITS, pscale);
|
2018-10-29 12:06:22 +00:00
|
|
|
|
|
|
|
// top offset
|
2020-11-22 23:02:47 +00:00
|
|
|
offsety = FixedMul(patch->topoffset<<FRACBITS, vscale);
|
2018-10-29 12:06:22 +00:00
|
|
|
|
|
|
|
// Subtract the offsets from x/y positions
|
|
|
|
x -= offsetx;
|
|
|
|
y -= offsety;
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
|
|
|
|
2018-01-20 22:14:24 +00:00
|
|
|
if (splitscreen && (scrn & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
vdup >>= 1;
|
2018-01-20 22:14:24 +00:00
|
|
|
rowfrac <<= 1;
|
|
|
|
y >>= 1;
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
fdup >>= 1;
|
2018-01-20 22:14:24 +00:00
|
|
|
colfrac <<= 1;
|
|
|
|
x >>= 1;
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-20 22:14:24 +00:00
|
|
|
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-20 22:14:24 +00:00
|
|
|
else if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-20 22:14:24 +00:00
|
|
|
x += adjustx;
|
|
|
|
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[thirddisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-20 22:14:24 +00:00
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[fourthdisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-20 22:14:24 +00:00
|
|
|
x += adjustx;
|
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle = 1;
|
2018-01-20 22:14:24 +00:00
|
|
|
scrn &= ~V_SNAPTOBOTTOM;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-20 22:14:24 +00:00
|
|
|
else //if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle = 2;
|
2018-01-20 22:14:24 +00:00
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
desttop = screens[scrn&V_PARAMMASK];
|
|
|
|
|
|
|
|
if (!desttop)
|
|
|
|
return;
|
|
|
|
|
|
|
|
deststop = desttop + vid.rowbytes * vid.height;
|
|
|
|
|
|
|
|
if (scrn & V_NOSCALESTART)
|
2014-03-21 18:42:55 +00:00
|
|
|
{
|
|
|
|
x >>= FRACBITS;
|
|
|
|
y >>= FRACBITS;
|
2014-03-15 16:59:03 +00:00
|
|
|
desttop += (y*vid.width) + x;
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
x = FixedMul(x,dupx<<FRACBITS);
|
|
|
|
y = FixedMul(y,dupy<<FRACBITS);
|
|
|
|
x >>= FRACBITS;
|
|
|
|
y >>= FRACBITS;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// Center it if necessary
|
|
|
|
if (!(scrn & V_SCALEPATCHMASK))
|
|
|
|
{
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
2020-11-22 23:02:47 +00:00
|
|
|
if (x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT)
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2020-08-08 08:16:47 +00:00
|
|
|
column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[0]));
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if (!column->topdelta)
|
|
|
|
{
|
|
|
|
source = (const UINT8 *)(column) + 3;
|
|
|
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]);
|
|
|
|
}
|
2018-08-25 18:52:17 +00:00
|
|
|
}
|
2017-08-22 20:02:33 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
|
|
|
{
|
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
if (scrn & V_SNAPTORIGHT)
|
2018-08-25 18:52:17 +00:00
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx));
|
2014-03-15 16:59:03 +00:00
|
|
|
else if (!(scrn & V_SNAPTOLEFT))
|
2018-08-25 18:52:17 +00:00
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 4)
|
|
|
|
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
else if (perplayershuffle & 8)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
2018-01-21 12:56:38 +00:00
|
|
|
if (scrn & V_SNAPTOBOTTOM)
|
2018-08-25 18:52:17 +00:00
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
2014-03-15 16:59:03 +00:00
|
|
|
else if (!(scrn & V_SNAPTOTOP))
|
2018-08-25 18:52:17 +00:00
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 1)
|
|
|
|
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
else if (perplayershuffle & 2)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-22 20:02:33 +00:00
|
|
|
|
|
|
|
desttop += (y*vid.width) + x;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2014-03-21 18:42:55 +00:00
|
|
|
|
2016-03-25 19:43:17 +00:00
|
|
|
if (pscale != FRACUNIT) // scale width properly
|
|
|
|
{
|
2020-11-22 23:02:47 +00:00
|
|
|
pwidth = patch->width<<FRACBITS;
|
2016-03-25 19:43:17 +00:00
|
|
|
pwidth = FixedMul(pwidth, pscale);
|
|
|
|
pwidth = FixedMul(pwidth, dupx<<FRACBITS);
|
|
|
|
pwidth >>= FRACBITS;
|
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
pwidth = patch->width * dupx;
|
2016-03-25 20:04:49 +00:00
|
|
|
|
|
|
|
deststart = desttop;
|
|
|
|
destend = desttop + pwidth;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 topdelta, prevdelta = -1;
|
2018-10-30 14:22:21 +00:00
|
|
|
if (scrn & V_FLIP) // offx is measured from right edge instead of left
|
2016-03-25 20:04:49 +00:00
|
|
|
{
|
|
|
|
if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
|
|
|
break;
|
|
|
|
if (x+pwidth-offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (x+offx < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
|
|
|
continue;
|
|
|
|
if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION)
|
|
|
|
break;
|
|
|
|
}
|
2020-08-08 08:16:47 +00:00
|
|
|
column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS]));
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
while (column->topdelta != 0xff)
|
|
|
|
{
|
|
|
|
topdelta = column->topdelta;
|
|
|
|
if (topdelta <= prevdelta)
|
|
|
|
topdelta += prevdelta;
|
|
|
|
prevdelta = topdelta;
|
|
|
|
source = (const UINT8 *)(column) + 3;
|
|
|
|
dest = desttop;
|
2018-10-30 14:22:21 +00:00
|
|
|
if (scrn & V_FLIP)
|
2014-03-15 16:59:03 +00:00
|
|
|
dest = deststart + (destend - desttop);
|
Sound test is cool now!
https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif
* Port MUSICDEFs from Kart.
* Safe to modify without modifying game, so we can put it in music.dta eventually.
* "Title", "AltTitle", "Authors" fields are self-evident.
* "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select).
* "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test.
* Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test).
* Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left).
* Change V_DrawFixedPatch to allow scaling on two seperate axes.
* Now called "V_DrawStretchyFixedPatch".
* "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes).
* Available to Lua under v.drawStretched!
* Even works in GL!
* Bugfix: Add SR_PLAYER to SOC's menutypes_list.
Stay tuned for the merge request, where I put the onus on the Music Team to finish this off...
2019-11-05 16:23:46 +00:00
|
|
|
dest += FixedInt(FixedMul(topdelta<<FRACBITS,vdup))*vid.width;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
for (ofs = 0; dest < deststop && (ofs>>FRACBITS) < column->length; ofs += rowfrac)
|
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
|
|
|
|
*dest = patchdrawfunc(dest, source, ofs);
|
2014-03-15 16:59:03 +00:00
|
|
|
dest += vid.width;
|
|
|
|
}
|
|
|
|
column = (const column_t *)((const UINT8 *)column + column->length + 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
// Draws a patch cropped and scaled to arbitrary size.
|
2020-12-11 22:43:38 +00:00
|
|
|
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2017-10-25 15:40:21 +00:00
|
|
|
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
2021-11-15 18:07:20 +00:00
|
|
|
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
|
|
|
|
UINT32 blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT);
|
2017-10-25 15:40:21 +00:00
|
|
|
// boolean flip = false;
|
|
|
|
|
2020-12-11 22:43:38 +00:00
|
|
|
fixed_t col, ofs, colfrac, rowfrac, fdup, vdup;
|
2014-03-15 16:59:03 +00:00
|
|
|
INT32 dupx, dupy;
|
|
|
|
const column_t *column;
|
2014-03-21 18:42:55 +00:00
|
|
|
UINT8 *desttop, *dest;
|
2014-03-15 16:59:03 +00:00
|
|
|
const UINT8 *source, *deststop;
|
2014-03-21 18:42:55 +00:00
|
|
|
|
2018-04-06 13:42:49 +00:00
|
|
|
UINT8 perplayershuffle = 0;
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-08-20 23:21:53 +00:00
|
|
|
//if (rendermode != render_soft && !con_startup) // Not this again
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-21 18:42:55 +00:00
|
|
|
{
|
2020-12-11 22:43:38 +00:00
|
|
|
HWR_DrawCroppedPatch(patch,x,y,pscale,vscale,scrn,colormap,sx,sy,w,h);
|
2014-03-15 16:59:03 +00:00
|
|
|
return;
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
#endif
|
|
|
|
|
2017-10-25 15:40:21 +00:00
|
|
|
patchdrawfunc = standardpdraw;
|
|
|
|
|
|
|
|
v_translevel = NULL;
|
2022-01-19 09:09:57 +00:00
|
|
|
if (alphalevel || blendmode)
|
2017-10-25 15:40:21 +00:00
|
|
|
{
|
2022-01-19 12:17:57 +00:00
|
|
|
if (alphalevel == 10) // V_HUDTRANSHALF
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudminusalpha[st_translucency];
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 11) // V_HUDTRANS
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = 10 - st_translucency;
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudplusalpha[st_translucency];
|
2017-10-25 15:40:21 +00:00
|
|
|
|
|
|
|
if (alphalevel >= 10)
|
|
|
|
return; // invis
|
|
|
|
|
2022-01-19 12:17:57 +00:00
|
|
|
if (alphalevel || blendmode)
|
|
|
|
{
|
2022-01-19 09:09:57 +00:00
|
|
|
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
2017-10-25 15:40:21 +00:00
|
|
|
patchdrawfunc = translucentpdraw;
|
2022-01-19 12:17:57 +00:00
|
|
|
}
|
2017-10-25 15:40:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-11 22:43:38 +00:00
|
|
|
v_colormap = NULL;
|
|
|
|
if (colormap)
|
|
|
|
{
|
|
|
|
v_colormap = colormap;
|
|
|
|
patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
|
|
|
|
}
|
|
|
|
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT)
|
|
|
|
{
|
|
|
|
case 1: // V_NOSCALEPATCH
|
|
|
|
dupx = dupy = 1;
|
|
|
|
break;
|
|
|
|
case 2: // V_SMALLSCALEPATCH
|
|
|
|
dupx = vid.smalldupx;
|
|
|
|
dupy = vid.smalldupy;
|
|
|
|
break;
|
|
|
|
case 3: // V_MEDSCALEPATCH
|
|
|
|
dupx = vid.meddupx;
|
|
|
|
dupy = vid.meddupy;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-21 18:42:55 +00:00
|
|
|
// only use one dup, to avoid stretching (har har)
|
2020-12-11 22:43:38 +00:00
|
|
|
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
|
|
|
fdup = vdup = FixedMul(dupx<<FRACBITS, pscale);
|
|
|
|
if (vscale != pscale)
|
|
|
|
vdup = FixedMul(dupx<<FRACBITS, vscale);
|
2014-03-15 16:59:03 +00:00
|
|
|
colfrac = FixedDiv(FRACUNIT, fdup);
|
2020-12-11 22:43:38 +00:00
|
|
|
rowfrac = FixedDiv(FRACUNIT, vdup);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
x -= FixedMul(patch->leftoffset<<FRACBITS, pscale);
|
2020-12-11 22:43:38 +00:00
|
|
|
y -= FixedMul(patch->topoffset<<FRACBITS, vscale);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2018-01-21 12:56:38 +00:00
|
|
|
if (splitscreen && (scrn & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
2020-12-11 22:43:38 +00:00
|
|
|
vdup >>= 1;
|
2018-01-21 12:56:38 +00:00
|
|
|
rowfrac <<= 1;
|
|
|
|
y >>= 1;
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
|
2020-12-11 22:43:38 +00:00
|
|
|
fdup >>= 1;
|
2018-01-21 12:56:38 +00:00
|
|
|
colfrac <<= 1;
|
|
|
|
x >>= 1;
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-21 12:56:38 +00:00
|
|
|
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-21 12:56:38 +00:00
|
|
|
else if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-21 12:56:38 +00:00
|
|
|
x += adjustx;
|
|
|
|
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[thirddisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-21 12:56:38 +00:00
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[fourthdisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-21 12:56:38 +00:00
|
|
|
x += adjustx;
|
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
2018-01-21 12:56:38 +00:00
|
|
|
scrn &= ~V_SNAPTOBOTTOM;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-21 12:56:38 +00:00
|
|
|
else //if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
2018-01-21 12:56:38 +00:00
|
|
|
y += adjusty;
|
|
|
|
scrn &= ~V_SNAPTOTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
desttop = screens[scrn&V_PARAMMASK];
|
|
|
|
|
|
|
|
if (!desttop)
|
|
|
|
return;
|
|
|
|
|
|
|
|
deststop = desttop + vid.rowbytes * vid.height;
|
|
|
|
|
2020-12-11 22:43:38 +00:00
|
|
|
if (scrn & V_NOSCALESTART)
|
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
x >>= FRACBITS;
|
|
|
|
y >>= FRACBITS;
|
2014-03-15 16:59:03 +00:00
|
|
|
desttop += (y*vid.width) + x;
|
2014-03-21 18:42:55 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
x = FixedMul(x,dupx<<FRACBITS);
|
|
|
|
y = FixedMul(y,dupy<<FRACBITS);
|
|
|
|
x >>= FRACBITS;
|
|
|
|
y >>= FRACBITS;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
// Center it if necessary
|
|
|
|
if (!(scrn & V_SCALEPATCHMASK))
|
|
|
|
{
|
2018-08-25 18:52:17 +00:00
|
|
|
// if it's meant to cover the whole screen, black out the rest
|
2019-07-28 16:47:57 +00:00
|
|
|
// no the patch is cropped do not do this ever
|
2017-08-23 16:41:16 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
|
|
|
{
|
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
if (scrn & V_SNAPTORIGHT)
|
2018-08-25 18:52:17 +00:00
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx));
|
2014-03-15 16:59:03 +00:00
|
|
|
else if (!(scrn & V_SNAPTOLEFT))
|
2018-08-25 18:52:17 +00:00
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 4)
|
|
|
|
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
else if (perplayershuffle & 8)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
|
|
|
if (scrn & V_SNAPTOBOTTOM)
|
2018-08-25 18:52:17 +00:00
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
2014-03-15 16:59:03 +00:00
|
|
|
else if (!(scrn & V_SNAPTOTOP))
|
2018-08-25 18:52:17 +00:00
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 1)
|
|
|
|
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
else if (perplayershuffle & 2)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-25 18:52:17 +00:00
|
|
|
|
|
|
|
desttop += (y*vid.width) + x;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2021-04-27 19:30:00 +00:00
|
|
|
// Auto-crop at splitscreen borders!
|
|
|
|
if (splitscreen && (scrn & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
#error Auto-cropping doesnt take quadscreen into account! Fix it!
|
|
|
|
// Hint: For player 1/2, copy player 1's code below. For player 3/4, copy player 2's code below
|
|
|
|
// For player 1/3 and 2/4, hijack the X wrap prevention lines? That's probably easiest
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
|
|
|
|
{
|
|
|
|
// Just put a big old stop sign halfway through the screen
|
|
|
|
deststop -= vid.rowbytes * (vid.height>>1);
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
|
|
|
|
{
|
|
|
|
if (y < (vid.height>>1)) // If the top is above the border
|
|
|
|
{
|
|
|
|
sy += ((vid.height>>1) - y) * rowfrac; // Start further down on the patch
|
|
|
|
h -= ((vid.height>>1) - y) * rowfrac; // Draw less downwards from the start
|
|
|
|
desttop += ((vid.height>>1) - y) * vid.width; // Start drawing at the border
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-11 22:43:38 +00:00
|
|
|
for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
INT32 topdelta, prevdelta = -1;
|
2014-08-27 03:56:30 +00:00
|
|
|
if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
2014-03-21 18:42:55 +00:00
|
|
|
continue;
|
2014-11-12 00:55:07 +00:00
|
|
|
if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION)
|
2014-03-21 18:42:55 +00:00
|
|
|
break;
|
2020-08-08 08:16:47 +00:00
|
|
|
column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS]));
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
while (column->topdelta != 0xff)
|
|
|
|
{
|
|
|
|
topdelta = column->topdelta;
|
|
|
|
if (topdelta <= prevdelta)
|
|
|
|
topdelta += prevdelta;
|
|
|
|
prevdelta = topdelta;
|
|
|
|
source = (const UINT8 *)(column) + 3;
|
|
|
|
dest = desttop;
|
2020-12-11 22:43:38 +00:00
|
|
|
if ((topdelta<<FRACBITS)-sy > 0)
|
2019-09-07 11:07:29 +00:00
|
|
|
{
|
2020-12-11 22:43:38 +00:00
|
|
|
dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup))*vid.width;
|
2019-09-07 11:07:29 +00:00
|
|
|
ofs = 0;
|
|
|
|
}
|
|
|
|
else
|
2020-12-11 22:43:38 +00:00
|
|
|
ofs = sy-(topdelta<<FRACBITS);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-12-11 22:43:38 +00:00
|
|
|
for (; dest < deststop && (ofs>>FRACBITS) < column->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2014-03-21 18:42:55 +00:00
|
|
|
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
|
2017-10-25 15:40:21 +00:00
|
|
|
*dest = patchdrawfunc(dest, source, ofs);
|
2014-03-15 16:59:03 +00:00
|
|
|
dest += vid.width;
|
|
|
|
}
|
|
|
|
column = (const column_t *)((const UINT8 *)column + column->length + 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DrawContinueIcon
|
|
|
|
// Draw a mini player! If we can, that is. Otherwise we draw a star.
|
|
|
|
//
|
2020-05-24 00:29:07 +00:00
|
|
|
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-11-25 18:52:38 +00:00
|
|
|
if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CONTINUE)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2019-09-10 23:50:51 +00:00
|
|
|
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
2019-10-16 02:54:21 +00:00
|
|
|
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE];
|
2019-09-08 21:27:35 +00:00
|
|
|
patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
|
2014-03-15 16:59:03 +00:00
|
|
|
const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE);
|
|
|
|
|
2019-09-10 23:50:51 +00:00
|
|
|
V_DrawMappedPatch(x, y, flags, patch, colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2019-09-10 23:50:51 +00:00
|
|
|
else
|
2019-09-28 01:53:57 +00:00
|
|
|
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_PATCH));
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DrawBlock
|
|
|
|
// Draw a linear block of pixels into the view buffer.
|
|
|
|
//
|
|
|
|
void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const UINT8 *src)
|
|
|
|
{
|
|
|
|
UINT8 *dest;
|
|
|
|
const UINT8 *deststop;
|
|
|
|
|
|
|
|
#ifdef RANGECHECK
|
|
|
|
if (x < 0 || x + width > vid.width || y < 0 || y + height > vid.height || (unsigned)scrn > 4)
|
|
|
|
I_Error("Bad V_DrawBlock");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dest = screens[scrn] + y*vid.width + x;
|
|
|
|
deststop = screens[scrn] + vid.rowbytes * vid.height;
|
|
|
|
|
|
|
|
while (height--)
|
|
|
|
{
|
|
|
|
M_Memcpy(dest, src, width);
|
|
|
|
|
|
|
|
src += width;
|
|
|
|
dest += vid.width;
|
|
|
|
if (dest > deststop)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void V_BlitScaledPic(INT32 px1, INT32 py1, INT32 scrn, pic_t *pic);
|
|
|
|
// Draw a linear pic, scaled, TOTALLY CRAP CODE!!! OPTIMISE AND ASM!!
|
|
|
|
//
|
|
|
|
void V_DrawScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, INT32 lumpnum)
|
|
|
|
{
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (rendermode != render_soft)
|
|
|
|
{
|
|
|
|
HWR_DrawPic(rx1, ry1, lumpnum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
V_BlitScaledPic(rx1, ry1, scrn, W_CacheLumpNum(lumpnum, PU_CACHE));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void V_BlitScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, pic_t * pic)
|
|
|
|
{
|
|
|
|
INT32 dupx, dupy;
|
|
|
|
INT32 x, y;
|
|
|
|
UINT8 *src, *dest;
|
|
|
|
INT32 width, height;
|
|
|
|
|
|
|
|
width = SHORT(pic->width);
|
|
|
|
height = SHORT(pic->height);
|
|
|
|
scrn &= V_PARAMMASK;
|
|
|
|
|
|
|
|
if (pic->mode != 0)
|
|
|
|
{
|
|
|
|
CONS_Debug(DBG_RENDER, "pic mode %d not supported in Software\n", pic->mode);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest = screens[scrn] + max(0, ry1 * vid.width) + max(0, rx1);
|
|
|
|
// y cliping to the screen
|
|
|
|
if (ry1 + height * vid.dupy >= vid.width)
|
|
|
|
height = (vid.width - ry1) / vid.dupy - 1;
|
|
|
|
// WARNING no x clipping (not needed for the moment)
|
|
|
|
|
|
|
|
for (y = max(0, -ry1 / vid.dupy); y < height; y++)
|
|
|
|
{
|
|
|
|
for (dupy = vid.dupy; dupy; dupy--)
|
|
|
|
{
|
|
|
|
src = pic->data + y * width;
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{
|
|
|
|
for (dupx = vid.dupx; dupx; dupx--)
|
|
|
|
*dest++ = *src;
|
|
|
|
src++;
|
|
|
|
}
|
|
|
|
dest += vid.width - vid.dupx * width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Fills a box of pixels with a single color, NOTE: scaled to screen size
|
|
|
|
//
|
|
|
|
void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|
|
|
{
|
|
|
|
UINT8 *dest;
|
|
|
|
const UINT8 *deststop;
|
2017-04-12 22:34:13 +00:00
|
|
|
|
2018-04-06 13:42:49 +00:00
|
|
|
UINT8 perplayershuffle = 0;
|
|
|
|
|
2017-04-12 22:34:13 +00:00
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-08-20 23:21:53 +00:00
|
|
|
//if (rendermode != render_soft && !con_startup) // Not this again
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
HWR_DrawFill(x, y, w, h, c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-01-21 12:56:38 +00:00
|
|
|
if (splitscreen && (c & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
h >>= 1;
|
|
|
|
y >>= 1;
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
w >>= 1;
|
|
|
|
x >>= 1;
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-21 12:56:38 +00:00
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-21 12:56:38 +00:00
|
|
|
else if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-21 12:56:38 +00:00
|
|
|
x += adjustx;
|
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[thirddisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
2018-01-21 12:56:38 +00:00
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[fourthdisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
2018-01-21 12:56:38 +00:00
|
|
|
x += adjustx;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer])
|
2018-04-06 13:42:49 +00:00
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
2018-01-21 12:56:38 +00:00
|
|
|
c &= ~V_SNAPTOBOTTOM;
|
2018-04-06 13:42:49 +00:00
|
|
|
}
|
2018-01-21 12:56:38 +00:00
|
|
|
else //if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
2018-04-06 13:42:49 +00:00
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
2018-01-21 12:56:38 +00:00
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-12 22:34:13 +00:00
|
|
|
if (!(c & V_NOSCALESTART))
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2017-04-12 22:34:13 +00:00
|
|
|
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
|
|
|
|
2016-11-04 00:30:30 +00:00
|
|
|
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
|
|
|
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
|
2018-08-25 18:52:17 +00:00
|
|
|
memset(screens[0], (c&255), vid.width * vid.height * vid.bpp);
|
2016-11-04 00:30:30 +00:00
|
|
|
return;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2016-11-04 00:30:30 +00:00
|
|
|
|
2017-04-12 22:34:13 +00:00
|
|
|
x *= dupx;
|
|
|
|
y *= dupy;
|
|
|
|
w *= dupx;
|
|
|
|
h *= dupy;
|
2016-11-04 00:30:30 +00:00
|
|
|
|
2017-04-12 22:34:13 +00:00
|
|
|
// Center it if necessary
|
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2017-04-12 22:34:13 +00:00
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
if (c & V_SNAPTORIGHT)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx));
|
|
|
|
else if (!(c & V_SNAPTOLEFT))
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 4)
|
|
|
|
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
else if (perplayershuffle & 8)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
2017-04-12 22:34:13 +00:00
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
|
|
|
if (c & V_SNAPTOBOTTOM)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
|
|
|
else if (!(c & V_SNAPTOTOP))
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
2018-04-06 13:42:49 +00:00
|
|
|
if (perplayershuffle & 1)
|
|
|
|
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
else if (perplayershuffle & 2)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-12 22:34:13 +00:00
|
|
|
if (x >= vid.width || y >= vid.height)
|
|
|
|
return; // off the screen
|
|
|
|
if (x < 0)
|
|
|
|
{
|
|
|
|
w += x;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if (y < 0)
|
|
|
|
{
|
|
|
|
h += y;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (w <= 0 || h <= 0)
|
|
|
|
return; // zero width/height wouldn't draw anything
|
|
|
|
if (x + w > vid.width)
|
|
|
|
w = vid.width - x;
|
|
|
|
if (y + h > vid.height)
|
|
|
|
h = vid.height - y;
|
|
|
|
|
|
|
|
dest = screens[0] + y*vid.width + x;
|
|
|
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
c &= 255;
|
|
|
|
|
2017-04-24 16:41:50 +00:00
|
|
|
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
2018-08-25 18:52:17 +00:00
|
|
|
memset(dest, c, w * vid.bpp);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 19:43:59 +00:00
|
|
|
#ifdef HWRENDER
|
|
|
|
// This is now a function since it's otherwise repeated 2 times and honestly looks retarded:
|
|
|
|
static UINT32 V_GetHWConsBackColor(void)
|
|
|
|
{
|
|
|
|
UINT32 hwcolor;
|
|
|
|
switch (cons_backcolor.value)
|
|
|
|
{
|
|
|
|
case 0: hwcolor = 0xffffff00; break; // White
|
2019-06-27 02:05:15 +00:00
|
|
|
case 1: hwcolor = 0x80808000; break; // Black
|
2018-12-17 19:43:59 +00:00
|
|
|
case 2: hwcolor = 0xdeb88700; break; // Sepia
|
|
|
|
case 3: hwcolor = 0x40201000; break; // Brown
|
|
|
|
case 4: hwcolor = 0xfa807200; break; // Pink
|
|
|
|
case 5: hwcolor = 0xff69b400; break; // Raspberry
|
|
|
|
case 6: hwcolor = 0xff000000; break; // Red
|
|
|
|
case 7: hwcolor = 0xffd68300; break; // Creamsicle
|
|
|
|
case 8: hwcolor = 0xff800000; break; // Orange
|
|
|
|
case 9: hwcolor = 0xdaa52000; break; // Gold
|
|
|
|
case 10: hwcolor = 0x80800000; break; // Yellow
|
|
|
|
case 11: hwcolor = 0x00ff0000; break; // Emerald
|
|
|
|
case 12: hwcolor = 0x00800000; break; // Green
|
|
|
|
case 13: hwcolor = 0x4080ff00; break; // Cyan
|
|
|
|
case 14: hwcolor = 0x4682b400; break; // Steel
|
|
|
|
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
|
|
|
|
case 16: hwcolor = 0x0000ff00; break; // Blue
|
|
|
|
case 17: hwcolor = 0xff00ff00; break; // Purple
|
|
|
|
case 18: hwcolor = 0xee82ee00; break; // Lavender
|
|
|
|
// Default green
|
|
|
|
default: hwcolor = 0x00800000; break;
|
|
|
|
}
|
|
|
|
return hwcolor;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2018-07-31 09:10:02 +00:00
|
|
|
// THANK YOU MPC!!!
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
// and thanks toaster for cleaning it up.
|
2018-07-31 09:10:02 +00:00
|
|
|
|
|
|
|
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|
|
|
{
|
|
|
|
UINT8 *dest;
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
const UINT8 *deststop;
|
|
|
|
INT32 u;
|
2018-12-17 20:57:53 +00:00
|
|
|
UINT8 *fadetable;
|
2018-07-31 09:10:02 +00:00
|
|
|
UINT32 alphalevel = 0;
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
UINT8 perplayershuffle = 0;
|
2018-07-31 09:10:02 +00:00
|
|
|
|
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2018-07-31 09:10:02 +00:00
|
|
|
{
|
2018-12-17 19:43:59 +00:00
|
|
|
UINT32 hwcolor = V_GetHWConsBackColor();
|
2019-08-04 09:27:09 +00:00
|
|
|
HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this.
|
2018-07-31 09:10:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
|
2018-07-31 09:10:02 +00:00
|
|
|
{
|
2022-01-19 12:17:57 +00:00
|
|
|
if (alphalevel == 10) // V_HUDTRANSHALF
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudminusalpha[st_translucency];
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 11) // V_HUDTRANS
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = 10 - st_translucency;
|
2022-01-19 12:17:57 +00:00
|
|
|
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
2019-11-18 14:39:54 +00:00
|
|
|
alphalevel = hudplusalpha[st_translucency];
|
2018-07-31 09:10:02 +00:00
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if (alphalevel >= 10)
|
|
|
|
return; // invis
|
|
|
|
}
|
|
|
|
|
|
|
|
if (splitscreen && (c & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
h >>= 1;
|
|
|
|
y >>= 1;
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
w >>= 1;
|
|
|
|
x >>= 1;
|
|
|
|
if (stplyr == &players[displayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
|
|
|
x += adjustx;
|
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[thirddisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[fourthdisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
|
|
|
x += adjustx;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
|
|
}
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
c &= ~V_SNAPTOBOTTOM;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(c & V_NOSCALESTART))
|
|
|
|
{
|
|
|
|
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
2018-07-31 09:10:02 +00:00
|
|
|
|
|
|
|
x *= dupx;
|
|
|
|
y *= dupy;
|
|
|
|
w *= dupx;
|
|
|
|
h *= dupy;
|
|
|
|
|
|
|
|
// Center it if necessary
|
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
|
|
|
{
|
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
if (c & V_SNAPTORIGHT)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx));
|
|
|
|
else if (!(c & V_SNAPTOLEFT))
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if (perplayershuffle & 4)
|
|
|
|
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
else if (perplayershuffle & 8)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
|
|
|
if (c & V_SNAPTOBOTTOM)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
|
|
|
else if (!(c & V_SNAPTOTOP))
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if (perplayershuffle & 1)
|
|
|
|
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
else if (perplayershuffle & 2)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x >= vid.width || y >= vid.height)
|
|
|
|
return; // off the screen
|
|
|
|
if (x < 0) {
|
|
|
|
w += x;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if (y < 0) {
|
|
|
|
h += y;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (w <= 0 || h <= 0)
|
|
|
|
return; // zero width/height wouldn't draw anything
|
|
|
|
if (x + w > vid.width)
|
|
|
|
w = vid.width-x;
|
|
|
|
if (y + h > vid.height)
|
|
|
|
h = vid.height-y;
|
|
|
|
|
|
|
|
dest = screens[0] + y*vid.width + x;
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
2018-07-31 09:10:02 +00:00
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
c &= 255;
|
|
|
|
|
|
|
|
// Jimita (12-04-2018)
|
|
|
|
if (alphalevel)
|
2018-07-31 09:10:02 +00:00
|
|
|
{
|
2020-10-27 03:03:41 +00:00
|
|
|
fadetable = R_GetTranslucencyTable(alphalevel) + (c*256);
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
|
|
|
{
|
|
|
|
u = 0;
|
|
|
|
while (u < w)
|
|
|
|
{
|
|
|
|
dest[u] = fadetable[consolebgmap[dest[u]]];
|
|
|
|
u++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
|
|
|
{
|
|
|
|
u = 0;
|
|
|
|
while (u < w)
|
|
|
|
{
|
|
|
|
dest[u] = consolebgmap[dest[u]];
|
|
|
|
u++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 09:10:02 +00:00
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
//
|
|
|
|
// If color is 0x00 to 0xFF, draw transtable (strength range 0-9).
|
|
|
|
// Else, use COLORMAP lump (strength range 0-31).
|
|
|
|
// c is not color, it is for flags only. transparency flags will be ignored.
|
|
|
|
// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH!
|
|
|
|
// I have kept the safety checks for strength out of this function;
|
|
|
|
// I don't trust Lua users with it, so it doesn't matter.
|
|
|
|
//
|
|
|
|
void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength)
|
|
|
|
{
|
|
|
|
UINT8 *dest;
|
|
|
|
const UINT8 *deststop;
|
|
|
|
INT32 u;
|
|
|
|
UINT8 *fadetable;
|
|
|
|
UINT8 perplayershuffle = 0;
|
|
|
|
|
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
{
|
|
|
|
// ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC
|
|
|
|
HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny
|
|
|
|
return;
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (splitscreen && (c & V_PERPLAYER))
|
|
|
|
{
|
|
|
|
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
h >>= 1;
|
|
|
|
y >>= 1;
|
|
|
|
#ifdef QUADS
|
|
|
|
if (splitscreen > 1) // 3 or 4 players
|
|
|
|
{
|
|
|
|
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
|
|
|
w >>= 1;
|
|
|
|
x >>= 1;
|
|
|
|
if (stplyr == &players[displayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
|
|
|
x += adjustx;
|
|
|
|
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
else if (stplyr == &players[thirddisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 4;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[fourthdisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
|
|
perplayershuffle |= 8;
|
|
|
|
x += adjustx;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
// 2 players
|
|
|
|
{
|
|
|
|
if (stplyr == &players[displayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 1;
|
|
|
|
c &= ~V_SNAPTOBOTTOM;
|
|
|
|
}
|
|
|
|
else //if (stplyr == &players[secondarydisplayplayer])
|
|
|
|
{
|
|
|
|
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
|
|
perplayershuffle |= 2;
|
|
|
|
y += adjusty;
|
|
|
|
c &= ~V_SNAPTOTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(c & V_NOSCALESTART))
|
|
|
|
{
|
|
|
|
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
|
|
|
|
|
|
|
x *= dupx;
|
|
|
|
y *= dupy;
|
|
|
|
w *= dupx;
|
|
|
|
h *= dupy;
|
|
|
|
|
|
|
|
// Center it if necessary
|
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
|
|
|
{
|
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
if (c & V_SNAPTORIGHT)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx));
|
|
|
|
else if (!(c & V_SNAPTOLEFT))
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
|
|
|
if (perplayershuffle & 4)
|
|
|
|
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
else if (perplayershuffle & 8)
|
|
|
|
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
|
|
|
if (c & V_SNAPTOBOTTOM)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
|
|
|
else if (!(c & V_SNAPTOTOP))
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
|
|
|
if (perplayershuffle & 1)
|
|
|
|
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
else if (perplayershuffle & 2)
|
|
|
|
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
|
|
|
}
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
if (x >= vid.width || y >= vid.height)
|
|
|
|
return; // off the screen
|
|
|
|
if (x < 0) {
|
|
|
|
w += x;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if (y < 0) {
|
|
|
|
h += y;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (w <= 0 || h <= 0)
|
|
|
|
return; // zero width/height wouldn't draw anything
|
|
|
|
if (x + w > vid.width)
|
|
|
|
w = vid.width-x;
|
|
|
|
if (y + h > vid.height)
|
|
|
|
h = vid.height-y;
|
|
|
|
|
|
|
|
dest = screens[0] + y*vid.width + x;
|
|
|
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
2018-07-31 09:10:02 +00:00
|
|
|
|
|
|
|
c &= 255;
|
|
|
|
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
fadetable = ((color & 0xFF00) // Color is not palette index?
|
|
|
|
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
|
2020-10-27 03:03:41 +00:00
|
|
|
: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
|
|
|
{
|
|
|
|
u = 0;
|
|
|
|
while (u < w)
|
2018-12-17 20:57:53 +00:00
|
|
|
{
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
dest[u] = fadetable[dest[u]];
|
|
|
|
u++;
|
2018-12-17 20:57:53 +00:00
|
|
|
}
|
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
|
|
|
}
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// Fills a box of pixels using a flat texture as a pattern, scaled to screen size.
|
|
|
|
//
|
|
|
|
void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
|
|
|
|
{
|
|
|
|
INT32 u, v, dupx, dupy;
|
|
|
|
fixed_t dx, dy, xfrac, yfrac;
|
|
|
|
const UINT8 *src, *deststop;
|
|
|
|
UINT8 *flat, *dest;
|
2022-11-16 01:40:54 +00:00
|
|
|
size_t lflatsize, flatshift;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
HWR_DrawFlatFill(x, y, w, h, flatnum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-11-16 01:40:54 +00:00
|
|
|
lflatsize = R_GetFlatSize(W_LumpLength(flatnum));
|
|
|
|
flatshift = R_GetFlatBits(lflatsize);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
flat = W_CacheLumpNum(flatnum, PU_CACHE);
|
|
|
|
|
|
|
|
dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
|
|
|
|
|
|
|
dest = screens[0] + y*dupy*vid.width + x*dupx;
|
|
|
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
|
|
|
|
|
|
|
// from V_DrawScaledPatch
|
|
|
|
if (vid.width != BASEVIDWIDTH * dupx)
|
|
|
|
{
|
|
|
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
|
|
|
// so center this imaginary screen
|
|
|
|
dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
|
|
|
}
|
|
|
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
|
|
{
|
|
|
|
// same thing here
|
|
|
|
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
w *= dupx;
|
|
|
|
h *= dupy;
|
|
|
|
|
|
|
|
dx = FixedDiv(FRACUNIT, dupx<<(FRACBITS-2));
|
|
|
|
dy = FixedDiv(FRACUNIT, dupy<<(FRACBITS-2));
|
|
|
|
|
|
|
|
yfrac = 0;
|
|
|
|
for (v = 0; v < h; v++, dest += vid.width)
|
|
|
|
{
|
|
|
|
xfrac = 0;
|
|
|
|
src = flat + (((yfrac>>FRACBITS) & (lflatsize - 1)) << flatshift);
|
|
|
|
for (u = 0; u < w; u++)
|
|
|
|
{
|
|
|
|
if (&dest[u] > deststop)
|
|
|
|
return;
|
|
|
|
dest[u] = src[(xfrac>>FRACBITS)&(lflatsize-1)];
|
|
|
|
xfrac += dx;
|
|
|
|
}
|
|
|
|
yfrac += dy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DrawPatchFill
|
|
|
|
//
|
|
|
|
void V_DrawPatchFill(patch_t *pat)
|
|
|
|
{
|
|
|
|
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
2020-11-22 23:02:47 +00:00
|
|
|
INT32 x, y, pw = pat->width * dupz, ph = pat->height * dupz;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
for (x = 0; x < vid.width; x += pw)
|
|
|
|
{
|
|
|
|
for (y = 0; y < vid.height; y += ph)
|
2014-03-21 18:42:55 +00:00
|
|
|
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Fade all the screen buffer, so that the menu is more readable,
|
|
|
|
// especially now that we use the small hufont in the menus...
|
2018-02-12 18:23:57 +00:00
|
|
|
// If color is 0x00 to 0xFF, draw transtable (strength range 0-9).
|
2018-02-12 17:47:31 +00:00
|
|
|
// Else, use COLORMAP lump (strength range 0-31).
|
|
|
|
// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH!
|
|
|
|
// I have kept the safety checks out of this function;
|
|
|
|
// the v.fadeScreen Lua interface handles those.
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
2018-02-12 17:47:31 +00:00
|
|
|
void V_DrawFadeScreen(UINT16 color, UINT8 strength)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2018-02-12 17:47:31 +00:00
|
|
|
HWR_FadeScreenMenuBack(color, strength);
|
2014-03-15 16:59:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-02-12 17:47:31 +00:00
|
|
|
{
|
|
|
|
const UINT8 *fadetable = ((color & 0xFF00) // Color is not palette index?
|
2019-11-23 21:15:09 +00:00
|
|
|
? ((UINT8 *)(((color & 0x0F00) == 0x0A00) ? fadecolormap // Do fadecolormap fade.
|
|
|
|
: (((color & 0x0F00) == 0x0B00) ? fadecolormap + (256 * FADECOLORMAPROWS) // Do white fadecolormap fade.
|
|
|
|
: colormaps)) + strength*256) // Do COLORMAP fade.
|
2020-10-27 03:03:41 +00:00
|
|
|
: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
|
2018-02-12 17:47:31 +00:00
|
|
|
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
|
|
|
|
UINT8 *buf = screens[0];
|
|
|
|
|
|
|
|
// heavily simplified -- we don't need to know x or y
|
|
|
|
// position when we're doing a full screen fade
|
|
|
|
for (; buf < deststop; ++buf)
|
|
|
|
*buf = fadetable[*buf];
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
// Simple translucency with one color, over a set number of lines starting from the top.
|
2016-11-02 21:26:35 +00:00
|
|
|
void V_DrawFadeConsBack(INT32 plines)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2016-11-02 21:26:35 +00:00
|
|
|
UINT8 *deststop, *buf;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2018-12-17 19:43:59 +00:00
|
|
|
UINT32 hwcolor = V_GetHWConsBackColor();
|
2014-08-04 03:49:33 +00:00
|
|
|
HWR_DrawConsoleBack(hwcolor, plines);
|
2014-03-15 16:59:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
// heavily simplified -- we don't need to know x or y position,
|
|
|
|
// just the stop position
|
|
|
|
deststop = screens[0] + vid.rowbytes * min(plines, vid.height);
|
|
|
|
for (buf = screens[0]; buf < deststop; ++buf)
|
2016-11-02 21:26:35 +00:00
|
|
|
*buf = consolebgmap[*buf];
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2018-09-04 18:21:58 +00:00
|
|
|
// Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom.
|
2018-11-10 03:38:55 +00:00
|
|
|
void V_DrawPromptBack(INT32 boxheight, INT32 color)
|
2018-09-04 18:21:58 +00:00
|
|
|
{
|
|
|
|
UINT8 *deststop, *buf;
|
|
|
|
|
2019-11-01 15:48:50 +00:00
|
|
|
if (color >= 256 && color < 512)
|
|
|
|
{
|
Introducing Marathon Run. (I was going to call it Marathon Mode, but NiGHTS Mode being right next to it on the menu looked terrible.)
Basically a dedicated Record Attack-like experience for speedrunning the game as a continuous chunk rather than ILs. Has several quality of life features.
Benefits include:
* An unambiguous real-time bar across the bottom of the screen, always displaying the current time, ticking up until you reach the ending.
* Disable the console (pausing is still allowed, but the timer will still increment).
* Automatically skip intermissions as if you're holding down the spin button.
* Show centiseconds on HUD automatically, like record attack.
* "Live Event Backups" - a category of run fit for major events like GDQ, where recovery from crashes or chokes makes for better entertainment. Essentially a modified SP savefile, down to using the same basic functions, but has its own filename and tweaked internal layout.
* "spmarathon_start" MainCfg block parameter and "marathonnext" mapheader parameter, allowing for a customised flow (makes this fit for purpose for an eventual SUGOI port).
* Disabling inter-level custom cutscenes by default with a menu option to toggle this (won't show up if the mod doesn't *have* any custom cutscenes), although either way ending cutscenes (vanilla or custom) remain intact since is time is called before them.
* Won't show up if you have a mod that consists of only one level (determined by spmarathon_start's nextlevel; this won't trip if you manually set its marathonnext).
* Unconditional gratitude on the evaluation screen, instead of a negging "Try again..." if you didn't get all the emeralds (which you may not have been aiming for).
* Gorgeous new menu (no new assets required, unless you wanna give it a header later).
Changes which were required for the above but affect other areas of the game include:
* "useBlackRock" MainCFG block parameter, which can be used to disable the presence of the Black Rock or Egg Rock in both the Evaluation screen and the Marathon Run menu (for total conversions with different stories).
* Disabling Continues in NiGHTS mode, to match the most common singleplayer experience post 2.2.4's release (is reverted if useContinues is set to true).
* Hiding the exitmove "powerup" outside of multiplayer. (Okay, this isn't really related, I just saw this bug in action a lot while doing test runs and got annoyed enough to fix it here.)
* The ability to use V_DrawPromptBack (in hardcode only at the moment, but) to draw in terms of pixels rather than rows of text, by providing negative instead of positive inputs).
* A refactoring of redundant game saves smattered across the ending, credits, and evaluation - in addition to saving the game slightly earlier.
* Minor m_menu.c touchups and refactorings here and there.
Built using feedback from the official server's #speedruns channel, among other places.
2020-05-14 22:10:00 +00:00
|
|
|
if (boxheight < 0)
|
|
|
|
boxheight = -boxheight;
|
|
|
|
else // 4 lines of space plus gaps between and some leeway
|
|
|
|
boxheight = ((boxheight * 4) + (boxheight/2)*5);
|
2019-11-01 15:48:50 +00:00
|
|
|
V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM);
|
|
|
|
return;
|
|
|
|
}
|
2018-11-03 09:05:15 +00:00
|
|
|
|
2019-11-25 00:08:38 +00:00
|
|
|
boxheight *= vid.dupy;
|
|
|
|
|
2018-11-10 03:38:55 +00:00
|
|
|
if (color == INT32_MAX)
|
|
|
|
color = cons_backcolor.value;
|
|
|
|
|
2018-09-04 18:21:58 +00:00
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode == render_opengl)
|
2018-11-03 21:14:17 +00:00
|
|
|
{
|
|
|
|
UINT32 hwcolor;
|
2018-11-10 03:38:55 +00:00
|
|
|
switch (color)
|
2018-11-03 21:14:17 +00:00
|
|
|
{
|
2019-06-27 02:05:15 +00:00
|
|
|
case 0: hwcolor = 0xffffff00; break; // White
|
|
|
|
case 1: hwcolor = 0x00000000; break; // Black // Note this is different from V_DrawFadeConsBack
|
|
|
|
case 2: hwcolor = 0xdeb88700; break; // Sepia
|
|
|
|
case 3: hwcolor = 0x40201000; break; // Brown
|
|
|
|
case 4: hwcolor = 0xfa807200; break; // Pink
|
|
|
|
case 5: hwcolor = 0xff69b400; break; // Raspberry
|
|
|
|
case 6: hwcolor = 0xff000000; break; // Red
|
|
|
|
case 7: hwcolor = 0xffd68300; break; // Creamsicle
|
|
|
|
case 8: hwcolor = 0xff800000; break; // Orange
|
|
|
|
case 9: hwcolor = 0xdaa52000; break; // Gold
|
|
|
|
case 10: hwcolor = 0x80800000; break; // Yellow
|
|
|
|
case 11: hwcolor = 0x00ff0000; break; // Emerald
|
|
|
|
case 12: hwcolor = 0x00800000; break; // Green
|
|
|
|
case 13: hwcolor = 0x4080ff00; break; // Cyan
|
|
|
|
case 14: hwcolor = 0x4682b400; break; // Steel
|
|
|
|
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
|
|
|
|
case 16: hwcolor = 0x0000ff00; break; // Blue
|
|
|
|
case 17: hwcolor = 0xff00ff00; break; // Purple
|
|
|
|
case 18: hwcolor = 0xee82ee00; break; // Lavender
|
2018-11-03 21:14:17 +00:00
|
|
|
// Default green
|
|
|
|
default: hwcolor = 0x00800000; break;
|
|
|
|
}
|
|
|
|
HWR_DrawTutorialBack(hwcolor, boxheight);
|
2018-09-04 18:21:58 +00:00
|
|
|
return;
|
2018-11-03 21:14:17 +00:00
|
|
|
}
|
2018-09-04 18:21:58 +00:00
|
|
|
#endif
|
|
|
|
|
2018-11-10 03:38:55 +00:00
|
|
|
CON_SetupBackColormapEx(color, true);
|
|
|
|
|
2018-09-04 18:21:58 +00:00
|
|
|
// heavily simplified -- we don't need to know x or y position,
|
|
|
|
// just the start and stop positions
|
Introducing Marathon Run. (I was going to call it Marathon Mode, but NiGHTS Mode being right next to it on the menu looked terrible.)
Basically a dedicated Record Attack-like experience for speedrunning the game as a continuous chunk rather than ILs. Has several quality of life features.
Benefits include:
* An unambiguous real-time bar across the bottom of the screen, always displaying the current time, ticking up until you reach the ending.
* Disable the console (pausing is still allowed, but the timer will still increment).
* Automatically skip intermissions as if you're holding down the spin button.
* Show centiseconds on HUD automatically, like record attack.
* "Live Event Backups" - a category of run fit for major events like GDQ, where recovery from crashes or chokes makes for better entertainment. Essentially a modified SP savefile, down to using the same basic functions, but has its own filename and tweaked internal layout.
* "spmarathon_start" MainCfg block parameter and "marathonnext" mapheader parameter, allowing for a customised flow (makes this fit for purpose for an eventual SUGOI port).
* Disabling inter-level custom cutscenes by default with a menu option to toggle this (won't show up if the mod doesn't *have* any custom cutscenes), although either way ending cutscenes (vanilla or custom) remain intact since is time is called before them.
* Won't show up if you have a mod that consists of only one level (determined by spmarathon_start's nextlevel; this won't trip if you manually set its marathonnext).
* Unconditional gratitude on the evaluation screen, instead of a negging "Try again..." if you didn't get all the emeralds (which you may not have been aiming for).
* Gorgeous new menu (no new assets required, unless you wanna give it a header later).
Changes which were required for the above but affect other areas of the game include:
* "useBlackRock" MainCFG block parameter, which can be used to disable the presence of the Black Rock or Egg Rock in both the Evaluation screen and the Marathon Run menu (for total conversions with different stories).
* Disabling Continues in NiGHTS mode, to match the most common singleplayer experience post 2.2.4's release (is reverted if useContinues is set to true).
* Hiding the exitmove "powerup" outside of multiplayer. (Okay, this isn't really related, I just saw this bug in action a lot while doing test runs and got annoyed enough to fix it here.)
* The ability to use V_DrawPromptBack (in hardcode only at the moment, but) to draw in terms of pixels rather than rows of text, by providing negative instead of positive inputs).
* A refactoring of redundant game saves smattered across the ending, credits, and evaluation - in addition to saving the game slightly earlier.
* Minor m_menu.c touchups and refactorings here and there.
Built using feedback from the official server's #speedruns channel, among other places.
2020-05-14 22:10:00 +00:00
|
|
|
buf = deststop = screens[0] + vid.rowbytes * vid.height;
|
|
|
|
if (boxheight < 0)
|
|
|
|
buf += vid.rowbytes * boxheight;
|
|
|
|
else // 4 lines of space plus gaps between and some leeway
|
|
|
|
buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5);
|
2018-09-04 18:21:58 +00:00
|
|
|
for (; buf < deststop; ++buf)
|
2018-11-10 03:38:55 +00:00
|
|
|
*buf = promptbgmap[*buf];
|
2018-09-04 18:21:58 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Gets string colormap, used for 0x80 color codes
|
|
|
|
//
|
2018-12-17 19:43:59 +00:00
|
|
|
UINT8 *V_GetStringColormap(INT32 colorflags)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
|
|
|
|
{
|
2018-03-02 13:32:55 +00:00
|
|
|
case 1: // 0x81, magenta
|
|
|
|
return magentamap;
|
|
|
|
case 2: // 0x82, yellow
|
2014-03-15 16:59:03 +00:00
|
|
|
return yellowmap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 3: // 0x83, lgreen
|
2014-03-15 16:59:03 +00:00
|
|
|
return lgreenmap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 4: // 0x84, blue
|
2014-03-15 16:59:03 +00:00
|
|
|
return bluemap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 5: // 0x85, red
|
2014-03-15 16:59:03 +00:00
|
|
|
return redmap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 6: // 0x86, gray
|
2014-03-15 16:59:03 +00:00
|
|
|
return graymap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 7: // 0x87, orange
|
2014-03-15 16:59:03 +00:00
|
|
|
return orangemap;
|
2018-03-02 13:32:55 +00:00
|
|
|
case 8: // 0x88, sky
|
|
|
|
return skymap;
|
|
|
|
case 9: // 0x89, purple
|
|
|
|
return purplemap;
|
|
|
|
case 10: // 0x8A, aqua
|
|
|
|
return aquamap;
|
|
|
|
case 11: // 0x8B, peridot
|
|
|
|
return peridotmap;
|
|
|
|
case 12: // 0x8C, azure
|
|
|
|
return azuremap;
|
|
|
|
case 13: // 0x8D, brown
|
|
|
|
return brownmap;
|
|
|
|
case 14: // 0x8E, rosy
|
|
|
|
return rosymap;
|
|
|
|
case 15: // 0x8F, invert
|
|
|
|
return invertmap;
|
2014-03-15 16:59:03 +00:00
|
|
|
default: // reset
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Writes a single character (draw WHITE if bit 7 set)
|
|
|
|
//
|
|
|
|
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed)
|
|
|
|
{
|
|
|
|
INT32 w, flags;
|
|
|
|
const UINT8 *colormap = V_GetStringColormap(c);
|
|
|
|
|
|
|
|
flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
|
|
|
|
c &= 0x7f;
|
|
|
|
if (lowercaseallowed)
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
else
|
|
|
|
c = toupper(c) - HU_FONTSTART;
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
return;
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
w = hu_font[c]->width;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (x + w > vid.width)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (colormap != NULL)
|
|
|
|
V_DrawMappedPatch(x, y, flags, hu_font[c], colormap);
|
|
|
|
else
|
|
|
|
V_DrawScaledPatch(x, y, flags, hu_font[c]);
|
|
|
|
}
|
|
|
|
|
2018-07-31 09:10:02 +00:00
|
|
|
// Writes a single character for the chat. (draw WHITE if bit 7 set)
|
|
|
|
// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge..
|
|
|
|
//
|
|
|
|
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap)
|
|
|
|
{
|
|
|
|
INT32 w, flags;
|
|
|
|
//const UINT8 *colormap = V_GetStringColormap(c);
|
|
|
|
|
|
|
|
flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
|
|
|
|
c &= 0x7f;
|
|
|
|
if (lowercaseallowed)
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
else
|
|
|
|
c = toupper(c) - HU_FONTSTART;
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
return;
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
w = (vid.width < 640 ) ? ((hu_font[c]->width / 2)) : (hu_font[c]->width); // use normal sized characters if we're using a terribly low resolution.
|
2018-07-31 09:10:02 +00:00
|
|
|
if (x + w > vid.width)
|
|
|
|
return;
|
2018-12-17 19:43:59 +00:00
|
|
|
|
2018-07-31 09:10:02 +00:00
|
|
|
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap);
|
|
|
|
|
2018-12-17 19:43:59 +00:00
|
|
|
|
2018-07-31 09:10:02 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Precompile a wordwrapped string to any given width.
|
|
|
|
// This is a muuuch better method than V_WORDWRAP.
|
|
|
|
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
size_t chw, i, lastusablespace = 0;
|
|
|
|
size_t slen;
|
|
|
|
char *newstring = Z_StrDup(string);
|
|
|
|
INT32 spacewidth = 4, charwidth = 0;
|
|
|
|
|
|
|
|
slen = strlen(string);
|
|
|
|
|
|
|
|
if (w == 0)
|
|
|
|
w = BASEVIDWIDTH;
|
|
|
|
w -= x;
|
|
|
|
x = 0;
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 8;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 8;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 6;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < slen; ++i)
|
|
|
|
{
|
|
|
|
c = newstring[i];
|
2019-12-05 19:43:37 +00:00
|
|
|
if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09
|
2014-03-15 16:59:03 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
lastusablespace = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(option & V_ALLOWLOWERCASE))
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
{
|
|
|
|
chw = spacewidth;
|
|
|
|
lastusablespace = i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
chw = (charwidth ? charwidth : hu_font[c]->width);
|
|
|
|
|
|
|
|
x += chw;
|
|
|
|
|
|
|
|
if (lastusablespace != 0 && x > w)
|
|
|
|
{
|
|
|
|
newstring[lastusablespace] = '\n';
|
|
|
|
i = lastusablespace;
|
|
|
|
lastusablespace = 0;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newstring;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write a string using the hu_font
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
|
|
|
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
2018-08-25 18:52:17 +00:00
|
|
|
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
const char *ch = string;
|
2018-06-05 16:22:28 +00:00
|
|
|
INT32 charflags = (option & V_CHARCOLORMASK);
|
2014-03-15 16:59:03 +00:00
|
|
|
const UINT8 *colormap = NULL;
|
|
|
|
INT32 spacewidth = 4, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2014-03-15 16:59:03 +00:00
|
|
|
dupx = dupy = 1;
|
2018-08-25 18:52:17 +00:00
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 8;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 8;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 6;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += 8*dupy;
|
|
|
|
else
|
|
|
|
cy += 12*dupy;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase)
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
// character does not exist or is a space
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
{
|
|
|
|
cx += spacewidth * dupx;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = charwidth * dupx;
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - hu_font[c]->width*dupx/2;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = hu_font[c]->width * dupx;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx+left + w < 0) //left boundary check
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
colormap = V_GetStringColormap(charflags);
|
2014-03-21 18:42:55 +00:00
|
|
|
V_DrawFixedPatch((cx + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, hu_font[c], colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_StringWidth(string, option)/2;
|
|
|
|
V_DrawString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
|
|
|
void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_StringWidth(string, option);
|
|
|
|
V_DrawString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write a string using the hu_font, 0.5x scale
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
|
|
|
void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
2018-08-25 18:52:17 +00:00
|
|
|
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
const char *ch = string;
|
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2014-03-15 16:59:03 +00:00
|
|
|
dupx = dupy = 1;
|
2018-08-25 18:52:17 +00:00
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 4;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 4;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += 4*dupy;
|
|
|
|
else
|
|
|
|
cy += 6*dupy;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase)
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
{
|
|
|
|
cx += spacewidth * dupx;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = charwidth * dupx;
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - hu_font[c]->width*dupx/4;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = hu_font[c]->width * dupx / 2;
|
2018-08-28 18:31:08 +00:00
|
|
|
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx+left + w < 0) //left boundary check
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
colormap = V_GetStringColormap(charflags);
|
2014-03-21 18:42:55 +00:00
|
|
|
V_DrawFixedPatch((cx + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT/2, option, hu_font[c], colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 07:57:19 +00:00
|
|
|
void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_SmallStringWidth(string, option)/2;
|
|
|
|
V_DrawSmallString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_SmallStringWidth(string, option);
|
|
|
|
V_DrawSmallString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// Write a string using the tny_font
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
|
|
|
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
2018-08-25 18:52:17 +00:00
|
|
|
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
const char *ch = string;
|
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2014-03-15 16:59:03 +00:00
|
|
|
dupx = dupy = 1;
|
2018-08-25 18:52:17 +00:00
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 5;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 5;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += 8*dupy;
|
|
|
|
else
|
|
|
|
cy += 12*dupy;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase || !tny_font[c-HU_FONTSTART])
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
|
|
|
|
{
|
|
|
|
cx += spacewidth * dupx;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
w = charwidth * dupx;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = tny_font[c]->width * dupx;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx+left + w < 0) //left boundary check
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
colormap = V_GetStringColormap(charflags);
|
2014-03-21 18:42:55 +00:00
|
|
|
V_DrawFixedPatch(cx<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, tny_font[c], colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 08:05:03 +00:00
|
|
|
void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_ThinStringWidth(string, option)/2;
|
|
|
|
V_DrawThinString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_ThinStringWidth(string, option);
|
|
|
|
V_DrawThinString(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-08-28 03:44:19 +00:00
|
|
|
//
|
|
|
|
// Write a string using the tny_font, 0.5x scale
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
2019-09-28 18:01:58 +00:00
|
|
|
// Literally a wrapper. ~Golden
|
2019-08-28 03:44:19 +00:00
|
|
|
void V_DrawSmallThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
2019-09-28 18:01:58 +00:00
|
|
|
x <<= FRACBITS;
|
|
|
|
y <<= FRACBITS;
|
|
|
|
V_DrawSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string);
|
2019-08-28 03:44:19 +00:00
|
|
|
}
|
|
|
|
|
2019-10-09 03:16:50 +00:00
|
|
|
void V_DrawCenteredSmallThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x <<= FRACBITS;
|
|
|
|
y <<= FRACBITS;
|
|
|
|
V_DrawCenteredSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-10-09 03:11:40 +00:00
|
|
|
void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
2019-10-09 02:54:18 +00:00
|
|
|
{
|
|
|
|
x <<= FRACBITS;
|
|
|
|
y <<= FRACBITS;
|
|
|
|
V_DrawRightAlignedSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string);
|
2019-10-09 03:11:40 +00:00
|
|
|
}
|
2019-10-09 02:54:18 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Draws a string at a fixed_t location.
|
|
|
|
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
fixed_t cx = x, cy = y;
|
2018-08-25 18:52:17 +00:00
|
|
|
INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
const char *ch = string;
|
2019-12-02 14:24:05 +00:00
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
2014-03-15 16:59:03 +00:00
|
|
|
INT32 spacewidth = 4, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2014-03-15 16:59:03 +00:00
|
|
|
dupx = dupy = 1;
|
2018-08-25 18:52:17 +00:00
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2019-12-02 14:24:05 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 8;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 8;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 6;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch & 0x80) //color ignoring
|
2019-12-02 14:24:05 +00:00
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
2014-03-15 16:59:03 +00:00
|
|
|
continue;
|
2019-12-02 14:24:05 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += (8*dupy)<<FRACBITS;
|
|
|
|
else
|
|
|
|
cy += (12*dupy)<<FRACBITS;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase)
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
// character does not exist or is a space
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
{
|
|
|
|
cx += (spacewidth * dupx)<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = charwidth * dupx;
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - hu_font[c]->width*(dupx/2);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = hu_font[c]->width * dupx;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2018-08-25 18:52:17 +00:00
|
|
|
if ((cx>>FRACBITS) > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2018-08-25 18:52:17 +00:00
|
|
|
if ((cx>>FRACBITS)+left + w < 0) //left boundary check
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:24:05 +00:00
|
|
|
colormap = V_GetStringColormap(charflags);
|
|
|
|
V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT, option, hu_font[c], colormap);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 08:36:12 +00:00
|
|
|
void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= (V_StringWidth(string, option) / 2)<<FRACBITS;
|
|
|
|
V_DrawStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-08-27 08:25:28 +00:00
|
|
|
void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_StringWidth(string, option)<<FRACBITS;
|
|
|
|
V_DrawStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-08-24 16:45:32 +00:00
|
|
|
// Draws a small string at a fixed_t location.
|
|
|
|
void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
fixed_t cx = x, cy = y;
|
|
|
|
INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0;
|
|
|
|
const char *ch = string;
|
2019-08-27 07:27:25 +00:00
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
2019-08-24 16:45:32 +00:00
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dupx = dupy = 1;
|
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2019-08-27 07:27:25 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
2019-08-24 16:45:32 +00:00
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 4;
|
|
|
|
/* FALLTHRU */
|
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 4;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
2019-08-27 07:27:25 +00:00
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
2019-08-24 16:45:32 +00:00
|
|
|
continue;
|
2019-08-27 07:27:25 +00:00
|
|
|
}
|
2019-08-24 16:45:32 +00:00
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += (4*dupy)<<FRACBITS;
|
|
|
|
else
|
|
|
|
cy += (6*dupy)<<FRACBITS;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase)
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
// character does not exist or is a space
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
{
|
|
|
|
cx += (spacewidth * dupx)<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = charwidth * dupx;
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - hu_font[c]->width*(dupx/4);
|
2019-08-24 16:45:32 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = hu_font[c]->width * dupx / 2;
|
2019-08-24 16:45:32 +00:00
|
|
|
|
|
|
|
if ((cx>>FRACBITS) > scrwidth)
|
|
|
|
break;
|
|
|
|
if ((cx>>FRACBITS)+left + w < 0) //left boundary check
|
|
|
|
{
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-27 07:27:25 +00:00
|
|
|
colormap = V_GetStringColormap(charflags);
|
|
|
|
|
|
|
|
V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT/2, option, hu_font[c], colormap);
|
2019-08-24 16:45:32 +00:00
|
|
|
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 01:41:34 +00:00
|
|
|
void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= (V_SmallStringWidth(string, option) / 2)<<FRACBITS;
|
|
|
|
V_DrawSmallStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-09-10 00:49:04 +00:00
|
|
|
void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_SmallStringWidth(string, option)<<FRACBITS;
|
|
|
|
V_DrawSmallStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-08-24 14:27:37 +00:00
|
|
|
// Draws a thin string at a fixed_t location.
|
|
|
|
void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
fixed_t cx = x, cy = y;
|
|
|
|
INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0;
|
|
|
|
const char *ch = string;
|
2019-08-27 07:27:25 +00:00
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
2019-08-24 14:27:37 +00:00
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dupx = dupy = 1;
|
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2019-08-27 07:27:25 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
2019-08-24 14:27:37 +00:00
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 8;
|
|
|
|
/* FALLTHRU */
|
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 8;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 6;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
2019-08-27 07:27:25 +00:00
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
2019-08-24 14:27:37 +00:00
|
|
|
continue;
|
2019-08-27 07:27:25 +00:00
|
|
|
}
|
2019-08-24 14:27:37 +00:00
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += (8*dupy)<<FRACBITS;
|
|
|
|
else
|
|
|
|
cy += (12*dupy)<<FRACBITS;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase || !tny_font[c-HU_FONTSTART])
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
// character does not exist or is a space
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
|
|
|
|
{
|
|
|
|
cx += (spacewidth * dupx)<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = charwidth * dupx;
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - tny_font[c]->width*(dupx/2);
|
2019-08-24 14:27:37 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = tny_font[c]->width * dupx;
|
2019-08-24 14:27:37 +00:00
|
|
|
|
|
|
|
if ((cx>>FRACBITS) > scrwidth)
|
|
|
|
break;
|
|
|
|
if ((cx>>FRACBITS)+left + w < 0) //left boundary check
|
|
|
|
{
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-27 07:27:25 +00:00
|
|
|
colormap = V_GetStringColormap(charflags);
|
|
|
|
|
|
|
|
V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT, option, tny_font[c], colormap);
|
2019-08-24 14:27:37 +00:00
|
|
|
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-07 22:55:33 +00:00
|
|
|
void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= (V_ThinStringWidth(string, option) / 2)<<FRACBITS;
|
|
|
|
V_DrawThinStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-09-07 22:37:21 +00:00
|
|
|
void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_ThinStringWidth(string, option)<<FRACBITS;
|
|
|
|
V_DrawThinStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-09-10 02:25:52 +00:00
|
|
|
// Draws a small string at a fixed_t location.
|
|
|
|
void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
fixed_t cx = x, cy = y;
|
|
|
|
INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0;
|
|
|
|
const char *ch = string;
|
|
|
|
INT32 charflags = 0;
|
|
|
|
const UINT8 *colormap = NULL;
|
|
|
|
INT32 spacewidth = 2<<FRACBITS, charwidth = 0;
|
|
|
|
|
|
|
|
INT32 lowercase = (option & V_ALLOWLOWERCASE);
|
|
|
|
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx<<FRACBITS;
|
|
|
|
dupy = vid.dupy<<FRACBITS;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dupx = dupy = FRACUNIT;
|
|
|
|
scrwidth = FixedDiv(vid.width<<FRACBITS, vid.dupx);
|
|
|
|
left = ((scrwidth - (BASEVIDWIDTH<<FRACBITS))/2);
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2019-09-10 02:25:52 +00:00
|
|
|
charflags = (option & V_CHARCOLORMASK);
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 4<<FRACBITS;
|
|
|
|
/* FALLTHRU */
|
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 4<<FRACBITS;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3<<FRACBITS;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
|
|
|
|
if (option & V_RETURN8)
|
|
|
|
cy += 4*dupy;
|
|
|
|
else
|
|
|
|
cy += 6*dupy;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *ch;
|
|
|
|
if (!lowercase)
|
|
|
|
c = toupper(c);
|
|
|
|
c -= HU_FONTSTART;
|
|
|
|
|
|
|
|
// character does not exist or is a space
|
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
|
|
|
|
{
|
|
|
|
cx += FixedMul(spacewidth, dupx);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charwidth)
|
|
|
|
{
|
|
|
|
w = FixedMul(charwidth, dupx);
|
2020-11-22 23:02:47 +00:00
|
|
|
center = w/2 - tny_font[c]->width*(dupx/4);
|
2019-09-10 02:25:52 +00:00
|
|
|
}
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w = tny_font[c]->width * dupx / 2;
|
2019-09-10 02:25:52 +00:00
|
|
|
|
|
|
|
if (cx > scrwidth)
|
|
|
|
break;
|
|
|
|
if (cx+left + w < 0) //left boundary check
|
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
colormap = V_GetStringColormap(charflags);
|
|
|
|
|
|
|
|
V_DrawFixedPatch(cx + center, cy, FRACUNIT/2, option, tny_font[c], colormap);
|
|
|
|
|
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-09 03:03:43 +00:00
|
|
|
void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_SmallThinStringWidth(string, option)/4;
|
|
|
|
V_DrawSmallThinStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2019-10-09 02:54:18 +00:00
|
|
|
void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
x -= V_SmallThinStringWidth(string, option)/2;
|
|
|
|
V_DrawSmallThinStringAtFixed(x, y, option, string);
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Draws a tallnum. Replaces two functions in y_inter and st_stuff
|
|
|
|
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num)
|
|
|
|
{
|
2020-11-22 23:02:47 +00:00
|
|
|
INT32 w = tallnum[0]->width;
|
2014-03-15 16:59:03 +00:00
|
|
|
boolean neg;
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (flags & (V_NOSCALESTART|V_NOSCALEPATCH))
|
2014-03-15 16:59:03 +00:00
|
|
|
w *= vid.dupx;
|
|
|
|
|
|
|
|
if ((neg = num < 0))
|
|
|
|
num = -num;
|
|
|
|
|
|
|
|
// draw the number
|
|
|
|
do
|
|
|
|
{
|
|
|
|
x -= w;
|
|
|
|
V_DrawScaledPatch(x, y, flags, tallnum[num % 10]);
|
|
|
|
num /= 10;
|
|
|
|
} while (num);
|
|
|
|
|
|
|
|
// draw a minus sign if necessary
|
|
|
|
if (neg)
|
|
|
|
V_DrawScaledPatch(x - w, y, flags, tallminus); // Tails
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draws a number with a set number of digits.
|
|
|
|
// Does not handle negative numbers in a special way, don't try to feed it any.
|
|
|
|
void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits)
|
|
|
|
{
|
2020-11-22 23:02:47 +00:00
|
|
|
INT32 w = tallnum[0]->width;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (flags & (V_NOSCALESTART|V_NOSCALEPATCH))
|
2014-03-15 16:59:03 +00:00
|
|
|
w *= vid.dupx;
|
|
|
|
|
|
|
|
if (num < 0)
|
|
|
|
num = -num;
|
|
|
|
|
|
|
|
// draw the number
|
|
|
|
do
|
|
|
|
{
|
|
|
|
x -= w;
|
|
|
|
V_DrawScaledPatch(x, y, flags, tallnum[num % 10]);
|
|
|
|
num /= 10;
|
|
|
|
} while (--digits);
|
|
|
|
}
|
|
|
|
|
2018-02-22 21:49:36 +00:00
|
|
|
// Draw an act number for a level title
|
2020-04-30 14:01:03 +00:00
|
|
|
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num)
|
2018-02-22 21:49:36 +00:00
|
|
|
{
|
2020-04-30 15:12:52 +00:00
|
|
|
if (num > 99)
|
2018-02-22 21:49:36 +00:00
|
|
|
return; // not supported
|
|
|
|
|
2020-04-30 14:01:03 +00:00
|
|
|
while (num > 0)
|
|
|
|
{
|
2020-04-30 15:12:52 +00:00
|
|
|
if (num > 9) // if there are two digits, draw second digit first
|
2020-04-30 14:01:03 +00:00
|
|
|
V_DrawScaledPatch(x + (V_LevelActNumWidth(num) - V_LevelActNumWidth(num%10)), y, flags, ttlnum[num%10]);
|
|
|
|
else
|
|
|
|
V_DrawScaledPatch(x, y, flags, ttlnum[num]);
|
|
|
|
num = num/10;
|
|
|
|
}
|
2018-02-22 21:49:36 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Write a string using the credit font
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
|
|
|
void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|
|
|
{
|
|
|
|
INT32 w, c, dupx, dupy, scrwidth = BASEVIDWIDTH;
|
|
|
|
fixed_t cx = x, cy = y;
|
|
|
|
const char *ch = string;
|
|
|
|
|
|
|
|
// It's possible for string to be a null pointer
|
|
|
|
if (!string)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dupx = dupy = 1;
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
c = *ch++;
|
|
|
|
if (!c)
|
|
|
|
break;
|
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
cy += (12*dupy)<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = toupper(c) - CRED_FONTSTART;
|
|
|
|
if (c < 0 || c >= CRED_FONTSIZE)
|
|
|
|
{
|
|
|
|
cx += (16*dupx)<<FRACBITS;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
w = cred_font[c]->width * dupx;
|
2018-08-25 18:52:17 +00:00
|
|
|
if ((cx>>FRACBITS) > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT);
|
|
|
|
cx += w<<FRACBITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 05:56:48 +00:00
|
|
|
// Draw a string using the nt_font
|
|
|
|
// Note that the outline is a seperate font set
|
2019-10-14 05:24:44 +00:00
|
|
|
static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string)
|
2019-10-09 04:28:01 +00:00
|
|
|
{
|
2019-10-14 05:24:44 +00:00
|
|
|
fixed_t cx, cy, w;
|
|
|
|
INT32 c, dupx, dupy, scrwidth, left = 0;
|
2019-10-09 04:28:01 +00:00
|
|
|
const char *ch = string;
|
|
|
|
|
2019-10-14 05:24:44 +00:00
|
|
|
if (option & V_CENTERNAMETAG)
|
|
|
|
x -= FixedInt(FixedMul((V_NameTagWidth(string)/2)*FRACUNIT, scale));
|
|
|
|
option &= ~V_CENTERNAMETAG; // which is also shared with V_ALLOWLOWERCASE...
|
|
|
|
|
|
|
|
cx = x<<FRACBITS;
|
|
|
|
cy = y<<FRACBITS;
|
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dupx = dupy = 1;
|
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2019-10-09 04:28:01 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2019-10-09 04:28:01 +00:00
|
|
|
for (;;ch++)
|
|
|
|
{
|
|
|
|
if (!*ch)
|
|
|
|
break;
|
|
|
|
if (*ch == '\n')
|
|
|
|
{
|
2019-10-14 05:24:44 +00:00
|
|
|
cx = x<<FRACBITS;
|
|
|
|
cy += FixedMul((21*dupy)*FRACUNIT, scale);
|
2019-10-09 04:28:01 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-10-14 05:24:44 +00:00
|
|
|
c = toupper(*ch);
|
2019-10-10 05:56:48 +00:00
|
|
|
c -= NT_FONTSTART;
|
2019-10-09 04:28:01 +00:00
|
|
|
|
|
|
|
// character does not exist or is a space
|
2019-10-10 05:56:48 +00:00
|
|
|
if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c])
|
2019-10-09 04:28:01 +00:00
|
|
|
{
|
2019-10-14 05:24:44 +00:00
|
|
|
cx += FixedMul((4 * dupx)*FRACUNIT, scale);
|
2019-10-09 04:28:01 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
w = FixedMul(((ntb_font[c]->width)+2 * dupx) * FRACUNIT, scale);
|
2019-10-09 04:28:01 +00:00
|
|
|
|
2019-10-14 05:24:44 +00:00
|
|
|
if (FixedInt(cx) > scrwidth)
|
2019-10-09 04:28:01 +00:00
|
|
|
continue;
|
2019-10-14 05:24:44 +00:00
|
|
|
if (cx+(left*FRACUNIT) + w < 0) // left boundary check
|
2019-10-09 04:28:01 +00:00
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-10-14 05:24:44 +00:00
|
|
|
V_DrawFixedPatch(cx, cy, scale, option, nto_font[c], outlinecolormap);
|
|
|
|
V_DrawFixedPatch(cx, cy, scale, option, ntb_font[c], basecolormap);
|
2019-10-09 04:28:01 +00:00
|
|
|
|
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-14 05:24:44 +00:00
|
|
|
// Looks familiar.
|
|
|
|
void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string)
|
|
|
|
{
|
2019-10-19 17:15:54 +00:00
|
|
|
const char *text = string;
|
|
|
|
const char *first_token = text;
|
2019-10-14 05:24:44 +00:00
|
|
|
char *last_token = strchr(text, '\n');
|
|
|
|
const INT32 lbreakheight = 21;
|
2019-10-19 17:15:54 +00:00
|
|
|
INT32 ntlines;
|
2019-10-14 05:24:44 +00:00
|
|
|
|
|
|
|
if (option & V_CENTERNAMETAG)
|
|
|
|
{
|
2019-10-19 17:15:54 +00:00
|
|
|
ntlines = V_CountNameTagLines(string);
|
|
|
|
y -= FixedInt(FixedMul(((lbreakheight/2) * (ntlines-1))*FRACUNIT, scale));
|
2019-10-14 05:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// No line breaks?
|
|
|
|
// Draw entire string
|
|
|
|
if (!last_token)
|
|
|
|
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, string);
|
|
|
|
// Split string by the line break character
|
|
|
|
else
|
|
|
|
{
|
2019-10-19 17:15:54 +00:00
|
|
|
char *str = NULL;
|
2019-10-14 05:24:44 +00:00
|
|
|
INT32 len;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
// There are still lines left to draw
|
|
|
|
if (last_token)
|
|
|
|
{
|
|
|
|
size_t shift = 0;
|
|
|
|
// Free this line
|
2019-10-19 17:15:54 +00:00
|
|
|
if (str)
|
|
|
|
Z_Free(str);
|
2019-10-14 05:24:44 +00:00
|
|
|
// Find string length, do a malloc...
|
|
|
|
len = (last_token-first_token)+1;
|
2019-10-19 17:15:54 +00:00
|
|
|
str = ZZ_Alloc(len);
|
2019-10-14 05:24:44 +00:00
|
|
|
// Copy the line
|
2019-10-19 17:15:54 +00:00
|
|
|
strncpy(str, first_token, len-1);
|
|
|
|
str[len-1] = '\0';
|
2019-10-14 05:24:44 +00:00
|
|
|
// Don't leave a line break character
|
|
|
|
// at the start of the string!
|
2019-10-19 17:15:54 +00:00
|
|
|
if ((strlen(str) >= 2) && (string[0] == '\n') && (string[1] != '\n'))
|
2019-10-14 05:24:44 +00:00
|
|
|
shift++;
|
|
|
|
// Then draw it
|
2019-10-19 17:15:54 +00:00
|
|
|
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, str+shift);
|
2019-10-14 05:24:44 +00:00
|
|
|
}
|
|
|
|
// No line break character was found
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Don't leave a line break character
|
|
|
|
// at the start of the string!
|
|
|
|
if ((strlen(first_token) >= 2) && (first_token[0] == '\n') && (first_token[1] != '\n'))
|
|
|
|
first_token++;
|
|
|
|
// Then draw it
|
|
|
|
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, first_token);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next line
|
|
|
|
y += FixedInt(FixedMul(lbreakheight*FRACUNIT, scale));
|
2019-10-19 17:15:54 +00:00
|
|
|
if ((last_token-text)+1 >= (signed)strlen(text))
|
2019-10-14 05:24:44 +00:00
|
|
|
last_token = NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
first_token = last_token;
|
|
|
|
last_token = strchr(first_token+1, '\n');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Free this line
|
2019-10-19 17:15:54 +00:00
|
|
|
if (str)
|
|
|
|
Z_Free(str);
|
2019-10-14 05:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Count the amount of lines in name tag string
|
|
|
|
INT32 V_CountNameTagLines(const char *string)
|
|
|
|
{
|
2019-10-19 17:15:54 +00:00
|
|
|
INT32 ntlines = 1;
|
|
|
|
const char *text = string;
|
|
|
|
const char *first_token = text;
|
2019-10-14 05:24:44 +00:00
|
|
|
char *last_token = strchr(text, '\n');
|
|
|
|
|
|
|
|
// No line breaks?
|
|
|
|
if (!last_token)
|
2019-10-19 17:15:54 +00:00
|
|
|
return ntlines;
|
2019-10-14 05:24:44 +00:00
|
|
|
// Split string by the line break character
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (last_token)
|
2019-10-19 17:15:54 +00:00
|
|
|
ntlines++;
|
2019-10-14 05:24:44 +00:00
|
|
|
// No line break character was found
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Next line
|
2019-10-19 17:15:54 +00:00
|
|
|
if ((last_token-text)+1 >= (signed)strlen(text))
|
2019-10-14 05:24:44 +00:00
|
|
|
last_token = NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
first_token = last_token;
|
|
|
|
last_token = strchr(first_token+1, '\n');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-19 17:15:54 +00:00
|
|
|
return ntlines;
|
2019-10-14 05:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
INT32 V_NameTagWidth(const char *string)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
// It's possible for string to be a null pointer
|
|
|
|
if (!string)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
|
|
|
c = toupper(string[i]) - NT_FONTSTART;
|
|
|
|
if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c])
|
|
|
|
w += 4;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += (ntb_font[c]->width)+2;
|
2019-10-14 05:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// Find string width from cred_font chars
|
|
|
|
//
|
|
|
|
INT32 V_CreditStringWidth(const char *string)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
// It's possible for string to be a null pointer
|
|
|
|
if (!string)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
|
|
|
c = toupper(string[i]) - CRED_FONTSTART;
|
|
|
|
if (c < 0 || c >= CRED_FONTSIZE)
|
2014-11-12 00:55:07 +00:00
|
|
|
w += 16;
|
2014-03-15 16:59:03 +00:00
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += cred_font[c]->width;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write a string using the level title font
|
|
|
|
// NOTE: the text is centered for screens larger than the base width
|
|
|
|
//
|
|
|
|
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
|
|
|
|
{
|
2018-08-25 18:52:17 +00:00
|
|
|
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
const char *ch = string;
|
2018-06-05 16:22:28 +00:00
|
|
|
INT32 charflags = (option & V_CHARCOLORMASK);
|
|
|
|
const UINT8 *colormap = NULL;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
if (option & V_NOSCALESTART)
|
|
|
|
{
|
|
|
|
dupx = vid.dupx;
|
|
|
|
dupy = vid.dupy;
|
|
|
|
scrwidth = vid.width;
|
|
|
|
}
|
|
|
|
else
|
2018-08-25 18:52:17 +00:00
|
|
|
{
|
2014-03-15 16:59:03 +00:00
|
|
|
dupx = dupy = 1;
|
2018-08-25 18:52:17 +00:00
|
|
|
scrwidth = vid.width/vid.dupx;
|
|
|
|
left = (scrwidth - BASEVIDWIDTH)/2;
|
|
|
|
scrwidth -= left;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & V_NOSCALEPATCH)
|
|
|
|
scrwidth *= vid.dupx;
|
|
|
|
|
2018-06-05 16:22:28 +00:00
|
|
|
for (;;ch++)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2018-06-05 16:22:28 +00:00
|
|
|
if (!*ch)
|
2014-03-15 16:59:03 +00:00
|
|
|
break;
|
2018-06-05 16:22:28 +00:00
|
|
|
if (*ch & 0x80) //color parsing -x 2.16.09
|
|
|
|
{
|
|
|
|
// manually set flags override color codes
|
|
|
|
if (!(option & V_CHARCOLORMASK))
|
|
|
|
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*ch == '\n')
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx = x;
|
|
|
|
cy += 12*dupy;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-03-17 20:44:24 +00:00
|
|
|
c = *ch - LT_FONTSTART;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
|
|
|
|
{
|
|
|
|
cx += 16*dupx;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
w = lt_font[c]->width * dupx;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx > scrwidth)
|
2019-08-20 23:33:39 +00:00
|
|
|
continue;
|
2018-08-25 18:52:17 +00:00
|
|
|
if (cx+left + w < 0) //left boundary check
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
|
|
|
cx += w;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-06-05 16:22:28 +00:00
|
|
|
colormap = V_GetStringColormap(charflags);
|
|
|
|
V_DrawFixedPatch(cx<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, lt_font[c], colormap);
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
cx += w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find string width from lt_font chars
|
|
|
|
//
|
|
|
|
INT32 V_LevelNameWidth(const char *string)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
2018-06-05 16:22:28 +00:00
|
|
|
if (string[i] & 0x80)
|
|
|
|
continue;
|
2019-03-17 20:44:24 +00:00
|
|
|
c = string[i] - LT_FONTSTART;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
|
|
|
|
w += 16;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += lt_font[c]->width;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find max height of the string
|
|
|
|
//
|
|
|
|
INT32 V_LevelNameHeight(const char *string)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
2019-03-17 20:44:24 +00:00
|
|
|
c = string[i] - LT_FONTSTART;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
|
|
|
|
continue;
|
|
|
|
|
2020-11-22 23:02:47 +00:00
|
|
|
if (lt_font[c]->height > w)
|
|
|
|
w = lt_font[c]->height;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2019-11-18 14:39:54 +00:00
|
|
|
// For ST_drawTitleCard
|
2020-04-30 15:12:52 +00:00
|
|
|
// Returns the width of the act num patch(es)
|
|
|
|
INT16 V_LevelActNumWidth(UINT8 num)
|
2018-02-22 21:49:36 +00:00
|
|
|
{
|
2020-04-30 15:12:52 +00:00
|
|
|
INT16 result = 0;
|
2018-02-22 21:49:36 +00:00
|
|
|
|
2020-04-30 14:01:03 +00:00
|
|
|
if (num == 0)
|
2020-11-22 23:02:47 +00:00
|
|
|
result = ttlnum[num]->width;
|
2018-02-22 21:49:36 +00:00
|
|
|
|
2020-04-30 15:12:52 +00:00
|
|
|
while (num > 0 && num <= 99)
|
2020-04-30 14:01:03 +00:00
|
|
|
{
|
2020-11-22 23:02:47 +00:00
|
|
|
result = result + ttlnum[num%10]->width;
|
2020-04-30 14:01:03 +00:00
|
|
|
num = num/10;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2018-02-22 21:49:36 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// Find string width from hu_font chars
|
|
|
|
//
|
|
|
|
INT32 V_StringWidth(const char *string, INT32 option)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
INT32 spacewidth = 4, charwidth = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 8;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 8;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 6;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
2018-06-05 16:22:28 +00:00
|
|
|
if (string[i] & 0x80)
|
2014-03-15 16:59:03 +00:00
|
|
|
continue;
|
2018-06-05 16:22:28 +00:00
|
|
|
c = toupper(string[i]) - HU_FONTSTART;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
w += spacewidth;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += (charwidth ? charwidth : hu_font[c]->width);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-09 16:03:02 +00:00
|
|
|
if (option & (V_NOSCALESTART|V_NOSCALEPATCH))
|
|
|
|
w *= vid.dupx;
|
2017-04-17 00:09:47 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
//
|
|
|
|
// Find string width from hu_font chars, 0.5x scale
|
|
|
|
//
|
|
|
|
INT32 V_SmallStringWidth(const char *string, INT32 option)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 4;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-08-04 03:49:33 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 4;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
2018-06-05 16:22:28 +00:00
|
|
|
if (string[i] & 0x80)
|
2014-08-04 03:49:33 +00:00
|
|
|
continue;
|
2018-06-05 16:22:28 +00:00
|
|
|
c = toupper(string[i]) - HU_FONTSTART;
|
2014-08-04 03:49:33 +00:00
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
|
|
|
w += spacewidth;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += (charwidth ? charwidth : (hu_font[c]->width / 2));
|
2014-08-04 03:49:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
// Find string width from tny_font chars
|
|
|
|
//
|
|
|
|
INT32 V_ThinStringWidth(const char *string, INT32 option)
|
|
|
|
{
|
|
|
|
INT32 c, w = 0;
|
|
|
|
INT32 spacewidth = 2, charwidth = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
switch (option & V_SPACINGMASK)
|
|
|
|
{
|
|
|
|
case V_MONOSPACE:
|
|
|
|
spacewidth = 5;
|
2017-09-28 13:39:47 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case V_OLDSPACING:
|
|
|
|
charwidth = 5;
|
|
|
|
break;
|
|
|
|
case V_6WIDTHSPACE:
|
|
|
|
spacewidth = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
2018-06-05 16:22:28 +00:00
|
|
|
if (string[i] & 0x80)
|
2014-03-15 16:59:03 +00:00
|
|
|
continue;
|
2018-06-05 16:22:28 +00:00
|
|
|
c = toupper(string[i]) - HU_FONTSTART;
|
2014-03-15 16:59:03 +00:00
|
|
|
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
|
|
|
|
w += spacewidth;
|
|
|
|
else
|
2020-11-22 23:02:47 +00:00
|
|
|
w += (charwidth ? charwidth : tny_font[c]->width);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2019-10-09 02:54:18 +00:00
|
|
|
//
|
|
|
|
// Find string width from tny_font chars, 0.5x scale
|
|
|
|
//
|
|
|
|
INT32 V_SmallThinStringWidth(const char *string, INT32 option)
|
|
|
|
{
|
|
|
|
INT32 w = V_ThinStringWidth(string, option)<<FRACBITS;
|
|
|
|
return w/2 + FRACUNIT; // +FRACUNIT because otherwise it's offset wrong.
|
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
boolean *heatshifter = NULL;
|
|
|
|
INT32 lastheight = 0;
|
|
|
|
INT32 heatindex[2] = { 0, 0 };
|
|
|
|
|
|
|
|
//
|
|
|
|
// V_DoPostProcessor
|
|
|
|
//
|
|
|
|
// Perform a particular image postprocessing function.
|
|
|
|
//
|
|
|
|
#include "p_local.h"
|
|
|
|
void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
|
|
|
|
{
|
|
|
|
#if NUMSCREENS < 5
|
|
|
|
// do not enable image post processing for ARM, SH and MIPS CPUs
|
|
|
|
(void)view;
|
|
|
|
(void)type;
|
|
|
|
(void)param;
|
|
|
|
#else
|
|
|
|
INT32 height, yoffset;
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
2019-12-25 19:22:01 +00:00
|
|
|
if (rendermode != render_soft)
|
2014-03-15 16:59:03 +00:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (view < 0 || view >= 2 || (view == 1 && !splitscreen))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (splitscreen)
|
|
|
|
height = vid.height/2;
|
|
|
|
else
|
|
|
|
height = vid.height;
|
|
|
|
|
|
|
|
if (view == 1)
|
|
|
|
yoffset = vid.height/2;
|
|
|
|
else
|
|
|
|
yoffset = 0;
|
|
|
|
|
|
|
|
if (type == postimg_water)
|
|
|
|
{
|
2014-08-04 03:49:33 +00:00
|
|
|
UINT8 *tmpscr = screens[4];
|
|
|
|
UINT8 *srcscr = screens[0];
|
|
|
|
INT32 y;
|
2022-11-13 15:15:15 +00:00
|
|
|
// Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic
|
|
|
|
angle_t disStart = (((leveltime-1)*128) + (rendertimefrac / (FRACUNIT/128))) & FINEMASK;
|
2014-08-04 03:49:33 +00:00
|
|
|
INT32 newpix;
|
|
|
|
INT32 sine;
|
2020-10-27 03:03:41 +00:00
|
|
|
//UINT8 *transme = R_GetTranslucencyTable(tr_trans50);
|
2014-08-04 03:49:33 +00:00
|
|
|
|
|
|
|
for (y = yoffset; y < yoffset+height; y++)
|
|
|
|
{
|
|
|
|
sine = (FINESINE(disStart)*5)>>FRACBITS;
|
|
|
|
newpix = abs(sine);
|
|
|
|
|
|
|
|
if (sine < 0)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2014-08-04 03:49:33 +00:00
|
|
|
M_Memcpy(&tmpscr[y*vid.width+newpix], &srcscr[y*vid.width], vid.width-newpix);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
// Cleanup edge
|
|
|
|
while (newpix)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2014-08-04 03:49:33 +00:00
|
|
|
tmpscr[y*vid.width+newpix] = srcscr[y*vid.width];
|
|
|
|
newpix--;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2014-08-04 03:49:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
M_Memcpy(&tmpscr[y*vid.width+0], &srcscr[y*vid.width+sine], vid.width-newpix);
|
|
|
|
|
|
|
|
// Cleanup edge
|
|
|
|
while (newpix)
|
2014-03-15 16:59:03 +00:00
|
|
|
{
|
2014-08-04 03:49:33 +00:00
|
|
|
tmpscr[y*vid.width+vid.width-newpix] = srcscr[y*vid.width+(vid.width-1)];
|
|
|
|
newpix--;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
2014-08-04 03:49:33 +00:00
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Unoptimized version
|
2014-08-04 03:49:33 +00:00
|
|
|
for (x = 0; x < vid.width*vid.bpp; x++)
|
|
|
|
{
|
|
|
|
newpix = (x + sine);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
if (newpix < 0)
|
|
|
|
newpix = 0;
|
|
|
|
else if (newpix >= vid.width)
|
|
|
|
newpix = vid.width-1;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
|
|
|
|
}*/
|
|
|
|
disStart += 22;//the offset into the displacement map, increment each game loop
|
|
|
|
disStart &= FINEMASK; //clip it to FINEMASK
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
2014-08-04 03:49:33 +00:00
|
|
|
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
|
|
|
|
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
else if (type == postimg_motion) // Motion Blur!
|
|
|
|
{
|
|
|
|
UINT8 *tmpscr = screens[4];
|
|
|
|
UINT8 *srcscr = screens[0];
|
|
|
|
INT32 x, y;
|
|
|
|
|
|
|
|
// TODO: Add a postimg_param so that we can pick the translucency level...
|
2020-10-27 03:03:41 +00:00
|
|
|
UINT8 *transme = R_GetTranslucencyTable(param);
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
for (y = yoffset; y < yoffset+height; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < vid.width; x++)
|
|
|
|
{
|
|
|
|
tmpscr[y*vid.width + x]
|
|
|
|
= colormaps[*(transme + (srcscr [y*vid.width+x ] <<8) + (tmpscr[y*vid.width+x]))];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
|
|
|
|
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
|
|
|
|
}
|
|
|
|
else if (type == postimg_flip) // Flip the screen upside-down
|
|
|
|
{
|
|
|
|
UINT8 *tmpscr = screens[4];
|
|
|
|
UINT8 *srcscr = screens[0];
|
|
|
|
INT32 y, y2;
|
|
|
|
|
|
|
|
for (y = yoffset, y2 = yoffset+height - 1; y < yoffset+height; y++, y2--)
|
|
|
|
M_Memcpy(&tmpscr[y2*vid.width], &srcscr[y*vid.width], vid.width);
|
|
|
|
|
|
|
|
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
|
|
|
|
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
|
|
|
|
}
|
|
|
|
else if (type == postimg_heat) // Heat wave
|
|
|
|
{
|
|
|
|
UINT8 *tmpscr = screens[4];
|
|
|
|
UINT8 *srcscr = screens[0];
|
|
|
|
INT32 y;
|
|
|
|
|
|
|
|
// Make sure table is built
|
|
|
|
if (heatshifter == NULL || lastheight != height)
|
|
|
|
{
|
|
|
|
if (heatshifter)
|
|
|
|
Z_Free(heatshifter);
|
|
|
|
|
|
|
|
heatshifter = Z_Calloc(height * sizeof(boolean), PU_STATIC, NULL);
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++)
|
|
|
|
{
|
2016-03-27 14:33:15 +00:00
|
|
|
if (M_RandomChance(FRACUNIT/8)) // 12.5%
|
2014-03-15 16:59:03 +00:00
|
|
|
heatshifter[y] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
heatindex[0] = heatindex[1] = 0;
|
|
|
|
lastheight = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (y = yoffset; y < yoffset+height; y++)
|
|
|
|
{
|
|
|
|
if (heatshifter[heatindex[view]++])
|
|
|
|
{
|
|
|
|
// Shift this row of pixels to the right by 2
|
|
|
|
tmpscr[y*vid.width] = srcscr[y*vid.width];
|
|
|
|
M_Memcpy(&tmpscr[y*vid.width+vid.dupx], &srcscr[y*vid.width], vid.width-vid.dupx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
M_Memcpy(&tmpscr[y*vid.width], &srcscr[y*vid.width], vid.width);
|
|
|
|
|
|
|
|
heatindex[view] %= height;
|
|
|
|
}
|
|
|
|
|
2022-11-13 15:15:15 +00:00
|
|
|
if (renderisnewtic) // This isn't interpolated... but how do you interpolate a one-pixel shift?
|
|
|
|
{
|
|
|
|
heatindex[view]++;
|
|
|
|
heatindex[view] %= vid.height;
|
|
|
|
}
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
|
|
|
|
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-09-10 04:43:46 +00:00
|
|
|
// Generates a RGB565 color look-up table
|
2020-09-10 05:10:31 +00:00
|
|
|
void InitColorLUT(colorlookup_t *lut, RGBA_t *palette, boolean makecolors)
|
2019-11-10 03:04:11 +00:00
|
|
|
{
|
2020-09-10 04:43:46 +00:00
|
|
|
size_t palsize = (sizeof(RGBA_t) * 256);
|
|
|
|
|
2020-09-10 05:10:31 +00:00
|
|
|
if (!lut->init || memcmp(lut->palette, palette, palsize))
|
2019-11-10 03:04:11 +00:00
|
|
|
{
|
2020-09-10 04:43:46 +00:00
|
|
|
INT32 i;
|
|
|
|
|
2020-09-10 05:10:31 +00:00
|
|
|
lut->init = true;
|
|
|
|
memcpy(lut->palette, palette, palsize);
|
2020-09-10 04:43:46 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 0xFFFF; i++)
|
2020-09-10 05:10:31 +00:00
|
|
|
lut->table[i] = 0xFFFF;
|
2020-09-10 04:43:46 +00:00
|
|
|
|
|
|
|
if (makecolors)
|
|
|
|
{
|
|
|
|
UINT8 r, g, b;
|
|
|
|
|
|
|
|
for (r = 0; r < 0xFF; r++)
|
|
|
|
for (g = 0; g < 0xFF; g++)
|
|
|
|
for (b = 0; b < 0xFF; b++)
|
|
|
|
{
|
|
|
|
i = CLUTINDEX(r, g, b);
|
2020-09-10 05:10:31 +00:00
|
|
|
if (lut->table[i] == 0xFFFF)
|
|
|
|
lut->table[i] = NearestPaletteColor(r, g, b, palette);
|
2020-09-10 04:43:46 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-10 03:04:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-10 05:10:31 +00:00
|
|
|
UINT8 GetColorLUT(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b)
|
2020-09-10 04:43:46 +00:00
|
|
|
{
|
|
|
|
INT32 i = CLUTINDEX(r, g, b);
|
2020-09-10 05:10:31 +00:00
|
|
|
if (lut->table[i] == 0xFFFF)
|
|
|
|
lut->table[i] = NearestPaletteColor(r, g, b, lut->palette);
|
|
|
|
return lut->table[i];
|
2020-09-10 04:43:46 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 05:10:31 +00:00
|
|
|
UINT8 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b)
|
2020-09-10 04:43:46 +00:00
|
|
|
{
|
|
|
|
INT32 i = CLUTINDEX(r, g, b);
|
2020-09-10 05:10:31 +00:00
|
|
|
return lut->table[i];
|
2020-09-10 04:43:46 +00:00
|
|
|
}
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// V_Init
|
|
|
|
// old software stuff, buffers are allocated at video mode setup
|
|
|
|
// here we set the screens[x] pointers accordingly
|
|
|
|
// WARNING: called at runtime (don't init cvar here)
|
|
|
|
void V_Init(void)
|
|
|
|
{
|
|
|
|
INT32 i;
|
|
|
|
UINT8 *base = vid.buffer;
|
|
|
|
const INT32 screensize = vid.rowbytes * vid.height;
|
|
|
|
|
|
|
|
LoadMapPalette();
|
2019-11-10 03:04:11 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
for (i = 0; i < NUMSCREENS; i++)
|
|
|
|
screens[i] = NULL;
|
|
|
|
|
|
|
|
// start address of NUMSCREENS * width*height vidbuffers
|
|
|
|
if (base)
|
|
|
|
{
|
|
|
|
for (i = 0; i < NUMSCREENS; i++)
|
|
|
|
screens[i] = base + i*screensize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vid.direct)
|
|
|
|
screens[0] = vid.direct;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
CONS_Debug(DBG_RENDER, "V_Init done:\n");
|
2020-05-28 17:07:12 +00:00
|
|
|
for (i = 0; i < NUMSCREENS; i++)
|
2014-03-15 16:59:03 +00:00
|
|
|
CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]);
|
|
|
|
#endif
|
|
|
|
}
|
2020-08-15 01:27:16 +00:00
|
|
|
|
|
|
|
void V_Recalc(void)
|
|
|
|
{
|
|
|
|
// scale 1,2,3 times in x and y the patches for the menus and overlays...
|
|
|
|
// calculated once and for all, used by routines in v_video.c and v_draw.c
|
|
|
|
vid.dupx = vid.width / BASEVIDWIDTH;
|
|
|
|
vid.dupy = vid.height / BASEVIDHEIGHT;
|
|
|
|
vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
|
|
|
vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT);
|
|
|
|
vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT);
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
//if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl
|
|
|
|
// 13/11/18:
|
|
|
|
// The above is no longer necessary, since we want OpenGL to be just like software now
|
|
|
|
// -- Monster Iestyn
|
|
|
|
#endif
|
|
|
|
vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy);
|
|
|
|
|
|
|
|
vid.meddupx = (UINT8)(vid.dupx >> 1) + 1;
|
|
|
|
vid.meddupy = (UINT8)(vid.dupy >> 1) + 1;
|
|
|
|
#ifdef HWRENDER
|
|
|
|
vid.fmeddupx = vid.meddupx*FRACUNIT;
|
|
|
|
vid.fmeddupy = vid.meddupy*FRACUNIT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
vid.smalldupx = (UINT8)(vid.dupx / 3) + 1;
|
|
|
|
vid.smalldupy = (UINT8)(vid.dupy / 3) + 1;
|
|
|
|
#ifdef HWRENDER
|
|
|
|
vid.fsmalldupx = vid.smalldupx*FRACUNIT;
|
|
|
|
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
|
|
|
|
#endif
|
|
|
|
}
|