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 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - -