- refactored all text output to use DrawText.

No more screentext mess.
This commit is contained in:
Christoph Oelckers 2020-07-03 10:53:35 +02:00
parent 691643b035
commit 4fbd476b17
15 changed files with 66 additions and 366 deletions

View file

@ -51,7 +51,6 @@ set( PCH_SOURCES
src/zz_premap.cpp
src/zz_savegame.cpp
src/zz_screens.cpp
src/zz_text.cpp
src/zz_sector.cpp
)

View file

@ -127,10 +127,10 @@ void InitFonts_d()
//
//==========================================================================
static void BigText(double x, double y, const char* text)
static void BigText(double x, double y, const char* text, double alpha = 1.)
{
auto width = BigFont->StringWidth(text);
DrawText(twod, BigFont, CR_UNTRANSLATED, x - width / 2, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE);
DrawText(twod, BigFont, CR_UNTRANSLATED, x - width / 2, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_Alpha, alpha, TAG_DONE);
}
static void GameText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
@ -1074,6 +1074,15 @@ public:
}
};
void PrintPaused_d()
{
BigText(160, 100, GStrings("Game Paused"));
}
void PrintLevelName_d(double alpha)
{
BigText(160, 114, currentLevel->DisplayName(), alpha);
}
// Utility for testing the above screens
CCMD(testscreen)

View file

@ -128,14 +128,13 @@ void InitFonts_r()
//
//==========================================================================
static void BigText(double x, double y, const char* text, int align)
static void BigText(double x, double y, const char* text, int align, double alpha = 1.)
{
//x *= 2.2; y *= 2.64;
if (align != -1)
x -= BigFont->StringWidth(text) * (align == 0 ? 0.5 : 1);
auto width = BigFont->StringWidth(text);
//DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 24, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 704, DTA_VirtualHeight, 528, TAG_DONE);
DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_ScaleX, 0.4, DTA_ScaleY, 0.4, TAG_DONE);
DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_ScaleX, 0.4, DTA_ScaleY, 0.4, DTA_Alpha, alpha, TAG_DONE);
}
static void GameText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
@ -643,6 +642,15 @@ public:
}
};
void PrintPaused_r()
{
BigText(160, 100, GStrings("Game Paused"), 0);
}
void PrintLevelName_r(double alpha)
{
BigText(160, 114, currentLevel->DisplayName(), 0, alpha);
}
// Utility for testing the above screens
CCMD(testrscreen)

View file

@ -116,6 +116,8 @@ void Logo_d(CompletionFunc);
void Logo_r(CompletionFunc);
void InitFonts_d();
void InitFonts_r();
void PrintPaused_d();
void PrintPaused_r();
Dispatcher fi;
@ -127,6 +129,8 @@ void SetDispatcher()
fi = {
Logo_d,
InitFonts_d,
PrintPaused_d,
think_d,
initactorflags_d,
isadoorwall_d,
@ -176,6 +180,8 @@ void SetDispatcher()
fi = {
Logo_r,
InitFonts_r,
PrintPaused_r,
think_r,
initactorflags_r,
isadoorwall_r,

View file

@ -117,7 +117,6 @@ END_DUKE_NS
#include "player.h"
#include "quotes.h"
#include "rts.h"
#include "zz_text.h"
#include "sector.h"
#include "sounds.h"
#include "soundefs.h"
@ -218,7 +217,6 @@ struct GameInterface : ::GameInterface
bool LoadGame(FSaveGameNode*) override;
void QuitToTitle() override;
FString GetCoordString() override;
int GetStringTile(int font, const char* t, int f) override;
};
END_DUKE_NS

View file

@ -140,8 +140,6 @@ typedef struct {
int32_t ffire,m_player_skill,m_level_number,m_volume_number,multimode;
int32_t player_skill,level_number,volume_number,marker;
int32_t playerbest;
//int32_t returnvar[MAX_RETURN_VALUES-1];
uint32_t userbytever;
@ -460,6 +458,7 @@ struct Dispatcher
// global stuff
void (*ShowLogo)(CompletionFunc completion);
void (*InitFonts)();
void (*PrintPaused)();
// sectors_?.cpp
void (*think)();

View file

@ -549,11 +549,13 @@ void drawoverheadmap(int cposx, int cposy, int czoom, int cang)
if (/*textret == 0 &&*/ ud.overhead_on == 2)
{
const int32_t a = RR ? 0 : ((ud.screen_size > 0) ? 147 : 179);
if (!G_HaveUserMap()) // && !(G_GetLogoFlags() & LOGO_HIDEEPISODE))
minitext(5, a + 6, GStrings.localize(gVolumeNames[ud.volume_number]), 0, 2 + 8 + 16 + 256);
minitext(5, a + 6 + 6, currentLevel->DisplayName(), 0, 2 + 8 + 16 + 256);
double scale = isRR() ? 0.5 : 1.;
int top = isRR() ? 0 : ((ud.screen_size > 0) ? 147 : 179);
if (!G_HaveUserMap())
DrawText(twod, SmallFont2, CR_UNDEFINED, 5, top+6, GStrings.localize(gVolumeNames[ud.volume_number]),
DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE);
DrawText(twod, SmallFont2, CR_UNDEFINED, 5, top + 12, currentLevel->DisplayName(),
DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE);
}
}

View file

@ -80,9 +80,9 @@ void DDukeCommonStatusBar::displayfragbar(void)
for (i = connecthead; i >= 0; i = connectpoint2[i])
{
minitext(21 + (73 * (i & 3)), 2 + ((i & 28) << 1), &ud.user_name[i][0], sprite[ps[i].i].pal, 2 + 8 + 16 + 128);
m initext(21 + (73 * (i & 3)), 2 + ((i & 28) << 1), &ud.user_name[i][0], sprite[ps[i].i].pal, 2 + 8 + 16 + 128);
sprintf(tempbuf, "%d", ps[i].frag - ps[i].fraggedself);
minitext(17 + 50 + (73 * (i & 3)), 2 + ((i & 28) << 1), tempbuf, sprite[ps[i].i].pal, 2 + 8 + 16 + 128);
m initext(17 + 50 + (73 * (i & 3)), 2 + ((i & 28) << 1), tempbuf, sprite[ps[i].i].pal, 2 + 8 + 16 + 128);
}
}
#endif

View file

@ -402,6 +402,8 @@ public:
};
void PrintLevelName_d(double alpha);
void drawstatusbar_d(int snum)
{
DDukeStatusBar dsb;
@ -413,6 +415,16 @@ void drawstatusbar_d(int snum)
{
dsb.Statusbar(snum);
}
if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1 && !M_Active())
{
double alpha;
if (g_levelTextTime > 16) alpha = 1.;
else alpha = (g_levelTextTime) / 16.;
PrintLevelName_d(alpha);
}
}
END_DUKE_NS

View file

@ -386,6 +386,8 @@ public:
}
};
void PrintLevelName_r(double alpha);
void drawstatusbar_r(int snum)
{
DRedneckStatusBar dsb;
@ -397,6 +399,15 @@ void drawstatusbar_r(int snum)
{
dsb.Statusbar(snum);
}
if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1 && !M_Active())
{
double alpha;
if (g_levelTextTime > 16) alpha = 1.;
else alpha = (g_levelTextTime) / 16.;
PrintLevelName_r(alpha);
}
}
END_DUKE_NS

View file

@ -1627,10 +1627,6 @@ static int G_EndOfLevel(void)
{
ready2send = 0;
if (g_player[myconnectindex].ps->player_par > 0 && (g_player[myconnectindex].ps->player_par < ud.playerbest || ud.playerbest < 0) &&
ud.display_bonus_screen == 1)
CONFIG_SetMapBestTime(g_loadedMapHack.md4, g_player[myconnectindex].ps->player_par);
if (ud.display_bonus_screen == 1)
{
int32_t i = ud.screen_size;
@ -1775,8 +1771,6 @@ int32_t SetDefaults(void)
return 0;
}
void Menu_Init(void);
int GameInterface::app_main()
{
for (int i = 0; i < MAXPLAYERS; i++)
@ -1914,21 +1908,6 @@ int GameInterface::app_main()
V_LoadTranslations();
videoSetPalette(BASEPAL, 0);
// check if the minifont will support lowercase letters (3136-3161)
// there is room for them in tiles012.art between "[\]^_." and "{|}~"
minitext_lowercase = 1;
for (bssize_t i = TILE_MINIFONT + ('a'-'!'); minitext_lowercase && i < TILE_MINIFONT + ('z'-'!') + 1; ++i)
minitext_lowercase &= (int)tileCheck(i);
/*if (RRRA)
playmve("REDINT.MVE"); still needs work on the audio side*/
//if (g_networkMode != NET_DEDICATED_SERVER)
{
Menu_Init();
}
FX_StopAllSounds();
S_ClearSoundLocks();
app_loop();

View file

@ -312,7 +312,6 @@ static int LoadTheMap(MapRecord &mi, DukePlayer_t *pPlayer, int gameMode)
{
char levelName[BMAX_PATH];
int16_t lbang;
if (!VOLUMEONE && Menu_HaveUserMap())
{
if (engineLoadBoard(boardfilename, 0, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0)
@ -326,7 +325,7 @@ static int LoadTheMap(MapRecord &mi, DukePlayer_t *pPlayer, int gameMode)
SECRET_SetMapName(currentLevel->DisplayName(), currentLevel->name);
STAT_NewLevel(boardfilename);
G_LoadMapHack(levelName, boardfilename);
userMapRecord.music = G_SetupFilenameBasedMusic(boardfilename, !RR? "dethtoll.mid" : nullptr);
userMapRecord.music = G_SetupFilenameBasedMusic(boardfilename, !RR ? "dethtoll.mid" : nullptr);
}
else if (engineLoadBoard(mi.fileName, VOLUMEONE, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0)
{
@ -372,12 +371,7 @@ static int LoadTheMap(MapRecord &mi, DukePlayer_t *pPlayer, int gameMode)
allignwarpelevators();
resetpspritevars(gameMode);
ud.playerbest = CONFIG_GetMapBestTime(Menu_HaveUserMap() ? boardfilename : mi.fileName.GetChars(), g_loadedMapHack.md4);
// G_FadeLoad(0,0,0, 252,0, -28, 4, -1);
if (isRR()) cacheit_r(); else cacheit_d();
//G_CacheMapData();
// G_FadeLoad(0,0,0, 0,252, 28, 4, -2);
return 0;
}

View file

@ -434,18 +434,6 @@ void G_DisplayRest(int32_t smoothratio)
if (isRR()) drawstatusbar_r(screenpeek);
else drawstatusbar_d(screenpeek);
if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1 && !M_Active())
{
int32_t o = 10|16;
if (g_levelTextTime < 3)
o |= 1|32;
else if (g_levelTextTime < 5)
o |= 1;
menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, currentLevel->DisplayName(), o, TEXT_XCENTER);
}
if (!DEER && g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && cl_crosshair && ud.camerasprite == -1)
{
int32_t a = TILE_CROSSHAIR;
@ -463,8 +451,8 @@ void G_DisplayRest(int32_t smoothratio)
}
}
if (ud.pause_on==1 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
menutext_center(100, GStrings("Game Paused"));
if (ud.pause_on == 1 && (g_player[myconnectindex].ps->gm & MODE_MENU) == 0)
fi.PrintPaused();
mdpause = (ud.pause_on || (ud.recstat==2 && (g_demo_paused && g_demo_goalCnt==0)) || (g_player[myconnectindex].ps->gm&MODE_MENU && numplayers < 2));

View file

@ -1,258 +0,0 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2016 EDuke32 developers and contributors
This file is part of EDuke32.
EDuke32 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#include "ns.h" // Must come before everything else!
#include "duke3d.h"
#include "compat.h"
#include "sbar.h"
#include "gstrings.h"
BEGIN_DUKE_NS
// a subset of screentext parameters, restricted because menus require accessibility
typedef struct MenuFont_t
{
// int32_t xspace, yline;
vec2_t emptychar, between;
int32_t zoom;
int32_t cursorLeftPosition, cursorCenterPosition, cursorScale, cursorScale2, cursorScale3;
int32_t textflags;
int16_t tilenum;
// selected shade glows, deselected shade is used by Blood, disabled shade is used by SW
int8_t shade_deselected, shade_disabled;
uint8_t pal;
uint8_t pal_selected, pal_deselected, pal_disabled;
uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right;
int32_t get_yline() const { return mulscale16(emptychar.y, zoom); }
} MenuFont_t;
// common font types
// tilenums are set after namesdyn runs.
// These are also modifiable by scripts.
// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags
// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled
MenuFont_t MF_Redfont = { { 5 << 16, 15 << 16 }, { 0, 0 }, 65536, 20 << 16, 110 << 16, 65536, 65536, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE,
-1, 10, 0, 0, 0, 0, 1,
0, 0, 1 };
MenuFont_t MF_Bluefont = { { 5 << 16, 7 << 16 }, { 0, 0 }, 65536, 10 << 16, 110 << 16, 32768, 65536, 65536, 0,
-1, 10, 0, 0, 10, 10, 16,
0, 0, 16 };
MenuFont_t MF_Minifont = { { 4 << 16, 5 << 16 }, { 1 << 16, 1 << 16 }, 65536, 10 << 16, 110 << 16, 32768, 65536, 65536, 0,
-1, 10, 0, 0, 2, 2, 0,
0, 0, 16 };
/*
This function prepares data after ART and CON have been processed.
It also initializes some data in loops rather than statically at compile time.
*/
void Menu_Init(void)
{
// prepare menu fonts
// check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS
if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = TILE_BIGALPHANUM;
if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = TILE_STARTALPHANUM;
if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = TILE_MINIFONT;
MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y << 16;
MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y << 16;
MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y << 16;
if (!minitext_lowercase)
MF_Minifont.textflags |= TEXT_UPPERCASE;
if (RR)
{
MF_Redfont.zoom = 32768;
MF_Redfont.emptychar.x <<= 1;
MF_Redfont.cursorScale = 13107;
MF_Redfont.cursorScale2 = 6553;
//MF_Redfont.emptychar.y <<= 1;
MF_Bluefont.zoom = 32768;
MF_Bluefont.emptychar.x <<= 1;
MF_Bluefont.cursorScale = 6553;
MF_Bluefont.cursorScale2 = 6553;
//MF_Bluefont.emptychar.y <<= 1;
MF_Minifont.zoom = 32768;
MF_Minifont.emptychar.x <<= 1;
MF_Minifont.cursorScale = 6553;
MF_Minifont.cursorScale2 = 6553;
//MF_Minifont.emptychar.y <<= 1;
}
}
// assign the character's tilenum
int GameInterface::GetStringTile(int font, const char* t, int f)
{
if (f & TEXT_DIGITALNUMBER)
return *t - '0' + font; // copied from digitalnumber
else if (f & (TEXT_BIGALPHANUM|TEXT_GRAYFONT))
{
int32_t offset = (f & TEXT_GRAYFONT) ? 26 : 0;
if (*t >= '0' && *t <= '9')
return *t - '0' + font + ((f & TEXT_GRAYFONT) ? 26 : -10);
else if (*t >= 'a' && *t <= 'z')
return *t - 'a' + font + ((f & TEXT_GRAYFONT) ? -26 : 26);
else if (*t >= 'A' && *t <= 'Z')
return *t - 'A' + font;
else switch (*t)
{
case '_':
case '-':
return font - (11 + offset);
break;
case '.':
return font + (TILE_BIGPERIOD - (TILE_BIGALPHANUM + offset));
break;
case ',':
return font + (TILE_BIGCOMMA - (TILE_BIGALPHANUM + offset));
break;
case '!':
return font + (TILE_BIGX_ - (TILE_BIGALPHANUM + offset));
break;
case '?':
return font + (TILE_BIGQ - (TILE_BIGALPHANUM + offset));
break;
case ';':
return font + (TILE_BIGSEMI - (TILE_BIGALPHANUM + offset));
break;
case ':':
return font + (TILE_BIGCOLIN - (TILE_BIGALPHANUM + offset));
break;
case '\\':
case '/':
return font + (68 - offset); // 3008-2940
break;
case '%':
return font + (69 - offset); // 3009-2940
break;
case '`':
case '\"': // could be better hacked in
case '\'':
return font + (TILE_BIGAPPOS - (TILE_BIGALPHANUM + offset));
break;
default: // unknown character
fallthrough__;
case '\t':
case ' ':
case '\n':
case '\x7F':
return font;
break;
}
}
else
{
int tt = *t;
if (tt >= 'a' && tt <= 'z') tt -= 32;
return tt - '!' + font; // uses ASCII order
}
}
vec2_t gametext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t o, int32_t a, int32_t f)
{
return G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, s, p, o|2|8|16|ROTATESPRITE_FULL16, a, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f, 0, 0, xdim-1, ydim-1);
}
static FORCE_INLINE int32_t sbarsc(int32_t sc)
{
return scale(sc, ud.statusbarscale, 100);
}
static int32_t sbarx16(int32_t x)
{
if (ud.screen_size == 4) return sbarsc(x);
return (((320 << 16) - sbarsc(320 << 16)) >> 1) + sbarsc(x);
}
static int32_t sbarxr16(int32_t x)
{
if (ud.screen_size == 4) return (320 << 16) - sbarsc(x);
return (((320 << 16) - sbarsc(320 << 16)) >> 1) + sbarsc(x);
}
static int32_t sbary16(int32_t y)
{
return (100 << 16) - sbarsc(200 << 16) + sbarsc(y);
}
// minitext_yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords,
// (sb&ROTATESPRITE_MAX) only.
int32_t minitext_yofs = 0;
int32_t minitext_lowercase = 0;
int32_t minitext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t sb)
{
vec2_t dim;
int32_t z = MF_Minifont.zoom;
if (t == NULL)
{
Printf("minitext: NULL text!\n");
return 0;
}
if (!(sb & ROTATESPRITE_FULL16))
{
x<<=16;
y<<=16;
}
if (sb & ROTATESPRITE_MAX)
{
if (sb & RS_ALIGN_R)
x = sbarxr16(x);
else
x = sbarx16(x);
y = minitext_yofs;
z = sbarsc(z);
}
sb &= (ROTATESPRITE_MAX-1)|RS_CENTERORIGIN;
dim = G_ScreenText(MF_Minifont.tilenum, x, y, z, 0, 0, t, s, p, sb|ROTATESPRITE_FULL16, 0, MF_Minifont.emptychar.x, MF_Minifont.emptychar.y, MF_Minifont.between.x, MF_Minifont.between.y, MF_Minifont.textflags, 0, 0, xdim-1, ydim-1);
x += dim.x;
if (!(sb & ROTATESPRITE_FULL16))
x >>= 16;
return x;
}
void menutext_(int32_t x, int32_t y, int32_t s, char const *t, int32_t o, int32_t f)
{
if (RR) f |= TEXT_RRMENUTEXTHACK;
G_ScreenText(MF_Redfont.tilenum, x, y - (12<<16), MF_Redfont.zoom, 0, 0, t, s, MF_Redfont.pal, o|ROTATESPRITE_FULL16, 0, MF_Redfont.emptychar.x, MF_Redfont.emptychar.y, MF_Redfont.between.x, MF_Redfont.between.y, f|MF_Redfont.textflags|TEXT_LITERALESCAPE, 0, 0, xdim-1, ydim-1);
}
END_DUKE_NS

View file

@ -1,47 +0,0 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2016 EDuke32 developers and contributors
This file is part of EDuke32.
EDuke32 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#pragma once
#include "screentext.h"
BEGIN_DUKE_NS
extern int32_t minitext_lowercase;
extern int32_t minitext_yofs;
extern int32_t minitext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t sb);
extern void menutext_(int32_t x, int32_t y, int32_t s, char const *t, int32_t o, int32_t f);
extern vec2_t gametext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t o, int32_t a, int32_t f);
inline int minitext(int x, int y, const char* t, int p, int sb)
{
return minitext_(x, y, t, 0, p, sb);
}
#define menutext_center(y, t) menutext_(160<<16, (y)<<16, 0, (t), 10|16, TEXT_XCENTER)
#define gametext_center_number(y, t) gametext_(160<<16, (y)<<16, (t), 0, MF_Bluefont.pal, 0, 0, TEXT_XCENTER|TEXT_GAMETEXTNUMHACK)
#define gametext_center_shade_pal(y, t, s, p) gametext_(160<<16, (y)<<16, (t), (s), (p), 0, 0, TEXT_XCENTER)
END_DUKE_NS