- Discovered that Shader Model 1.4 clamps my constants, so I can't use

palettes smaller than 256 entries with the shader I wrote for it. Is there
  a list of gotchas like this listed some where? I'd really like to see it.
  
  Well, when compiled with SM2.0, the PalTex shader seems to be every-so-
  slightly faster on my GF7950GT than the SM1.4 version, so I guess it's a
  minor win for cards that support it.
- Fixed: ST_Endoom() failed to free the bitmap it used.
- Added the DTA_ColorOverlay attribute to blend a color with the texture
  being drawn. For software, this (currently) only works with black. For
  hardware, it works with any color. The motiviation for this was so I could
  rewrite the status bar calls that passed DIM_MAP to DTA_Translation to
  draw darker icons into something that didn't require making a whole new
  remap table.
- After having an "OMG! How could I have been so stupid?" moment, I have
  removed the off-by-one check from D3DFB. I had thought the off-by-one error
  was caused by rounding errors by the shader hardware. Not so. Rather, I
  wasn't sampling what I thought I was sampling. A texture that uses palette
  index 255 passes the value 1.0 to the shader. The shader needs to adjust the
  range of its palette indexes, or it will end up trying to read color 256
  from the palette texture when it should be reading color 255. Doh!
- The TranslationToTable() function has been added to map from translation
  numbers used by actors to the tables those numbers represent. This function
  performs validation for the input and returns NULL if the input value
  is invalid.
- Major changes to the way translation tables work: No longer are they each a
  256-byte array. Instead, the FRemapTable structure is used to represent each
  one. It includes a remap array for the software renderer, a palette array
  for a hardware renderer, and a native texture pointer for D3DFB. The
  translationtables array itself is now an array of TArrays that point to the
  real tables. The DTA_Translation attribute must also be passed a pointer
  to a FRemapTable, not a byte array as previously.
- Modified DFrameBuffer::DrawRateStuff() so that it can do its thing properly
  for D3DFB's 2D mode. Before, any fullscreen graphics (like help images)
  covered it up.


SVN r640 (trunk)
This commit is contained in:
Randy Heit 2007-12-26 04:42:15 +00:00
parent 6b9f3c8247
commit 1acc3d00c4
35 changed files with 1157 additions and 794 deletions

View file

@ -1,9 +1,45 @@
December 25, 2007
- Discovered that Shader Model 1.4 clamps my constants, so I can't use
palettes smaller than 256 entries with the shader I wrote for it. Is there
a list of gotchas like this listed some where? I'd really like to see it.
Well, when compiled with SM2.0, the PalTex shader seems to be every-so-
slightly faster on my GF7950GT than the SM1.4 version, so I guess it's a
minor win for cards that support it.
December 25, 2007 (Changes by Graf Zahl)
- added a P_PointInSector function and replaced all calls to retrieve an
actor's sector in the game engine code with it. This way there's a clear
distinction between renderer-specific and game-specific calls.
- added UseInventory/UseActorInventory ACS functions.
December 24, 2007
- Fixed: ST_Endoom() failed to free the bitmap it used.
- Added the DTA_ColorOverlay attribute to blend a color with the texture
being drawn. For software, this (currently) only works with black. For
hardware, it works with any color. The motiviation for this was so I could
rewrite the status bar calls that passed DIM_MAP to DTA_Translation to
draw darker icons into something that didn't require making a whole new
remap table.
- After having an "OMG! How could I have been so stupid?" moment, I have
removed the off-by-one check from D3DFB. I had thought the off-by-one error
was caused by rounding errors by the shader hardware. Not so. Rather, I
wasn't sampling what I thought I was sampling. A texture that uses palette
index 255 passes the value 1.0 to the shader. The shader needs to adjust the
range of its palette indexes, or it will end up trying to read color 256
from the palette texture when it should be reading color 255. Doh!
- The TranslationToTable() function has been added to map from translation
numbers used by actors to the tables those numbers represent. This function
performs validation for the input and returns NULL if the input value
is invalid.
- Major changes to the way translation tables work: No longer are they each a
256-byte array. Instead, the FRemapTable structure is used to represent each
one. It includes a remap array for the software renderer, a palette array
for a hardware renderer, and a native texture pointer for D3DFB. The
translationtables array itself is now an array of TArrays that point to the
real tables. The DTA_Translation attribute must also be passed a pointer
to a FRemapTable, not a byte array as previously.
December 24, 2007 (Changes by Graf Zahl)
- added some functionality to FDynamicColormap to allow not creating
the colormap data.
@ -65,6 +101,9 @@ December 23, 2007 (Changes by Graf Zahl)
- Fixed: UpdateTeam passed an FString to Printf.
December 22, 2007
- Modified DFrameBuffer::DrawRateStuff() so that it can do its thing properly
for D3DFB's 2D mode. Before, any fullscreen graphics (like help images)
covered it up.
- Had a look at sbarinfo.cpp and noticed a few places where it allocated
character arrays and never freed them. Those have been replaced with
uses of FString. (One of these was even an instance of a member variable

View file

@ -1678,7 +1678,7 @@ static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust,
DTA_ClipLeft, f_x,
DTA_ClipRight, f_x + f_w,
DTA_FlipX, flip,
DTA_Translation, translation,
DTA_Translation, TranslationToTable(translation),
DTA_Alpha, alpha,
DTA_FillColor, alphacolor,
DTA_RenderStyle, renderstyle,

View file

@ -80,7 +80,7 @@ static bool TabbedList; // True if tab list was shown
CVAR (Bool, con_notablist, false, CVAR_ARCHIVE)
static int conback;
static int conshade;
static DWORD conshade;
static bool conline;
extern int gametic;
@ -296,8 +296,8 @@ void C_InitConsole (int width, int height, bool ingame)
if (conback <= 0)
{
conshade = DIM_MAP;
conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch);
conshade = MAKEARGB(80,0,0,0);
conline = true;
}
else
@ -1137,7 +1137,7 @@ void C_DrawConsole ()
screen->DrawTexture (conpic, 0, visheight - screen->GetHeight(),
DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(),
DTA_Translation, conshade,
DTA_ColorOverlay, conshade,
DTA_Masked, false,
TAG_DONE);
if (conline && visheight < screen->GetHeight())

View file

@ -437,7 +437,7 @@ CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY);
// Draw current display, possibly wiping it from the previous
//
//==========================================================================
CVAR(Bool,test2d,true,0)
CVAR(Bool,test2d,false,0)
void D_Display (bool screenshot)
{
bool wipe;
@ -601,7 +601,10 @@ void D_Display (bool screenshot)
break;
}
}
//screen->Begin2D();
if (!screenshot && (!wipe || NoWipe) && test2d)
{
screen->Begin2D();
}
// draw pause pic
if (paused && menuactive == MENU_Off)
{
@ -638,21 +641,6 @@ void D_Display (bool screenshot)
FStat::PrintStat ();
if (!screenshot)
{
#if 0
if (test2d)
screen->Begin2D();
screen->DrawTexture(TexMan["M_HTIC"], 0, 0,
DTA_Clean, true,
TAG_DONE);
screen->DrawTexture(TexMan["XHAIRB3"], 200, 100,
DTA_DestWidth, 128,
DTA_DestHeight, 128,
DTA_Alpha, ((gametic & 31) + 1) << (16-5),
// DTA_RenderStyle, STYLE_Add,
DTA_FillColor, MAKEARGB(ColorMatcher.Pick(254,254,0),254,254,0),
DTA_AlphaChannel, true,
TAG_DONE);
#endif
screen->Update (); // page flip or blit buffer
}
}

View file

@ -377,6 +377,7 @@ void F_TextWrite (void)
int c;
int cx;
int cy;
const FRemapTable *range;
int leftmargin;
int rowheight;
bool scale;
@ -402,6 +403,7 @@ void F_TextWrite (void)
ch = FinaleText.GetChars();
count = (FinaleCount - 10)/TEXTSPEED;
range = screen->Font->GetColorTranslation (CR_UNTRANSLATED);
for ( ; count ; count-- )
{
@ -425,8 +427,7 @@ void F_TextWrite (void)
screen->DrawTexture (pic,
cx + 320 / 2,
cy + 200 / 2,
DTA_Font, screen->Font,
DTA_Translation, CR_UNTRANSLATED,
DTA_Translation, range,
DTA_Clean, true,
TAG_DONE);
}
@ -435,8 +436,7 @@ void F_TextWrite (void)
screen->DrawTexture (pic,
cx + 320 / 2,
cy + 200 / 2,
DTA_Font, screen->Font,
DTA_Translation, CR_UNTRANSLATED,
DTA_Translation, range,
TAG_DONE);
}
}
@ -522,7 +522,7 @@ static struct
int castnum;
int casttics;
int castsprite; // [RH] For overriding the player sprite with a skin
int casttranslation; // [RH] Draw "our hero" with their chosen suit color
const FRemapTable *casttranslation; // [RH] Draw "our hero" with their chosen suit color
FState* caststate;
bool castdeath;
int castframes;
@ -582,7 +582,7 @@ void F_StartCast (void)
castnum = 0;
caststate = castorder[castnum].info->SeeState;
castsprite = caststate->sprite.index;
casttranslation = 0;
casttranslation = NULL;
casttics = caststate->GetTics ();
castdeath = false;
FinaleStage = 3;
@ -632,12 +632,12 @@ void F_CastTicker (void)
if (castnum == 16)
{
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
casttranslation = TRANSLATION(TRANSLATION_Players, consoleplayer);
casttranslation = translationtables[TRANSLATION_Players][consoleplayer];
}
else
{
castsprite = caststate->sprite.index;
casttranslation = 0;
casttranslation = NULL;
}
castframes = 0;
}

View file

@ -130,7 +130,7 @@ public:
{
// draw face background
StatusBarTex.DrawToBar ("STFBANY", 143, 1,
translationtables[TRANSLATION_Players] + (CPlayer - players)*256);
translationtables[TRANSLATION_Players][int(CPlayer - players)]->Remap);
}
}
@ -147,7 +147,7 @@ public:
{
// draw face background
StatusBarTex.DrawToBar ("STFBANY", 143, 1,
translationtables[TRANSLATION_Players] + (CPlayer - players)*256);
translationtables[TRANSLATION_Players][int(CPlayer - players)]->Remap);
}
bEvilGrin = false;
}
@ -203,7 +203,7 @@ private:
const BYTE *GetPixels ();
void Unload ();
~FDoomStatusBarTexture ();
void DrawToBar (const char *name, int x, int y, BYTE *colormap_in = NULL);
void DrawToBar (const char *name, int x, int y, const BYTE *colormap_in = NULL);
protected:
void MakeTexture ();
@ -477,7 +477,7 @@ private:
}
else
{
DrawImage (TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount <= 0);
if (CPlayer->mo->InvSel->Amount != 1)
{
DrSmallNumber (CPlayer->mo->InvSel->Amount, 165, 24);
@ -563,7 +563,7 @@ private:
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i)
{
DrawImage (Images[imgARTIBOX], 50+i*31, 2);
DrawImage (TexMan(item->Icon), 50+i*31, 2, item->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0);
if (item->Amount != 1)
{
DrSmallNumber (item->Amount, 66+i*31, 24);
@ -706,7 +706,7 @@ private:
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -14, ammotop - 1/*-24*/,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
DrBNumberOuter (CPlayer->mo->InvSel->Amount, -68, ammotop - 18/*-41*/);
}
@ -725,7 +725,7 @@ private:
TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -105+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (item->Amount != 1)
{
@ -1096,7 +1096,7 @@ void FDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
memcpy(Pixels, pix, Width*Height);
}
void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, BYTE *colormap_in)
void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap_in)
{
FTexture *pic;
BYTE colormap[256];

View file

@ -273,7 +273,7 @@ private:
DrawImage (Images[imgCHAINBACK], 0, 32);
DrawImage (Images[imgCHAIN], 2+(healthPos%17), chainY);
DrawImage (Images[imgLIFEGEM], 17+healthPos, chainY, multiplayer ?
TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer-players)) : 0);
translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)] : NULL);
DrawImage (Images[imgLTFACE], 0, 32);
DrawImage (Images[imgRTFACE], 276, 32);
screen->DrawTexture (&ChainShade, ST_X+19, ST_Y+32,
@ -324,7 +324,7 @@ private:
DrawImage (Images[imgBLACKSQ], 180, 3);
if (oldarti != NULL)
{
DrawImage (TexMan(oldarti->Icon), 179, 2, oldarti->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(oldarti->Icon), 179, 2, oldarti->Amount <= 0);
if (oldartiCount != 1)
{
DrSmallNumber (oldartiCount, 197, 24);
@ -483,7 +483,7 @@ private:
{
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i)
{
DrawImage (TexMan(item->Icon), 50+i*31, 2, item->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0);
if (item->Amount != 1)
{
DrSmallNumber (item->Amount, 65+i*31, 24);
@ -638,7 +638,7 @@ private:
TAG_DONE);
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -61, -31,
DTA_HUDRules, HUD_Normal,
DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (CPlayer->mo->InvSel->Amount != 1)
{
@ -660,7 +660,7 @@ private:
TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -100+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (item->Amount != 1)
{

View file

@ -367,7 +367,7 @@ private:
healthPos = clamp (HealthMarker, 0, 100);
DrawImage (ClassImages[lifeClass][imgCHAIN], 35+((healthPos*196/100)%9), 31);
DrawImage (ClassImages[lifeClass][imgLIFEGEM], 7+(healthPos*11/5), 31, multiplayer ?
TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer-players)) : 0);
translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)] : NULL);
DrawImage (Images[imgLFEDGE], 0, 31);
DrawImage (Images[imgRTEDGE], 277, 31);
}
@ -403,7 +403,7 @@ private:
DrawImage (Images[imgARTICLEAR], 144, -1);
if (oldarti != NULL)
{
DrawImage (TexMan(oldarti->Icon), 143, 2, oldarti->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(oldarti->Icon), 143, 2, oldarti->Amount <= 0);
if (oldartiCount != 1)
{
DrSmallNumber (oldartiCount, 162, 23);
@ -713,7 +713,7 @@ private:
{
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i)
{
DrawImage (TexMan(item->Icon), 50+i*31, 1, item->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(item->Icon), 50+i*31, 1, item->Amount <= 0);
if (item->Amount != 1)
{
DrSmallNumber (item->Amount, 68+i*31, 23);
@ -912,7 +912,7 @@ private:
TAG_DONE);
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -82, -31,
DTA_HUDRules, HUD_Normal,
DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (CPlayer->mo->InvSel->Amount != 1)
{
@ -934,7 +934,7 @@ private:
TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -108+i*31, -33,
DTA_HUDRules, HUD_HorizCenter,
DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (item->Amount != 1)
{

View file

@ -2687,15 +2687,16 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
arc << level.total_monsters << level.total_items << level.total_secrets;
// Does this level have custom translations?
FRemapTable *trans;
if (arc.IsStoring ())
{
for (i = 0; i < MAX_ACS_TRANSLATIONS; ++i)
for (i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i)
{
BYTE *trans = &translationtables[TRANSLATION_LevelScripted][i*256];
trans = translationtables[TRANSLATION_LevelScripted][i];
int j;
for (j = 0; j < 256; ++j)
{
if (trans[j] != j)
if (trans->Remap[j] != j)
{
break;
}
@ -2704,7 +2705,13 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
{
t = i;
arc << t;
arc.Write (trans, 256);
arc.Write (trans->Remap, 256);
for (j = 0; j < 256; ++j)
{
arc << trans->Palette[j].r
<< trans->Palette[j].g
<< trans->Palette[j].b;
}
}
}
t = 255;
@ -2719,7 +2726,19 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
{ // hack hack to avoid crashing
t = 0;
}
arc.Read (&translationtables[TRANSLATION_LevelScripted][t*256], 256);
trans = translationtables[TRANSLATION_LevelScripted].GetVal(t);
if (trans == NULL)
{
trans = new FRemapTable;
translationtables[TRANSLATION_LevelScripted].SetVal(t, trans);
}
arc.Read (trans->Remap, 256);
for (int j = 0; j < 256; ++j)
{
arc << trans->Palette[j].r
<< trans->Palette[j].g
<< trans->Palette[j].b;
}
arc << t;
}
}

View file

@ -39,6 +39,7 @@
struct patch_t;
class player_s;
struct FRemapTable;
extern int SB_state;
@ -198,7 +199,8 @@ protected:
void DrawPowerups ();
void UpdateRect (int x, int y, int width, int height) const;
void DrawImage (FTexture *image, int x, int y, int translation=0, FFont *font=NULL) const;
void DrawImage (FTexture *image, int x, int y, FRemapTable *translation=NULL) const;
void DrawDimImage (FTexture *image, int x, int y, bool dimmed) const;
void DrawFadedImage (FTexture *image, int x, int y, fixed_t shade) const;
void DrawPartialImage (FTexture *image, int wx, int ww) const;

View file

@ -1453,11 +1453,11 @@ private:
{
if((cmd.flags & DRAWSELECTEDINVENTORY_ARTIFLASH) && artiflash)
{
DrawImage(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0);
}
else
{
DrawImage(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0);
}
if(CPlayer->mo->InvSel->Amount != 1)
{
@ -1696,7 +1696,7 @@ private:
continue;
}
x += (character->LeftOffset+1); //ignore x offsets since we adapt to character size
DrawImage(character, x, y, translation, drawingFont);
DrawImage(character, x, y, drawingFont->GetColorTranslation(translation));
x += width + spacing - (character->LeftOffset+1);
str++;
}
@ -1852,7 +1852,7 @@ private:
{
DrawImage (Images[invBarOffset + imgARTIBOX], x+i*31, y);
}
DrawImage (TexMan(item->Icon), x+i*31, y, item->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(item->Icon), x+i*31, y, item->Amount <= 0);
if(item->Amount != 1)
{
DrawNumber(item->Amount, 3, counterx+i*31, countery, translation);
@ -1906,13 +1906,14 @@ private:
DrawImage(chain, x+(offset%chainsize), y);
}
if(gem != NULL)
DrawImage(gem, x+padleft+offset, y, translate ? getTranslation() : 0);
DrawImage(gem, x+padleft+offset, y, translate ? getTranslation() : NULL);
}
int getTranslation()
FRemapTable* getTranslation()
{
if(gameinfo.gametype & GAME_Raven) return TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer - players));
else return TRANSLATION(TRANSLATION_Players, BYTE(CPlayer - players));
if(gameinfo.gametype & GAME_Raven)
return translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)];
return translationtables[TRANSLATION_Players][int(CPlayer - players)];
}
FImageCollection Images;

View file

@ -408,18 +408,38 @@ void FBaseStatusBar::ShowPlayerName ()
//---------------------------------------------------------------------------
void FBaseStatusBar::DrawImage (FTexture *img,
int x, int y, int translation, FFont *font) const
int x, int y, FRemapTable *translation) const
{
if (img != NULL)
{
screen->DrawTexture (img, x + ST_X, y + ST_Y,
DTA_Font, font,
DTA_Translation, translation,
DTA_320x200, Scaled,
TAG_DONE);
}
}
//---------------------------------------------------------------------------
//
// PROC DrawImage
//
// Draws an optionally dimmed image with the status bar's upper-left corner
// as the origin.
//
//---------------------------------------------------------------------------
void FBaseStatusBar::DrawDimImage (FTexture *img,
int x, int y, bool dimmed) const
{
if (img != NULL)
{
screen->DrawTexture (img, x + ST_X, y + ST_Y,
DTA_ColorOverlay, dimmed ? DIM_OVERLAY : 0,
DTA_320x200, Scaled,
TAG_DONE);
}
}
//---------------------------------------------------------------------------
//
// PROC DrawImage
@ -796,13 +816,11 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
return;
}
@ -823,8 +841,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
val /= 10;
xpos -= w;
@ -838,8 +855,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
}
}
@ -852,8 +868,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
pic = BigFont->GetChar ('0' + val % 10, &v);
screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
val /= 10;
xpos -= w;
@ -865,8 +880,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
{
screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont,
DTA_TranslationPtr, CR_UNTRANSLATED,
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
TAG_DONE);
}
}

View file

@ -438,7 +438,7 @@ private:
}
if (item->Icon != 0)
{
DrawImage (TexMan(item->Icon), 48 + 35*i, 14, item->Amount > 0 ? NULL : DIM_MAP);
DrawDimImage (TexMan(item->Icon), 48 + 35*i, 14, item->Amount <= 0);
}
DrINumber (item->Amount, 74 + 35*i, 23, imgFONY0);
}
@ -512,7 +512,7 @@ private:
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -42, -17,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
}
}
@ -536,7 +536,7 @@ private:
{
screen->DrawTexture (TexMan(item->Icon), -94 + i*35, -19,
DTA_HUDRules, HUD_HorizCenter,
DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
}
DrINumberOuter (item->Amount, -89 + i*35, -10, true, 7);

View file

@ -86,7 +86,7 @@ struct FSaveGameNode : public Node
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void M_DrawSlider (int x, int y, float min, float max, float cur);
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, BYTE *table);
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -1984,7 +1984,7 @@ void M_PlayerSetup (void)
PlayerClass = &PlayerClasses[players[consoleplayer].CurrentPlayerClass];
}
PlayerSkin = players[consoleplayer].userinfo.skin;
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS);
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState;
PlayerTics = PlayerState->GetTics();
if (FireScreen == NULL)
@ -2019,7 +2019,7 @@ static void M_PlayerSetupTicker (void)
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, PlayerClass - &PlayerClasses[0]);
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
&skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS);
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
}
if (PlayerState->GetTics () != -1 && PlayerState->GetNextState () != NULL)
@ -2133,7 +2133,7 @@ static void M_PlayerSetupDrawer ()
(PSetupDef.y + LINEHEIGHT*3 + 57 - 104)*CleanYfac + (SCREENHEIGHT/2),
DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, Scale),
DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, Scale),
DTA_Translation, TRANSLATION(TRANSLATION_Players, 0),
DTA_Translation, translationtables[TRANSLATION_Players][MAXPLAYERS],
TAG_DONE);
}
}
@ -2410,7 +2410,7 @@ static void M_ChangeSkin (int choice)
PlayerSkin = (PlayerSkin < (int)numskins - 1) ? PlayerSkin + 1 : 0;
} while (!PlayerClass->CheckSkin (PlayerSkin));
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS);
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
cvar_set ("skin", skins[PlayerSkin].name);
}
@ -2534,7 +2534,7 @@ static void SendNewColor (int red, int green, int blue)
sprintf (command, "color \"%02x %02x %02x\"", red, green, blue);
C_DoCommand (command);
R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS);
R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
}
static void M_SlidePlayerRed (int choice)

View file

@ -2324,7 +2324,7 @@ int DLevelScript::RunScript ()
DACSThinker *controller = DACSThinker::ActiveThinker;
SDWORD *locals = localvars;
ScriptFunction *activeFunction = NULL;
BYTE *translation = 0;
FRemapTable *translation = 0;
int resultValue = 1;
switch (state)
@ -4674,11 +4674,13 @@ int DLevelScript::RunScript ()
sp--;
if (i >= 1 && i <= MAX_ACS_TRANSLATIONS)
{
translation = &translationtables[TRANSLATION_LevelScripted][i*256-256];
for (i = 0; i < 256; ++i)
translation = translationtables[TRANSLATION_LevelScripted].GetVal(i - 1);
if (translation == NULL)
{
translation[i] = i;
translation = new FRemapTable;
translationtables[TRANSLATION_LevelScripted].SetVal(i - 1, translation);
}
translation->MakeIdentity();
}
}
break;
@ -4703,14 +4705,16 @@ int DLevelScript::RunScript ()
}
else if (start == end)
{
translation[start] = pal1;
translation->Remap[start] = pal1;
translation->Palette[start] = GPalette.BaseColors[pal1];
break;
}
palcol = pal1 << FRACBITS;
palstep = ((pal2 << FRACBITS) - palcol) / (end - start);
for (int i = start; i <= end; palcol += palstep, ++i)
{
translation[i] = palcol >> FRACBITS;
translation->Remap[i] = palcol >> FRACBITS;
translation->Palette[i] = GPalette.BaseColors[palcol >> FRACBITS];
}
}
break;
@ -4755,8 +4759,9 @@ int DLevelScript::RunScript ()
}
if (start == end)
{
translation[start] = ColorMatcher.Pick
translation->Remap[start] = ColorMatcher.Pick
(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS);
translation->Palette[start] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS);
break;
}
rs /= (end - start);
@ -4764,8 +4769,9 @@ int DLevelScript::RunScript ()
bs /= (end - start);
for (int i = start; i <= end; ++i)
{
translation[i] = ColorMatcher.Pick
translation->Remap[i] = ColorMatcher.Pick
(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS);
translation->Palette[i] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS);
r += rs;
g += gs;
b += bs;
@ -4776,6 +4782,7 @@ int DLevelScript::RunScript ()
case PCD_ENDTRANSLATION:
// This might be useful for hardware rendering, but
// for software it is superfluous.
translation->UpdateNative();
translation = NULL;
break;

View file

@ -3406,16 +3406,18 @@ void P_SetupLevel (char *lumpname, int position)
{
players[i].mo = NULL;
}
// [RH] Set default scripted translation colors
for (i = 0; i < 256; ++i)
// [RH] Clear any scripted translation colors the previous level may have set.
for (i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i)
{
translationtables[TRANSLATION_LevelScripted][i] = i;
}
for (i = 1; i < MAX_ACS_TRANSLATIONS; ++i)
FRemapTable *table = translationtables[TRANSLATION_LevelScripted][i];
if (table != NULL)
{
memcpy (&translationtables[TRANSLATION_LevelScripted][i*256],
translationtables[TRANSLATION_LevelScripted], 256);
delete table;
translationtables[TRANSLATION_LevelScripted][i] = NULL;
}
}
translationtables[TRANSLATION_LevelScripted].Clear();
// Initial height of PointOfView will be set by player think.
players[consoleplayer].viewz = 1;

View file

@ -56,8 +56,6 @@ extern int ST_Y;
// and the total size == width*height*depth/8.,
//
extern BYTE decorate_translations[];
BYTE* viewimage;
extern "C" {
int viewwidth;
@ -134,7 +132,8 @@ cycle_t DetailDoubleCycles;
int dc_fillcolor;
BYTE *dc_translation;
BYTE *translationtables[NUM_TRANSLATION_TABLES];
TAutoGrowArray<FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
BYTE shadetables[NUMCOLORMAPS*16*256];
/************************************/
/* */
@ -1410,6 +1409,133 @@ void tmvline4_addclamp ()
/****************************************************/
/****************************************************/
FRemapTable::FRemapTable(int count)
{
assert(count <= 256);
Alloc(count);
// Note that the tables are left uninitialized. It is assumed that
// the caller will do that next, if only by calling MakeIdentity().
}
FRemapTable::~FRemapTable()
{
Free();
}
void FRemapTable::Alloc(int count)
{
Remap = (BYTE *)M_Malloc(count*sizeof(*Remap) + count*sizeof(*Palette));
assert (Remap != NULL);
Palette = (PalEntry *)(Remap + count*(sizeof(*Remap)));
Native = NULL;
NumEntries = count;
}
void FRemapTable::Free()
{
KillNative();
if (Remap != NULL)
{
free(Remap);
Remap = NULL;
Palette = NULL;
NumEntries = 0;
}
}
FRemapTable::FRemapTable(const FRemapTable &o)
{
Remap = NULL;
Native = NULL;
NumEntries = 0;
operator= (o);
}
FRemapTable &FRemapTable::operator=(const FRemapTable &o)
{
if (&o == this)
{
return *this;
}
if (o.NumEntries != NumEntries)
{
Free();
}
if (Remap == NULL)
{
Alloc(o.NumEntries);
}
memcpy(Remap, o.Remap, NumEntries*sizeof(*Remap) + NumEntries*sizeof(*Palette));
return *this;
}
void FRemapTable::MakeIdentity()
{
int i;
for (i = 0; i < NumEntries; ++i)
{
Remap[i] = i;
}
for (i = 0; i < NumEntries; ++i)
{
Palette[i] = GPalette.BaseColors[i];
}
}
void FRemapTable::KillNative()
{
if (Native != NULL)
{
delete Native;
Native = NULL;
}
}
void FRemapTable::UpdateNative()
{
if (Native != NULL)
{
Native->Update();
}
}
FNativeTexture *FRemapTable::GetNative()
{
if (Native == NULL)
{
Native = screen->CreatePalette(this);
}
return Native;
}
FRemapTable *TranslationToTable(int translation)
{
unsigned int type = (translation & 0xFF00) >> 8;
unsigned int index = (translation & 0x00FF);
TAutoGrowArray<FRemapTable *> *slots;
if (type <= 0 || type >= NUM_TRANSLATION_TABLES)
{
return NULL;
}
slots = &translationtables[type];
if (index >= slots->Size())
{
return NULL;
}
return slots->operator[](index);
}
static void PushIdentityTable(int slot)
{
FRemapTable *table = new FRemapTable;
table->MakeIdentity();
translationtables[slot].Push(table);
}
//
// R_InitTranslationTables
// Creates the translation tables to map the green color ramp to gray,
@ -1417,132 +1543,118 @@ void tmvline4_addclamp ()
//
void R_InitTranslationTables ()
{
static BYTE MainTranslationTables[256*
(NUMCOLORMAPS*16 // Shaded
+MAXPLAYERS*2+1 // Players + PlayersExtra + Menu player
+8 // Standard (7 for Strife, 3 for the rest)
+MAX_ACS_TRANSLATIONS // LevelScripted
+BODYQUESIZE // PlayerCorpses
+1
)];
int i, j;
// Diminishing translucency tables for shaded actors. Not really
// translation tables, but putting them here was convenient, particularly
// since translationtables[0] would otherwise be wasted.
translationtables[0] = MainTranslationTables;
// Player translations, one for each player
translationtables[TRANSLATION_Players] =
translationtables[0] + NUMCOLORMAPS*16*256;
// Extra player translations, one for each player, unused by Doom
translationtables[TRANSLATION_PlayersExtra] =
translationtables[TRANSLATION_Players] + (MAXPLAYERS+1)*256;
// Each player gets two translations. Doom and Strife don't use the
// extra ones, but Heretic and Hexen do. These are set up during
// netgame arbitration and as-needed, so they just get to be identity
// maps until then so they won't be invalid.
for (i = 0; i < MAXPLAYERS; ++i)
{
PushIdentityTable(TRANSLATION_Players);
PushIdentityTable(TRANSLATION_PlayersExtra);
}
// The menu player also gets a separate translation table
PushIdentityTable(TRANSLATION_Players);
// The three standard translations from Doom or Heretic (seven for Strife),
// plus the generic ice translation.
translationtables[TRANSLATION_Standard] =
translationtables[TRANSLATION_PlayersExtra] + MAXPLAYERS*256;
translationtables[TRANSLATION_LevelScripted] =
translationtables[TRANSLATION_Standard] + 8*256;
translationtables[TRANSLATION_PlayerCorpses] =
translationtables[TRANSLATION_LevelScripted] + MAX_ACS_TRANSLATIONS*256;
translationtables[TRANSLATION_Dim] =
translationtables[TRANSLATION_PlayerCorpses] + BODYQUESIZE*256;
translationtables[TRANSLATION_Decorate] = decorate_translations;
translationtables[TRANSLATION_Blood] = decorate_translations + MAX_DECORATE_TRANSLATIONS*256;
// [RH] Each player now gets their own translation table. These are set
// up during netgame arbitration and as-needed rather than in here.
for (i = 0; i < 256; ++i)
for (i = 0; i < 8; ++i)
{
translationtables[0][i] = i;
PushIdentityTable(TRANSLATION_Standard);
}
for (i = 0; i < MAXPLAYERS; ++i)
// Each player corpse has its own translation so they won't change
// color if the player who created them changes theirs.
for (i = 0; i < BODYQUESIZE; ++i)
{
memcpy (translationtables[TRANSLATION_Players] + i*256, translationtables[0], 256);
memcpy (translationtables[TRANSLATION_PlayersExtra] + i*256, translationtables[0], 256);
PushIdentityTable(TRANSLATION_PlayerCorpses);
}
// Create the standard translation tables
for (i = 0; i < 7; ++i)
{
memcpy (translationtables[TRANSLATION_Standard] + i*256, translationtables[0], 256);
}
if (gameinfo.gametype == GAME_Doom)
{
for (i = 0x70; i < 0x80; i++)
{ // map green ramp to gray, brown, red
translationtables[TRANSLATION_Standard][i ] = 0x60 + (i&0xf);
translationtables[TRANSLATION_Standard][i+256] = 0x40 + (i&0xf);
translationtables[TRANSLATION_Standard][i+512] = 0x20 + (i&0xf);
translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x60 + (i&0xf);
translationtables[TRANSLATION_Standard][1]->Remap[i] = 0x40 + (i&0xf);
translationtables[TRANSLATION_Standard][2]->Remap[i] = 0x20 + (i&0xf);
translationtables[TRANSLATION_Standard][0]->Palette[i] = GPalette.BaseColors[0x60 + (i&0xf)];
translationtables[TRANSLATION_Standard][1]->Palette[i] = GPalette.BaseColors[0x40 + (i&0xf)];
translationtables[TRANSLATION_Standard][2]->Palette[i] = GPalette.BaseColors[0x20 + (i&0xf)];
}
}
else if (gameinfo.gametype == GAME_Heretic)
{
for (i = 225; i <= 240; i++)
{
translationtables[TRANSLATION_Standard][i ] = 114+(i-225); // yellow
translationtables[TRANSLATION_Standard][i+256] = 145+(i-225); // red
translationtables[TRANSLATION_Standard][i+512] = 190+(i-225); // blue
translationtables[TRANSLATION_Standard][0]->Remap[i] = 114+(i-225); // yellow
translationtables[TRANSLATION_Standard][1]->Remap[i] = 145+(i-225); // red
translationtables[TRANSLATION_Standard][2]->Remap[i] = 190+(i-225); // blue
translationtables[TRANSLATION_Standard][0]->Palette[i] = GPalette.BaseColors[114+(i-225)];
translationtables[TRANSLATION_Standard][1]->Palette[i] = GPalette.BaseColors[145+(i-225)];
translationtables[TRANSLATION_Standard][2]->Palette[i] = GPalette.BaseColors[190+(i-225)];
}
}
else if (gameinfo.gametype == GAME_Strife)
{
for (i = 0x20; i <= 0x3F; ++i)
{
translationtables[TRANSLATION_Standard][i ] = i - 0x20;
translationtables[TRANSLATION_Standard][i+1*256] = i - 0x20;
translationtables[TRANSLATION_Standard][i+2*256] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+3*256] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+4*256] = i - 0x20;
translationtables[TRANSLATION_Standard][i+5*256] = i - 0x20;
translationtables[TRANSLATION_Standard][i+6*256] = i - 0x20;
translationtables[TRANSLATION_Standard][0]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][1]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][2]->Remap[i] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][3]->Remap[i] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][4]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][5]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][6]->Remap[i] = i - 0x20;
}
for (i = 0x50; i <= 0x5F; ++i)
{
// Merchant hair
translationtables[TRANSLATION_Standard][i+4*256] = 0x80 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x10 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = 0x40 + (i&0xf);
translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x80 + (i&0xf);
translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x10 + (i&0xf);
translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x40 + (i&0xf);
}
for (i = 0x80; i <= 0x8F; ++i)
{
translationtables[TRANSLATION_Standard][i ] = 0x40 + (i&0xf); // red
translationtables[TRANSLATION_Standard][i+1*256] = 0xB0 + (i&0xf); // rust
translationtables[TRANSLATION_Standard][i+2*256] = 0x10 + (i&0xf); // gray
translationtables[TRANSLATION_Standard][i+3*256] = 0x30 + (i&0xf); // dark green
translationtables[TRANSLATION_Standard][i+4*256] = 0x50 + (i&0xf); // gold
translationtables[TRANSLATION_Standard][i+5*256] = 0x60 + (i&0xf); // bright green
translationtables[TRANSLATION_Standard][i+6*256] = 0x90 + (i&0xf); // blue
translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x40 + (i&0xf); // red
translationtables[TRANSLATION_Standard][1]->Remap[i] = 0xB0 + (i&0xf); // rust
translationtables[TRANSLATION_Standard][2]->Remap[i] = 0x10 + (i&0xf); // gray
translationtables[TRANSLATION_Standard][3]->Remap[i] = 0x30 + (i&0xf); // dark green
translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x50 + (i&0xf); // gold
translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x60 + (i&0xf); // bright green
translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x90 + (i&0xf); // blue
}
for (i = 0xC0; i <= 0xCF; ++i)
{
translationtables[TRANSLATION_Standard][i+4*256] = 0xA0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x20 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = (i&0xf);
translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xA0 + (i&0xf);
translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x20 + (i&0xf);
translationtables[TRANSLATION_Standard][6]->Remap[i] = (i&0xf);
}
translationtables[TRANSLATION_Standard][0xC0+6*256] = 1;
translationtables[TRANSLATION_Standard][6]->Remap[0xC0] = 1;
for (i = 0xD0; i <= 0xDF; ++i)
{
translationtables[TRANSLATION_Standard][i+4*256] = 0xB0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x30 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = 0x10 + (i&0xf);
translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xB0 + (i&0xf);
translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x30 + (i&0xf);
translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x10 + (i&0xf);
}
for (i = 0xF1; i <= 0xF6; ++i)
{
translationtables[TRANSLATION_Standard][i ] = 0xDF + (i&0xf);
translationtables[TRANSLATION_Standard][0]->Remap[i] = 0xDF + (i&0xf);
}
for (i = 0xF7; i <= 0xFB; ++i)
{
translationtables[TRANSLATION_Standard][i ] = i - 6;
translationtables[TRANSLATION_Standard][0]->Remap[i] = i - 6;
}
for (i = 0; i < 7; ++i)
{
for (int j = 0x20; j <= 0xFB; ++j)
{
translationtables[TRANSLATION_Standard][i]->Palette[j] =
GPalette.BaseColors[translationtables[TRANSLATION_Standard][i]->Remap[j]];
}
}
}
@ -1574,19 +1686,21 @@ void R_InitTranslationTables ()
{
IcePaletteRemap[i] = ColorMatcher.Pick (IcePalette[i][0], IcePalette[i][1], IcePalette[i][2]);
}
FRemapTable *remap = translationtables[TRANSLATION_Standard][7];
for (i = 0; i < 256; ++i)
{
int r = GPalette.BaseColors[i].r;
int g = GPalette.BaseColors[i].g;
int b = GPalette.BaseColors[i].b;
int v = (r*77 + g*143 + b*37) >> 12;
translationtables[TRANSLATION_Standard][7*256+i] = IcePaletteRemap[v];
remap->Remap[i] = IcePaletteRemap[v];
remap->Palette[i] = PalEntry(IcePalette[v][0], IcePalette[v][1], IcePalette[v][2]);
}
// set up shading tables for shaded columns
// 16 colormap sets, progressing from full alpha to minimum visible alpha
BYTE *table = translationtables[TRANSLATION_Shaded];
BYTE *table = shadetables;
// Full alpha
for (i = 0; i < 16; ++i)
@ -1602,32 +1716,35 @@ void R_InitTranslationTables ()
table += 256;
}
}
}
// Dim map
void R_DeinitTranslationTables()
{
for (int i = 0; i < NUM_TRANSLATION_TABLES; ++i)
{
BYTE *dim_map = translationtables[TRANSLATION_Dim];
BYTE unremap[256];
BYTE shadetmp[256];
FWadLump palookup = Wads.OpenLumpName ("COLORMAP");
palookup.Seek (22*256, SEEK_CUR);
palookup.Read (shadetmp, 256);
memset (unremap, 0, 256);
for (i = 0; i < 256; ++i)
for (unsigned int j = 0; j < translationtables[i].Size(); ++j)
{
unremap[GPalette.Remap[i]] = i;
if (translationtables[i][j] != NULL)
{
delete translationtables[i][j];
translationtables[i][j] = NULL;
}
for (i = 0; i < 256; ++i)
{
dim_map[i] = GPalette.Remap[shadetmp[unremap[i]]];
}
dim_map[0] = GPalette.Remap[0];
}
}
// [RH] Create a player's translation table based on a given mid-range color.
// [GRB] Split to 2 functions (because of player setup menu)
static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, BYTE *table, BYTE *alttable)
static void SetRemap(FRemapTable *table, int i, float r, float g, float b)
{
int ir = clamp (int(r * 255.f), 0, 255);
int ig = clamp (int(g * 255.f), 0, 255);
int ib = clamp (int(b * 255.f), 0, 255);
table->Remap[i] = ColorMatcher.Pick (ir, ig, ib);
table->Palette[i] = PalEntry(ir, ig, ib);
}
static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable)
{
int i;
BYTE start = skin->range0start;
@ -1643,19 +1760,24 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
// the current one.
if (skin->othergame)
{
memcpy (table, OtherGameSkinRemap, 256);
memcpy (table->Remap, OtherGameSkinRemap, 256);
memcpy (table->Palette, OtherGameSkinPalette, sizeof(table->Palette));
}
else
{
for (i = 0; i < 256; ++i)
{
table[i] = i;
table->Remap[i] = i;
}
memcpy(table->Palette, GPalette.BaseColors, sizeof(table->Palette));
}
// [GRB] Don't translate skins with color range 0-0 (APlayerPawn default)
if (start == 0 && end == 0)
{
table->UpdateNative();
return;
}
range = (float)(end-start+1);
@ -1676,10 +1798,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
uses = clamp (s, 0.f, 1.f);
usev = clamp (v, 0.f, 1.f);
HSVtoRGB (&r, &g, &b, h, uses, usev);
table[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
SetRemap(table, i, r, g, b);
s += sdelta;
v += vdelta;
}
@ -1694,10 +1813,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
v = vdelta * (float)(i - start) + basev - 0.2352937f;
v = clamp (v, 0.f, 1.f);
HSVtoRGB (&r, &g, &b, h, s, v);
table[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
SetRemap(table, i, r, g, b);
}
// Build rain/lifegem translation
@ -1710,11 +1826,9 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
s = MIN (bases, 0.8965f - 0.0962f*(float)(i - 161));
v = MIN (1.f, (0.2102f + 0.0489f*(float)(i - 144)) * basev);
HSVtoRGB (&r, &g, &b, h, s, v);
alttable[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
SetRemap(alttable, i, r, g, b);
}
alttable->UpdateNative();
}
}
else if (gameinfo.gametype == GAME_Hexen)
@ -1731,10 +1845,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
for (i = start; i <= end; i++)
{
HSVtoRGB (&r, &g, &b, h, s, vs[(i-start)*9/(int)range]*basev);
table[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
SetRemap(table, i, r, g, b);
}
}
else
@ -1748,10 +1859,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
for (i = start; i <= end; i++)
{
HSVtoRGB (&r, &g, &b, h, ms[(i-start)*18/(int)range]*bases, mv[(i-start)*18/(int)range]*basev);
table[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
SetRemap(table, i, r, g, b);
}
}
@ -1765,13 +1873,12 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
RGBtoHSV (base->r/255.f, base->g/255.f, base->b/255.f, &dummy, &s, &v);
HSVtoRGB (&r, &g, &b, h, s*bases, v*basev);
alttable[i] = ColorMatcher.Pick (
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
}
SetRemap(alttable, i, r, g, b);
}
alttable->UpdateNative();
}
}
table->UpdateNative();
}
void R_BuildPlayerTranslation (int player)
@ -1782,11 +1889,11 @@ void R_BuildPlayerTranslation (int player)
R_CreatePlayerTranslation (h, s, v,
&skins[players[player].userinfo.skin],
&translationtables[TRANSLATION_Players][player*256],
&translationtables[TRANSLATION_PlayersExtra][player*256]);
translationtables[TRANSLATION_Players][player],
translationtables[TRANSLATION_PlayersExtra][player]);
}
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, BYTE *table)
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table)
{
float h, s, v;
@ -2141,14 +2248,14 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col
alpha = clamp<fixed_t> (alpha, 0, FRACUNIT);
dc_translation = NULL;
if (translation != 0)
{
dc_translation = translationtables[(translation&0xff00)>>8]
+ (translation&0x00ff)*256;
}
else
FRemapTable *table = TranslationToTable(translation);
if (table != NULL)
{
dc_translation = NULL;
dc_translation = table->Remap;
}
}
basecolormapsave = basecolormap;
stencilling = false;
@ -2169,7 +2276,7 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col
hcolfunc_post1 = rt_shaded1col;
hcolfunc_post4 = rt_shaded4cols;
dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap[APART(color)];
dc_colormap = basecolormap = &translationtables[TRANSLATION_Shaded][((16-alpha)*NUMCOLORMAPS)*256];
dc_colormap = basecolormap = &shadetables[((16-alpha)*NUMCOLORMAPS)*256];
if (fixedlightlev)
{
dc_colormap += fixedlightlev;

View file

@ -203,7 +203,7 @@ extern "C" int ds_color; // [RH] For flat color (no texturing)
enum
{
TRANSLATION_Shaded,
TRANSLATION_Invalid,
TRANSLATION_Players,
TRANSLATION_PlayersExtra,
TRANSLATION_Standard,
@ -217,8 +217,31 @@ enum
NUM_TRANSLATION_TABLES
};
extern BYTE* translationtables[NUM_TRANSLATION_TABLES];
extern BYTE* dc_translation;
struct FRemapTable
{
FRemapTable(int count=256);
FRemapTable(const FRemapTable &o);
~FRemapTable();
FRemapTable &operator= (const FRemapTable &o);
void MakeIdentity();
void KillNative();
void UpdateNative();
FNativeTexture *GetNative();
BYTE *Remap; // For the software renderer
PalEntry *Palette; // The ideal palette this maps to
FNativeTexture *Native; // The Palette stored in a HW texture
int NumEntries; // # of elements in this table (usually 256)
private:
void Free();
void Alloc(int count);
};
extern TAutoGrowArray<FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
extern BYTE shadetables[NUMCOLORMAPS*16*256];
extern BYTE *dc_translation;
inline WORD TRANSLATION(BYTE a, BYTE b)
{
@ -228,6 +251,8 @@ inline int GetTranslationType(WORD trans)
{
return trans >> 8;
}
// Retrieve the FRemapTable that an actor's translation value maps to.
FRemapTable *TranslationToTable(int translation);
#define DIM_MAP TRANSLATION(TRANSLATION_Dim, 0)
@ -245,9 +270,9 @@ inline void R_CopyTranslation (WORD to, WORD from)
void R_DetailDouble (void);
// Initialize color translation tables,
// for player rendering etc.
// Initialize color translation tables, for player rendering etc.
void R_InitTranslationTables (void);
void R_DeinitTranslationTables();
// [RH] Actually create a player's translation table.
void R_BuildPlayerTranslation (int player);

View file

@ -807,6 +807,7 @@ void R_Init ()
static void R_Shutdown ()
{
R_DeinitParticles();
R_DeinitTranslationTables();
R_DeinitPlanes();
R_DeinitData();
}

View file

@ -46,6 +46,7 @@ extern size_t numskins; // [RH]
extern FPlayerSkin * skins; // [RH]
extern BYTE OtherGameSkinRemap[256];
extern PalEntry OtherGameSkinPalette[256];
//

View file

@ -103,6 +103,7 @@ char* spritename;
FPlayerSkin *skins;
size_t numskins;
BYTE OtherGameSkinRemap[256];
PalEntry OtherGameSkinPalette[256];
// [RH] particle globals
WORD NumParticles;
@ -834,6 +835,7 @@ static void R_CreateSkinTranslation (const char *palname)
for (int i = 0; i < 256; ++i)
{
OtherGameSkinRemap[i] = ColorMatcher.Pick (otherPal[0], otherPal[1], otherPal[2]);
OtherGameSkinPalette[i] = PalEntry(otherPal[0], otherPal[1], otherPal[2]);
otherPal += 3;
}
}

View file

@ -408,6 +408,10 @@ FNativeTexture *FTexture::GetNative()
{
if (Native != NULL)
{
if (CheckModified())
{
Native->Update();
}
return Native;
}
Native = screen->CreateTexture(this);

View file

@ -3,7 +3,7 @@
** Draw patches and blocks to a canvas
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -71,7 +71,7 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
DrawParms parms;
if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms))
if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms, false))
{
return;
}
@ -88,18 +88,23 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
fixedcolormap = identitymap;
ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor);
if (APART(parms.colorOverlay) != 0)
{
// In software, DTA_ColorOverlay only does black overlays.
// Maybe I will change this later, but right now white is the only
// color that is actually used for this parameter.
// Note that this is also overriding DTA_Translation in software.
if ((parms.colorOverlay & MAKEARGB(0,255,255,255)) == 0)
{
parms.translation = &NormalLight.Maps[(APART(parms.colorOverlay)*NUMCOLORMAPS/255)*256];
}
}
if (parms.style != STYLE_Shaded)
{
if (parms.font != NULL)
if (parms.translation != NULL)
{
if (img->UseType == FTexture::TEX_FontChar)
dc_colormap = parms.font->GetColorTranslation (EColorRange(parms.translation));
else
dc_colormap = identitymap;
}
else if (parms.translation != 0)
{
dc_colormap = translationtables[(parms.translation&0xff00)>>8] + (parms.translation&0x00ff)*256;
dc_colormap = (lighttable_t *)parms.translation;
}
else
{
@ -254,7 +259,7 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
}
}
bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms) const
bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const
{
INTBOOL boolval;
int intval;
@ -280,8 +285,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->left = img->GetScaledLeftOffset();
parms->alpha = FRACUNIT;
parms->fillcolor = -1;
parms->font = NULL;
parms->translation = 0;
parms->remap = NULL;
parms->translation = NULL;
parms->colorOverlay = 0;
parms->alphaChannel = false;
parms->flipX = false;
parms->shadowAlpha = 0;
@ -406,19 +412,12 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->fillcolor = va_arg (tags, int);
break;
case DTA_Font:
parms->font = va_arg(tags, FFont*);
if (!translationset)
{
// default translation for fonts should be untranslated which unfortunately is not 0.
parms->translation = CR_UNTRANSLATED;
translationset = true;
}
case DTA_Translation:
parms->remap = va_arg (tags, FRemapTable *);
break;
case DTA_Translation:
parms->translation = va_arg(tags, int);
translationset = true;
case DTA_ColorOverlay:
parms->colorOverlay = va_arg (tags, DWORD);
break;
case DTA_FlipX:
@ -560,6 +559,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
return false;
}
if (parms->remap != NULL)
{
parms->translation = parms->remap->Remap;
}
if (parms->style == STYLE_Count)
{
if (parms->fillcolor != -1)

View file

@ -3,7 +3,7 @@
** Font management
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -52,6 +52,7 @@
#include "cmdlib.h"
#include "sc_man.h"
#include "hu_stuff.h"
#include "r_draw.h"
// MACROS ------------------------------------------------------------------
@ -263,8 +264,6 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
Chars = new CharData[count];
charlumps = new int[count];
PatchRemap = new BYTE[256];
Ranges = NULL;
PalRanges = NULL;
FirstChar = first;
LastChar = first + count - 1;
FontHeight = 0;
@ -334,7 +333,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
{
SpaceWidth = 4;
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0]);
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors);
delete[] luminosity;
delete[] charlumps;
@ -362,16 +361,6 @@ FFont::~FFont ()
delete[] Chars;
Chars = NULL;
}
if (Ranges)
{
delete[] Ranges;
Ranges = NULL;
}
if (PalRanges)
{
delete[] PalRanges;
PalRanges = NULL;
}
if (PatchRemap)
{
delete[] PatchRemap;
@ -552,42 +541,40 @@ int FFont::SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *reverse
//
//==========================================================================
void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges)
void FFont::BuildTranslations (const double *luminosity, const BYTE *identity,
const void *ranges, int total_colors)
{
int i, j;
const TranslationParm *parmstart = (const TranslationParm *)ranges;
BYTE *range;
PalEntry *prange;
range = Ranges = new BYTE[NumTextColors * ActiveColors];
// this is padded so that each palette can be treated as if it had 256 colors
prange = PalRanges = new PalEntry[NumTextColors * ActiveColors + 256];
FRemapTable remap(total_colors);
// Create different translations for different color ranges
Ranges.Clear();
for (i = 0; i < NumTextColors; i++)
{
if (i == CR_UNTRANSLATED)
{
if (identity != NULL)
{
memcpy (range, identity, ActiveColors);
memcpy (remap.Remap, identity, ActiveColors);
for (j = 0; j < ActiveColors; ++j)
{
remap.Palette[j] = GPalette.BaseColors[identity[j]];
}
}
else
{
memcpy (range, Ranges, ActiveColors);
remap = Ranges[0];
}
for (j = 0; j < ActiveColors; j++)
{
*prange++ = GPalette.BaseColors[range[j]];
}
range += ActiveColors;
Ranges.Push(remap);
continue;
}
assert(parmstart->RangeStart >= 0);
*range++ = 0;
*prange++ = PalEntry(0);
remap.Remap[0] = 0;
remap.Palette[0] = 0;
for (j = 1; j < ActiveColors; j++)
{
@ -608,12 +595,13 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, c
int r = ((parms->Start[0] << 8) + rangev * (parms->End[0] - parms->Start[0])) >> 8; // red
int g = ((parms->Start[1] << 8) + rangev * (parms->End[1] - parms->Start[1])) >> 8; // green
int b = ((parms->Start[2] << 8) + rangev * (parms->End[2] - parms->Start[2])) >> 8; // blue
r=clamp(r, 0, 255);
g=clamp(g, 0, 255);
b=clamp(b, 0, 255);
*range++ = ColorMatcher.Pick (r, g, b);
*prange++ = PalEntry(r, g, b);
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
remap.Remap[j] = ColorMatcher.Pick(r, g, b);
remap.Palette[j] = PalEntry(255,r,g,b);
}
Ranges.Push(remap);
// Advance to the next color range.
while (parmstart[1].RangeStart > parmstart[0].RangeEnd)
@ -630,25 +618,15 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, c
//
//==========================================================================
BYTE *FFont::GetColorTranslation (EColorRange range) const
FRemapTable *FFont::GetColorTranslation (EColorRange range) const
{
if (ActiveColors == 0)
return NULL;
else if (range >= NumTextColors)
range = CR_UNTRANSLATED;
return Ranges + ActiveColors * range;
return &Ranges[range];
}
PalEntry *FFont::GetTranslatedPalette (EColorRange range) const
{
if (ActiveColors == 0)
return NULL;
else if (range >= NumTextColors)
range = CR_UNTRANSLATED;
return PalRanges + ActiveColors * range;
}
//==========================================================================
//
// FFont :: GetChar
@ -725,8 +703,6 @@ int FFont::GetCharWidth (int code) const
FFont::FFont ()
{
Chars = NULL;
Ranges = NULL;
PalRanges = NULL;
PatchRemap = NULL;
Name = NULL;
}
@ -836,7 +812,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
PatchRemap = new BYTE[256];
CheckFON1Chars (lump, data, luminosity);
BuildTranslations (luminosity, NULL, &TranslationParms[1][0]);
BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors);
}
//==========================================================================
@ -862,7 +838,6 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
FirstChar = data[6];
LastChar = data[7];
ActiveColors = data[10];
Ranges = NULL;
count = LastChar - FirstChar + 1;
Chars = new CharData[count];
@ -948,7 +923,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
}
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0]);
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors);
delete[] widths2;
}
@ -1382,7 +1357,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis
Chars = new CharData[count];
charlumps = new int[count];
PatchRemap = new BYTE[256];
Ranges = NULL;
FirstChar = first;
LastChar = first + count - 1;
FontHeight = 0;
@ -1463,31 +1437,20 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis
SpaceWidth = 4;
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0]);
BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors);
// add the untranslated colors to the Ranges table
// add the untranslated colors to the Ranges tables
if (ActiveColors < TotalColors)
{
int factor = 1;
BYTE *oldranges = Ranges;
PalEntry *oldpranges = PalRanges;
Ranges = new BYTE[NumTextColors * TotalColors]; // palette map + true color map + padding
PalRanges = new PalEntry[NumTextColors * TotalColors + 256]; // padded so that each palette can be treated as if it had 256 colors
for (i = 0; i < NumTextColors; i++)
{
memcpy(&Ranges [i * TotalColors], &oldranges [i * ActiveColors], ActiveColors);
memcpy(&PalRanges[i * TotalColors], &oldpranges[i * ActiveColors], ActiveColors*sizeof(PalEntry));
for(j=ActiveColors;j<TotalColors;j++)
FRemapTable *remap = &Ranges[i];
for (j = ActiveColors; j < TotalColors; ++j)
{
Ranges[TotalColors*i + j] = identity[j];
PalRanges[TotalColors*i + j] = GPalette.BaseColors[identity[j]];
remap->Remap[j] = identity[j];
remap->Palette[j] = GPalette.BaseColors[j];
}
}
delete[] oldranges;
delete[] oldpranges;
}
ActiveColors = TotalColors;

View file

@ -2,7 +2,7 @@
** v_font.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -39,6 +39,7 @@
class DCanvas;
class FTexture;
struct FRemapTable;
enum EColorRange
{
@ -86,8 +87,7 @@ public:
FTexture *GetChar (int code, int *const width) const;
int GetCharWidth (int code) const;
BYTE *GetColorTranslation (EColorRange range) const;
PalEntry *GetTranslatedPalette (EColorRange range) const;
FRemapTable *GetColorTranslation (EColorRange range) const;
int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; }
int GetDefaultKerning () const { return GlobalKerning; }
@ -101,7 +101,7 @@ public:
protected:
FFont ();
void BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges);
void BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges, int total_colors);
static int SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *identity, double **luminosity);
@ -114,8 +114,7 @@ protected:
FTexture *Pic;
} *Chars;
int ActiveColors;
BYTE *Ranges;
PalEntry *PalRanges;
TArray<FRemapTable> Ranges;
BYTE *PatchRemap;
char *Name;

View file

@ -90,6 +90,9 @@ extern "C" {
extern FDynamicColormap NormalLight;
}
// The color overlay to use for depleted items
#define DIM_OVERLAY MAKEARGB(170,0,0,0)
extern int Near255; // A color near 255 in appearance, but not 255
int BestColor (const uint32 *pal, int r, int g, int b, int first=1, int num=255);

View file

@ -70,9 +70,10 @@ void STACK_ARGS DCanvas::DrawChar (int normalcolor, int x, int y, BYTE character
if (NULL != (pic = Font->GetChar (character, &dummy)))
{
const FRemapTable *range = Font->GetColorTranslation ((EColorRange)normalcolor);
va_list taglist;
va_start (taglist, character);
DrawTexture (pic, x, y, DTA_Font, Font, DTA_Translation, normalcolor, TAG_MORE, &taglist);
DrawTexture (pic, x, y, DTA_Translation, range, TAG_MORE, &taglist);
va_end (taglist);
}
}
@ -95,13 +96,11 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
int cx;
int cy;
int boldcolor;
int range;
const FRemapTable *range;
int height;
int forcedwidth = 0;
int scalex, scaley;
int kerning;
FFont *Font = this->Font;
FTexture *pic;
if (Font == NULL || string == NULL)
@ -111,7 +110,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
normalcolor = CR_UNTRANSLATED;
boldcolor = normalcolor ? normalcolor - 1 : NumTextColors - 1;
range = normalcolor;
range = Font->GetColorTranslation ((EColorRange)normalcolor);
height = Font->GetHeight () + 1;
kerning = Font->GetDefaultKerning ();
@ -130,6 +129,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
{
va_list *more_p;
DWORD data;
void *ptrval;
switch (tag)
{
@ -158,12 +158,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
// Translation is specified explicitly by the text.
case DTA_Translation:
*(DWORD *)tags = TAG_IGNORE;
data = va_arg (tags, int);
break;
case DTA_Font:
*(DWORD *)tags = TAG_IGNORE;
Font = va_arg (tags, FFont*);
ptrval = va_arg (tags, void*);
break;
case DTA_CleanNoMove:
@ -219,7 +214,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
EColorRange newcolor = V_ParseFontColor (ch, normalcolor, boldcolor);
if (newcolor != CR_UNDEFINED)
{
range = newcolor;
range = Font->GetColorTranslation (newcolor);
}
continue;
}
@ -239,7 +234,6 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
{
w = forcedwidth;
DrawTexture (pic, cx, cy,
DTA_Font, Font,
DTA_Translation, range,
DTA_DestWidth, forcedwidth,
DTA_DestHeight, height,
@ -248,7 +242,6 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
else
{
DrawTexture (pic, cx, cy,
DTA_Font, Font,
DTA_Translation, range,
TAG_MORE, &taglist);
}

View file

@ -102,6 +102,28 @@ IMPLEMENT_ABSTRACT_CLASS (DDummyFrameBuffer)
// try to generate a CreateNew() function.
IMPLEMENT_ABSTRACT_CLASS (DSimpleCanvas)
class FPaletteTester : public FTexture
{
public:
FPaletteTester ();
const BYTE *GetColumn(unsigned int column, const Span **spans_out);
const BYTE *GetPixels();
void Unload();
bool CheckModified();
void SetTranslation(int num);
protected:
BYTE Pixels[16*16];
int CurTranslation;
int WantTranslation;
static const Span DummySpan[2];
void MakeTexture();
};
const FTexture::Span FPaletteTester::DummySpan[2] = { { 0, 24 }, { 0, 0 } };
int DisplayWidth, DisplayHeight, DisplayBits;
FFont *SmallFont, *SmallFont2, *BigFont, *ConFont;
@ -226,7 +248,7 @@ void DCanvas::FlatFill (int left, int top, int right, int bottom, FTexture *src)
// [RH] Set an area to a specified color
void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const
void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color)
{
int x, y;
BYTE *dest;
@ -267,7 +289,7 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin
}
}
void DCanvas::Dim (PalEntry color) const
void DCanvas::Dim (PalEntry color)
{
PalEntry dimmer;
float amount = dimamount;
@ -289,7 +311,7 @@ void DCanvas::Dim (PalEntry color) const
Dim (dimmer, amount, 0, 0, Width, Height);
}
void DCanvas::Dim (PalEntry color, float damount, int x1, int y1, int w, int h) const
void DCanvas::Dim (PalEntry color, float damount, int x1, int y1, int w, int h)
{
if (damount == 0.f)
return;
@ -701,7 +723,6 @@ DFrameBuffer::DFrameBuffer (int width, int height)
void DFrameBuffer::DrawRateStuff ()
{
// Draws frame time and cumulative fps
RateX = 0;
if (vid_fps)
{
DWORD ms = I_MSTime ();
@ -710,12 +731,13 @@ void DFrameBuffer::DrawRateStuff ()
{
char fpsbuff[40];
int chars;
int rate_x;
chars = sprintf (fpsbuff, "%2u ms (%3u fps)", howlong, LastCount);
RateX = Width - chars * 8;
Clear (RateX, 0, Width, 8, 0, 0);
rate_x = Width - chars * 8;
Clear (rate_x, 0, Width, 8, 0, 0);
SetFont (ConFont);
DrawText (CR_WHITE, RateX, 0, (char *)&fpsbuff[0], TAG_DONE);
DrawText (CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
SetFont (SmallFont);
DWORD thisSec = ms/1000;
@ -735,47 +757,114 @@ void DFrameBuffer::DrawRateStuff ()
{
int i = I_GetTime(false);
int tics = i - LastTic;
BYTE *buffer = GetBuffer () + (GetHeight()-1)*GetPitch();
BYTE *buffer = GetBuffer();
LastTic = i;
if (tics > 20) tics = 20;
// Buffer can be NULL if we're doing hardware accelerated 2D
if (buffer != NULL)
{
buffer += (GetHeight()-1)*GetPitch();
for (i = 0; i < tics*2; i += 2) buffer[i] = 0xff;
for ( ; i < 20*2; i += 2) buffer[i] = 0x00;
}
else
{
for (i = 0; i < tics*2; i += 2) Clear(i, Height-1, i+1, Height, 255, 0);
for ( ; i < 20*2; i += 2) Clear(i, Height-1, i+1, Height, 0, 0);
}
}
// draws the palette for debugging
if (vid_showpalette)
{
int i, j, k, l;
// This used to just write the palette to the display buffer.
// With hardware-accelerated 2D, that doesn't work anymore.
// Drawing it as a texture does and continues to show how
// well the PalTex shader is working.
static FPaletteTester palette;
BYTE *buffer = GetBuffer();
for (i = k = 0; i < 16; ++i)
{
for (j = 0; j < 8; ++j)
{
for (l = 0; l < 16; ++l)
{
int color;
palette.SetTranslation(vid_showpalette);
DrawTexture(&palette, 0, 0,
DTA_DestWidth, 16*7,
DTA_DestHeight, 16*7,
DTA_Masked, false,
TAG_DONE);
}
}
if (vid_showpalette > 1 && vid_showpalette < 9)
FPaletteTester::FPaletteTester()
{
Width = 16;
Height = 16;
WidthBits = 4;
HeightBits = 4;
WidthMask = 15;
CurTranslation = 0;
WantTranslation = 1;
MakeTexture();
}
bool FPaletteTester::CheckModified()
{
return CurTranslation != WantTranslation;
}
void FPaletteTester::SetTranslation(int num)
{
if (num >= 1 && num <= 9)
{
color = translationtables[TRANSLATION_Standard][(vid_showpalette-2)*256+k];
WantTranslation = num;
}
else
}
void FPaletteTester::Unload()
{
}
const BYTE *FPaletteTester::GetColumn (unsigned int column, const Span **spans_out)
{
if (CurTranslation != WantTranslation)
{
color = k;
MakeTexture();
}
memset (buffer, color, 8);
buffer += 8;
k++;
column &= 15;
if (spans_out != NULL)
{
*spans_out = DummySpan;
}
k -= 16;
buffer += GetPitch() - 16*8;
return Pixels + column*16;
}
const BYTE *FPaletteTester::GetPixels ()
{
if (CurTranslation != WantTranslation)
{
MakeTexture();
}
return Pixels;
}
void FPaletteTester::MakeTexture()
{
int i, j, k, t;
BYTE *p;
t = WantTranslation;
p = Pixels;
k = 0;
for (i = 0; i < 16; ++i)
{
for (j = 0; j < 16; ++j)
{
*p++ = (t > 1) ? translationtables[TRANSLATION_Standard][t - 2]->Remap[k] : k;
k += 16;
}
k -= 255;
}
CurTranslation = t;
}
void DFrameBuffer::CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest)
@ -812,7 +901,7 @@ FNativeTexture *DFrameBuffer::CreateTexture(FTexture *gametex)
return NULL;
}
FNativeTexture *DFrameBuffer::CreatePalette(const PalEntry *pal)
FNativeTexture *DFrameBuffer::CreatePalette(FRemapTable *remap)
{
return NULL;
}

View file

@ -76,9 +76,7 @@ enum
DTA_DestHeight, // height of area to draw to
DTA_Alpha, // alpha value for translucency
DTA_FillColor, // color to stencil onto the destination
DTA_Font, // For characters: Font it belongs to
DTA_Translation, // translation table to recolor the source
DTA_TranslationPtr, // translation table to recolor the source
DTA_AlphaChannel, // bool: the source is an alpha channel; used with DTA_FillColor
DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac
DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen
@ -103,6 +101,7 @@ enum
DTA_HUDRules, // use fullscreen HUD rules to position and size textures
DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3
DTA_RenderStyle, // same as render style for actors
DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image. Limited under software.
// For DrawText calls:
DTA_TextLen, // stop after this many characters, even if \0 not hit
@ -156,16 +155,16 @@ public:
virtual void GetBlock (int x, int y, int width, int height, BYTE *dest) const;
// Dim the entire canvas for the menus
virtual void Dim (PalEntry color = 0) const;
virtual void Dim (PalEntry color = 0);
// Dim part of the canvas
virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const;
virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h);
// Fill an area with a texture
virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src);
// Set an area to a specified color
virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const;
virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color);
// renders the player backdrop for the menu
virtual void DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y);
@ -218,8 +217,9 @@ protected:
int left;
fixed_t alpha;
int fillcolor;
FFont *font;
int translation;
FRemapTable *remap;
const BYTE *translation;
DWORD colorOverlay;
INTBOOL alphaChannel;
INTBOOL flipX;
fixed_t shadowAlpha;
@ -233,7 +233,7 @@ protected:
bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const;
virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms) const;
bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const;
DCanvas() {}
@ -327,8 +327,8 @@ public:
// Create a native texture from a game texture.
virtual FNativeTexture *CreateTexture(FTexture *gametex);
// Create a palette texture from a 256-entry palette.
virtual FNativeTexture *CreatePalette(const PalEntry *pal);
// Create a palette texture from a palette.
virtual FNativeTexture *CreatePalette(FRemapTable *remap);
// texture copy functions
virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
@ -354,9 +354,6 @@ protected:
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y);
int RateX;
private:
DWORD LastMS, LastSec, FrameCount, LastCount, LastTic;
};
@ -366,6 +363,7 @@ class FNativeTexture
{
public:
virtual ~FNativeTexture();
virtual bool Update() = 0;
};
extern FColorMatcher ColorMatcher;

View file

@ -698,8 +698,7 @@ static void WI_DrawCharPatch (FTexture *patch, int x, int y)
screen->DrawTexture (patch, x, y,
DTA_Clean, true,
DTA_ShadowAlpha, (gameinfo.gametype == GAME_Doom) ? 0 : FRACUNIT/2,
DTA_Font, BigFont,
DTA_Translation, CR_UNTRANSLATED, // otherwise it doesn't look good in Strife!
DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), // otherwise it doesn't look good in Strife!
TAG_DONE);
}
}
@ -1584,13 +1583,13 @@ void WI_drawNetgameStats ()
x = NG_STATSX;
// [RH] Only use one graphic for the face backgrounds
screen->DrawTexture (p, x - p->GetWidth(), y,
DTA_Translation, TRANSLATION(TRANSLATION_Players, i),
DTA_Translation, translationtables[TRANSLATION_Players][i],
DTA_Clean, true,
TAG_DONE);
if (i == me)
screen->DrawTexture (star, x - p->GetWidth(), y,
DTA_Translation, TRANSLATION(TRANSLATION_Players, i),
DTA_Translation, translationtables[TRANSLATION_Players][i],
DTA_Clean, true,
TAG_DONE);
@ -1634,7 +1633,7 @@ void WI_drawNetgameStats ()
if (gameinfo.gametype == GAME_Heretic)
{
screen->DrawTexture (star, 25, y,
DTA_Translation, TRANSLATION(TRANSLATION_Players, i),
DTA_Translation, translationtables[TRANSLATION_Players][i],
DTA_Clean, true,
TAG_DONE);
}

View file

@ -3,7 +3,7 @@
** Code to let ZDoom use Direct3D 9 as a simple framebuffer
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -60,6 +60,7 @@
#include "v_pfx.h"
#include "stats.h"
#include "doomerrors.h"
#include "r_draw.h"
#include "win32iface.h"
@ -102,6 +103,20 @@ public:
FTextureFormat ToTexFmt(D3DFORMAT fmt);
};
class D3DPal : public FNativeTexture
{
public:
D3DPal(FRemapTable *remap, D3DFB *fb);
~D3DPal();
IDirect3DTexture9 *Tex;
bool Update();
FRemapTable *Remap;
int RoundedPaletteSize;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -152,7 +167,6 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
FBFormat = D3DFMT_UNKNOWN;
PalFormat = D3DFMT_UNKNOWN;
VSync = vid_vsync;
OffByOneAt = -1;
BlendingRect.left = 0;
BlendingRect.top = 0;
BlendingRect.right = FBWidth;
@ -216,6 +230,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
if (D3DDevice != NULL)
{
CreateResources ();
// Be sure we know what the alpha blend is
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
AlphaBlendEnabled = FALSE;
AlphaSrcBlend = D3DBLEND(0);
AlphaDestBlend = D3DBLEND(0);
}
}
@ -274,12 +294,19 @@ bool D3DFB::CreateResources ()
I_RestoreWindowedPos ();
VidResizing = false;
}
if (FAILED(D3DDevice->CreatePixelShader (PalTexShaderDef, &PalTexShader)) ||
FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) ||
SM14 = false;
if (FAILED(D3DDevice->CreatePixelShader (PalTexShader20Def, &PalTexShader)) &&
(SM14 = true, FAILED(D3DDevice->CreatePixelShader (PalTexShader14Def, &PalTexShader))))
{
return false;
}
if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) ||
FAILED(D3DDevice->CreatePixelShader (DimShaderDef, &DimShader)))
{
return false;
}
CurPixelShader = NULL;
memset(Constant, 0, sizeof(Constant));
if (!CreateFBTexture() ||
!CreatePaletteTexture() ||
!CreateStencilPaletteTexture() ||
@ -292,6 +319,7 @@ bool D3DFB::CreateResources ()
return false;
}
SetGamma (Gamma);
return true;
}
@ -364,190 +392,9 @@ bool D3DFB::Reset ()
{
return false;
}
if (OffByOneAt < 256)
{
D3DDevice->SetSamplerState (1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
D3DDevice->SetSamplerState (1, D3DSAMP_BORDERCOLOR,
D3DCOLOR_XRGB(GammaTable[SourcePalette[255].r],
GammaTable[SourcePalette[255].g],
GammaTable[SourcePalette[255].b]));
}
return true;
}
//==========================================================================
//
// DoOffByOneCheck
//
// NVidia hardware has an off-by-one error in the pixel shader.
// On a Geforce 7950GT and a 6200, I have witnessed it skip palette entry
// 240. I have a report that an FX card skips in a totally different spot.
// So rather than try and correct it in the shader, we detect it here and
// compensate when uploading the palette and when drawing by setting the
// sampler mode for the palette to border and making the border color the
// final color in the palette.
//
// Interestingly, a Radeon x300 doesn't have this problem. I am curious
// if other ATI hardware is the same.
//
//==========================================================================
void D3DFB::DoOffByOneCheck ()
{
IDirect3DSurface9 *savedrendertarget;
IDirect3DSurface9 *testsurf, *readsurf;
D3DSURFACE_DESC desc;
D3DLOCKED_RECT lockrect;
RECT testrect = { 0, 0, 256, 1 };
float texright = 256.f / float(FBWidth);
float texbot = 1.f / float(FBHeight);
FBVERTEX verts[4] =
{
{ -0.5f, -0.5f, 0.5f, 1.f, 0.f, 0.f },
{ 255.5f, -0.5f, 0.5f, 1.f, texright, 0.f },
{ 255.5f, 0.5f, 0.5f, 1.f, texright, texbot },
{ -0.5f, 0.5f, 0.5f, 1.f, 0.f, texbot }
};
float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
union
{
BYTE Pal32[256][4];
WORD Pal16[256];
};
int i, c;
if (OffByOneAt >= 0)
{
return;
}
// Create an easily recognizable R3G3B2 palette.
for (i = 0; i < 256; ++i)
{
Pal32[i][0] = BYTE(i & 0x03) << 6; // blue
Pal32[i][1] = BYTE(i & 0x1C) << 3; // green
Pal32[i][2] = BYTE(i & 0xE0); // red;
Pal32[i][3] = 255;
}
// Upload the palette
if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0)))
{
memcpy (lockrect.pBits, Pal32, 256 * 4);
PaletteTexture->UnlockRect (0);
}
else
{
return;
}
// Prepare a texture with values 0-256.
if (SUCCEEDED(FBTexture->LockRect (0, &lockrect, &testrect, 0)))
{
for (i = 0; i < 256; ++i)
{
((BYTE *)lockrect.pBits)[i] = (BYTE)i;
}
FBTexture->UnlockRect (0);
}
else
{
return;
}
// Create a render target that we can draw it to.
if (FAILED(D3DDevice->GetRenderTarget (0, &savedrendertarget)))
{
return;
}
if (FAILED(D3DDevice->CreateRenderTarget (256, 1, PalFormat, D3DMULTISAMPLE_NONE, 0, FALSE, &testsurf, NULL)))
{
return;
}
if (FAILED(D3DDevice->CreateOffscreenPlainSurface (256, 1, PalFormat, D3DPOOL_SYSTEMMEM, &readsurf, NULL)))
{
testsurf->Release();
return;
}
if (FAILED(D3DDevice->SetRenderTarget (0, testsurf)))
{
testsurf->Release();
readsurf->Release();
return;
}
// Write it to the render target using the pixel shader.
D3DDevice->BeginScene();
D3DDevice->SetTexture (0, FBTexture);
D3DDevice->SetTexture (1, PaletteTexture);
D3DDevice->SetFVF (D3DFVF_FBVERTEX);
D3DDevice->SetPixelShader (PalTexShader);
D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2);
D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
D3DDevice->EndScene();
D3DDevice->SetRenderTarget (0, savedrendertarget);
savedrendertarget->Release();
// Now read it back and see where it skips an entry
if (SUCCEEDED(D3DDevice->GetRenderTargetData (testsurf, readsurf)) &&
SUCCEEDED(readsurf->LockRect (&lockrect, &testrect, D3DLOCK_READONLY)))
{
desc.Format = PalFormat;
if (desc.Format == D3DFMT_A8R8G8B8 || desc.Format == D3DFMT_X8R8G8B8)
{
const BYTE *pix = (const BYTE *)lockrect.pBits;
for (i = 0; i < 256; ++i, pix += 4)
{
c = (pix[0] >> 6) | // blue
((pix[1] >> 5) << 2) | // green
((pix[2] >> 5) << 5); // red
if (c != i)
{
break;
}
}
}
else if (desc.Format == D3DFMT_A1R5G5B5 || desc.Format == D3DFMT_X1R5G5B5)
{
const WORD *pix = (const WORD *)lockrect.pBits;
for (i = 0; i < 256; ++i, ++pix)
{
c = ((*pix & 0x0018) >> 3) | // blue
((*pix & 0x0380) >> 5) | // green
((*pix & 0x7C00) >> 7) ; // red
if (c != i)
{
break;
}
}
}
else if (desc.Format == D3DFMT_R5G6B5)
{
const WORD *pix = (const WORD *)lockrect.pBits;
for (i = 0; i < 256; ++i, ++pix)
{
c = ((*pix & 0x0018) >> 3) | // blue
((*pix & 0x0700) >> 6) | // green
((*pix & 0xE000) >> 8) ; // red
if (c != i)
{
break;
}
}
}
else
{
// Huh? What kind of backbuffer is this?
i = 256;
}
}
readsurf->UnlockRect();
readsurf->Release();
testsurf->Release();
OffByOneAt = i;
if (i < 256)
{
D3DDevice->SetSamplerState (1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
}
}
bool D3DFB::CreateFBTexture ()
{
if (FAILED(D3DDevice->CreateTexture (Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL)))
@ -811,6 +658,7 @@ void D3DFB::Update ()
{
if (In2D == 2)
{
DrawRateStuff();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
In2D = 0;
@ -819,7 +667,7 @@ void D3DFB::Update ()
if (LockCount != 1)
{
//I_FatalError ("Framebuffer must have exactly 1 lock to be updated");
I_FatalError ("Framebuffer must have exactly 1 lock to be updated");
if (LockCount > 0)
{
UpdatePending = true;
@ -828,7 +676,10 @@ void D3DFB::Update ()
return;
}
DrawRateStuff ();
if (In2D == 0)
{
DrawRateStuff();
}
if (NeedGammaUpdate)
{
@ -915,13 +766,13 @@ void D3DFB::Draw3DPart()
D3DDevice->Clear (2, rects, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.f, 0);
}
D3DDevice->BeginScene();
D3DDevice->SetTexture (0, FBTexture);
D3DDevice->SetTexture (1, PaletteTexture);
SetTexture (0, FBTexture);
SetPaletteTexture(PaletteTexture, 256);
D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX));
D3DDevice->SetFVF (D3DFVF_FBVERTEX);
D3DDevice->SetPixelShader (PalTexShader);
D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2);
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
memcpy(Constant, FlashConstants, sizeof(FlashConstants));
SetAlphaBlend(FALSE);
if (!UseBlendingRect || FlashConstants[1][0] == 1)
{ // The whole screen as a single quad.
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
@ -933,32 +784,13 @@ void D3DFB::Draw3DPart()
// The rest is drawn unblended, so reset the shader constant.
static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2);
memcpy(Constant, FlashZero, sizeof(FlashZero));
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top
}
if (UseBlendingRect && FlashConstants[1][0] != 1 && RateX)
{
float left = float(RateX) - 0.5f;
float top = (TrueHeight - Height) * 0.5f - 0.5f;
float right = float(Width) - 0.5f;
float bot = float(8) + top;
float texleft = float(RateX) / float(FBWidth);
float texright = float(Width) / float(FBWidth);
float texbot = float(8) / float(FBHeight);
// Redraw the vid_fps part without the flash
FBVERTEX verts[4] =
{
{ left, top, 0.5f, 1.f, texleft, 0.f },
{ right, top, 0.5f, 1.f, texright, 0.f },
{ right, bot, 0.5f, 1.f, texright, texbot },
{ left, bot, 0.5f, 1.f, texleft, texbot }
};
D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
}
}
void D3DFB::UploadPalette ()
@ -966,18 +798,10 @@ void D3DFB::UploadPalette ()
D3DLOCKED_RECT lockrect;
int i;
if (OffByOneAt < 0)
{
DoOffByOneCheck ();
}
if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0)))
{
// Keep trying to update the palette if we haven't done the off-by-one
// check yet. Otherwise, wait until the next time the palette changes.
NeedPalUpdate = (OffByOneAt < 0);
BYTE *pix = (BYTE *)lockrect.pBits;
for (i = 0; i < OffByOneAt; ++i, pix += 4)
for (i = 0; i < 256; ++i, pix += 4)
{
pix[0] = GammaTable[SourcePalette[i].b];
pix[1] = GammaTable[SourcePalette[i].g];
@ -985,22 +809,8 @@ void D3DFB::UploadPalette ()
pix[3] = (i == 0 ? 0 : 255);
// To let masked textures work, the first palette entry's alpha is 0.
}
for (; i < 256; ++i, pix += 4)
{
pix[0] = GammaTable[SourcePalette[i-1].b];
pix[1] = GammaTable[SourcePalette[i-1].g];
pix[2] = GammaTable[SourcePalette[i-1].r];
pix[3] = 255;
}
PaletteTexture->UnlockRect (0);
}
if (OffByOneAt < 256)
{
D3DDevice->SetSamplerState (1, D3DSAMP_BORDERCOLOR,
D3DCOLOR_XRGB(GammaTable[SourcePalette[255].r],
GammaTable[SourcePalette[255].g],
GammaTable[SourcePalette[255].b]));
}
}
PalEntry *D3DFB::GetPalette ()
@ -1145,8 +955,6 @@ bool D3DTex::Create(IDirect3DDevice9 *D3DDevice)
w = GameTex->GetWidth();
h = GameTex->GetHeight();
// We don't really want mip-maps, but specifying the flag is the only
// way to use D3DPOOL_MANAGED, according to the docs.
hr = D3DDevice->CreateTexture(w, h, 1, 0,
GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL);
if (FAILED(hr))
@ -1260,6 +1068,97 @@ FTextureFormat D3DTex::ToTexFmt(D3DFORMAT fmt)
}
}
//==========================================================================
//
// D3DPal Constructor
//
//==========================================================================
D3DPal::D3DPal(FRemapTable *remap, D3DFB *fb)
: Tex(NULL), Remap(remap)
{
int count;
// Palette textures must be 256 entries for Shader Model 1.4
if (fb->SM14)
{
count = 256;
}
else
{
int pow2count;
// Round up to the nearest power of 2.
for (pow2count = 1; pow2count < remap->NumEntries; pow2count <<= 1)
{ }
count = pow2count;
}
RoundedPaletteSize = count;
if (SUCCEEDED(fb->D3DDevice->CreateTexture(count, 1, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &Tex, NULL)))
{
if (!Update())
{
Tex->Release();
Tex = NULL;
}
}
}
//==========================================================================
//
// D3DPal Destructor
//
//==========================================================================
D3DPal::~D3DPal()
{
if (Tex != NULL)
{
Tex->Release();
Tex = NULL;
}
}
//==========================================================================
//
// D3DPal :: Update
//
// Copies the palette to the texture.
//
//==========================================================================
bool D3DPal::Update()
{
D3DLOCKED_RECT lrect;
D3DCOLOR *buff;
const PalEntry *pal;
assert(Tex != NULL);
if (FAILED(Tex->LockRect(0, &lrect, NULL, 0)))
{
return false;
}
buff = (D3DCOLOR *)lrect.pBits;
pal = Remap->Palette;
// Should I allow the source palette to specify alpha values?
buff[0] = D3DCOLOR_ARGB(0,
static_cast<D3DFB *>(screen)->GammaTable[pal[0].r],
static_cast<D3DFB *>(screen)->GammaTable[pal[0].g],
static_cast<D3DFB *>(screen)->GammaTable[pal[0].b]);
for (int i = 1; i < Remap->NumEntries; ++i)
{
buff[i] = D3DCOLOR_XRGB(
static_cast<D3DFB *>(screen)->GammaTable[pal[i].r],
static_cast<D3DFB *>(screen)->GammaTable[pal[i].g],
static_cast<D3DFB *>(screen)->GammaTable[pal[i].b]);
}
Tex->UnlockRect(0);
return true;
}
//==========================================================================
//
// D3DFB :: Begin2D
@ -1280,19 +1179,47 @@ void D3DFB::Begin2D()
In2D = 2;
// Set default state for 2D rendering.
float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2);
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
// This is set by Update()
//D3DDevice->SetTexture(1, PaletteTexture);
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
}
//==========================================================================
//
// D3DFB :: CreateTexture
//
// Returns a native texture that wraps a FTexture.
//
//==========================================================================
FNativeTexture *D3DFB::CreateTexture(FTexture *gametex)
{
return new D3DTex(gametex, D3DDevice);
D3DTex *tex = new D3DTex(gametex, D3DDevice);
if (tex->Tex == NULL)
{
delete tex;
return NULL;
}
return tex;
}
//==========================================================================
//
// D3DFB :: CreatePalette
//
// Returns a native texture that contains a palette.
//
// Pre: count is a power of 2
//
//==========================================================================
FNativeTexture *D3DFB::CreatePalette(FRemapTable *remap)
{
D3DPal *tex = new D3DPal(remap, this);
if (tex->Tex == NULL)
{
delete tex;
return NULL;
}
return tex;
}
//==========================================================================
@ -1303,7 +1230,7 @@ FNativeTexture *D3DFB::CreateTexture(FTexture *gametex)
//
//==========================================================================
void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const
void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color)
{
if (In2D < 2)
{
@ -1314,6 +1241,11 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3
{
color = GPalette.BaseColors[palcolor];
}
else if (APART(color) < 255)
{
Dim(color, APART(color)/255.f, left, top, right - left, bottom - top);
return;
}
D3DRECT rect = { left, top, right, bottom };
D3DDevice->Clear(1, &rect, D3DCLEAR_TARGET, color | 0xFF000000, 1.f, 0);
}
@ -1324,7 +1256,7 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3
//
//==========================================================================
void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const
void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h)
{
if (amount <= 0)
return;
@ -1348,14 +1280,10 @@ void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) con
{ x1+w-0.5f, y1+h-0.5f, 0.5f, 1, 0, 0 },
{ x1-0.5f, y1+h-0.5f, 0.5f, 1, 0, 0 }
};
float constant[4] =
{
RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, APART(color)/255.f,
};
D3DDevice->SetPixelShader(DimShader);
D3DDevice->SetPixelShaderConstantF(1, constant, 1);
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
SetPixelShader(DimShader);
SetConstant(1, color.r/255.f, color.g/255.f, color.b/255.f, amount);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX));
D3DDevice->SetPixelShader(PalTexShader);
}
}
@ -1378,7 +1306,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
DrawParms parms;
if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms))
if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true))
{
return;
}
@ -1450,12 +1378,12 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
{ x0, y1, 0.5f, 1.f, u0, v1 }
};
if (!SetStyle(parms.style, parms.alpha, parms.fillcolor, parms.masked))
if (!SetStyle(parms))
{
return;
}
D3DDevice->SetTexture(0, tex->Tex);
SetTexture(0, tex->Tex);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX));
}
@ -1467,13 +1395,14 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
//
//==========================================================================
bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked)
bool D3DFB::SetStyle(DrawParms &parms)
{
ERenderStyle style = parms.style;
D3DBLEND fglevel, bglevel;
float alpha;
bool stencilling;
alpha = clamp<fixed_t> (alpha_fixed, 0, FRACUNIT) / 65536.f;
alpha = clamp<fixed_t> (parms.alpha, 0, FRACUNIT) / 65536.f;
if (style == STYLE_OptFuzzy)
{
@ -1500,12 +1429,9 @@ bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked
case STYLE_Shaded:
if (alpha > 0)
{
float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha };
D3DDevice->SetPixelShaderConstantF(1, constant, 1);
D3DDevice->SetTexture(1, ShadedPaletteTexture);
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha);
SetPaletteTexture(ShadedPaletteTexture, 256);
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
return true;
}
return false;
@ -1545,28 +1471,146 @@ bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked
// Masking can only be turned off for STYLE_Normal, because it requires
// turning off the alpha blend.
if (!masked && style == STYLE_Normal)
if (!parms.masked && style == STYLE_Normal)
{
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
SetAlphaBlend(FALSE);
SetColorOverlay(parms.colorOverlay, 1);
SetPaletteTexture(PaletteTexture, 256);
}
else
{
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
D3DDevice->SetRenderState(D3DRS_SRCBLEND, fglevel);
D3DDevice->SetRenderState(D3DRS_DESTBLEND, bglevel);
SetAlphaBlend(TRUE, fglevel, bglevel);
if (!stencilling)
{
float constant[4] = { 1,1,1,alpha };
D3DDevice->SetPixelShaderConstantF(1, constant, 1);
D3DDevice->SetTexture(1, PaletteTexture);
if (parms.remap != NULL)
{
D3DPal *pal = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize);
}
else
{
float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha };
D3DDevice->SetPixelShaderConstantF(1, constant, 1);
D3DDevice->SetTexture(1, StencilPaletteTexture);
SetPaletteTexture(PaletteTexture, 256);
}
SetColorOverlay(parms.colorOverlay, alpha);
}
else
{
SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha);
SetPaletteTexture(StencilPaletteTexture, 256);
}
}
return true;
}
void D3DFB::SetColorOverlay(DWORD color, float alpha)
{
if (APART(color) != 0)
{
float a = 255.f / APART(color);
float r = RPART(color) * a;
float g = GPART(color) * a;
float b = BPART(color) * a;
SetConstant(0, r, g, b, 0);
a = 1 - 1 / a;
SetConstant(1, a, a, a, alpha);
}
else
{
SetConstant(0, 0, 0, 0, 0);
SetConstant(1, 1, 1, 1, alpha);
}
}
void D3DFB::SetAlphaBlend(BOOL enabled, D3DBLEND srcblend, D3DBLEND destblend)
{
if (!enabled)
{ // Disable alpha blend
if (AlphaBlendEnabled)
{
AlphaBlendEnabled = FALSE;
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
}
else
{ // Enable alpha blend
assert(srcblend != 0);
assert(destblend != 0);
if (!AlphaBlendEnabled)
{
AlphaBlendEnabled = TRUE;
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
}
if (AlphaSrcBlend != srcblend)
{
AlphaSrcBlend = srcblend;
D3DDevice->SetRenderState(D3DRS_SRCBLEND, srcblend);
}
if (AlphaDestBlend != destblend)
{
AlphaDestBlend = destblend;
D3DDevice->SetRenderState(D3DRS_DESTBLEND, destblend);
}
}
}
void D3DFB::SetConstant(int cnum, float r, float g, float b, float a)
{
if (Constant[cnum][0] != r ||
Constant[cnum][1] != g ||
Constant[cnum][2] != b ||
Constant[cnum][3] != a)
{
Constant[cnum][0] = r;
Constant[cnum][1] = g;
Constant[cnum][2] = b;
Constant[cnum][3] = a;
D3DDevice->SetPixelShaderConstantF(cnum, Constant[cnum], 1);
}
}
void D3DFB::SetPixelShader(IDirect3DPixelShader9 *shader)
{
if (CurPixelShader != shader)
{
CurPixelShader = shader;
D3DDevice->SetPixelShader(shader);
}
}
void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture)
{
if (Texture[tnum] != texture)
{
Texture[tnum] = texture;
D3DDevice->SetTexture(tnum, texture);
}
}
void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count)
{
if (SM14)
{
// Shader Model 1.4 only uses 256-color palettes.
SetConstant(2, 255 / 256.f, 0.5f / 256.f, 0, 0);
}
else
{
// The pixel shader receives color indexes in the range [0.0,1.0].
// The palette texture is also addressed in the range [0.0,1.0],
// HOWEVER the coordinate 1.0 is the right edge of the texture and
// not actually the texture itself. We need to scale and shift
// the palette indexes so they lie exactly in the center of each
// texel. For a normal palette with 256 entries, that means the
// range we use should be [0.5,255.5], adjusted so the coordinate
// is still with [0.0,1.0].
//
// The constant register c2 is used to hold the multiplier in the
// x part and the adder in the y part.
float fcount = 1 / float(count);
SetConstant(2, 255 * fcount, 0.5f * fcount, 0, 0);
}
SetTexture(1, texture);
SetPixelShader(PalTexShader);
}

View file

@ -12,19 +12,20 @@ sampler2D Image : register(s0);
sampler2D Palette : register(s1);
float4 Flash : register(c0);
float4 InvFlash : register(c1);
float4 PaletteMod : register(c2);
float4 main (float2 texCoord : TEXCOORD0) : COLOR
{
float4 index = tex2D (Image, texCoord);
index.x = index.x * PaletteMod.x + PaletteMod.y;
float4 rgb = tex2D (Palette, index);
return Flash + rgb * InvFlash;
}
#endif
#if SHADER_ASSEMBLY_CODE
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc paltex.ps /Tps_1_4 /VnPalTexShaderDef /Fh
// fxc paltex.ps /Tps_1_4 /VnPalTexShader14Def /Fh
//
//
// Parameters:
@ -33,6 +34,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
// sampler2D Image;
// float4 InvFlash;
// sampler2D Palette;
// float4 PaletteMod;
//
//
// Registers:
@ -41,34 +43,75 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
// ------------ ----- ----
// Flash c0 1
// InvFlash c1 1
// PaletteMod c2 1
// Image s0 1
// Palette s1 1
//
ps_1_4
texld r0, t0
mad r0.x, r0.x, c2.x, c2.y
phase
texld r1, r0
mad r0, r1, c1, c0
// approximately 3 instruction slots used (2 texture, 1 arithmetic)
// approximately 4 instruction slots used (2 texture, 2 arithmetic)
#endif
const DWORD PalTexShaderDef[] =
const DWORD PalTexShader14Def[] =
{
0xffff0104, 0x003bfffe, 0x42415443, 0x0000001c, 0x000000b4, 0xffff0104,
0x00000004, 0x0000001c, 0x00000100, 0x000000ad, 0x0000006c, 0x00000002,
0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00000003, 0x00000001,
0x0000008c, 0x00000000, 0x0000009c, 0x00010002, 0x00020001, 0x00000074,
0x00000000, 0x000000a5, 0x00010003, 0x00000001, 0x0000008c, 0x00000000,
0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000,
0x46766e49, 0x6873616c, 0x6c615000, 0x65747465, 0x5f737000, 0x00345f31,
0x7263694d, 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853,
0x43207265, 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e,
0xabab0030, 0x00000042, 0x800f0000, 0xb0e40000, 0x0000fffd, 0x00000042,
0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, 0xa0e40001,
0xa0e40000, 0x0000ffff
0xffff0104, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d3, 0xffff0104,
0x00000005, 0x0000001c, 0x00000100, 0x000000cc, 0x00000080, 0x00000002,
0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00000003, 0x00000001,
0x000000a0, 0x00000000, 0x000000b0, 0x00010002, 0x00020001, 0x00000088,
0x00000000, 0x000000b9, 0x00010003, 0x00000001, 0x000000a0, 0x00000000,
0x000000c1, 0x00020002, 0x00020001, 0x00000088, 0x00000000, 0x73616c46,
0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49,
0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x46766e49,
0x6873616c, 0x6c615000, 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d,
0x315f7370, 0x4d00345f, 0x6f726369, 0x74666f73, 0x29522820, 0x44334420,
0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e,
0x2e393737, 0x30303030, 0xababab00, 0x00000042, 0x800f0000, 0xb0e40000,
0x00000004, 0x80010000, 0x80000000, 0xa0000002, 0xa0550002, 0x0000fffd,
0x00000042, 0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001,
0xa0e40001, 0xa0e40000, 0x0000ffff
};
#if SHADER_ASSEMBLY_CODE
ps_2_0
dcl t0.xy
dcl_2d s0
dcl_2d s1
texld r0, t0, s0
mad r0.x, r0.x, c2.x, c2.y
texld r0, r0, s1
mov r1, c1
mad r0, r0, r1, c0
mov oC0, r0
// approximately 6 instruction slots used (2 texture, 4 arithmetic)
#endif
const DWORD PalTexShader20Def[] =
{
0xffff0200, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d3, 0xffff0200,
0x00000005, 0x0000001c, 0x00000100, 0x000000cc, 0x00000080, 0x00000002,
0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00000003, 0x00000001,
0x000000a0, 0x00000000, 0x000000b0, 0x00010002, 0x00020001, 0x00000088,
0x00000000, 0x000000b9, 0x00010003, 0x00000001, 0x000000a0, 0x00000000,
0x000000c1, 0x00020002, 0x00020001, 0x00000088, 0x00000000, 0x73616c46,
0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49,
0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x46766e49,
0x6873616c, 0x6c615000, 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d,
0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x44334420,
0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e,
0x2e393737, 0x30303030, 0xababab00, 0x0200001f, 0x80000000, 0xb0030000,
0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801,
0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x04000004, 0x80010000,
0x80000000, 0xa0000002, 0xa0550002, 0x03000042, 0x800f0000, 0x80e40000,
0xa0e40801, 0x02000001, 0x800f0001, 0xa0e40001, 0x04000004, 0x800f0000,
0x80e40000, 0x80e40001, 0xa0e40000, 0x02000001, 0x800f0800, 0x80e40000,
0x0000ffff
};
// A texture that doesn't look up colors from a palette.
@ -84,8 +127,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
float4 index = tex2D (Image, texCoord);
return Flash + index * InvFlash;
}
#endif
#if SHADER_ASSEMBLY_CODE
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
@ -131,6 +173,7 @@ const DWORD PlainShaderDef[] =
};
// A shader that just returns the value of c1
#if HLSL_SOURCE_CODE
float4 Color : register(c1);
@ -138,8 +181,7 @@ float4 main () : COLOR
{
return Color;
}
#endif
#if SHADER_ASSEMBLY_CODE
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//

View file

@ -1172,6 +1172,7 @@ void ST_Endoom()
{
KillTimer (Window, 0x5A15A);
}
ST_Util_FreeBitmap (StartupBitmap);
ST_Util_FreeFont (font);
exit (int(bRet == 0 ? mess.wParam : 0));
}

View file

@ -235,10 +235,10 @@ public:
void SetBlendingRect (int x1, int y1, int x2, int y2);
void Begin2D ();
FNativeTexture *CreateTexture (FTexture *gametex);
FNativeTexture *CreatePalette (FTexture *pal);
FNativeTexture *CreatePalette (FRemapTable *remap);
void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const;
void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const;
void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color);
void Dim (PalEntry color, float amount, int x1, int y1, int w, int h);
HRESULT GetHR ();
private:
@ -249,13 +249,27 @@ private:
bool CreateStencilPaletteTexture();
bool CreateShadedPaletteTexture();
bool CreateVertexes();
void DoOffByOneCheck();
void UploadPalette();
void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync);
bool UploadVertices();
bool Reset();
void Draw3DPart();
bool SetStyle(int style, fixed_t alpha, DWORD color, INTBOOL masked);
bool SetStyle(DCanvas::DrawParms &parms);
void SetColorOverlay(DWORD color, float alpha);
// State
void SetAlphaBlend(BOOL enabled, D3DBLEND srcblend=D3DBLEND(0), D3DBLEND destblend=D3DBLEND(0));
void SetConstant(int cnum, float r, float g, float b, float a);
void SetPixelShader(IDirect3DPixelShader9 *shader);
void SetTexture(int tnum, IDirect3DTexture9 *texture);
void SetPaletteTexture(IDirect3DTexture9 *texture, int count);
BOOL AlphaBlendEnabled;
D3DBLEND AlphaSrcBlend;
D3DBLEND AlphaDestBlend;
float Constant[3][4];
IDirect3DPixelShader9 *CurPixelShader;
IDirect3DTexture9 *Texture[2];
BYTE GammaTable[256];
PalEntry SourcePalette[256];
@ -270,11 +284,11 @@ private:
D3DFORMAT FBFormat;
D3DFORMAT PalFormat;
int FBWidth, FBHeight;
int OffByOneAt;
bool VSync;
RECT BlendingRect;
bool UseBlendingRect;
int In2D;
bool SM14;
IDirect3DDevice9 *D3DDevice;
IDirect3DVertexBuffer9 *VertexBuffer;
@ -287,6 +301,8 @@ private:
IDirect3DPixelShader9 *DimShader;
D3DFB() {}
friend class D3DPal;
};
#if 0

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Version="8.00"
Name="updaterevision"
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
RootNamespace="updaterevision"
@ -95,6 +95,82 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
@ -172,82 +248,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"