- 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) December 25, 2007 (Changes by Graf Zahl)
- added a P_PointInSector function and replaced all calls to retrieve an - 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 actor's sector in the game engine code with it. This way there's a clear
distinction between renderer-specific and game-specific calls. distinction between renderer-specific and game-specific calls.
- added UseInventory/UseActorInventory ACS functions. - 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) December 24, 2007 (Changes by Graf Zahl)
- added some functionality to FDynamicColormap to allow not creating - added some functionality to FDynamicColormap to allow not creating
the colormap data. the colormap data.
@ -65,6 +101,9 @@ December 23, 2007 (Changes by Graf Zahl)
- Fixed: UpdateTeam passed an FString to Printf. - Fixed: UpdateTeam passed an FString to Printf.
December 22, 2007 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 - 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 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 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_ClipLeft, f_x,
DTA_ClipRight, f_x + f_w, DTA_ClipRight, f_x + f_w,
DTA_FlipX, flip, DTA_FlipX, flip,
DTA_Translation, translation, DTA_Translation, TranslationToTable(translation),
DTA_Alpha, alpha, DTA_Alpha, alpha,
DTA_FillColor, alphacolor, DTA_FillColor, alphacolor,
DTA_RenderStyle, renderstyle, 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) CVAR (Bool, con_notablist, false, CVAR_ARCHIVE)
static int conback; static int conback;
static int conshade; static DWORD conshade;
static bool conline; static bool conline;
extern int gametic; extern int gametic;
@ -296,8 +296,8 @@ void C_InitConsole (int width, int height, bool ingame)
if (conback <= 0) if (conback <= 0)
{ {
conshade = DIM_MAP;
conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch); conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch);
conshade = MAKEARGB(80,0,0,0);
conline = true; conline = true;
} }
else else
@ -1137,7 +1137,7 @@ void C_DrawConsole ()
screen->DrawTexture (conpic, 0, visheight - screen->GetHeight(), screen->DrawTexture (conpic, 0, visheight - screen->GetHeight(),
DTA_DestWidth, screen->GetWidth(), DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(), DTA_DestHeight, screen->GetHeight(),
DTA_Translation, conshade, DTA_ColorOverlay, conshade,
DTA_Masked, false, DTA_Masked, false,
TAG_DONE); TAG_DONE);
if (conline && visheight < screen->GetHeight()) 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 // Draw current display, possibly wiping it from the previous
// //
//========================================================================== //==========================================================================
CVAR(Bool,test2d,true,0) CVAR(Bool,test2d,false,0)
void D_Display (bool screenshot) void D_Display (bool screenshot)
{ {
bool wipe; bool wipe;
@ -601,7 +601,10 @@ void D_Display (bool screenshot)
break; break;
} }
} }
//screen->Begin2D(); if (!screenshot && (!wipe || NoWipe) && test2d)
{
screen->Begin2D();
}
// draw pause pic // draw pause pic
if (paused && menuactive == MENU_Off) if (paused && menuactive == MENU_Off)
{ {
@ -638,21 +641,6 @@ void D_Display (bool screenshot)
FStat::PrintStat (); FStat::PrintStat ();
if (!screenshot) 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 screen->Update (); // page flip or blit buffer
} }
} }

View File

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

View File

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

View File

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

View File

@ -367,7 +367,7 @@ private:
healthPos = clamp (HealthMarker, 0, 100); healthPos = clamp (HealthMarker, 0, 100);
DrawImage (ClassImages[lifeClass][imgCHAIN], 35+((healthPos*196/100)%9), 31); DrawImage (ClassImages[lifeClass][imgCHAIN], 35+((healthPos*196/100)%9), 31);
DrawImage (ClassImages[lifeClass][imgLIFEGEM], 7+(healthPos*11/5), 31, multiplayer ? 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[imgLFEDGE], 0, 31);
DrawImage (Images[imgRTEDGE], 277, 31); DrawImage (Images[imgRTEDGE], 277, 31);
} }
@ -403,7 +403,7 @@ private:
DrawImage (Images[imgARTICLEAR], 144, -1); DrawImage (Images[imgARTICLEAR], 144, -1);
if (oldarti != NULL) 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) if (oldartiCount != 1)
{ {
DrSmallNumber (oldartiCount, 162, 23); DrSmallNumber (oldartiCount, 162, 23);
@ -713,7 +713,7 @@ private:
{ {
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i) 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) if (item->Amount != 1)
{ {
DrSmallNumber (item->Amount, 68+i*31, 23); DrSmallNumber (item->Amount, 68+i*31, 23);
@ -912,7 +912,7 @@ private:
TAG_DONE); TAG_DONE);
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -82, -31, screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -82, -31,
DTA_HUDRules, HUD_Normal, 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); TAG_DONE);
if (CPlayer->mo->InvSel->Amount != 1) if (CPlayer->mo->InvSel->Amount != 1)
{ {
@ -934,7 +934,7 @@ private:
TAG_DONE); TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -108+i*31, -33, screen->DrawTexture (TexMan(item->Icon), -108+i*31, -33,
DTA_HUDRules, HUD_HorizCenter, DTA_HUDRules, HUD_HorizCenter,
DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP, DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE); TAG_DONE);
if (item->Amount != 1) 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; arc << level.total_monsters << level.total_items << level.total_secrets;
// Does this level have custom translations? // Does this level have custom translations?
FRemapTable *trans;
if (arc.IsStoring ()) 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; int j;
for (j = 0; j < 256; ++j) for (j = 0; j < 256; ++j)
{ {
if (trans[j] != j) if (trans->Remap[j] != j)
{ {
break; break;
} }
@ -2704,7 +2705,13 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
{ {
t = i; t = i;
arc << t; 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; t = 255;
@ -2719,7 +2726,19 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
{ // hack hack to avoid crashing { // hack hack to avoid crashing
t = 0; 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; arc << t;
} }
} }

View File

@ -39,6 +39,7 @@
struct patch_t; struct patch_t;
class player_s; class player_s;
struct FRemapTable;
extern int SB_state; extern int SB_state;
@ -198,7 +199,8 @@ protected:
void DrawPowerups (); void DrawPowerups ();
void UpdateRect (int x, int y, int width, int height) const; 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 DrawFadedImage (FTexture *image, int x, int y, fixed_t shade) const;
void DrawPartialImage (FTexture *image, int wx, int ww) const; void DrawPartialImage (FTexture *image, int wx, int ww) const;

View File

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

View File

@ -408,18 +408,38 @@ void FBaseStatusBar::ShowPlayerName ()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FBaseStatusBar::DrawImage (FTexture *img, void FBaseStatusBar::DrawImage (FTexture *img,
int x, int y, int translation, FFont *font) const int x, int y, FRemapTable *translation) const
{ {
if (img != NULL) if (img != NULL)
{ {
screen->DrawTexture (img, x + ST_X, y + ST_Y, screen->DrawTexture (img, x + ST_X, y + ST_Y,
DTA_Font, font,
DTA_Translation, translation, DTA_Translation, translation,
DTA_320x200, Scaled, DTA_320x200, Scaled,
TAG_DONE); 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 // PROC DrawImage
@ -796,13 +816,11 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW, DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0, DTA_FillColor, 0,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); TAG_DONE);
screen->DrawTexture (pic, xpos - v/2, y, screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); TAG_DONE);
return; return;
} }
@ -823,8 +841,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW, DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0, DTA_FillColor, 0,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); TAG_DONE);
val /= 10; val /= 10;
xpos -= w; xpos -= w;
@ -838,8 +855,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size)
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Alpha, HR_SHADOW, DTA_Alpha, HR_SHADOW,
DTA_FillColor, 0, DTA_FillColor, 0,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); 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); pic = BigFont->GetChar ('0' + val % 10, &v);
screen->DrawTexture (pic, xpos - v/2, y, screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); TAG_DONE);
val /= 10; val /= 10;
xpos -= w; 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, screen->DrawTexture (pic, xpos - v/2, y,
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_Font, BigFont, DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED),
DTA_TranslationPtr, CR_UNTRANSLATED,
TAG_DONE); TAG_DONE);
} }
} }

View File

@ -438,7 +438,7 @@ private:
} }
if (item->Icon != 0) 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); DrINumber (item->Amount, 74 + 35*i, 23, imgFONY0);
} }
@ -512,7 +512,7 @@ private:
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -42, -17, screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -42, -17,
DTA_HUDRules, HUD_Normal, DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true, 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); TAG_DONE);
} }
} }
@ -536,7 +536,7 @@ private:
{ {
screen->DrawTexture (TexMan(item->Icon), -94 + i*35, -19, screen->DrawTexture (TexMan(item->Icon), -94 + i*35, -19,
DTA_HUDRules, HUD_HorizCenter, 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); TAG_DONE);
} }
DrINumberOuter (item->Amount, -89 + i*35, -10, true, 7); DrINumberOuter (item->Amount, -89 + i*35, -10, true, 7);

View File

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

View File

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

View File

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

View File

@ -56,8 +56,6 @@ extern int ST_Y;
// and the total size == width*height*depth/8., // and the total size == width*height*depth/8.,
// //
extern BYTE decorate_translations[];
BYTE* viewimage; BYTE* viewimage;
extern "C" { extern "C" {
int viewwidth; int viewwidth;
@ -134,7 +132,8 @@ cycle_t DetailDoubleCycles;
int dc_fillcolor; int dc_fillcolor;
BYTE *dc_translation; 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 // R_InitTranslationTables
// Creates the translation tables to map the green color ramp to gray, // Creates the translation tables to map the green color ramp to gray,
@ -1417,132 +1543,118 @@ void tmvline4_addclamp ()
// //
void R_InitTranslationTables () 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; int i, j;
// Diminishing translucency tables for shaded actors. Not really // Each player gets two translations. Doom and Strife don't use the
// translation tables, but putting them here was convenient, particularly // extra ones, but Heretic and Hexen do. These are set up during
// since translationtables[0] would otherwise be wasted. // netgame arbitration and as-needed, so they just get to be identity
translationtables[0] = MainTranslationTables; // maps until then so they won't be invalid.
for (i = 0; i < MAXPLAYERS; ++i)
// Player translations, one for each player {
translationtables[TRANSLATION_Players] = PushIdentityTable(TRANSLATION_Players);
translationtables[0] + NUMCOLORMAPS*16*256; PushIdentityTable(TRANSLATION_PlayersExtra);
}
// Extra player translations, one for each player, unused by Doom // The menu player also gets a separate translation table
translationtables[TRANSLATION_PlayersExtra] = PushIdentityTable(TRANSLATION_Players);
translationtables[TRANSLATION_Players] + (MAXPLAYERS+1)*256;
// The three standard translations from Doom or Heretic (seven for Strife), // The three standard translations from Doom or Heretic (seven for Strife),
// plus the generic ice translation. // plus the generic ice translation.
translationtables[TRANSLATION_Standard] = for (i = 0; i < 8; ++i)
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)
{ {
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); PushIdentityTable(TRANSLATION_PlayerCorpses);
memcpy (translationtables[TRANSLATION_PlayersExtra] + i*256, translationtables[0], 256);
} }
// Create the standard translation tables // 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) if (gameinfo.gametype == GAME_Doom)
{ {
for (i = 0x70; i < 0x80; i++) for (i = 0x70; i < 0x80; i++)
{ // map green ramp to gray, brown, red { // map green ramp to gray, brown, red
translationtables[TRANSLATION_Standard][i ] = 0x60 + (i&0xf); translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x60 + (i&0xf);
translationtables[TRANSLATION_Standard][i+256] = 0x40 + (i&0xf); translationtables[TRANSLATION_Standard][1]->Remap[i] = 0x40 + (i&0xf);
translationtables[TRANSLATION_Standard][i+512] = 0x20 + (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) else if (gameinfo.gametype == GAME_Heretic)
{ {
for (i = 225; i <= 240; i++) for (i = 225; i <= 240; i++)
{ {
translationtables[TRANSLATION_Standard][i ] = 114+(i-225); // yellow translationtables[TRANSLATION_Standard][0]->Remap[i] = 114+(i-225); // yellow
translationtables[TRANSLATION_Standard][i+256] = 145+(i-225); // red translationtables[TRANSLATION_Standard][1]->Remap[i] = 145+(i-225); // red
translationtables[TRANSLATION_Standard][i+512] = 190+(i-225); // blue 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) else if (gameinfo.gametype == GAME_Strife)
{ {
for (i = 0x20; i <= 0x3F; ++i) for (i = 0x20; i <= 0x3F; ++i)
{ {
translationtables[TRANSLATION_Standard][i ] = i - 0x20; translationtables[TRANSLATION_Standard][0]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][i+1*256] = i - 0x20; translationtables[TRANSLATION_Standard][1]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][i+2*256] = 0xD0 + (i&0xf); translationtables[TRANSLATION_Standard][2]->Remap[i] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+3*256] = 0xD0 + (i&0xf); translationtables[TRANSLATION_Standard][3]->Remap[i] = 0xD0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+4*256] = i - 0x20; translationtables[TRANSLATION_Standard][4]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][i+5*256] = i - 0x20; translationtables[TRANSLATION_Standard][5]->Remap[i] = i - 0x20;
translationtables[TRANSLATION_Standard][i+6*256] = i - 0x20; translationtables[TRANSLATION_Standard][6]->Remap[i] = i - 0x20;
} }
for (i = 0x50; i <= 0x5F; ++i) for (i = 0x50; i <= 0x5F; ++i)
{ {
// Merchant hair // Merchant hair
translationtables[TRANSLATION_Standard][i+4*256] = 0x80 + (i&0xf); translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x80 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x10 + (i&0xf); translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x10 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = 0x40 + (i&0xf); translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x40 + (i&0xf);
} }
for (i = 0x80; i <= 0x8F; ++i) for (i = 0x80; i <= 0x8F; ++i)
{ {
translationtables[TRANSLATION_Standard][i ] = 0x40 + (i&0xf); // red translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x40 + (i&0xf); // red
translationtables[TRANSLATION_Standard][i+1*256] = 0xB0 + (i&0xf); // rust translationtables[TRANSLATION_Standard][1]->Remap[i] = 0xB0 + (i&0xf); // rust
translationtables[TRANSLATION_Standard][i+2*256] = 0x10 + (i&0xf); // gray translationtables[TRANSLATION_Standard][2]->Remap[i] = 0x10 + (i&0xf); // gray
translationtables[TRANSLATION_Standard][i+3*256] = 0x30 + (i&0xf); // dark green translationtables[TRANSLATION_Standard][3]->Remap[i] = 0x30 + (i&0xf); // dark green
translationtables[TRANSLATION_Standard][i+4*256] = 0x50 + (i&0xf); // gold translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x50 + (i&0xf); // gold
translationtables[TRANSLATION_Standard][i+5*256] = 0x60 + (i&0xf); // bright green translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x60 + (i&0xf); // bright green
translationtables[TRANSLATION_Standard][i+6*256] = 0x90 + (i&0xf); // blue translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x90 + (i&0xf); // blue
} }
for (i = 0xC0; i <= 0xCF; ++i) for (i = 0xC0; i <= 0xCF; ++i)
{ {
translationtables[TRANSLATION_Standard][i+4*256] = 0xA0 + (i&0xf); translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xA0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x20 + (i&0xf); translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x20 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = (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) for (i = 0xD0; i <= 0xDF; ++i)
{ {
translationtables[TRANSLATION_Standard][i+4*256] = 0xB0 + (i&0xf); translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xB0 + (i&0xf);
translationtables[TRANSLATION_Standard][i+5*256] = 0x30 + (i&0xf); translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x30 + (i&0xf);
translationtables[TRANSLATION_Standard][i+6*256] = 0x10 + (i&0xf); translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x10 + (i&0xf);
} }
for (i = 0xF1; i <= 0xF6; ++i) 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) 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]); 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) for (i = 0; i < 256; ++i)
{ {
int r = GPalette.BaseColors[i].r; int r = GPalette.BaseColors[i].r;
int g = GPalette.BaseColors[i].g; int g = GPalette.BaseColors[i].g;
int b = GPalette.BaseColors[i].b; int b = GPalette.BaseColors[i].b;
int v = (r*77 + g*143 + b*37) >> 12; 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 // set up shading tables for shaded columns
// 16 colormap sets, progressing from full alpha to minimum visible alpha // 16 colormap sets, progressing from full alpha to minimum visible alpha
BYTE *table = translationtables[TRANSLATION_Shaded]; BYTE *table = shadetables;
// Full alpha // Full alpha
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
@ -1602,32 +1716,35 @@ void R_InitTranslationTables ()
table += 256; table += 256;
} }
} }
}
// Dim map void R_DeinitTranslationTables()
{
for (int i = 0; i < NUM_TRANSLATION_TABLES; ++i)
{ {
BYTE *dim_map = translationtables[TRANSLATION_Dim]; for (unsigned int j = 0; j < translationtables[i].Size(); ++j)
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)
{ {
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. // [RH] Create a player's translation table based on a given mid-range color.
// [GRB] Split to 2 functions (because of player setup menu) // [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; int i;
BYTE start = skin->range0start; BYTE start = skin->range0start;
@ -1643,19 +1760,24 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
// the current one. // the current one.
if (skin->othergame) if (skin->othergame)
{ {
memcpy (table, OtherGameSkinRemap, 256); memcpy (table->Remap, OtherGameSkinRemap, 256);
memcpy (table->Palette, OtherGameSkinPalette, sizeof(table->Palette));
} }
else else
{ {
for (i = 0; i < 256; ++i) 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) // [GRB] Don't translate skins with color range 0-0 (APlayerPawn default)
if (start == 0 && end == 0) if (start == 0 && end == 0)
{
table->UpdateNative();
return; return;
}
range = (float)(end-start+1); 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); uses = clamp (s, 0.f, 1.f);
usev = clamp (v, 0.f, 1.f); usev = clamp (v, 0.f, 1.f);
HSVtoRGB (&r, &g, &b, h, uses, usev); HSVtoRGB (&r, &g, &b, h, uses, usev);
table[i] = ColorMatcher.Pick ( SetRemap(table, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
s += sdelta; s += sdelta;
v += vdelta; 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 = vdelta * (float)(i - start) + basev - 0.2352937f;
v = clamp (v, 0.f, 1.f); v = clamp (v, 0.f, 1.f);
HSVtoRGB (&r, &g, &b, h, s, v); HSVtoRGB (&r, &g, &b, h, s, v);
table[i] = ColorMatcher.Pick ( SetRemap(table, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
} }
// Build rain/lifegem translation // 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)); s = MIN (bases, 0.8965f - 0.0962f*(float)(i - 161));
v = MIN (1.f, (0.2102f + 0.0489f*(float)(i - 144)) * basev); v = MIN (1.f, (0.2102f + 0.0489f*(float)(i - 144)) * basev);
HSVtoRGB (&r, &g, &b, h, s, v); HSVtoRGB (&r, &g, &b, h, s, v);
alttable[i] = ColorMatcher.Pick ( SetRemap(alttable, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
} }
alttable->UpdateNative();
} }
} }
else if (gameinfo.gametype == GAME_Hexen) 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++) for (i = start; i <= end; i++)
{ {
HSVtoRGB (&r, &g, &b, h, s, vs[(i-start)*9/(int)range]*basev); HSVtoRGB (&r, &g, &b, h, s, vs[(i-start)*9/(int)range]*basev);
table[i] = ColorMatcher.Pick ( SetRemap(table, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
} }
} }
else else
@ -1748,10 +1859,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
for (i = start; i <= end; i++) 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); HSVtoRGB (&r, &g, &b, h, ms[(i-start)*18/(int)range]*bases, mv[(i-start)*18/(int)range]*basev);
table[i] = ColorMatcher.Pick ( SetRemap(table, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
} }
} }
@ -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); 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); HSVtoRGB (&r, &g, &b, h, s*bases, v*basev);
alttable[i] = ColorMatcher.Pick ( SetRemap(alttable, i, r, g, b);
clamp ((int)(r * 255.f), 0, 255),
clamp ((int)(g * 255.f), 0, 255),
clamp ((int)(b * 255.f), 0, 255));
} }
alttable->UpdateNative();
} }
} }
table->UpdateNative();
} }
void R_BuildPlayerTranslation (int player) void R_BuildPlayerTranslation (int player)
@ -1782,11 +1889,11 @@ void R_BuildPlayerTranslation (int player)
R_CreatePlayerTranslation (h, s, v, R_CreatePlayerTranslation (h, s, v,
&skins[players[player].userinfo.skin], &skins[players[player].userinfo.skin],
&translationtables[TRANSLATION_Players][player*256], translationtables[TRANSLATION_Players][player],
&translationtables[TRANSLATION_PlayersExtra][player*256]); 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; 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); alpha = clamp<fixed_t> (alpha, 0, FRACUNIT);
dc_translation = NULL;
if (translation != 0) if (translation != 0)
{ {
dc_translation = translationtables[(translation&0xff00)>>8] FRemapTable *table = TranslationToTable(translation);
+ (translation&0x00ff)*256; if (table != NULL)
} {
else dc_translation = table->Remap;
{ }
dc_translation = NULL;
} }
basecolormapsave = basecolormap; basecolormapsave = basecolormap;
stencilling = false; stencilling = false;
@ -2169,7 +2276,7 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col
hcolfunc_post1 = rt_shaded1col; hcolfunc_post1 = rt_shaded1col;
hcolfunc_post4 = rt_shaded4cols; hcolfunc_post4 = rt_shaded4cols;
dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap[APART(color)]; 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) if (fixedlightlev)
{ {
dc_colormap += fixedlightlev; dc_colormap += fixedlightlev;

View File

@ -203,7 +203,7 @@ extern "C" int ds_color; // [RH] For flat color (no texturing)
enum enum
{ {
TRANSLATION_Shaded, TRANSLATION_Invalid,
TRANSLATION_Players, TRANSLATION_Players,
TRANSLATION_PlayersExtra, TRANSLATION_PlayersExtra,
TRANSLATION_Standard, TRANSLATION_Standard,
@ -217,8 +217,31 @@ enum
NUM_TRANSLATION_TABLES NUM_TRANSLATION_TABLES
}; };
extern BYTE* translationtables[NUM_TRANSLATION_TABLES]; struct FRemapTable
extern BYTE* dc_translation; {
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) inline WORD TRANSLATION(BYTE a, BYTE b)
{ {
@ -228,6 +251,8 @@ inline int GetTranslationType(WORD trans)
{ {
return trans >> 8; 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) #define DIM_MAP TRANSLATION(TRANSLATION_Dim, 0)
@ -245,9 +270,9 @@ inline void R_CopyTranslation (WORD to, WORD from)
void R_DetailDouble (void); void R_DetailDouble (void);
// Initialize color translation tables, // Initialize color translation tables, for player rendering etc.
// for player rendering etc.
void R_InitTranslationTables (void); void R_InitTranslationTables (void);
void R_DeinitTranslationTables();
// [RH] Actually create a player's translation table. // [RH] Actually create a player's translation table.
void R_BuildPlayerTranslation (int player); void R_BuildPlayerTranslation (int player);

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
** Draw patches and blocks to a canvas ** Draw patches and blocks to a canvas
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit ** Copyright 1998-2008 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** 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; DrawParms parms;
if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms)) if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms, false))
{ {
return; return;
} }
@ -88,23 +88,28 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
fixedcolormap = identitymap; fixedcolormap = identitymap;
ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor); 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.style != STYLE_Shaded)
{ {
if (parms.font != NULL) if (parms.translation != NULL)
{ {
if (img->UseType == FTexture::TEX_FontChar) dc_colormap = (lighttable_t *)parms.translation;
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;
} }
else else
{ {
dc_colormap = identitymap; dc_colormap = identitymap;
} }
} }
BYTE *destorgsave = dc_destorg; BYTE *destorgsave = dc_destorg;
@ -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; INTBOOL boolval;
int intval; int intval;
@ -280,8 +285,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->left = img->GetScaledLeftOffset(); parms->left = img->GetScaledLeftOffset();
parms->alpha = FRACUNIT; parms->alpha = FRACUNIT;
parms->fillcolor = -1; parms->fillcolor = -1;
parms->font = NULL; parms->remap = NULL;
parms->translation = 0; parms->translation = NULL;
parms->colorOverlay = 0;
parms->alphaChannel = false; parms->alphaChannel = false;
parms->flipX = false; parms->flipX = false;
parms->shadowAlpha = 0; 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); parms->fillcolor = va_arg (tags, int);
break; break;
case DTA_Font: case DTA_Translation:
parms->font = va_arg(tags, FFont*); parms->remap = va_arg (tags, FRemapTable *);
if (!translationset)
{
// default translation for fonts should be untranslated which unfortunately is not 0.
parms->translation = CR_UNTRANSLATED;
translationset = true;
}
break; break;
case DTA_Translation: case DTA_ColorOverlay:
parms->translation = va_arg(tags, int); parms->colorOverlay = va_arg (tags, DWORD);
translationset = true;
break; break;
case DTA_FlipX: case DTA_FlipX:
@ -560,6 +559,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
return false; return false;
} }
if (parms->remap != NULL)
{
parms->translation = parms->remap->Remap;
}
if (parms->style == STYLE_Count) if (parms->style == STYLE_Count)
{ {
if (parms->fillcolor != -1) if (parms->fillcolor != -1)

View File

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

View File

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

View File

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

View File

@ -102,6 +102,28 @@ IMPLEMENT_ABSTRACT_CLASS (DDummyFrameBuffer)
// try to generate a CreateNew() function. // try to generate a CreateNew() function.
IMPLEMENT_ABSTRACT_CLASS (DSimpleCanvas) 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; int DisplayWidth, DisplayHeight, DisplayBits;
FFont *SmallFont, *SmallFont2, *BigFont, *ConFont; 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 // [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; int x, y;
BYTE *dest; 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; PalEntry dimmer;
float amount = dimamount; float amount = dimamount;
@ -289,7 +311,7 @@ void DCanvas::Dim (PalEntry color) const
Dim (dimmer, amount, 0, 0, Width, Height); 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) if (damount == 0.f)
return; return;
@ -701,7 +723,6 @@ DFrameBuffer::DFrameBuffer (int width, int height)
void DFrameBuffer::DrawRateStuff () void DFrameBuffer::DrawRateStuff ()
{ {
// Draws frame time and cumulative fps // Draws frame time and cumulative fps
RateX = 0;
if (vid_fps) if (vid_fps)
{ {
DWORD ms = I_MSTime (); DWORD ms = I_MSTime ();
@ -710,12 +731,13 @@ void DFrameBuffer::DrawRateStuff ()
{ {
char fpsbuff[40]; char fpsbuff[40];
int chars; int chars;
int rate_x;
chars = sprintf (fpsbuff, "%2u ms (%3u fps)", howlong, LastCount); chars = sprintf (fpsbuff, "%2u ms (%3u fps)", howlong, LastCount);
RateX = Width - chars * 8; rate_x = Width - chars * 8;
Clear (RateX, 0, Width, 8, 0, 0); Clear (rate_x, 0, Width, 8, 0, 0);
SetFont (ConFont); 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); SetFont (SmallFont);
DWORD thisSec = ms/1000; DWORD thisSec = ms/1000;
@ -735,47 +757,114 @@ void DFrameBuffer::DrawRateStuff ()
{ {
int i = I_GetTime(false); int i = I_GetTime(false);
int tics = i - LastTic; int tics = i - LastTic;
BYTE *buffer = GetBuffer () + (GetHeight()-1)*GetPitch(); BYTE *buffer = GetBuffer();
LastTic = i; LastTic = i;
if (tics > 20) tics = 20; if (tics > 20) tics = 20;
for (i = 0; i < tics*2; i += 2) buffer[i] = 0xff; // Buffer can be NULL if we're doing hardware accelerated 2D
for ( ; i < 20*2; i += 2) buffer[i] = 0x00; 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 // draws the palette for debugging
if (vid_showpalette) 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(); palette.SetTranslation(vid_showpalette);
for (i = k = 0; i < 16; ++i) DrawTexture(&palette, 0, 0,
DTA_DestWidth, 16*7,
DTA_DestHeight, 16*7,
DTA_Masked, false,
TAG_DONE);
}
}
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)
{
WantTranslation = num;
}
}
void FPaletteTester::Unload()
{
}
const BYTE *FPaletteTester::GetColumn (unsigned int column, const Span **spans_out)
{
if (CurTranslation != WantTranslation)
{
MakeTexture();
}
column &= 15;
if (spans_out != NULL)
{
*spans_out = DummySpan;
}
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)
{ {
for (j = 0; j < 8; ++j) *p++ = (t > 1) ? translationtables[TRANSLATION_Standard][t - 2]->Remap[k] : k;
{
for (l = 0; l < 16; ++l)
{
int color;
if (vid_showpalette > 1 && vid_showpalette < 9)
{
color = translationtables[TRANSLATION_Standard][(vid_showpalette-2)*256+k];
}
else
{
color = k;
}
memset (buffer, color, 8);
buffer += 8;
k++;
}
k -= 16;
buffer += GetPitch() - 16*8;
}
k += 16; k += 16;
} }
k -= 255;
} }
CurTranslation = t;
} }
void DFrameBuffer::CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest) void DFrameBuffer::CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest)
@ -812,7 +901,7 @@ FNativeTexture *DFrameBuffer::CreateTexture(FTexture *gametex)
return NULL; return NULL;
} }
FNativeTexture *DFrameBuffer::CreatePalette(const PalEntry *pal) FNativeTexture *DFrameBuffer::CreatePalette(FRemapTable *remap)
{ {
return NULL; return NULL;
} }

View File

@ -76,9 +76,7 @@ enum
DTA_DestHeight, // height of area to draw to DTA_DestHeight, // height of area to draw to
DTA_Alpha, // alpha value for translucency DTA_Alpha, // alpha value for translucency
DTA_FillColor, // color to stencil onto the destination 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_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_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_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 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_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_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_RenderStyle, // same as render style for actors
DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image. Limited under software.
// For DrawText calls: // For DrawText calls:
DTA_TextLen, // stop after this many characters, even if \0 not hit 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; virtual void GetBlock (int x, int y, int width, int height, BYTE *dest) const;
// Dim the entire canvas for the menus // 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 // 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 // Fill an area with a texture
virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src); virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src);
// Set an area to a specified color // 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 // renders the player backdrop for the menu
virtual void DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y); virtual void DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y);
@ -218,8 +217,9 @@ protected:
int left; int left;
fixed_t alpha; fixed_t alpha;
int fillcolor; int fillcolor;
FFont *font; FRemapTable *remap;
int translation; const BYTE *translation;
DWORD colorOverlay;
INTBOOL alphaChannel; INTBOOL alphaChannel;
INTBOOL flipX; INTBOOL flipX;
fixed_t shadowAlpha; 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; 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); 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() {} DCanvas() {}
@ -327,8 +327,8 @@ public:
// Create a native texture from a game texture. // Create a native texture from a game texture.
virtual FNativeTexture *CreateTexture(FTexture *gametex); virtual FNativeTexture *CreateTexture(FTexture *gametex);
// Create a palette texture from a 256-entry palette. // Create a palette texture from a palette.
virtual FNativeTexture *CreatePalette(const PalEntry *pal); virtual FNativeTexture *CreatePalette(FRemapTable *remap);
// texture copy functions // texture copy functions
virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy, 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, bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y); const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y);
int RateX;
private: private:
DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; DWORD LastMS, LastSec, FrameCount, LastCount, LastTic;
}; };
@ -366,6 +363,7 @@ class FNativeTexture
{ {
public: public:
virtual ~FNativeTexture(); virtual ~FNativeTexture();
virtual bool Update() = 0;
}; };
extern FColorMatcher ColorMatcher; extern FColorMatcher ColorMatcher;

