From 1acc3d00c4fb0bd637a49ff021966a66582bf638 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 26 Dec 2007 04:42:15 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 39 ++ src/am_map.cpp | 2 +- src/c_console.cpp | 6 +- src/d_main.cpp | 22 +- src/f_finale.cpp | 16 +- src/g_doom/doom_sbar.cpp | 16 +- src/g_heretic/heretic_sbar.cpp | 10 +- src/g_hexen/hexen_sbar.cpp | 10 +- src/g_level.cpp | 29 +- src/g_shared/sbar.h | 4 +- src/g_shared/sbarinfo.cpp | 17 +- src/g_shared/shared_sbar.cpp | 42 +- src/g_strife/strife_sbar.cpp | 6 +- src/m_menu.cpp | 12 +- src/p_acs.cpp | 23 +- src/p_setup.cpp | 18 +- src/r_draw.cpp | 383 ++++++++----- src/r_draw.h | 35 +- src/r_main.cpp | 1 + src/r_state.h | 1 + src/r_things.cpp | 2 + src/textures/texture.cpp | 4 + src/v_draw.cpp | 56 +- src/v_font.cpp | 101 ++-- src/v_font.h | 11 +- src/v_palette.h | 3 + src/v_text.cpp | 21 +- src/v_video.cpp | 161 ++++-- src/v_video.h | 24 +- src/wi_stuff.cpp | 9 +- src/win32/fb_d3d9.cpp | 598 +++++++++++---------- src/win32/fb_d3d9_shaders.h | 86 ++- src/win32/st_start.cpp | 1 + src/win32/win32iface.h | 28 +- tools/updaterevision/updaterevision.vcproj | 154 +++--- 35 files changed, 1157 insertions(+), 794 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b850157769..d2d01e37eb 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,9 +1,45 @@ +December 25, 2007 +- Discovered that Shader Model 1.4 clamps my constants, so I can't use + palettes smaller than 256 entries with the shader I wrote for it. Is there + a list of gotchas like this listed some where? I'd really like to see it. + + Well, when compiled with SM2.0, the PalTex shader seems to be every-so- + slightly faster on my GF7950GT than the SM1.4 version, so I guess it's a + minor win for cards that support it. + December 25, 2007 (Changes by Graf Zahl) - added a P_PointInSector function and replaced all calls to retrieve an actor's sector in the game engine code with it. This way there's a clear distinction between renderer-specific and game-specific calls. - added UseInventory/UseActorInventory ACS functions. +December 24, 2007 +- Fixed: ST_Endoom() failed to free the bitmap it used. +- Added the DTA_ColorOverlay attribute to blend a color with the texture + being drawn. For software, this (currently) only works with black. For + hardware, it works with any color. The motiviation for this was so I could + rewrite the status bar calls that passed DIM_MAP to DTA_Translation to + draw darker icons into something that didn't require making a whole new + remap table. +- After having an "OMG! How could I have been so stupid?" moment, I have + removed the off-by-one check from D3DFB. I had thought the off-by-one error + was caused by rounding errors by the shader hardware. Not so. Rather, I + wasn't sampling what I thought I was sampling. A texture that uses palette + index 255 passes the value 1.0 to the shader. The shader needs to adjust the + range of its palette indexes, or it will end up trying to read color 256 + from the palette texture when it should be reading color 255. Doh! +- The TranslationToTable() function has been added to map from translation + numbers used by actors to the tables those numbers represent. This function + performs validation for the input and returns NULL if the input value + is invalid. +- Major changes to the way translation tables work: No longer are they each a + 256-byte array. Instead, the FRemapTable structure is used to represent each + one. It includes a remap array for the software renderer, a palette array + for a hardware renderer, and a native texture pointer for D3DFB. The + translationtables array itself is now an array of TArrays that point to the + real tables. The DTA_Translation attribute must also be passed a pointer + to a FRemapTable, not a byte array as previously. + December 24, 2007 (Changes by Graf Zahl) - added some functionality to FDynamicColormap to allow not creating the colormap data. @@ -65,6 +101,9 @@ December 23, 2007 (Changes by Graf Zahl) - Fixed: UpdateTeam passed an FString to Printf. December 22, 2007 +- Modified DFrameBuffer::DrawRateStuff() so that it can do its thing properly + for D3DFB's 2D mode. Before, any fullscreen graphics (like help images) + covered it up. - Had a look at sbarinfo.cpp and noticed a few places where it allocated character arrays and never freed them. Those have been replaced with uses of FString. (One of these was even an instance of a member variable diff --git a/src/am_map.cpp b/src/am_map.cpp index 1acf8f4d3f..66fc2435cf 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1678,7 +1678,7 @@ static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust, DTA_ClipLeft, f_x, DTA_ClipRight, f_x + f_w, DTA_FlipX, flip, - DTA_Translation, translation, + DTA_Translation, TranslationToTable(translation), DTA_Alpha, alpha, DTA_FillColor, alphacolor, DTA_RenderStyle, renderstyle, diff --git a/src/c_console.cpp b/src/c_console.cpp index a3ef245c36..70a7507ade 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -80,7 +80,7 @@ static bool TabbedList; // True if tab list was shown CVAR (Bool, con_notablist, false, CVAR_ARCHIVE) static int conback; -static int conshade; +static DWORD conshade; static bool conline; extern int gametic; @@ -296,8 +296,8 @@ void C_InitConsole (int width, int height, bool ingame) if (conback <= 0) { - conshade = DIM_MAP; conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch); + conshade = MAKEARGB(80,0,0,0); conline = true; } else @@ -1137,7 +1137,7 @@ void C_DrawConsole () screen->DrawTexture (conpic, 0, visheight - screen->GetHeight(), DTA_DestWidth, screen->GetWidth(), DTA_DestHeight, screen->GetHeight(), - DTA_Translation, conshade, + DTA_ColorOverlay, conshade, DTA_Masked, false, TAG_DONE); if (conline && visheight < screen->GetHeight()) diff --git a/src/d_main.cpp b/src/d_main.cpp index 65b81234f4..3a418e8f5c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -437,7 +437,7 @@ CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY); // Draw current display, possibly wiping it from the previous // //========================================================================== -CVAR(Bool,test2d,true,0) +CVAR(Bool,test2d,false,0) void D_Display (bool screenshot) { bool wipe; @@ -601,7 +601,10 @@ void D_Display (bool screenshot) break; } } - //screen->Begin2D(); + if (!screenshot && (!wipe || NoWipe) && test2d) + { + screen->Begin2D(); + } // draw pause pic if (paused && menuactive == MENU_Off) { @@ -638,21 +641,6 @@ void D_Display (bool screenshot) FStat::PrintStat (); if (!screenshot) { -#if 0 - if (test2d) - screen->Begin2D(); - screen->DrawTexture(TexMan["M_HTIC"], 0, 0, - DTA_Clean, true, - TAG_DONE); - screen->DrawTexture(TexMan["XHAIRB3"], 200, 100, - DTA_DestWidth, 128, - DTA_DestHeight, 128, - DTA_Alpha, ((gametic & 31) + 1) << (16-5), -// DTA_RenderStyle, STYLE_Add, - DTA_FillColor, MAKEARGB(ColorMatcher.Pick(254,254,0),254,254,0), - DTA_AlphaChannel, true, - TAG_DONE); -#endif screen->Update (); // page flip or blit buffer } } diff --git a/src/f_finale.cpp b/src/f_finale.cpp index 4370a52a39..77873af680 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -377,6 +377,7 @@ void F_TextWrite (void) int c; int cx; int cy; + const FRemapTable *range; int leftmargin; int rowheight; bool scale; @@ -402,6 +403,7 @@ void F_TextWrite (void) ch = FinaleText.GetChars(); count = (FinaleCount - 10)/TEXTSPEED; + range = screen->Font->GetColorTranslation (CR_UNTRANSLATED); for ( ; count ; count-- ) { @@ -425,8 +427,7 @@ void F_TextWrite (void) screen->DrawTexture (pic, cx + 320 / 2, cy + 200 / 2, - DTA_Font, screen->Font, - DTA_Translation, CR_UNTRANSLATED, + DTA_Translation, range, DTA_Clean, true, TAG_DONE); } @@ -435,8 +436,7 @@ void F_TextWrite (void) screen->DrawTexture (pic, cx + 320 / 2, cy + 200 / 2, - DTA_Font, screen->Font, - DTA_Translation, CR_UNTRANSLATED, + DTA_Translation, range, TAG_DONE); } } @@ -522,7 +522,7 @@ static struct int castnum; int casttics; int castsprite; // [RH] For overriding the player sprite with a skin -int casttranslation; // [RH] Draw "our hero" with their chosen suit color +const FRemapTable *casttranslation; // [RH] Draw "our hero" with their chosen suit color FState* caststate; bool castdeath; int castframes; @@ -582,7 +582,7 @@ void F_StartCast (void) castnum = 0; caststate = castorder[castnum].info->SeeState; castsprite = caststate->sprite.index; - casttranslation = 0; + casttranslation = NULL; casttics = caststate->GetTics (); castdeath = false; FinaleStage = 3; @@ -632,12 +632,12 @@ void F_CastTicker (void) if (castnum == 16) { castsprite = skins[players[consoleplayer].userinfo.skin].sprite; - casttranslation = TRANSLATION(TRANSLATION_Players, consoleplayer); + casttranslation = translationtables[TRANSLATION_Players][consoleplayer]; } else { castsprite = caststate->sprite.index; - casttranslation = 0; + casttranslation = NULL; } castframes = 0; } diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp index e66fe6e828..64b4174894 100644 --- a/src/g_doom/doom_sbar.cpp +++ b/src/g_doom/doom_sbar.cpp @@ -130,7 +130,7 @@ public: { // draw face background StatusBarTex.DrawToBar ("STFBANY", 143, 1, - translationtables[TRANSLATION_Players] + (CPlayer - players)*256); + translationtables[TRANSLATION_Players][int(CPlayer - players)]->Remap); } } @@ -147,7 +147,7 @@ public: { // draw face background StatusBarTex.DrawToBar ("STFBANY", 143, 1, - translationtables[TRANSLATION_Players] + (CPlayer - players)*256); + translationtables[TRANSLATION_Players][int(CPlayer - players)]->Remap); } bEvilGrin = false; } @@ -203,7 +203,7 @@ private: const BYTE *GetPixels (); void Unload (); ~FDoomStatusBarTexture (); - void DrawToBar (const char *name, int x, int y, BYTE *colormap_in = NULL); + void DrawToBar (const char *name, int x, int y, const BYTE *colormap_in = NULL); protected: void MakeTexture (); @@ -477,7 +477,7 @@ private: } else { - DrawImage (TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount <= 0); if (CPlayer->mo->InvSel->Amount != 1) { DrSmallNumber (CPlayer->mo->InvSel->Amount, 165, 24); @@ -563,7 +563,7 @@ private: for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i) { DrawImage (Images[imgARTIBOX], 50+i*31, 2); - DrawImage (TexMan(item->Icon), 50+i*31, 2, item->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0); if (item->Amount != 1) { DrSmallNumber (item->Amount, 66+i*31, 24); @@ -706,7 +706,7 @@ private: screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -14, ammotop - 1/*-24*/, DTA_HUDRules, HUD_Normal, DTA_CenterBottomOffset, true, - DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); DrBNumberOuter (CPlayer->mo->InvSel->Amount, -68, ammotop - 18/*-41*/); } @@ -725,7 +725,7 @@ private: TAG_DONE); screen->DrawTexture (TexMan(item->Icon), -105+i*31, -32, DTA_HUDRules, HUD_HorizCenter, - DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); if (item->Amount != 1) { @@ -1096,7 +1096,7 @@ void FDoomStatusBar::FDoomStatusBarTexture::MakeTexture () memcpy(Pixels, pix, Width*Height); } -void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, BYTE *colormap_in) +void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap_in) { FTexture *pic; BYTE colormap[256]; diff --git a/src/g_heretic/heretic_sbar.cpp b/src/g_heretic/heretic_sbar.cpp index 596e2daa13..05a93004e4 100644 --- a/src/g_heretic/heretic_sbar.cpp +++ b/src/g_heretic/heretic_sbar.cpp @@ -273,7 +273,7 @@ private: DrawImage (Images[imgCHAINBACK], 0, 32); DrawImage (Images[imgCHAIN], 2+(healthPos%17), chainY); DrawImage (Images[imgLIFEGEM], 17+healthPos, chainY, multiplayer ? - TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer-players)) : 0); + translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)] : NULL); DrawImage (Images[imgLTFACE], 0, 32); DrawImage (Images[imgRTFACE], 276, 32); screen->DrawTexture (&ChainShade, ST_X+19, ST_Y+32, @@ -324,7 +324,7 @@ private: DrawImage (Images[imgBLACKSQ], 180, 3); if (oldarti != NULL) { - DrawImage (TexMan(oldarti->Icon), 179, 2, oldarti->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(oldarti->Icon), 179, 2, oldarti->Amount <= 0); if (oldartiCount != 1) { DrSmallNumber (oldartiCount, 197, 24); @@ -483,7 +483,7 @@ private: { for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i) { - DrawImage (TexMan(item->Icon), 50+i*31, 2, item->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0); if (item->Amount != 1) { DrSmallNumber (item->Amount, 65+i*31, 24); @@ -638,7 +638,7 @@ private: TAG_DONE); screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -61, -31, DTA_HUDRules, HUD_Normal, - DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); if (CPlayer->mo->InvSel->Amount != 1) { @@ -660,7 +660,7 @@ private: TAG_DONE); screen->DrawTexture (TexMan(item->Icon), -100+i*31, -32, DTA_HUDRules, HUD_HorizCenter, - DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); if (item->Amount != 1) { diff --git a/src/g_hexen/hexen_sbar.cpp b/src/g_hexen/hexen_sbar.cpp index 397c9d02a2..c0e6fea9fc 100644 --- a/src/g_hexen/hexen_sbar.cpp +++ b/src/g_hexen/hexen_sbar.cpp @@ -367,7 +367,7 @@ private: healthPos = clamp (HealthMarker, 0, 100); DrawImage (ClassImages[lifeClass][imgCHAIN], 35+((healthPos*196/100)%9), 31); DrawImage (ClassImages[lifeClass][imgLIFEGEM], 7+(healthPos*11/5), 31, multiplayer ? - TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer-players)) : 0); + translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)] : NULL); DrawImage (Images[imgLFEDGE], 0, 31); DrawImage (Images[imgRTEDGE], 277, 31); } @@ -403,7 +403,7 @@ private: DrawImage (Images[imgARTICLEAR], 144, -1); if (oldarti != NULL) { - DrawImage (TexMan(oldarti->Icon), 143, 2, oldarti->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(oldarti->Icon), 143, 2, oldarti->Amount <= 0); if (oldartiCount != 1) { DrSmallNumber (oldartiCount, 162, 23); @@ -713,7 +713,7 @@ private: { for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i) { - DrawImage (TexMan(item->Icon), 50+i*31, 1, item->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(item->Icon), 50+i*31, 1, item->Amount <= 0); if (item->Amount != 1) { DrSmallNumber (item->Amount, 68+i*31, 23); @@ -912,7 +912,7 @@ private: TAG_DONE); screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -82, -31, DTA_HUDRules, HUD_Normal, - DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); if (CPlayer->mo->InvSel->Amount != 1) { @@ -934,7 +934,7 @@ private: TAG_DONE); screen->DrawTexture (TexMan(item->Icon), -108+i*31, -33, DTA_HUDRules, HUD_HorizCenter, - DTA_Translation, item->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); if (item->Amount != 1) { diff --git a/src/g_level.cpp b/src/g_level.cpp index 699bdc15e2..df3fc0b7a9 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2687,15 +2687,16 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) arc << level.total_monsters << level.total_items << level.total_secrets; // Does this level have custom translations? + FRemapTable *trans; if (arc.IsStoring ()) { - for (i = 0; i < MAX_ACS_TRANSLATIONS; ++i) + for (i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i) { - BYTE *trans = &translationtables[TRANSLATION_LevelScripted][i*256]; + trans = translationtables[TRANSLATION_LevelScripted][i]; int j; for (j = 0; j < 256; ++j) { - if (trans[j] != j) + if (trans->Remap[j] != j) { break; } @@ -2704,7 +2705,13 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) { t = i; arc << t; - arc.Write (trans, 256); + arc.Write (trans->Remap, 256); + for (j = 0; j < 256; ++j) + { + arc << trans->Palette[j].r + << trans->Palette[j].g + << trans->Palette[j].b; + } } } t = 255; @@ -2719,7 +2726,19 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) { // hack hack to avoid crashing t = 0; } - arc.Read (&translationtables[TRANSLATION_LevelScripted][t*256], 256); + trans = translationtables[TRANSLATION_LevelScripted].GetVal(t); + if (trans == NULL) + { + trans = new FRemapTable; + translationtables[TRANSLATION_LevelScripted].SetVal(t, trans); + } + arc.Read (trans->Remap, 256); + for (int j = 0; j < 256; ++j) + { + arc << trans->Palette[j].r + << trans->Palette[j].g + << trans->Palette[j].b; + } arc << t; } } diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index e80d474d16..1e845a4311 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -39,6 +39,7 @@ struct patch_t; class player_s; +struct FRemapTable; extern int SB_state; @@ -198,7 +199,8 @@ protected: void DrawPowerups (); void UpdateRect (int x, int y, int width, int height) const; - void DrawImage (FTexture *image, int x, int y, int translation=0, FFont *font=NULL) const; + void DrawImage (FTexture *image, int x, int y, FRemapTable *translation=NULL) const; + void DrawDimImage (FTexture *image, int x, int y, bool dimmed) const; void DrawFadedImage (FTexture *image, int x, int y, fixed_t shade) const; void DrawPartialImage (FTexture *image, int wx, int ww) const; diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 1d1752b115..eff8549cec 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1453,11 +1453,11 @@ private: { if((cmd.flags & DRAWSELECTEDINVENTORY_ARTIFLASH) && artiflash) { - DrawImage(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0); } else { - DrawImage(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0); } if(CPlayer->mo->InvSel->Amount != 1) { @@ -1696,7 +1696,7 @@ private: continue; } x += (character->LeftOffset+1); //ignore x offsets since we adapt to character size - DrawImage(character, x, y, translation, drawingFont); + DrawImage(character, x, y, drawingFont->GetColorTranslation(translation)); x += width + spacing - (character->LeftOffset+1); str++; } @@ -1852,7 +1852,7 @@ private: { DrawImage (Images[invBarOffset + imgARTIBOX], x+i*31, y); } - DrawImage (TexMan(item->Icon), x+i*31, y, item->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(item->Icon), x+i*31, y, item->Amount <= 0); if(item->Amount != 1) { DrawNumber(item->Amount, 3, counterx+i*31, countery, translation); @@ -1906,13 +1906,14 @@ private: DrawImage(chain, x+(offset%chainsize), y); } if(gem != NULL) - DrawImage(gem, x+padleft+offset, y, translate ? getTranslation() : 0); + DrawImage(gem, x+padleft+offset, y, translate ? getTranslation() : NULL); } - int getTranslation() + FRemapTable* getTranslation() { - if(gameinfo.gametype & GAME_Raven) return TRANSLATION(TRANSLATION_PlayersExtra, BYTE(CPlayer - players)); - else return TRANSLATION(TRANSLATION_Players, BYTE(CPlayer - players)); + if(gameinfo.gametype & GAME_Raven) + return translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)]; + return translationtables[TRANSLATION_Players][int(CPlayer - players)]; } FImageCollection Images; diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 841d7e047a..b24ad15ac3 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -408,18 +408,38 @@ void FBaseStatusBar::ShowPlayerName () //--------------------------------------------------------------------------- void FBaseStatusBar::DrawImage (FTexture *img, - int x, int y, int translation, FFont *font) const + int x, int y, FRemapTable *translation) const { if (img != NULL) { screen->DrawTexture (img, x + ST_X, y + ST_Y, - DTA_Font, font, DTA_Translation, translation, DTA_320x200, Scaled, TAG_DONE); } } +//--------------------------------------------------------------------------- +// +// PROC DrawImage +// +// Draws an optionally dimmed image with the status bar's upper-left corner +// as the origin. +// +//--------------------------------------------------------------------------- + +void FBaseStatusBar::DrawDimImage (FTexture *img, + int x, int y, bool dimmed) const +{ + if (img != NULL) + { + screen->DrawTexture (img, x + ST_X, y + ST_Y, + DTA_ColorOverlay, dimmed ? DIM_OVERLAY : 0, + DTA_320x200, Scaled, + TAG_DONE); + } +} + //--------------------------------------------------------------------------- // // PROC DrawImage @@ -796,13 +816,11 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) DTA_HUDRules, HUD_Normal, DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); screen->DrawTexture (pic, xpos - v/2, y, DTA_HUDRules, HUD_Normal, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); return; } @@ -823,8 +841,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) DTA_HUDRules, HUD_Normal, DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); val /= 10; xpos -= w; @@ -838,8 +855,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) DTA_HUDRules, HUD_Normal, DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); } } @@ -852,8 +868,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) pic = BigFont->GetChar ('0' + val % 10, &v); screen->DrawTexture (pic, xpos - v/2, y, DTA_HUDRules, HUD_Normal, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); val /= 10; xpos -= w; @@ -865,8 +880,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) { screen->DrawTexture (pic, xpos - v/2, y, DTA_HUDRules, HUD_Normal, - DTA_Font, BigFont, - DTA_TranslationPtr, CR_UNTRANSLATED, + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), TAG_DONE); } } diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 06ac615821..a6590f237b 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -438,7 +438,7 @@ private: } if (item->Icon != 0) { - DrawImage (TexMan(item->Icon), 48 + 35*i, 14, item->Amount > 0 ? NULL : DIM_MAP); + DrawDimImage (TexMan(item->Icon), 48 + 35*i, 14, item->Amount <= 0); } DrINumber (item->Amount, 74 + 35*i, 23, imgFONY0); } @@ -512,7 +512,7 @@ private: screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -42, -17, DTA_HUDRules, HUD_Normal, DTA_CenterBottomOffset, true, - DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); } } @@ -536,7 +536,7 @@ private: { screen->DrawTexture (TexMan(item->Icon), -94 + i*35, -19, DTA_HUDRules, HUD_HorizCenter, - DTA_Translation, CPlayer->mo->InvSel->Amount > 0 ? NULL : DIM_MAP, + DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, TAG_DONE); } DrINumberOuter (item->Amount, -89 + i*35, -10, true, 7); diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 08477b14de..dffa64b9e2 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -86,7 +86,7 @@ struct FSaveGameNode : public Node // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void M_DrawSlider (int x, int y, float min, float max, float cur); -void R_GetPlayerTranslation (int color, FPlayerSkin *skin, BYTE *table); +void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -1984,7 +1984,7 @@ void M_PlayerSetup (void) PlayerClass = &PlayerClasses[players[consoleplayer].CurrentPlayerClass]; } PlayerSkin = players[consoleplayer].userinfo.skin; - R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS); + R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState; PlayerTics = PlayerState->GetTics(); if (FireScreen == NULL) @@ -2019,7 +2019,7 @@ static void M_PlayerSetupTicker (void) PlayerSkin = R_FindSkin (skins[PlayerSkin].name, PlayerClass - &PlayerClasses[0]); R_GetPlayerTranslation (players[consoleplayer].userinfo.color, - &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS); + &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } if (PlayerState->GetTics () != -1 && PlayerState->GetNextState () != NULL) @@ -2133,7 +2133,7 @@ static void M_PlayerSetupDrawer () (PSetupDef.y + LINEHEIGHT*3 + 57 - 104)*CleanYfac + (SCREENHEIGHT/2), DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, Scale), DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, Scale), - DTA_Translation, TRANSLATION(TRANSLATION_Players, 0), + DTA_Translation, translationtables[TRANSLATION_Players][MAXPLAYERS], TAG_DONE); } } @@ -2410,7 +2410,7 @@ static void M_ChangeSkin (int choice) PlayerSkin = (PlayerSkin < (int)numskins - 1) ? PlayerSkin + 1 : 0; } while (!PlayerClass->CheckSkin (PlayerSkin)); - R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS); + R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); cvar_set ("skin", skins[PlayerSkin].name); } @@ -2534,7 +2534,7 @@ static void SendNewColor (int red, int green, int blue) sprintf (command, "color \"%02x %02x %02x\"", red, green, blue); C_DoCommand (command); - R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players] + 256 * MAXPLAYERS); + R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } static void M_SlidePlayerRed (int choice) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 19d50bc005..73ae1e90f8 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2324,7 +2324,7 @@ int DLevelScript::RunScript () DACSThinker *controller = DACSThinker::ActiveThinker; SDWORD *locals = localvars; ScriptFunction *activeFunction = NULL; - BYTE *translation = 0; + FRemapTable *translation = 0; int resultValue = 1; switch (state) @@ -4674,11 +4674,13 @@ int DLevelScript::RunScript () sp--; if (i >= 1 && i <= MAX_ACS_TRANSLATIONS) { - translation = &translationtables[TRANSLATION_LevelScripted][i*256-256]; - for (i = 0; i < 256; ++i) + translation = translationtables[TRANSLATION_LevelScripted].GetVal(i - 1); + if (translation == NULL) { - translation[i] = i; + translation = new FRemapTable; + translationtables[TRANSLATION_LevelScripted].SetVal(i - 1, translation); } + translation->MakeIdentity(); } } break; @@ -4703,14 +4705,16 @@ int DLevelScript::RunScript () } else if (start == end) { - translation[start] = pal1; + translation->Remap[start] = pal1; + translation->Palette[start] = GPalette.BaseColors[pal1]; break; } palcol = pal1 << FRACBITS; palstep = ((pal2 << FRACBITS) - palcol) / (end - start); for (int i = start; i <= end; palcol += palstep, ++i) { - translation[i] = palcol >> FRACBITS; + translation->Remap[i] = palcol >> FRACBITS; + translation->Palette[i] = GPalette.BaseColors[palcol >> FRACBITS]; } } break; @@ -4755,8 +4759,9 @@ int DLevelScript::RunScript () } if (start == end) { - translation[start] = ColorMatcher.Pick + translation->Remap[start] = ColorMatcher.Pick (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + translation->Palette[start] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); break; } rs /= (end - start); @@ -4764,8 +4769,9 @@ int DLevelScript::RunScript () bs /= (end - start); for (int i = start; i <= end; ++i) { - translation[i] = ColorMatcher.Pick + translation->Remap[i] = ColorMatcher.Pick (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + translation->Palette[i] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); r += rs; g += gs; b += bs; @@ -4776,6 +4782,7 @@ int DLevelScript::RunScript () case PCD_ENDTRANSLATION: // This might be useful for hardware rendering, but // for software it is superfluous. + translation->UpdateNative(); translation = NULL; break; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index e58f7036e9..8b5a03e4ed 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3406,16 +3406,18 @@ void P_SetupLevel (char *lumpname, int position) { players[i].mo = NULL; } - // [RH] Set default scripted translation colors - for (i = 0; i < 256; ++i) + // [RH] Clear any scripted translation colors the previous level may have set. + for (i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i) { - translationtables[TRANSLATION_LevelScripted][i] = i; - } - for (i = 1; i < MAX_ACS_TRANSLATIONS; ++i) - { - memcpy (&translationtables[TRANSLATION_LevelScripted][i*256], - translationtables[TRANSLATION_LevelScripted], 256); + FRemapTable *table = translationtables[TRANSLATION_LevelScripted][i]; + if (table != NULL) + { + delete table; + translationtables[TRANSLATION_LevelScripted][i] = NULL; + } } + translationtables[TRANSLATION_LevelScripted].Clear(); + // Initial height of PointOfView will be set by player think. players[consoleplayer].viewz = 1; diff --git a/src/r_draw.cpp b/src/r_draw.cpp index ca3fdaf5e9..3c24e0e756 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -56,8 +56,6 @@ extern int ST_Y; // and the total size == width*height*depth/8., // -extern BYTE decorate_translations[]; - BYTE* viewimage; extern "C" { int viewwidth; @@ -134,7 +132,8 @@ cycle_t DetailDoubleCycles; int dc_fillcolor; BYTE *dc_translation; -BYTE *translationtables[NUM_TRANSLATION_TABLES]; +TAutoGrowArray 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 *slots; + + if (type <= 0 || type >= NUM_TRANSLATION_TABLES) + { + return NULL; + } + slots = &translationtables[type]; + if (index >= slots->Size()) + { + return NULL; + } + return slots->operator[](index); +} + +static void PushIdentityTable(int slot) +{ + FRemapTable *table = new FRemapTable; + table->MakeIdentity(); + translationtables[slot].Push(table); +} + // // R_InitTranslationTables // Creates the translation tables to map the green color ramp to gray, @@ -1417,132 +1543,118 @@ void tmvline4_addclamp () // void R_InitTranslationTables () { - static BYTE MainTranslationTables[256* - (NUMCOLORMAPS*16 // Shaded - +MAXPLAYERS*2+1 // Players + PlayersExtra + Menu player - +8 // Standard (7 for Strife, 3 for the rest) - +MAX_ACS_TRANSLATIONS // LevelScripted - +BODYQUESIZE // PlayerCorpses - +1 - )]; int i, j; - // Diminishing translucency tables for shaded actors. Not really - // translation tables, but putting them here was convenient, particularly - // since translationtables[0] would otherwise be wasted. - translationtables[0] = MainTranslationTables; - - // Player translations, one for each player - translationtables[TRANSLATION_Players] = - translationtables[0] + NUMCOLORMAPS*16*256; - - // Extra player translations, one for each player, unused by Doom - translationtables[TRANSLATION_PlayersExtra] = - translationtables[TRANSLATION_Players] + (MAXPLAYERS+1)*256; + // Each player gets two translations. Doom and Strife don't use the + // extra ones, but Heretic and Hexen do. These are set up during + // netgame arbitration and as-needed, so they just get to be identity + // maps until then so they won't be invalid. + for (i = 0; i < MAXPLAYERS; ++i) + { + PushIdentityTable(TRANSLATION_Players); + PushIdentityTable(TRANSLATION_PlayersExtra); + } + // The menu player also gets a separate translation table + PushIdentityTable(TRANSLATION_Players); // The three standard translations from Doom or Heretic (seven for Strife), // plus the generic ice translation. - translationtables[TRANSLATION_Standard] = - translationtables[TRANSLATION_PlayersExtra] + MAXPLAYERS*256; - - translationtables[TRANSLATION_LevelScripted] = - translationtables[TRANSLATION_Standard] + 8*256; - - translationtables[TRANSLATION_PlayerCorpses] = - translationtables[TRANSLATION_LevelScripted] + MAX_ACS_TRANSLATIONS*256; - - translationtables[TRANSLATION_Dim] = - translationtables[TRANSLATION_PlayerCorpses] + BODYQUESIZE*256; - - translationtables[TRANSLATION_Decorate] = decorate_translations; - translationtables[TRANSLATION_Blood] = decorate_translations + MAX_DECORATE_TRANSLATIONS*256; - - - // [RH] Each player now gets their own translation table. These are set - // up during netgame arbitration and as-needed rather than in here. - - for (i = 0; i < 256; ++i) + for (i = 0; i < 8; ++i) { - translationtables[0][i] = i; + PushIdentityTable(TRANSLATION_Standard); } - for (i = 0; i < MAXPLAYERS; ++i) + + // Each player corpse has its own translation so they won't change + // color if the player who created them changes theirs. + for (i = 0; i < BODYQUESIZE; ++i) { - memcpy (translationtables[TRANSLATION_Players] + i*256, translationtables[0], 256); - memcpy (translationtables[TRANSLATION_PlayersExtra] + i*256, translationtables[0], 256); + PushIdentityTable(TRANSLATION_PlayerCorpses); } // Create the standard translation tables - for (i = 0; i < 7; ++i) - { - memcpy (translationtables[TRANSLATION_Standard] + i*256, translationtables[0], 256); - } if (gameinfo.gametype == GAME_Doom) { for (i = 0x70; i < 0x80; i++) { // map green ramp to gray, brown, red - translationtables[TRANSLATION_Standard][i ] = 0x60 + (i&0xf); - translationtables[TRANSLATION_Standard][i+256] = 0x40 + (i&0xf); - translationtables[TRANSLATION_Standard][i+512] = 0x20 + (i&0xf); + translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x60 + (i&0xf); + translationtables[TRANSLATION_Standard][1]->Remap[i] = 0x40 + (i&0xf); + translationtables[TRANSLATION_Standard][2]->Remap[i] = 0x20 + (i&0xf); + + translationtables[TRANSLATION_Standard][0]->Palette[i] = GPalette.BaseColors[0x60 + (i&0xf)]; + translationtables[TRANSLATION_Standard][1]->Palette[i] = GPalette.BaseColors[0x40 + (i&0xf)]; + translationtables[TRANSLATION_Standard][2]->Palette[i] = GPalette.BaseColors[0x20 + (i&0xf)]; } } else if (gameinfo.gametype == GAME_Heretic) { for (i = 225; i <= 240; i++) { - translationtables[TRANSLATION_Standard][i ] = 114+(i-225); // yellow - translationtables[TRANSLATION_Standard][i+256] = 145+(i-225); // red - translationtables[TRANSLATION_Standard][i+512] = 190+(i-225); // blue + translationtables[TRANSLATION_Standard][0]->Remap[i] = 114+(i-225); // yellow + translationtables[TRANSLATION_Standard][1]->Remap[i] = 145+(i-225); // red + translationtables[TRANSLATION_Standard][2]->Remap[i] = 190+(i-225); // blue + + translationtables[TRANSLATION_Standard][0]->Palette[i] = GPalette.BaseColors[114+(i-225)]; + translationtables[TRANSLATION_Standard][1]->Palette[i] = GPalette.BaseColors[145+(i-225)]; + translationtables[TRANSLATION_Standard][2]->Palette[i] = GPalette.BaseColors[190+(i-225)]; } } else if (gameinfo.gametype == GAME_Strife) { for (i = 0x20; i <= 0x3F; ++i) { - translationtables[TRANSLATION_Standard][i ] = i - 0x20; - translationtables[TRANSLATION_Standard][i+1*256] = i - 0x20; - translationtables[TRANSLATION_Standard][i+2*256] = 0xD0 + (i&0xf); - translationtables[TRANSLATION_Standard][i+3*256] = 0xD0 + (i&0xf); - translationtables[TRANSLATION_Standard][i+4*256] = i - 0x20; - translationtables[TRANSLATION_Standard][i+5*256] = i - 0x20; - translationtables[TRANSLATION_Standard][i+6*256] = i - 0x20; + translationtables[TRANSLATION_Standard][0]->Remap[i] = i - 0x20; + translationtables[TRANSLATION_Standard][1]->Remap[i] = i - 0x20; + translationtables[TRANSLATION_Standard][2]->Remap[i] = 0xD0 + (i&0xf); + translationtables[TRANSLATION_Standard][3]->Remap[i] = 0xD0 + (i&0xf); + translationtables[TRANSLATION_Standard][4]->Remap[i] = i - 0x20; + translationtables[TRANSLATION_Standard][5]->Remap[i] = i - 0x20; + translationtables[TRANSLATION_Standard][6]->Remap[i] = i - 0x20; } for (i = 0x50; i <= 0x5F; ++i) { // Merchant hair - translationtables[TRANSLATION_Standard][i+4*256] = 0x80 + (i&0xf); - translationtables[TRANSLATION_Standard][i+5*256] = 0x10 + (i&0xf); - translationtables[TRANSLATION_Standard][i+6*256] = 0x40 + (i&0xf); + translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x80 + (i&0xf); + translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x10 + (i&0xf); + translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x40 + (i&0xf); } for (i = 0x80; i <= 0x8F; ++i) { - translationtables[TRANSLATION_Standard][i ] = 0x40 + (i&0xf); // red - translationtables[TRANSLATION_Standard][i+1*256] = 0xB0 + (i&0xf); // rust - translationtables[TRANSLATION_Standard][i+2*256] = 0x10 + (i&0xf); // gray - translationtables[TRANSLATION_Standard][i+3*256] = 0x30 + (i&0xf); // dark green - translationtables[TRANSLATION_Standard][i+4*256] = 0x50 + (i&0xf); // gold - translationtables[TRANSLATION_Standard][i+5*256] = 0x60 + (i&0xf); // bright green - translationtables[TRANSLATION_Standard][i+6*256] = 0x90 + (i&0xf); // blue + translationtables[TRANSLATION_Standard][0]->Remap[i] = 0x40 + (i&0xf); // red + translationtables[TRANSLATION_Standard][1]->Remap[i] = 0xB0 + (i&0xf); // rust + translationtables[TRANSLATION_Standard][2]->Remap[i] = 0x10 + (i&0xf); // gray + translationtables[TRANSLATION_Standard][3]->Remap[i] = 0x30 + (i&0xf); // dark green + translationtables[TRANSLATION_Standard][4]->Remap[i] = 0x50 + (i&0xf); // gold + translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x60 + (i&0xf); // bright green + translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x90 + (i&0xf); // blue } for (i = 0xC0; i <= 0xCF; ++i) { - translationtables[TRANSLATION_Standard][i+4*256] = 0xA0 + (i&0xf); - translationtables[TRANSLATION_Standard][i+5*256] = 0x20 + (i&0xf); - translationtables[TRANSLATION_Standard][i+6*256] = (i&0xf); + translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xA0 + (i&0xf); + translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x20 + (i&0xf); + translationtables[TRANSLATION_Standard][6]->Remap[i] = (i&0xf); } - translationtables[TRANSLATION_Standard][0xC0+6*256] = 1; + translationtables[TRANSLATION_Standard][6]->Remap[0xC0] = 1; for (i = 0xD0; i <= 0xDF; ++i) { - translationtables[TRANSLATION_Standard][i+4*256] = 0xB0 + (i&0xf); - translationtables[TRANSLATION_Standard][i+5*256] = 0x30 + (i&0xf); - translationtables[TRANSLATION_Standard][i+6*256] = 0x10 + (i&0xf); + translationtables[TRANSLATION_Standard][4]->Remap[i] = 0xB0 + (i&0xf); + translationtables[TRANSLATION_Standard][5]->Remap[i] = 0x30 + (i&0xf); + translationtables[TRANSLATION_Standard][6]->Remap[i] = 0x10 + (i&0xf); } for (i = 0xF1; i <= 0xF6; ++i) { - translationtables[TRANSLATION_Standard][i ] = 0xDF + (i&0xf); + translationtables[TRANSLATION_Standard][0]->Remap[i] = 0xDF + (i&0xf); } for (i = 0xF7; i <= 0xFB; ++i) { - translationtables[TRANSLATION_Standard][i ] = i - 6; + translationtables[TRANSLATION_Standard][0]->Remap[i] = i - 6; + } + for (i = 0; i < 7; ++i) + { + for (int j = 0x20; j <= 0xFB; ++j) + { + translationtables[TRANSLATION_Standard][i]->Palette[j] = + GPalette.BaseColors[translationtables[TRANSLATION_Standard][i]->Remap[j]]; + } } } @@ -1574,19 +1686,21 @@ void R_InitTranslationTables () { IcePaletteRemap[i] = ColorMatcher.Pick (IcePalette[i][0], IcePalette[i][1], IcePalette[i][2]); } + FRemapTable *remap = translationtables[TRANSLATION_Standard][7]; for (i = 0; i < 256; ++i) { int r = GPalette.BaseColors[i].r; int g = GPalette.BaseColors[i].g; int b = GPalette.BaseColors[i].b; int v = (r*77 + g*143 + b*37) >> 12; - translationtables[TRANSLATION_Standard][7*256+i] = IcePaletteRemap[v]; + remap->Remap[i] = IcePaletteRemap[v]; + remap->Palette[i] = PalEntry(IcePalette[v][0], IcePalette[v][1], IcePalette[v][2]); } // set up shading tables for shaded columns // 16 colormap sets, progressing from full alpha to minimum visible alpha - BYTE *table = translationtables[TRANSLATION_Shaded]; + BYTE *table = shadetables; // Full alpha for (i = 0; i < 16; ++i) @@ -1602,32 +1716,35 @@ void R_InitTranslationTables () table += 256; } } +} - // Dim map +void R_DeinitTranslationTables() +{ + for (int i = 0; i < NUM_TRANSLATION_TABLES; ++i) { - BYTE *dim_map = translationtables[TRANSLATION_Dim]; - BYTE unremap[256]; - BYTE shadetmp[256]; - - FWadLump palookup = Wads.OpenLumpName ("COLORMAP"); - palookup.Seek (22*256, SEEK_CUR); - palookup.Read (shadetmp, 256); - memset (unremap, 0, 256); - for (i = 0; i < 256; ++i) + for (unsigned int j = 0; j < translationtables[i].Size(); ++j) { - unremap[GPalette.Remap[i]] = i; + if (translationtables[i][j] != NULL) + { + delete translationtables[i][j]; + translationtables[i][j] = NULL; + } } - for (i = 0; i < 256; ++i) - { - dim_map[i] = GPalette.Remap[shadetmp[unremap[i]]]; - } - dim_map[0] = GPalette.Remap[0]; } } // [RH] Create a player's translation table based on a given mid-range color. // [GRB] Split to 2 functions (because of player setup menu) -static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, BYTE *table, BYTE *alttable) +static void SetRemap(FRemapTable *table, int i, float r, float g, float b) +{ + int ir = clamp (int(r * 255.f), 0, 255); + int ig = clamp (int(g * 255.f), 0, 255); + int ib = clamp (int(b * 255.f), 0, 255); + table->Remap[i] = ColorMatcher.Pick (ir, ig, ib); + table->Palette[i] = PalEntry(ir, ig, ib); +} + +static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable) { int i; BYTE start = skin->range0start; @@ -1643,19 +1760,24 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s // the current one. if (skin->othergame) { - memcpy (table, OtherGameSkinRemap, 256); + memcpy (table->Remap, OtherGameSkinRemap, 256); + memcpy (table->Palette, OtherGameSkinPalette, sizeof(table->Palette)); } else { for (i = 0; i < 256; ++i) { - table[i] = i; + table->Remap[i] = i; } + memcpy(table->Palette, GPalette.BaseColors, sizeof(table->Palette)); } // [GRB] Don't translate skins with color range 0-0 (APlayerPawn default) if (start == 0 && end == 0) + { + table->UpdateNative(); return; + } range = (float)(end-start+1); @@ -1676,10 +1798,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s uses = clamp (s, 0.f, 1.f); usev = clamp (v, 0.f, 1.f); HSVtoRGB (&r, &g, &b, h, uses, usev); - table[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(table, i, r, g, b); s += sdelta; v += vdelta; } @@ -1694,10 +1813,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s v = vdelta * (float)(i - start) + basev - 0.2352937f; v = clamp (v, 0.f, 1.f); HSVtoRGB (&r, &g, &b, h, s, v); - table[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(table, i, r, g, b); } // Build rain/lifegem translation @@ -1710,11 +1826,9 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s s = MIN (bases, 0.8965f - 0.0962f*(float)(i - 161)); v = MIN (1.f, (0.2102f + 0.0489f*(float)(i - 144)) * basev); HSVtoRGB (&r, &g, &b, h, s, v); - alttable[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(alttable, i, r, g, b); } + alttable->UpdateNative(); } } else if (gameinfo.gametype == GAME_Hexen) @@ -1731,10 +1845,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s for (i = start; i <= end; i++) { HSVtoRGB (&r, &g, &b, h, s, vs[(i-start)*9/(int)range]*basev); - table[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(table, i, r, g, b); } } else @@ -1748,10 +1859,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s for (i = start; i <= end; i++) { HSVtoRGB (&r, &g, &b, h, ms[(i-start)*18/(int)range]*bases, mv[(i-start)*18/(int)range]*basev); - table[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(table, i, r, g, b); } } @@ -1765,13 +1873,12 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s RGBtoHSV (base->r/255.f, base->g/255.f, base->b/255.f, &dummy, &s, &v); HSVtoRGB (&r, &g, &b, h, s*bases, v*basev); - alttable[i] = ColorMatcher.Pick ( - clamp ((int)(r * 255.f), 0, 255), - clamp ((int)(g * 255.f), 0, 255), - clamp ((int)(b * 255.f), 0, 255)); + SetRemap(alttable, i, r, g, b); } + alttable->UpdateNative(); } } + table->UpdateNative(); } void R_BuildPlayerTranslation (int player) @@ -1782,11 +1889,11 @@ void R_BuildPlayerTranslation (int player) R_CreatePlayerTranslation (h, s, v, &skins[players[player].userinfo.skin], - &translationtables[TRANSLATION_Players][player*256], - &translationtables[TRANSLATION_PlayersExtra][player*256]); + translationtables[TRANSLATION_Players][player], + translationtables[TRANSLATION_PlayersExtra][player]); } -void R_GetPlayerTranslation (int color, FPlayerSkin *skin, BYTE *table) +void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table) { float h, s, v; @@ -2141,14 +2248,14 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col alpha = clamp (alpha, 0, FRACUNIT); + dc_translation = NULL; if (translation != 0) { - dc_translation = translationtables[(translation&0xff00)>>8] - + (translation&0x00ff)*256; - } - else - { - dc_translation = NULL; + FRemapTable *table = TranslationToTable(translation); + if (table != NULL) + { + dc_translation = table->Remap; + } } basecolormapsave = basecolormap; stencilling = false; @@ -2169,7 +2276,7 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col hcolfunc_post1 = rt_shaded1col; hcolfunc_post4 = rt_shaded4cols; dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap[APART(color)]; - dc_colormap = basecolormap = &translationtables[TRANSLATION_Shaded][((16-alpha)*NUMCOLORMAPS)*256]; + dc_colormap = basecolormap = &shadetables[((16-alpha)*NUMCOLORMAPS)*256]; if (fixedlightlev) { dc_colormap += fixedlightlev; diff --git a/src/r_draw.h b/src/r_draw.h index 0789dc855e..41a6360401 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -203,7 +203,7 @@ extern "C" int ds_color; // [RH] For flat color (no texturing) enum { - TRANSLATION_Shaded, + TRANSLATION_Invalid, TRANSLATION_Players, TRANSLATION_PlayersExtra, TRANSLATION_Standard, @@ -217,8 +217,31 @@ enum NUM_TRANSLATION_TABLES }; -extern BYTE* translationtables[NUM_TRANSLATION_TABLES]; -extern BYTE* dc_translation; +struct FRemapTable +{ + FRemapTable(int count=256); + FRemapTable(const FRemapTable &o); + ~FRemapTable(); + + FRemapTable &operator= (const FRemapTable &o); + void MakeIdentity(); + void KillNative(); + void UpdateNative(); + FNativeTexture *GetNative(); + + BYTE *Remap; // For the software renderer + PalEntry *Palette; // The ideal palette this maps to + FNativeTexture *Native; // The Palette stored in a HW texture + int NumEntries; // # of elements in this table (usually 256) + +private: + void Free(); + void Alloc(int count); +}; + +extern TAutoGrowArray translationtables[NUM_TRANSLATION_TABLES]; +extern BYTE shadetables[NUMCOLORMAPS*16*256]; +extern BYTE *dc_translation; inline WORD TRANSLATION(BYTE a, BYTE b) { @@ -228,6 +251,8 @@ inline int GetTranslationType(WORD trans) { return trans >> 8; } +// Retrieve the FRemapTable that an actor's translation value maps to. +FRemapTable *TranslationToTable(int translation); #define DIM_MAP TRANSLATION(TRANSLATION_Dim, 0) @@ -245,9 +270,9 @@ inline void R_CopyTranslation (WORD to, WORD from) void R_DetailDouble (void); -// Initialize color translation tables, -// for player rendering etc. +// Initialize color translation tables, for player rendering etc. void R_InitTranslationTables (void); +void R_DeinitTranslationTables(); // [RH] Actually create a player's translation table. void R_BuildPlayerTranslation (int player); diff --git a/src/r_main.cpp b/src/r_main.cpp index 1ef130790d..cdf21c1815 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -807,6 +807,7 @@ void R_Init () static void R_Shutdown () { R_DeinitParticles(); + R_DeinitTranslationTables(); R_DeinitPlanes(); R_DeinitData(); } diff --git a/src/r_state.h b/src/r_state.h index 535f4e7d37..c8544650cb 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -46,6 +46,7 @@ extern size_t numskins; // [RH] extern FPlayerSkin * skins; // [RH] extern BYTE OtherGameSkinRemap[256]; +extern PalEntry OtherGameSkinPalette[256]; // diff --git a/src/r_things.cpp b/src/r_things.cpp index 019b4ede2d..6d08c565a9 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -103,6 +103,7 @@ char* spritename; FPlayerSkin *skins; size_t numskins; BYTE OtherGameSkinRemap[256]; +PalEntry OtherGameSkinPalette[256]; // [RH] particle globals WORD NumParticles; @@ -834,6 +835,7 @@ static void R_CreateSkinTranslation (const char *palname) for (int i = 0; i < 256; ++i) { OtherGameSkinRemap[i] = ColorMatcher.Pick (otherPal[0], otherPal[1], otherPal[2]); + OtherGameSkinPalette[i] = PalEntry(otherPal[0], otherPal[1], otherPal[2]); otherPal += 3; } } diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 1535207b2c..6145fe33cb 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -408,6 +408,10 @@ FNativeTexture *FTexture::GetNative() { if (Native != NULL) { + if (CheckModified()) + { + Native->Update(); + } return Native; } Native = screen->CreateTexture(this); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 14b189c19b..b836174fb9 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -3,7 +3,7 @@ ** Draw patches and blocks to a canvas ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -71,7 +71,7 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v DrawParms parms; - if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms)) + if (!ParseDrawTextureTags(img, x, y, tag, tags, &parms, false)) { return; } @@ -88,23 +88,28 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v fixedcolormap = identitymap; ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor); + if (APART(parms.colorOverlay) != 0) + { + // In software, DTA_ColorOverlay only does black overlays. + // Maybe I will change this later, but right now white is the only + // color that is actually used for this parameter. + // Note that this is also overriding DTA_Translation in software. + if ((parms.colorOverlay & MAKEARGB(0,255,255,255)) == 0) + { + parms.translation = &NormalLight.Maps[(APART(parms.colorOverlay)*NUMCOLORMAPS/255)*256]; + } + } + if (parms.style != STYLE_Shaded) { - if (parms.font != NULL) + if (parms.translation != NULL) { - if (img->UseType == FTexture::TEX_FontChar) - dc_colormap = parms.font->GetColorTranslation (EColorRange(parms.translation)); - else - dc_colormap = identitymap; - } - else if (parms.translation != 0) - { - dc_colormap = translationtables[(parms.translation&0xff00)>>8] + (parms.translation&0x00ff)*256; + dc_colormap = (lighttable_t *)parms.translation; } else { dc_colormap = identitymap; - } + } } 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; int intval; @@ -280,8 +285,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->left = img->GetScaledLeftOffset(); parms->alpha = FRACUNIT; parms->fillcolor = -1; - parms->font = NULL; - parms->translation = 0; + parms->remap = NULL; + parms->translation = NULL; + parms->colorOverlay = 0; parms->alphaChannel = false; parms->flipX = false; parms->shadowAlpha = 0; @@ -406,19 +412,12 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->fillcolor = va_arg (tags, int); break; - case DTA_Font: - parms->font = va_arg(tags, FFont*); - if (!translationset) - { - // default translation for fonts should be untranslated which unfortunately is not 0. - parms->translation = CR_UNTRANSLATED; - translationset = true; - } + case DTA_Translation: + parms->remap = va_arg (tags, FRemapTable *); break; - case DTA_Translation: - parms->translation = va_arg(tags, int); - translationset = true; + case DTA_ColorOverlay: + parms->colorOverlay = va_arg (tags, DWORD); break; case DTA_FlipX: @@ -560,6 +559,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l return false; } + if (parms->remap != NULL) + { + parms->translation = parms->remap->Remap; + } + if (parms->style == STYLE_Count) { if (parms->fillcolor != -1) diff --git a/src/v_font.cpp b/src/v_font.cpp index 7e17521bf0..3dd4add188 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -3,7 +3,7 @@ ** Font management ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ #include "cmdlib.h" #include "sc_man.h" #include "hu_stuff.h" +#include "r_draw.h" // MACROS ------------------------------------------------------------------ @@ -263,8 +264,6 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, Chars = new CharData[count]; charlumps = new int[count]; PatchRemap = new BYTE[256]; - Ranges = NULL; - PalRanges = NULL; FirstChar = first; LastChar = first + count - 1; FontHeight = 0; @@ -334,7 +333,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, { SpaceWidth = 4; } - BuildTranslations (luminosity, identity, &TranslationParms[0][0]); + BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors); delete[] luminosity; delete[] charlumps; @@ -362,16 +361,6 @@ FFont::~FFont () delete[] Chars; Chars = NULL; } - if (Ranges) - { - delete[] Ranges; - Ranges = NULL; - } - if (PalRanges) - { - delete[] PalRanges; - PalRanges = NULL; - } if (PatchRemap) { delete[] PatchRemap; @@ -552,42 +541,40 @@ int FFont::SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *reverse // //========================================================================== -void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges) +void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, + const void *ranges, int total_colors) { int i, j; const TranslationParm *parmstart = (const TranslationParm *)ranges; - BYTE *range; - PalEntry *prange; - range = Ranges = new BYTE[NumTextColors * ActiveColors]; - // this is padded so that each palette can be treated as if it had 256 colors - prange = PalRanges = new PalEntry[NumTextColors * ActiveColors + 256]; + FRemapTable remap(total_colors); // Create different translations for different color ranges + Ranges.Clear(); for (i = 0; i < NumTextColors; i++) { if (i == CR_UNTRANSLATED) { if (identity != NULL) { - memcpy (range, identity, ActiveColors); + memcpy (remap.Remap, identity, ActiveColors); + for (j = 0; j < ActiveColors; ++j) + { + remap.Palette[j] = GPalette.BaseColors[identity[j]]; + } } else { - memcpy (range, Ranges, ActiveColors); + remap = Ranges[0]; } - for (j = 0; j < ActiveColors; j++) - { - *prange++ = GPalette.BaseColors[range[j]]; - } - range += ActiveColors; + Ranges.Push(remap); continue; } assert(parmstart->RangeStart >= 0); - *range++ = 0; - *prange++ = PalEntry(0); + remap.Remap[0] = 0; + remap.Palette[0] = 0; for (j = 1; j < ActiveColors; j++) { @@ -608,12 +595,13 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, c int r = ((parms->Start[0] << 8) + rangev * (parms->End[0] - parms->Start[0])) >> 8; // red int g = ((parms->Start[1] << 8) + rangev * (parms->End[1] - parms->Start[1])) >> 8; // green int b = ((parms->Start[2] << 8) + rangev * (parms->End[2] - parms->Start[2])) >> 8; // blue - r=clamp(r, 0, 255); - g=clamp(g, 0, 255); - b=clamp(b, 0, 255); - *range++ = ColorMatcher.Pick (r, g, b); - *prange++ = PalEntry(r, g, b); + r = clamp(r, 0, 255); + g = clamp(g, 0, 255); + b = clamp(b, 0, 255); + remap.Remap[j] = ColorMatcher.Pick(r, g, b); + remap.Palette[j] = PalEntry(255,r,g,b); } + Ranges.Push(remap); // Advance to the next color range. while (parmstart[1].RangeStart > parmstart[0].RangeEnd) @@ -630,25 +618,15 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, c // //========================================================================== -BYTE *FFont::GetColorTranslation (EColorRange range) const +FRemapTable *FFont::GetColorTranslation (EColorRange range) const { if (ActiveColors == 0) return NULL; else if (range >= NumTextColors) range = CR_UNTRANSLATED; - return Ranges + ActiveColors * range; + return &Ranges[range]; } -PalEntry *FFont::GetTranslatedPalette (EColorRange range) const -{ - if (ActiveColors == 0) - return NULL; - else if (range >= NumTextColors) - range = CR_UNTRANSLATED; - return PalRanges + ActiveColors * range; -} - - //========================================================================== // // FFont :: GetChar @@ -725,8 +703,6 @@ int FFont::GetCharWidth (int code) const FFont::FFont () { Chars = NULL; - Ranges = NULL; - PalRanges = NULL; PatchRemap = NULL; Name = NULL; } @@ -836,7 +812,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data) PatchRemap = new BYTE[256]; CheckFON1Chars (lump, data, luminosity); - BuildTranslations (luminosity, NULL, &TranslationParms[1][0]); + BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors); } //========================================================================== @@ -862,7 +838,6 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data) FirstChar = data[6]; LastChar = data[7]; ActiveColors = data[10]; - Ranges = NULL; count = LastChar - FirstChar + 1; Chars = new CharData[count]; @@ -948,7 +923,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data) } } - BuildTranslations (luminosity, identity, &TranslationParms[0][0]); + BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors); delete[] widths2; } @@ -1382,7 +1357,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis Chars = new CharData[count]; charlumps = new int[count]; PatchRemap = new BYTE[256]; - Ranges = NULL; FirstChar = first; LastChar = first + count - 1; FontHeight = 0; @@ -1463,31 +1437,20 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis SpaceWidth = 4; } - BuildTranslations (luminosity, identity, &TranslationParms[0][0]); + BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors); - // add the untranslated colors to the Ranges table + // add the untranslated colors to the Ranges tables if (ActiveColors < TotalColors) { - int factor = 1; - BYTE *oldranges = Ranges; - PalEntry *oldpranges = PalRanges; - - Ranges = new BYTE[NumTextColors * TotalColors]; // palette map + true color map + padding - PalRanges = new PalEntry[NumTextColors * TotalColors + 256]; // padded so that each palette can be treated as if it had 256 colors - for (i = 0; i < NumTextColors; i++) { - memcpy(&Ranges [i * TotalColors], &oldranges [i * ActiveColors], ActiveColors); - memcpy(&PalRanges[i * TotalColors], &oldpranges[i * ActiveColors], ActiveColors*sizeof(PalEntry)); - - for(j=ActiveColors;jRemap[j] = identity[j]; + remap->Palette[j] = GPalette.BaseColors[j]; } } - delete[] oldranges; - delete[] oldpranges; } ActiveColors = TotalColors; diff --git a/src/v_font.h b/src/v_font.h index f5c57a6c92..ee9a137124 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -2,7 +2,7 @@ ** v_font.h ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -39,6 +39,7 @@ class DCanvas; class FTexture; +struct FRemapTable; enum EColorRange { @@ -86,8 +87,7 @@ public: FTexture *GetChar (int code, int *const width) const; int GetCharWidth (int code) const; - BYTE *GetColorTranslation (EColorRange range) const; - PalEntry *GetTranslatedPalette (EColorRange range) const; + FRemapTable *GetColorTranslation (EColorRange range) const; int GetSpaceWidth () const { return SpaceWidth; } int GetHeight () const { return FontHeight; } int GetDefaultKerning () const { return GlobalKerning; } @@ -101,7 +101,7 @@ public: protected: FFont (); - void BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges); + void BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges, int total_colors); static int SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *identity, double **luminosity); @@ -114,8 +114,7 @@ protected: FTexture *Pic; } *Chars; int ActiveColors; - BYTE *Ranges; - PalEntry *PalRanges; + TArray Ranges; BYTE *PatchRemap; char *Name; diff --git a/src/v_palette.h b/src/v_palette.h index 146654ce1d..0ea60dd156 100644 --- a/src/v_palette.h +++ b/src/v_palette.h @@ -90,6 +90,9 @@ extern "C" { extern FDynamicColormap NormalLight; } +// The color overlay to use for depleted items +#define DIM_OVERLAY MAKEARGB(170,0,0,0) + extern int Near255; // A color near 255 in appearance, but not 255 int BestColor (const uint32 *pal, int r, int g, int b, int first=1, int num=255); diff --git a/src/v_text.cpp b/src/v_text.cpp index 7c69e33494..5d24b9b422 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -70,9 +70,10 @@ void STACK_ARGS DCanvas::DrawChar (int normalcolor, int x, int y, BYTE character if (NULL != (pic = Font->GetChar (character, &dummy))) { + const FRemapTable *range = Font->GetColorTranslation ((EColorRange)normalcolor); va_list taglist; va_start (taglist, character); - DrawTexture (pic, x, y, DTA_Font, Font, DTA_Translation, normalcolor, TAG_MORE, &taglist); + DrawTexture (pic, x, y, DTA_Translation, range, TAG_MORE, &taglist); va_end (taglist); } } @@ -95,13 +96,11 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st int cx; int cy; int boldcolor; - int range; + const FRemapTable *range; int height; int forcedwidth = 0; int scalex, scaley; int kerning; - FFont *Font = this->Font; - FTexture *pic; if (Font == NULL || string == NULL) @@ -111,7 +110,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st normalcolor = CR_UNTRANSLATED; boldcolor = normalcolor ? normalcolor - 1 : NumTextColors - 1; - range = normalcolor; + range = Font->GetColorTranslation ((EColorRange)normalcolor); height = Font->GetHeight () + 1; kerning = Font->GetDefaultKerning (); @@ -130,6 +129,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st { va_list *more_p; DWORD data; + void *ptrval; switch (tag) { @@ -158,12 +158,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st // Translation is specified explicitly by the text. case DTA_Translation: *(DWORD *)tags = TAG_IGNORE; - data = va_arg (tags, int); - break; - - case DTA_Font: - *(DWORD *)tags = TAG_IGNORE; - Font = va_arg (tags, FFont*); + ptrval = va_arg (tags, void*); break; case DTA_CleanNoMove: @@ -219,7 +214,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st EColorRange newcolor = V_ParseFontColor (ch, normalcolor, boldcolor); if (newcolor != CR_UNDEFINED) { - range = newcolor; + range = Font->GetColorTranslation (newcolor); } continue; } @@ -239,7 +234,6 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st { w = forcedwidth; DrawTexture (pic, cx, cy, - DTA_Font, Font, DTA_Translation, range, DTA_DestWidth, forcedwidth, DTA_DestHeight, height, @@ -248,7 +242,6 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st else { DrawTexture (pic, cx, cy, - DTA_Font, Font, DTA_Translation, range, TAG_MORE, &taglist); } diff --git a/src/v_video.cpp b/src/v_video.cpp index 199310c307..7a7b9297b1 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -102,6 +102,28 @@ IMPLEMENT_ABSTRACT_CLASS (DDummyFrameBuffer) // try to generate a CreateNew() function. IMPLEMENT_ABSTRACT_CLASS (DSimpleCanvas) +class FPaletteTester : public FTexture +{ +public: + FPaletteTester (); + + const BYTE *GetColumn(unsigned int column, const Span **spans_out); + const BYTE *GetPixels(); + void Unload(); + bool CheckModified(); + void SetTranslation(int num); + +protected: + BYTE Pixels[16*16]; + int CurTranslation; + int WantTranslation; + static const Span DummySpan[2]; + + void MakeTexture(); +}; + +const FTexture::Span FPaletteTester::DummySpan[2] = { { 0, 24 }, { 0, 0 } }; + int DisplayWidth, DisplayHeight, DisplayBits; FFont *SmallFont, *SmallFont2, *BigFont, *ConFont; @@ -226,7 +248,7 @@ void DCanvas::FlatFill (int left, int top, int right, int bottom, FTexture *src) // [RH] Set an area to a specified color -void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const +void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) { int x, y; BYTE *dest; @@ -267,7 +289,7 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin } } -void DCanvas::Dim (PalEntry color) const +void DCanvas::Dim (PalEntry color) { PalEntry dimmer; float amount = dimamount; @@ -289,7 +311,7 @@ void DCanvas::Dim (PalEntry color) const Dim (dimmer, amount, 0, 0, Width, Height); } -void DCanvas::Dim (PalEntry color, float damount, int x1, int y1, int w, int h) const +void DCanvas::Dim (PalEntry color, float damount, int x1, int y1, int w, int h) { if (damount == 0.f) return; @@ -701,7 +723,6 @@ DFrameBuffer::DFrameBuffer (int width, int height) void DFrameBuffer::DrawRateStuff () { // Draws frame time and cumulative fps - RateX = 0; if (vid_fps) { DWORD ms = I_MSTime (); @@ -710,12 +731,13 @@ void DFrameBuffer::DrawRateStuff () { char fpsbuff[40]; int chars; + int rate_x; chars = sprintf (fpsbuff, "%2u ms (%3u fps)", howlong, LastCount); - RateX = Width - chars * 8; - Clear (RateX, 0, Width, 8, 0, 0); + rate_x = Width - chars * 8; + Clear (rate_x, 0, Width, 8, 0, 0); SetFont (ConFont); - DrawText (CR_WHITE, RateX, 0, (char *)&fpsbuff[0], TAG_DONE); + DrawText (CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE); SetFont (SmallFont); DWORD thisSec = ms/1000; @@ -735,47 +757,114 @@ void DFrameBuffer::DrawRateStuff () { int i = I_GetTime(false); int tics = i - LastTic; - BYTE *buffer = GetBuffer () + (GetHeight()-1)*GetPitch(); + BYTE *buffer = GetBuffer(); LastTic = i; if (tics > 20) tics = 20; - - for (i = 0; i < tics*2; i += 2) buffer[i] = 0xff; - for ( ; i < 20*2; i += 2) buffer[i] = 0x00; + + // Buffer can be NULL if we're doing hardware accelerated 2D + if (buffer != NULL) + { + buffer += (GetHeight()-1)*GetPitch(); + + for (i = 0; i < tics*2; i += 2) buffer[i] = 0xff; + for ( ; i < 20*2; i += 2) buffer[i] = 0x00; + } + else + { + for (i = 0; i < tics*2; i += 2) Clear(i, Height-1, i+1, Height, 255, 0); + for ( ; i < 20*2; i += 2) Clear(i, Height-1, i+1, Height, 0, 0); + } } // draws the palette for debugging if (vid_showpalette) { - int i, j, k, l; + // This used to just write the palette to the display buffer. + // With hardware-accelerated 2D, that doesn't work anymore. + // Drawing it as a texture does and continues to show how + // well the PalTex shader is working. + static FPaletteTester palette; - BYTE *buffer = GetBuffer(); - for (i = k = 0; i < 16; ++i) + palette.SetTranslation(vid_showpalette); + 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) - { - 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; - } + *p++ = (t > 1) ? translationtables[TRANSLATION_Standard][t - 2]->Remap[k] : k; k += 16; } + k -= 255; } + CurTranslation = t; } void DFrameBuffer::CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest) @@ -812,7 +901,7 @@ FNativeTexture *DFrameBuffer::CreateTexture(FTexture *gametex) return NULL; } -FNativeTexture *DFrameBuffer::CreatePalette(const PalEntry *pal) +FNativeTexture *DFrameBuffer::CreatePalette(FRemapTable *remap) { return NULL; } diff --git a/src/v_video.h b/src/v_video.h index 302ba4f5c2..294ef598df 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -76,9 +76,7 @@ enum DTA_DestHeight, // height of area to draw to DTA_Alpha, // alpha value for translucency DTA_FillColor, // color to stencil onto the destination - DTA_Font, // For characters: Font it belongs to DTA_Translation, // translation table to recolor the source - DTA_TranslationPtr, // translation table to recolor the source DTA_AlphaChannel, // bool: the source is an alpha channel; used with DTA_FillColor DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen @@ -103,6 +101,7 @@ enum DTA_HUDRules, // use fullscreen HUD rules to position and size textures DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3 DTA_RenderStyle, // same as render style for actors + DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image. Limited under software. // For DrawText calls: DTA_TextLen, // stop after this many characters, even if \0 not hit @@ -156,16 +155,16 @@ public: virtual void GetBlock (int x, int y, int width, int height, BYTE *dest) const; // Dim the entire canvas for the menus - virtual void Dim (PalEntry color = 0) const; + virtual void Dim (PalEntry color = 0); // Dim part of the canvas - virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const; + virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); // Fill an area with a texture virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src); // Set an area to a specified color - virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const; + virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color); // renders the player backdrop for the menu virtual void DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y); @@ -218,8 +217,9 @@ protected: int left; fixed_t alpha; int fillcolor; - FFont *font; - int translation; + FRemapTable *remap; + const BYTE *translation; + DWORD colorOverlay; INTBOOL alphaChannel; INTBOOL flipX; fixed_t shadowAlpha; @@ -233,7 +233,7 @@ protected: bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); - bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms) const; + bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const; DCanvas() {} @@ -327,8 +327,8 @@ public: // Create a native texture from a game texture. virtual FNativeTexture *CreateTexture(FTexture *gametex); - // Create a palette texture from a 256-entry palette. - virtual FNativeTexture *CreatePalette(const PalEntry *pal); + // Create a palette texture from a palette. + virtual FNativeTexture *CreatePalette(FRemapTable *remap); // texture copy functions virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy, @@ -354,9 +354,6 @@ protected: bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y); - - int RateX; - private: DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; }; @@ -366,6 +363,7 @@ class FNativeTexture { public: virtual ~FNativeTexture(); + virtual bool Update() = 0; }; extern FColorMatcher ColorMatcher; diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 619b6bc6b0..09f301b92b 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -698,8 +698,7 @@ static void WI_DrawCharPatch (FTexture *patch, int x, int y) screen->DrawTexture (patch, x, y, DTA_Clean, true, DTA_ShadowAlpha, (gameinfo.gametype == GAME_Doom) ? 0 : FRACUNIT/2, - DTA_Font, BigFont, - DTA_Translation, CR_UNTRANSLATED, // otherwise it doesn't look good in Strife! + DTA_Translation, BigFont->GetColorTranslation (CR_UNTRANSLATED), // otherwise it doesn't look good in Strife! TAG_DONE); } } @@ -1584,13 +1583,13 @@ void WI_drawNetgameStats () x = NG_STATSX; // [RH] Only use one graphic for the face backgrounds screen->DrawTexture (p, x - p->GetWidth(), y, - DTA_Translation, TRANSLATION(TRANSLATION_Players, i), + DTA_Translation, translationtables[TRANSLATION_Players][i], DTA_Clean, true, TAG_DONE); if (i == me) screen->DrawTexture (star, x - p->GetWidth(), y, - DTA_Translation, TRANSLATION(TRANSLATION_Players, i), + DTA_Translation, translationtables[TRANSLATION_Players][i], DTA_Clean, true, TAG_DONE); @@ -1634,7 +1633,7 @@ void WI_drawNetgameStats () if (gameinfo.gametype == GAME_Heretic) { screen->DrawTexture (star, 25, y, - DTA_Translation, TRANSLATION(TRANSLATION_Players, i), + DTA_Translation, translationtables[TRANSLATION_Players][i], DTA_Clean, true, TAG_DONE); } diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 048143b427..12320c3d6d 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -3,7 +3,7 @@ ** Code to let ZDoom use Direct3D 9 as a simple framebuffer ** **--------------------------------------------------------------------------- -** Copyright 1998-2007 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -60,6 +60,7 @@ #include "v_pfx.h" #include "stats.h" #include "doomerrors.h" +#include "r_draw.h" #include "win32iface.h" @@ -102,6 +103,20 @@ public: FTextureFormat ToTexFmt(D3DFORMAT fmt); }; +class D3DPal : public FNativeTexture +{ +public: + D3DPal(FRemapTable *remap, D3DFB *fb); + ~D3DPal(); + + IDirect3DTexture9 *Tex; + + bool Update(); + + FRemapTable *Remap; + int RoundedPaletteSize; +}; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -152,7 +167,6 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) FBFormat = D3DFMT_UNKNOWN; PalFormat = D3DFMT_UNKNOWN; VSync = vid_vsync; - OffByOneAt = -1; BlendingRect.left = 0; BlendingRect.top = 0; BlendingRect.right = FBWidth; @@ -216,6 +230,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) if (D3DDevice != NULL) { CreateResources (); + + // Be sure we know what the alpha blend is + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + AlphaBlendEnabled = FALSE; + AlphaSrcBlend = D3DBLEND(0); + AlphaDestBlend = D3DBLEND(0); } } @@ -274,12 +294,19 @@ bool D3DFB::CreateResources () I_RestoreWindowedPos (); VidResizing = false; } - if (FAILED(D3DDevice->CreatePixelShader (PalTexShaderDef, &PalTexShader)) || - FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) || + SM14 = false; + if (FAILED(D3DDevice->CreatePixelShader (PalTexShader20Def, &PalTexShader)) && + (SM14 = true, FAILED(D3DDevice->CreatePixelShader (PalTexShader14Def, &PalTexShader)))) + { + return false; + } + if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) || FAILED(D3DDevice->CreatePixelShader (DimShaderDef, &DimShader))) { return false; } + CurPixelShader = NULL; + memset(Constant, 0, sizeof(Constant)); if (!CreateFBTexture() || !CreatePaletteTexture() || !CreateStencilPaletteTexture() || @@ -292,6 +319,7 @@ bool D3DFB::CreateResources () return false; } SetGamma (Gamma); + return true; } @@ -364,190 +392,9 @@ bool D3DFB::Reset () { return false; } - if (OffByOneAt < 256) - { - D3DDevice->SetSamplerState (1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); - D3DDevice->SetSamplerState (1, D3DSAMP_BORDERCOLOR, - D3DCOLOR_XRGB(GammaTable[SourcePalette[255].r], - GammaTable[SourcePalette[255].g], - GammaTable[SourcePalette[255].b])); - } return true; } -//========================================================================== -// -// DoOffByOneCheck -// -// NVidia hardware has an off-by-one error in the pixel shader. -// On a Geforce 7950GT and a 6200, I have witnessed it skip palette entry -// 240. I have a report that an FX card skips in a totally different spot. -// So rather than try and correct it in the shader, we detect it here and -// compensate when uploading the palette and when drawing by setting the -// sampler mode for the palette to border and making the border color the -// final color in the palette. -// -// Interestingly, a Radeon x300 doesn't have this problem. I am curious -// if other ATI hardware is the same. -// -//========================================================================== - -void D3DFB::DoOffByOneCheck () -{ - IDirect3DSurface9 *savedrendertarget; - IDirect3DSurface9 *testsurf, *readsurf; - D3DSURFACE_DESC desc; - D3DLOCKED_RECT lockrect; - RECT testrect = { 0, 0, 256, 1 }; - float texright = 256.f / float(FBWidth); - float texbot = 1.f / float(FBHeight); - FBVERTEX verts[4] = - { - { -0.5f, -0.5f, 0.5f, 1.f, 0.f, 0.f }, - { 255.5f, -0.5f, 0.5f, 1.f, texright, 0.f }, - { 255.5f, 0.5f, 0.5f, 1.f, texright, texbot }, - { -0.5f, 0.5f, 0.5f, 1.f, 0.f, texbot } - }; - float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; - - union - { - BYTE Pal32[256][4]; - WORD Pal16[256]; - }; - int i, c; - - if (OffByOneAt >= 0) - { - return; - } - - // Create an easily recognizable R3G3B2 palette. - for (i = 0; i < 256; ++i) - { - Pal32[i][0] = BYTE(i & 0x03) << 6; // blue - Pal32[i][1] = BYTE(i & 0x1C) << 3; // green - Pal32[i][2] = BYTE(i & 0xE0); // red; - Pal32[i][3] = 255; - } - - // Upload the palette - if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) - { - memcpy (lockrect.pBits, Pal32, 256 * 4); - PaletteTexture->UnlockRect (0); - } - else - { - return; - } - // Prepare a texture with values 0-256. - if (SUCCEEDED(FBTexture->LockRect (0, &lockrect, &testrect, 0))) - { - for (i = 0; i < 256; ++i) - { - ((BYTE *)lockrect.pBits)[i] = (BYTE)i; - } - FBTexture->UnlockRect (0); - } - else - { - return; - } - // Create a render target that we can draw it to. - if (FAILED(D3DDevice->GetRenderTarget (0, &savedrendertarget))) - { - return; - } - if (FAILED(D3DDevice->CreateRenderTarget (256, 1, PalFormat, D3DMULTISAMPLE_NONE, 0, FALSE, &testsurf, NULL))) - { - return; - } - if (FAILED(D3DDevice->CreateOffscreenPlainSurface (256, 1, PalFormat, D3DPOOL_SYSTEMMEM, &readsurf, NULL))) - { - testsurf->Release(); - return; - } - if (FAILED(D3DDevice->SetRenderTarget (0, testsurf))) - { - testsurf->Release(); - readsurf->Release(); - return; - } - // Write it to the render target using the pixel shader. - D3DDevice->BeginScene(); - D3DDevice->SetTexture (0, FBTexture); - D3DDevice->SetTexture (1, PaletteTexture); - D3DDevice->SetFVF (D3DFVF_FBVERTEX); - D3DDevice->SetPixelShader (PalTexShader); - D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2); - D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); - D3DDevice->EndScene(); - D3DDevice->SetRenderTarget (0, savedrendertarget); - savedrendertarget->Release(); - // Now read it back and see where it skips an entry - if (SUCCEEDED(D3DDevice->GetRenderTargetData (testsurf, readsurf)) && - SUCCEEDED(readsurf->LockRect (&lockrect, &testrect, D3DLOCK_READONLY))) - { - desc.Format = PalFormat; - if (desc.Format == D3DFMT_A8R8G8B8 || desc.Format == D3DFMT_X8R8G8B8) - { - const BYTE *pix = (const BYTE *)lockrect.pBits; - for (i = 0; i < 256; ++i, pix += 4) - { - c = (pix[0] >> 6) | // blue - ((pix[1] >> 5) << 2) | // green - ((pix[2] >> 5) << 5); // red - if (c != i) - { - break; - } - } - } - else if (desc.Format == D3DFMT_A1R5G5B5 || desc.Format == D3DFMT_X1R5G5B5) - { - const WORD *pix = (const WORD *)lockrect.pBits; - for (i = 0; i < 256; ++i, ++pix) - { - c = ((*pix & 0x0018) >> 3) | // blue - ((*pix & 0x0380) >> 5) | // green - ((*pix & 0x7C00) >> 7) ; // red - if (c != i) - { - break; - } - } - } - else if (desc.Format == D3DFMT_R5G6B5) - { - const WORD *pix = (const WORD *)lockrect.pBits; - for (i = 0; i < 256; ++i, ++pix) - { - c = ((*pix & 0x0018) >> 3) | // blue - ((*pix & 0x0700) >> 6) | // green - ((*pix & 0xE000) >> 8) ; // red - if (c != i) - { - break; - } - } - } - else - { - // Huh? What kind of backbuffer is this? - i = 256; - } - } - readsurf->UnlockRect(); - readsurf->Release(); - testsurf->Release(); - OffByOneAt = i; - if (i < 256) - { - D3DDevice->SetSamplerState (1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); - } -} - bool D3DFB::CreateFBTexture () { if (FAILED(D3DDevice->CreateTexture (Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) @@ -811,6 +658,7 @@ void D3DFB::Update () { if (In2D == 2) { + DrawRateStuff(); D3DDevice->EndScene(); D3DDevice->Present(NULL, NULL, NULL, NULL); In2D = 0; @@ -819,7 +667,7 @@ void D3DFB::Update () if (LockCount != 1) { - //I_FatalError ("Framebuffer must have exactly 1 lock to be updated"); + I_FatalError ("Framebuffer must have exactly 1 lock to be updated"); if (LockCount > 0) { UpdatePending = true; @@ -828,7 +676,10 @@ void D3DFB::Update () return; } - DrawRateStuff (); + if (In2D == 0) + { + DrawRateStuff(); + } if (NeedGammaUpdate) { @@ -915,13 +766,13 @@ void D3DFB::Draw3DPart() D3DDevice->Clear (2, rects, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.f, 0); } D3DDevice->BeginScene(); - D3DDevice->SetTexture (0, FBTexture); - D3DDevice->SetTexture (1, PaletteTexture); + SetTexture (0, FBTexture); + SetPaletteTexture(PaletteTexture, 256); D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX)); D3DDevice->SetFVF (D3DFVF_FBVERTEX); - D3DDevice->SetPixelShader (PalTexShader); D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2); - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + memcpy(Constant, FlashConstants, sizeof(FlashConstants)); + SetAlphaBlend(FALSE); if (!UseBlendingRect || FlashConstants[1][0] == 1) { // The whole screen as a single quad. D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2); @@ -933,32 +784,13 @@ void D3DFB::Draw3DPart() // The rest is drawn unblended, so reset the shader constant. static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2); + memcpy(Constant, FlashZero, sizeof(FlashZero)); D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top } - if (UseBlendingRect && FlashConstants[1][0] != 1 && RateX) - { - float left = float(RateX) - 0.5f; - float top = (TrueHeight - Height) * 0.5f - 0.5f; - float right = float(Width) - 0.5f; - float bot = float(8) + top; - float texleft = float(RateX) / float(FBWidth); - float texright = float(Width) / float(FBWidth); - float texbot = float(8) / float(FBHeight); - - // Redraw the vid_fps part without the flash - FBVERTEX verts[4] = - { - { left, top, 0.5f, 1.f, texleft, 0.f }, - { right, top, 0.5f, 1.f, texright, 0.f }, - { right, bot, 0.5f, 1.f, texright, texbot }, - { left, bot, 0.5f, 1.f, texleft, texbot } - }; - D3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); - } } void D3DFB::UploadPalette () @@ -966,18 +798,10 @@ void D3DFB::UploadPalette () D3DLOCKED_RECT lockrect; int i; - if (OffByOneAt < 0) - { - DoOffByOneCheck (); - } if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) { - // Keep trying to update the palette if we haven't done the off-by-one - // check yet. Otherwise, wait until the next time the palette changes. - NeedPalUpdate = (OffByOneAt < 0); - BYTE *pix = (BYTE *)lockrect.pBits; - for (i = 0; i < OffByOneAt; ++i, pix += 4) + for (i = 0; i < 256; ++i, pix += 4) { pix[0] = GammaTable[SourcePalette[i].b]; pix[1] = GammaTable[SourcePalette[i].g]; @@ -985,22 +809,8 @@ void D3DFB::UploadPalette () pix[3] = (i == 0 ? 0 : 255); // To let masked textures work, the first palette entry's alpha is 0. } - for (; i < 256; ++i, pix += 4) - { - pix[0] = GammaTable[SourcePalette[i-1].b]; - pix[1] = GammaTable[SourcePalette[i-1].g]; - pix[2] = GammaTable[SourcePalette[i-1].r]; - pix[3] = 255; - } PaletteTexture->UnlockRect (0); } - if (OffByOneAt < 256) - { - D3DDevice->SetSamplerState (1, D3DSAMP_BORDERCOLOR, - D3DCOLOR_XRGB(GammaTable[SourcePalette[255].r], - GammaTable[SourcePalette[255].g], - GammaTable[SourcePalette[255].b])); - } } PalEntry *D3DFB::GetPalette () @@ -1145,8 +955,6 @@ bool D3DTex::Create(IDirect3DDevice9 *D3DDevice) w = GameTex->GetWidth(); h = GameTex->GetHeight(); - // We don't really want mip-maps, but specifying the flag is the only - // way to use D3DPOOL_MANAGED, according to the docs. hr = D3DDevice->CreateTexture(w, h, 1, 0, GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL); if (FAILED(hr)) @@ -1260,6 +1068,97 @@ FTextureFormat D3DTex::ToTexFmt(D3DFORMAT fmt) } } +//========================================================================== +// +// D3DPal Constructor +// +//========================================================================== + +D3DPal::D3DPal(FRemapTable *remap, D3DFB *fb) + : Tex(NULL), Remap(remap) +{ + int count; + + // Palette textures must be 256 entries for Shader Model 1.4 + if (fb->SM14) + { + count = 256; + } + else + { + int pow2count; + + // Round up to the nearest power of 2. + for (pow2count = 1; pow2count < remap->NumEntries; pow2count <<= 1) + { } + count = pow2count; + } + RoundedPaletteSize = count; + if (SUCCEEDED(fb->D3DDevice->CreateTexture(count, 1, 1, 0, + D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &Tex, NULL))) + { + if (!Update()) + { + Tex->Release(); + Tex = NULL; + } + } +} + +//========================================================================== +// +// D3DPal Destructor +// +//========================================================================== + +D3DPal::~D3DPal() +{ + if (Tex != NULL) + { + Tex->Release(); + Tex = NULL; + } +} + +//========================================================================== +// +// D3DPal :: Update +// +// Copies the palette to the texture. +// +//========================================================================== + +bool D3DPal::Update() +{ + D3DLOCKED_RECT lrect; + D3DCOLOR *buff; + const PalEntry *pal; + + assert(Tex != NULL); + + if (FAILED(Tex->LockRect(0, &lrect, NULL, 0))) + { + return false; + } + buff = (D3DCOLOR *)lrect.pBits; + pal = Remap->Palette; + + // Should I allow the source palette to specify alpha values? + buff[0] = D3DCOLOR_ARGB(0, + static_cast(screen)->GammaTable[pal[0].r], + static_cast(screen)->GammaTable[pal[0].g], + static_cast(screen)->GammaTable[pal[0].b]); + for (int i = 1; i < Remap->NumEntries; ++i) + { + buff[i] = D3DCOLOR_XRGB( + static_cast(screen)->GammaTable[pal[i].r], + static_cast(screen)->GammaTable[pal[i].g], + static_cast(screen)->GammaTable[pal[i].b]); + } + Tex->UnlockRect(0); + return true; +} + //========================================================================== // // D3DFB :: Begin2D @@ -1280,19 +1179,47 @@ void D3DFB::Begin2D() In2D = 2; // Set default state for 2D rendering. - float ps_constants[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; - D3DDevice->SetPixelShaderConstantF (0, ps_constants[0], 2); - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - - // This is set by Update() - //D3DDevice->SetTexture(1, PaletteTexture); + SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); } +//========================================================================== +// +// D3DFB :: CreateTexture +// +// Returns a native texture that wraps a FTexture. +// +//========================================================================== + FNativeTexture *D3DFB::CreateTexture(FTexture *gametex) { - return new D3DTex(gametex, D3DDevice); + D3DTex *tex = new D3DTex(gametex, D3DDevice); + if (tex->Tex == NULL) + { + delete tex; + return NULL; + } + return tex; +} + +//========================================================================== +// +// D3DFB :: CreatePalette +// +// Returns a native texture that contains a palette. +// +// Pre: count is a power of 2 +// +//========================================================================== + +FNativeTexture *D3DFB::CreatePalette(FRemapTable *remap) +{ + D3DPal *tex = new D3DPal(remap, this); + if (tex->Tex == NULL) + { + delete tex; + return NULL; + } + return tex; } //========================================================================== @@ -1303,7 +1230,7 @@ FNativeTexture *D3DFB::CreateTexture(FTexture *gametex) // //========================================================================== -void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const +void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) { if (In2D < 2) { @@ -1314,6 +1241,11 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 { color = GPalette.BaseColors[palcolor]; } + else if (APART(color) < 255) + { + Dim(color, APART(color)/255.f, left, top, right - left, bottom - top); + return; + } D3DRECT rect = { left, top, right, bottom }; D3DDevice->Clear(1, &rect, D3DCLEAR_TARGET, color | 0xFF000000, 1.f, 0); } @@ -1324,7 +1256,7 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 // //========================================================================== -void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const +void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) return; @@ -1348,14 +1280,10 @@ void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) con { x1+w-0.5f, y1+h-0.5f, 0.5f, 1, 0, 0 }, { x1-0.5f, y1+h-0.5f, 0.5f, 1, 0, 0 } }; - float constant[4] = - { - RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, APART(color)/255.f, - }; - D3DDevice->SetPixelShader(DimShader); - D3DDevice->SetPixelShaderConstantF(1, constant, 1); + SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); + SetPixelShader(DimShader); + SetConstant(1, color.r/255.f, color.g/255.f, color.b/255.f, amount); D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX)); - D3DDevice->SetPixelShader(PalTexShader); } } @@ -1378,7 +1306,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi DrawParms parms; - if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms)) + if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true)) { return; } @@ -1450,12 +1378,12 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi { x0, y1, 0.5f, 1.f, u0, v1 } }; - if (!SetStyle(parms.style, parms.alpha, parms.fillcolor, parms.masked)) + if (!SetStyle(parms)) { return; } - D3DDevice->SetTexture(0, tex->Tex); + SetTexture(0, tex->Tex); D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, &verts, sizeof(FBVERTEX)); } @@ -1467,13 +1395,14 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi // //========================================================================== -bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked) +bool D3DFB::SetStyle(DrawParms &parms) { + ERenderStyle style = parms.style; D3DBLEND fglevel, bglevel; float alpha; bool stencilling; - alpha = clamp (alpha_fixed, 0, FRACUNIT) / 65536.f; + alpha = clamp (parms.alpha, 0, FRACUNIT) / 65536.f; if (style == STYLE_OptFuzzy) { @@ -1500,12 +1429,9 @@ bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked case STYLE_Shaded: if (alpha > 0) { - float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; - D3DDevice->SetPixelShaderConstantF(1, constant, 1); - D3DDevice->SetTexture(1, ShadedPaletteTexture); - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - D3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha); + SetPaletteTexture(ShadedPaletteTexture, 256); + SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); return true; } return false; @@ -1545,28 +1471,146 @@ bool D3DFB::SetStyle(int style, fixed_t alpha_fixed, DWORD color, INTBOOL masked // Masking can only be turned off for STYLE_Normal, because it requires // turning off the alpha blend. - if (!masked && style == STYLE_Normal) + if (!parms.masked && style == STYLE_Normal) { - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + SetAlphaBlend(FALSE); + SetColorOverlay(parms.colorOverlay, 1); + SetPaletteTexture(PaletteTexture, 256); } else { - D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - D3DDevice->SetRenderState(D3DRS_SRCBLEND, fglevel); - D3DDevice->SetRenderState(D3DRS_DESTBLEND, bglevel); + SetAlphaBlend(TRUE, fglevel, bglevel); if (!stencilling) { - float constant[4] = { 1,1,1,alpha }; - D3DDevice->SetPixelShaderConstantF(1, constant, 1); - D3DDevice->SetTexture(1, PaletteTexture); + if (parms.remap != NULL) + { + D3DPal *pal = reinterpret_cast(parms.remap->GetNative()); + SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize); + } + else + { + SetPaletteTexture(PaletteTexture, 256); + } + SetColorOverlay(parms.colorOverlay, alpha); } else { - float constant[4] = { RPART(color)/255.f,GPART(color)/255.f,BPART(color)/255.f,alpha }; - D3DDevice->SetPixelShaderConstantF(1, constant, 1); - D3DDevice->SetTexture(1, StencilPaletteTexture); + SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha); + SetPaletteTexture(StencilPaletteTexture, 256); } } return true; -} \ No newline at end of file +} + +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); +} diff --git a/src/win32/fb_d3d9_shaders.h b/src/win32/fb_d3d9_shaders.h index 995dc58c1d..628981206d 100644 --- a/src/win32/fb_d3d9_shaders.h +++ b/src/win32/fb_d3d9_shaders.h @@ -12,19 +12,20 @@ sampler2D Image : register(s0); sampler2D Palette : register(s1); float4 Flash : register(c0); float4 InvFlash : register(c1); +float4 PaletteMod : register(c2); float4 main (float2 texCoord : TEXCOORD0) : COLOR { float4 index = tex2D (Image, texCoord); + index.x = index.x * PaletteMod.x + PaletteMod.y; float4 rgb = tex2D (Palette, index); return Flash + rgb * InvFlash; } -#endif -#if SHADER_ASSEMBLY_CODE +#elif SHADER_ASSEMBLY_CODE // // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // -// fxc paltex.ps /Tps_1_4 /VnPalTexShaderDef /Fh +// fxc paltex.ps /Tps_1_4 /VnPalTexShader14Def /Fh // // // Parameters: @@ -33,6 +34,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR // sampler2D Image; // float4 InvFlash; // sampler2D Palette; +// float4 PaletteMod; // // // Registers: @@ -41,34 +43,75 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR // ------------ ----- ---- // Flash c0 1 // InvFlash c1 1 +// PaletteMod c2 1 // Image s0 1 // Palette s1 1 // ps_1_4 texld r0, t0 + mad r0.x, r0.x, c2.x, c2.y phase texld r1, r0 mad r0, r1, c1, c0 -// approximately 3 instruction slots used (2 texture, 1 arithmetic) +// approximately 4 instruction slots used (2 texture, 2 arithmetic) #endif -const DWORD PalTexShaderDef[] = +const DWORD PalTexShader14Def[] = { - 0xffff0104, 0x003bfffe, 0x42415443, 0x0000001c, 0x000000b4, 0xffff0104, - 0x00000004, 0x0000001c, 0x00000100, 0x000000ad, 0x0000006c, 0x00000002, - 0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00000003, 0x00000001, - 0x0000008c, 0x00000000, 0x0000009c, 0x00010002, 0x00020001, 0x00000074, - 0x00000000, 0x000000a5, 0x00010003, 0x00000001, 0x0000008c, 0x00000000, - 0x73616c46, 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, - 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, - 0x46766e49, 0x6873616c, 0x6c615000, 0x65747465, 0x5f737000, 0x00345f31, - 0x7263694d, 0x666f736f, 0x52282074, 0x33442029, 0x20395844, 0x64616853, - 0x43207265, 0x69706d6f, 0x2072656c, 0x35312e39, 0x3937372e, 0x3030302e, - 0xabab0030, 0x00000042, 0x800f0000, 0xb0e40000, 0x0000fffd, 0x00000042, - 0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, 0xa0e40001, - 0xa0e40000, 0x0000ffff + 0xffff0104, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d3, 0xffff0104, + 0x00000005, 0x0000001c, 0x00000100, 0x000000cc, 0x00000080, 0x00000002, + 0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00000003, 0x00000001, + 0x000000a0, 0x00000000, 0x000000b0, 0x00010002, 0x00020001, 0x00000088, + 0x00000000, 0x000000b9, 0x00010003, 0x00000001, 0x000000a0, 0x00000000, + 0x000000c1, 0x00020002, 0x00020001, 0x00000088, 0x00000000, 0x73616c46, + 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49, + 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x46766e49, + 0x6873616c, 0x6c615000, 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d, + 0x315f7370, 0x4d00345f, 0x6f726369, 0x74666f73, 0x29522820, 0x44334420, + 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e, + 0x2e393737, 0x30303030, 0xababab00, 0x00000042, 0x800f0000, 0xb0e40000, + 0x00000004, 0x80010000, 0x80000000, 0xa0000002, 0xa0550002, 0x0000fffd, + 0x00000042, 0x800f0001, 0x80e40000, 0x00000004, 0x800f0000, 0x80e40001, + 0xa0e40001, 0xa0e40000, 0x0000ffff +}; + +#if SHADER_ASSEMBLY_CODE + ps_2_0 + dcl t0.xy + dcl_2d s0 + dcl_2d s1 + texld r0, t0, s0 + mad r0.x, r0.x, c2.x, c2.y + texld r0, r0, s1 + mov r1, c1 + mad r0, r0, r1, c0 + mov oC0, r0 + +// approximately 6 instruction slots used (2 texture, 4 arithmetic) +#endif + +const DWORD PalTexShader20Def[] = +{ + 0xffff0200, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d3, 0xffff0200, + 0x00000005, 0x0000001c, 0x00000100, 0x000000cc, 0x00000080, 0x00000002, + 0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00000003, 0x00000001, + 0x000000a0, 0x00000000, 0x000000b0, 0x00010002, 0x00020001, 0x00000088, + 0x00000000, 0x000000b9, 0x00010003, 0x00000001, 0x000000a0, 0x00000000, + 0x000000c1, 0x00020002, 0x00020001, 0x00000088, 0x00000000, 0x73616c46, + 0xabab0068, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x67616d49, + 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x46766e49, + 0x6873616c, 0x6c615000, 0x65747465, 0x6c615000, 0x65747465, 0x00646f4d, + 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x44334420, + 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e, + 0x2e393737, 0x30303030, 0xababab00, 0x0200001f, 0x80000000, 0xb0030000, + 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, + 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x04000004, 0x80010000, + 0x80000000, 0xa0000002, 0xa0550002, 0x03000042, 0x800f0000, 0x80e40000, + 0xa0e40801, 0x02000001, 0x800f0001, 0xa0e40001, 0x04000004, 0x800f0000, + 0x80e40000, 0x80e40001, 0xa0e40000, 0x02000001, 0x800f0800, 0x80e40000, + 0x0000ffff }; // A texture that doesn't look up colors from a palette. @@ -84,8 +127,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR float4 index = tex2D (Image, texCoord); return Flash + index * InvFlash; } -#endif -#if SHADER_ASSEMBLY_CODE +#elif SHADER_ASSEMBLY_CODE // // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // @@ -131,6 +173,7 @@ const DWORD PlainShaderDef[] = }; // A shader that just returns the value of c1 + #if HLSL_SOURCE_CODE float4 Color : register(c1); @@ -138,8 +181,7 @@ float4 main () : COLOR { return Color; } -#endif -#if SHADER_ASSEMBLY_CODE +#elif SHADER_ASSEMBLY_CODE // // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index ff83f00d7b..43511136ff 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -1172,6 +1172,7 @@ void ST_Endoom() { KillTimer (Window, 0x5A15A); } + ST_Util_FreeBitmap (StartupBitmap); ST_Util_FreeFont (font); exit (int(bRet == 0 ? mess.wParam : 0)); } diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index bd91df1a50..5faa5e215d 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -235,10 +235,10 @@ public: void SetBlendingRect (int x1, int y1, int x2, int y2); void Begin2D (); FNativeTexture *CreateTexture (FTexture *gametex); - FNativeTexture *CreatePalette (FTexture *pal); + FNativeTexture *CreatePalette (FRemapTable *remap); void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); - void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const; - void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const; + void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color); + void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); HRESULT GetHR (); private: @@ -249,13 +249,27 @@ private: bool CreateStencilPaletteTexture(); bool CreateShadedPaletteTexture(); bool CreateVertexes(); - void DoOffByOneCheck(); void UploadPalette(); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); bool UploadVertices(); bool Reset(); void Draw3DPart(); - bool SetStyle(int style, fixed_t alpha, DWORD color, INTBOOL masked); + bool SetStyle(DCanvas::DrawParms &parms); + void SetColorOverlay(DWORD color, float alpha); + + // State + void SetAlphaBlend(BOOL enabled, D3DBLEND srcblend=D3DBLEND(0), D3DBLEND destblend=D3DBLEND(0)); + void SetConstant(int cnum, float r, float g, float b, float a); + void SetPixelShader(IDirect3DPixelShader9 *shader); + void SetTexture(int tnum, IDirect3DTexture9 *texture); + void SetPaletteTexture(IDirect3DTexture9 *texture, int count); + + BOOL AlphaBlendEnabled; + D3DBLEND AlphaSrcBlend; + D3DBLEND AlphaDestBlend; + float Constant[3][4]; + IDirect3DPixelShader9 *CurPixelShader; + IDirect3DTexture9 *Texture[2]; BYTE GammaTable[256]; PalEntry SourcePalette[256]; @@ -270,11 +284,11 @@ private: D3DFORMAT FBFormat; D3DFORMAT PalFormat; int FBWidth, FBHeight; - int OffByOneAt; bool VSync; RECT BlendingRect; bool UseBlendingRect; int In2D; + bool SM14; IDirect3DDevice9 *D3DDevice; IDirect3DVertexBuffer9 *VertexBuffer; @@ -287,6 +301,8 @@ private: IDirect3DPixelShader9 *DimShader; D3DFB() {} + + friend class D3DPal; }; #if 0 diff --git a/tools/updaterevision/updaterevision.vcproj b/tools/updaterevision/updaterevision.vcproj index f39914dcac..202c9d042b 100644 --- a/tools/updaterevision/updaterevision.vcproj +++ b/tools/updaterevision/updaterevision.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - -