/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : Command & Conquer * * * * $Archive:: /G/wwlib/Convert.cpp $* * * * $Author:: Eric_c $* * * * $Modtime:: 2/19/99 11:51a $* * * * $Revision:: 2 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "always.h" #include "blitblit.h" #include "convert.h" #include "dsurface.h" #include "hsv.h" #include "rlerle.h" ConvertClass::ConvertClass(PaletteClass const & artpalette, PaletteClass const & screenpalette, Surface const & surface) : BBP(surface.Bytes_Per_Pixel()), PlainBlitter(NULL), TransBlitter(NULL), ShadowBlitter(NULL), RemapBlitter(NULL), Translucent1Blitter(NULL), Translucent2Blitter(NULL), Translucent3Blitter(NULL), RLETransBlitter(NULL), RLEShadowBlitter(NULL), RLERemapBlitter(NULL), RLETranslucent1Blitter(NULL), RLETranslucent2Blitter(NULL), RLETranslucent3Blitter(NULL), Translator(NULL), ShadowTable(NULL), RemapTable(NULL) { /* ** The draw data initialization is greatly dependant upon the pixel format ** of the display surface. Check the pixel format and set the values accordingly. */ if (BBP == 1) { /* ** Build the shadow table by creating a slightly darker version of ** the color and then finding the closest match to it. */ ShadowTable = new unsigned char [256]; ShadowTable[0] = 0; for (int shadow = 1; shadow < 256; shadow++) { HSVClass hsv = artpalette[shadow]; hsv.Set_Value((unsigned char)(hsv.Get_Value() / 2)); ShadowTable[shadow] = (unsigned char)artpalette.Closest_Color(hsv); } /* ** The translator table is created by finding the closest color ** in the display palette from each color in the source art ** palette. */ unsigned char * trans = new unsigned char [256]; trans[0] = 0; for (int index = 1; index < 256; index++) { trans[index] = (unsigned char)screenpalette.Closest_Color(artpalette[index]); } Translator = (void *)trans; /* ** Construct all the blitter objects necessary to support the functionality ** required for the draw permutations. */ PlainBlitter = new BlitPlainXlat((unsigned char const *)Translator); TransBlitter = new BlitTransXlat((unsigned char const *)Translator); RemapBlitter = new BlitTransZRemapXlat(&RemapTable, (unsigned char const *)Translator); ShadowBlitter = new BlitTransRemapDest(ShadowTable); Translucent1Blitter = new BlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); Translucent2Blitter = new BlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); Translucent3Blitter = new BlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); /* ** Create the RLE aware blitter objects. */ RLETransBlitter = new RLEBlitTransXlat((unsigned char const *)Translator); RLERemapBlitter = new RLEBlitTransZRemapXlat(&RemapTable, (unsigned char const *)Translator); RLEShadowBlitter = new RLEBlitTransRemapDest(ShadowTable); RLETranslucent1Blitter = new RLEBlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); RLETranslucent2Blitter = new RLEBlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); RLETranslucent3Blitter = new RLEBlitTransRemapXlat(ShadowTable, (unsigned char const *)Translator); } else { /* ** The hicolor translation table is constructed according to the pixel ** format of the display and the source art palette. */ //assert(surface.Is_Direct_Draw()); Translator = new unsigned short [256]; ((DSurface &)surface).Build_Remap_Table((unsigned short *)Translator, artpalette); /* ** Fetch the pixel mask values to be used for the various algorithmic ** pixel processing performed for hicolor displays. */ int maskhalf = ((DSurface &)surface).Get_Halfbright_Mask(); int maskquarter = ((DSurface &)surface).Get_Quarterbright_Mask(); /* ** Construct all the blitter objects necessary to support the functionality ** required for the draw permutations. */ PlainBlitter = new BlitPlainXlat((unsigned short const *)Translator); TransBlitter = new BlitTransXlat((unsigned short const *)Translator); RemapBlitter = new BlitTransZRemapXlat(&RemapTable, (unsigned short const *)Translator); ShadowBlitter = new BlitTransDarken((unsigned short)maskhalf); Translucent1Blitter = new BlitTransLucent75((unsigned short const *)Translator, (unsigned short)maskquarter); Translucent2Blitter = new BlitTransLucent50((unsigned short const *)Translator, (unsigned short)maskhalf); Translucent3Blitter = new BlitTransLucent25((unsigned short const *)Translator, (unsigned short)maskquarter); /* ** Create the RLE aware blitter objects. */ RLETransBlitter = new RLEBlitTransXlat((unsigned short const *)Translator); RLERemapBlitter = new RLEBlitTransZRemapXlat(&RemapTable, (unsigned short const *)Translator); RLEShadowBlitter = new RLEBlitTransDarken((unsigned short)maskhalf); RLETranslucent1Blitter = new RLEBlitTransLucent75((unsigned short const *)Translator, (unsigned short)maskquarter); RLETranslucent2Blitter = new RLEBlitTransLucent50((unsigned short const *)Translator, (unsigned short)maskhalf); RLETranslucent3Blitter = new RLEBlitTransLucent25((unsigned short const *)Translator, (unsigned short)maskquarter); } } ConvertClass::~ConvertClass(void) { delete PlainBlitter; PlainBlitter = NULL; delete TransBlitter; TransBlitter = NULL; delete ShadowBlitter; ShadowBlitter = NULL; delete RemapBlitter; RemapBlitter = NULL; delete Translucent1Blitter; Translucent1Blitter = NULL; delete Translucent2Blitter; Translucent2Blitter = NULL; delete Translucent3Blitter; Translucent3Blitter = NULL; delete [] Translator; Translator = NULL; delete [] ShadowTable; ShadowTable = NULL; delete RLETransBlitter; RLETransBlitter = NULL; delete RLEShadowBlitter; RLEShadowBlitter = NULL; delete RLERemapBlitter; RLERemapBlitter = NULL; delete RLETranslucent1Blitter; RLETranslucent1Blitter = NULL; delete RLETranslucent2Blitter; RLETranslucent2Blitter = NULL; delete RLETranslucent3Blitter; RLETranslucent3Blitter = NULL; } Blitter const * ConvertClass::Blitter_From_Flags(ShapeFlags_Type flags) const { if (flags & SHAPE_REMAP) return(RemapBlitter); /* ** Quick check to see if this is a translucent operation. If so, then no ** further examination of the flags is necessary. */ switch (flags & (SHAPE_TRANSLUCENT25 | SHAPE_TRANSLUCENT50 | SHAPE_TRANSLUCENT75)) { case SHAPE_TRANSLUCENT25: return(Translucent3Blitter); case SHAPE_TRANSLUCENT50: return(Translucent2Blitter); case SHAPE_TRANSLUCENT75: return(Translucent1Blitter); } if (flags & SHAPE_DARKEN) return(ShadowBlitter); if (flags & SHAPE_NOTRANS) return(PlainBlitter); return(TransBlitter); } RLEBlitter const * ConvertClass::RLEBlitter_From_Flags(ShapeFlags_Type flags) const { if (flags & SHAPE_REMAP) return(RLERemapBlitter); /* ** Quick check to see if this is a translucent operation. If so, then no ** further examination of the flags is necessary. */ switch (flags & (SHAPE_TRANSLUCENT25 | SHAPE_TRANSLUCENT50 | SHAPE_TRANSLUCENT75)) { case SHAPE_TRANSLUCENT25: return(RLETranslucent3Blitter); case SHAPE_TRANSLUCENT50: return(RLETranslucent2Blitter); case SHAPE_TRANSLUCENT75: return(RLETranslucent1Blitter); } if (flags & SHAPE_DARKEN) return(RLEShadowBlitter); // This should be fixed to return the RLEPlainBlitter when one is available // but if you need to use this in the mean time just don't RLE compress the // shape (since it only compresses transparent pixels and the reason we compress // them is so we can skip them easily.) if (flags & SHAPE_NOTRANS) return(RLETransBlitter); return(RLETransBlitter); }