View File

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

View File

@ -3,7 +3,7 @@
** Code to let ZDoom use Direct3D 9 as a simple framebuffer ** Code to let ZDoom use Direct3D 9 as a simple framebuffer
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit ** Copyright 1998-2008 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -60,6 +60,7 @@
#include "v_pfx.h" #include "v_pfx.h"
#include "stats.h" #include "stats.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "r_draw.h"
#include "win32iface.h" #include "win32iface.h"
@ -102,6 +103,20 @@ public:
FTextureFormat ToTexFmt(D3DFORMAT fmt); 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 -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -152,7 +167,6 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
FBFormat = D3DFMT_UNKNOWN; FBFormat = D3DFMT_UNKNOWN;
PalFormat = D3DFMT_UNKNOWN; PalFormat = D3DFMT_UNKNOWN;
VSync = vid_vsync; VSync = vid_vsync;
OffByOneAt = -1;
BlendingRect.left = 0; BlendingRect.left = 0;
BlendingRect.top = 0; BlendingRect.top = 0;
BlendingRect.right = FBWidth; BlendingRect.right = FBWidth;
@ -216,6 +230,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
if (D3DDevice != NULL) if (D3DDevice != NULL)
{ {
CreateResources (); 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 (); I_RestoreWindowedPos ();
VidResizing = false; VidResizing = false;
} }
if (FAILED(D3DDevice->CreatePixelShader (PalTexShaderDef, &PalTexShader)) || SM14 = false;
FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) || 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))) FAILED(D3DDevice->CreatePixelShader (DimShaderDef, &DimShader)))
{ {
return false; return false;
} }
CurPixelShader = NULL;
memset(Constant, 0, sizeof(Constant));
if (!CreateFBTexture() || if (!CreateFBTexture() ||
!CreatePaletteTexture() || !CreatePaletteTexture() ||
!CreateStencilPaletteTexture() || !CreateStencilPaletteTexture() ||
@ -292,6 +319,7 @@ bool D3DFB::CreateResources ()
return false; return false;
} }
SetGamma (Gamma); SetGamma (Gamma);
return true; return true;
} }
@ -364,190 +392,9 @@ bool D3DFB::Reset ()
{ {
return false; 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; 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 () bool D3DFB::CreateFBTexture ()
{ {
if (FAILED(D3DDevice->CreateTexture (Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) 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) if (In2D == 2)
{ {
DrawRateStuff();
D3DDevice->EndScene(); D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL); D3DDevice->Present(NULL, NULL, NULL, NULL);
In2D = 0; In2D = 0;
@ -819,7 +667,7 @@ void D3DFB::Update ()
if (LockCount != 1) 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) if (LockCount > 0)
{ {
UpdatePending = true; UpdatePending = true;
@ -828,7 +676,10 @@ void D3DFB::Update ()
return; return;
} }
DrawRateStuff (); if (In2D == 0)
{
DrawRateStuff();
}
if (NeedGammaUpdate) if (NeedGammaUpdate)
{ {
@ -915,13 +766,13 @@ void D3DFB::Draw3DPart()
D3DDevice->Clear (2, rects, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.f, 0); D3DDevice->Clear (2, rects, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.f, 0);
} }
D3DDevice->BeginScene(); D3DDevice->BeginScene();
D3DDevice->SetTexture (0, FBTexture); SetTexture (0, FBTexture);
D3DDevice->SetTexture (1, PaletteTexture); SetPaletteTexture(PaletteTexture, 256);
D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX)); D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX));
D3DDevice->SetFVF (D3DFVF_FBVERTEX); D3DDevice->SetFVF (D3DFVF_FBVERTEX);
D3DDevice->SetPixelShader (PalTexShader);
D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2); D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2);
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); memcpy(Constant, FlashConstants, sizeof(FlashConstants));
SetAlphaBlend(FALSE);
if (!UseBlendingRect || FlashConstants[1][0] == 1) if (!UseBlendingRect || FlashConstants[1][0] == 1)
{ // The whole screen as a single quad. { // The whole screen as a single quad.
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2); D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
@ -933,32 +784,13 @@ void D3DFB::Draw3DPart()
// The rest is drawn unblended, so reset the shader constant. // The rest is drawn unblended, so reset the shader constant.
static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2); D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2);
memcpy(Constant, FlashZero, sizeof(FlashZero));
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top 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 () void D3DFB::UploadPalette ()
@ -966,18 +798,10 @@ void D3DFB::UploadPalette ()
D3DLOCKED_RECT lockrect; D3DLOCKED_RECT lockrect;
int i; int i;
if (OffByOneAt < 0)
{
DoOffByOneCheck ();
}
if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) 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; 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[0] = GammaTable[SourcePalette[i].b];
pix[1] = GammaTable[SourcePalette[i].g]; pix[1] = GammaTable[SourcePalette[i].g];
@ -985,22 +809,8 @@ void D3DFB::UploadPalette ()
pix[3] = (i == 0 ? 0 : 255); pix[3] = (i == 0 ? 0 : 255);
// To let masked textures work, the first palette entry's alpha is 0. // 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); 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 () PalEntry *D3DFB::GetPalette ()
@ -1145,8 +955,6 @@ bool D3DTex::Create(IDirect3DDevice9 *D3DDevice)
w = GameTex->GetWidth(); w = GameTex->GetWidth();
h = GameTex->GetHeight(); 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, hr = D3DDevice->CreateTexture(w, h, 1, 0,
GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL); GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL);
if (FAILED(hr)) 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 // D3DFB :: Begin2D
@ -1280,19 +1179,47 @@ void D3DFB::Begin2D()
In2D = 2; In2D = 2;
// Set default state for 2D rendering. // Set default state for 2D rendering.
float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
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);
} }
//==========================================================================
//
// D3DFB :: CreateTexture
//
// Returns a native texture that wraps a FTexture.
//
//==========================================================================
FNativeTexture *D3DFB::CreateTexture(FTexture *gametex) 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) 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]; 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 }; D3DRECT rect = { left, top, right, bottom };
D3DDevice->Clear(1, &rect, D3DCLEAR_TARGET, color | 0xFF000000, 1.f, 0); 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) if (amount <= 0)
return; 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+w-0.5f, y1+h-0.5f, 0.5f, 1, 0, 0 },
{ x1-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] = SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
{ SetPixelShader(DimShader);
RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, APART(color)/255.f, SetConstant(1, color.r/255.f, color.g/255.f, color.b/255.f, amount);
};
D3DDevice->SetPixelShader(DimShader);
D3DDevice->SetPixelShaderConstantF(1, constant, 1);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX)); 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; DrawParms parms;
if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms)) if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true))
{ {
return; 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 } { x0, y1, 0.5f, 1.f, u0, v1 }
}; };
if (!SetStyle(parms.style, parms.alpha, parms.fillcolor, parms.masked)) if (!SetStyle(parms))
{ {
return; return;
} }
D3DDevice->SetTexture(0, tex->Tex); SetTexture(0, tex->Tex);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX)); 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; D3DBLEND fglevel, bglevel;
float alpha; float alpha;
bool stencilling; 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) if (style == STYLE_OptFuzzy)
{ {
@ -1500,12 +1429,9 @@ bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked
case STYLE_Shaded: case STYLE_Shaded:
if (alpha > 0) if (alpha > 0)
{ {
float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha);
D3DDevice->SetPixelShaderConstantF(1, constant, 1); SetPaletteTexture(ShadedPaletteTexture, 256);
D3DDevice->SetTexture(1, ShadedPaletteTexture); SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
return true; return true;
} }
return false; 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 // Masking can only be turned off for STYLE_Normal, because it requires
// turning off the alpha blend. // 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 else
{ {
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); SetAlphaBlend(TRUE, fglevel, bglevel);
D3DDevice->SetRenderState(D3DRS_SRCBLEND, fglevel);
D3DDevice->SetRenderState(D3DRS_DESTBLEND, bglevel);
if (!stencilling) if (!stencilling)
{ {
float constant[4] = { 1,1,1,alpha }; if (parms.remap != NULL)
D3DDevice->SetPixelShaderConstantF(1, constant, 1); {
D3DDevice->SetTexture(1, PaletteTexture); D3DPal *pal = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize);
}
else
{
SetPaletteTexture(PaletteTexture, 256);
}
SetColorOverlay(parms.colorOverlay, alpha);
} }
else else
{ {
float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha);
D3DDevice->SetPixelShaderConstantF(1, constant, 1); SetPaletteTexture(StencilPaletteTexture, 256);
D3DDevice->SetTexture(1, StencilPaletteTexture);
} }
} }
return true; 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); sampler2D Palette : register(s1);
float4 Flash : register(c0); float4 Flash : register(c0);
float4 InvFlash : register(c1); float4 InvFlash : register(c1);
float4 PaletteMod : register(c2);
float4 main (float2 texCoord : TEXCOORD0) : COLOR float4 main (float2 texCoord : TEXCOORD0) : COLOR
{ {
float4 index = tex2D (Image, texCoord); float4 index = tex2D (Image, texCoord);
index.x = index.x * PaletteMod.x + PaletteMod.y;
float4 rgb = tex2D (Palette, index); float4 rgb = tex2D (Palette, index);
return Flash + rgb * InvFlash; return Flash + rgb * InvFlash;
} }
#endif #elif SHADER_ASSEMBLY_CODE
#if SHADER_ASSEMBLY_CODE
// //
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // 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: // Parameters:
@ -33,6 +34,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
// sampler2D Image; // sampler2D Image;
// float4 InvFlash; // float4 InvFlash;
// sampler2D Palette; // sampler2D Palette;
// float4 PaletteMod;
// //
// //
// Registers: // Registers:
@ -41,34 +43,75 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
// ------------ ----- ---- // ------------ ----- ----
// Flash c0 1 // Flash c0 1
// InvFlash c1 1 // InvFlash c1 1
// PaletteMod c2 1
// Image s0 1 // Image s0 1
// Palette s1 1 // Palette s1 1
// //
ps_1_4 ps_1_4
texld r0, t0 texld r0, t0
mad r0.x, r0.x, c2.x, c2.y
phase phase
texld r1, r0 texld r1, r0
mad r0, r1, c1, c0 mad r0, r1, c1, c0
// approximately 3 instruction slots used (2 texture, 1 arithmetic) // approximately 4 instruction slots used (2 texture, 2 arithmetic)
#endif #endif
const DWORD PalTexShaderDef[] = const DWORD PalTexShader14Def[] =
{ {
0xffff0104, 0x003bfffe, 0x42415443, 0x0000001c, 0x000000b4, 0xffff0104, 0xffff0104, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d3, 0xffff0104,
0x00000004, 0x0000001c, 0x00000100, 0x000000ad, 0x0000006c, 0x00000002, 0x00000005, 0x0000001c, 0x00000100, 0x000000cc, 0x00000080, 0x00000002,
0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00000003, 0x00000001, 0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00000003, 0x00000001,
0x0000008c, 0x00000000, 0x0000009c, 0x00010002, 0x00020001, 0x00000074, 0x000000a0, 0x00000000, 0x000000b0, 0x00010002, 0x00020001, 0x00000088,
0x00000000, 0x000000a5, 0x00010003, 0x00000001, 0x0000008c, 0x00000000, 0x00000000, 0x000000b9, 0x00010003, 0x00000001, 0x000000a0, 0x00000000,
0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x000000c1, 0x00020002, 0x00020001, 0x00000088, 0x00000000, 0x73616c46,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49,
0x46766e49, 0x6873616c, 0x6c615000, 0x65747465, 0x5f737000, 0x00345f31, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x46766e49,
0x7263694d, 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853, 0x6873616c, 0x6c615000, 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d,
0x43207265, 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e, 0x315f7370, 0x4d00345f, 0x6f726369, 0x74666f73, 0x29522820, 0x44334420,
0xabab0030, 0x00000042, 0x800f0000, 0xb0e40000, 0x0000fffd, 0x00000042, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e,
0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, 0xa0e40001, 0x2e393737, 0x30303030, 0xababab00, 0x00000042, 0x800f0000, 0xb0e40000,
0xa0e40000, 0x0000ffff 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. // 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); float4 index = tex2D (Image, texCoord);
return Flash + index * InvFlash; return Flash + index * InvFlash;
} }
#endif #elif SHADER_ASSEMBLY_CODE
#if SHADER_ASSEMBLY_CODE
// //
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // 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 // A shader that just returns the value of c1
#if HLSL_SOURCE_CODE #if HLSL_SOURCE_CODE
float4 Color : register(c1); float4 Color : register(c1);
@ -138,8 +181,7 @@ float4 main () : COLOR
{ {
return Color; return Color;
} }
#endif #elif SHADER_ASSEMBLY_CODE
#if SHADER_ASSEMBLY_CODE
// //
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
// //

View File

@ -1172,6 +1172,7 @@ void ST_Endoom()
{ {
KillTimer (Window, 0x5A15A); KillTimer (Window, 0x5A15A);
} }
ST_Util_FreeBitmap (StartupBitmap);
ST_Util_FreeFont (font); ST_Util_FreeFont (font);
exit (int(bRet == 0 ? mess.wParam : 0)); 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 SetBlendingRect (int x1, int y1, int x2, int y2);
void Begin2D (); void Begin2D ();
FNativeTexture *CreateTexture (FTexture *gametex); 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 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 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) const; void Dim (PalEntry color, float amount, int x1, int y1, int w, int h);
HRESULT GetHR (); HRESULT GetHR ();
private: private:
@ -249,13 +249,27 @@ private:
bool CreateStencilPaletteTexture(); bool CreateStencilPaletteTexture();
bool CreateShadedPaletteTexture(); bool CreateShadedPaletteTexture();
bool CreateVertexes(); bool CreateVertexes();
void DoOffByOneCheck();
void UploadPalette(); void UploadPalette();
void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync);
bool UploadVertices(); bool UploadVertices();
bool Reset(); bool Reset();
void Draw3DPart(); 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]; BYTE GammaTable[256];
PalEntry SourcePalette[256]; PalEntry SourcePalette[256];
@ -270,11 +284,11 @@ private:
D3DFORMAT FBFormat; D3DFORMAT FBFormat;
D3DFORMAT PalFormat; D3DFORMAT PalFormat;
int FBWidth, FBHeight; int FBWidth, FBHeight;
int OffByOneAt;
bool VSync; bool VSync;
RECT BlendingRect; RECT BlendingRect;
bool UseBlendingRect; bool UseBlendingRect;
int In2D; int In2D;
bool SM14;
IDirect3DDevice9 *D3DDevice; IDirect3DDevice9 *D3DDevice;
IDirect3DVertexBuffer9 *VertexBuffer; IDirect3DVertexBuffer9 *VertexBuffer;
@ -287,6 +301,8 @@ private:
IDirect3DPixelShader9 *DimShader; IDirect3DPixelShader9 *DimShader;
D3DFB() {} D3DFB() {}
friend class D3DPal;
}; };
#if 0 #if 0

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8,00" Version="8.00"
Name="updaterevision" Name="updaterevision"
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}" ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
RootNamespace="updaterevision" RootNamespace="updaterevision"
@ -95,6 +95,82 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </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 <Configuration
Name="Release|Win32" Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)" OutputDirectory="$(SolutionDir)$(ConfigurationName)"
@ -172,82 +248,6 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </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 <Configuration
Name="Release|x64" Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"