PALETTEC.CPP (24713B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/palette.cpp 2 9/23/97 11:00p Steve_t $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : PALETTE.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 12/02/95 * 28 * * 29 * Last Update : February 5, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * PaletteClass::Adjust -- Adjusts the palette toward another palette. * 34 * PaletteClass::Adjust -- Adjusts this palette toward black. * 35 * PaletteClass::Closest_Color -- Finds closest match to color specified. * 36 * PaletteClass::Set -- Fade the display palette to this palette. * 37 * PaletteClass::PaletteClass -- Constructor that fills palette with color specified. * 38 * PaletteClass::operator = -- Assignment operator for palette objects. * 39 * PaletteClass::operator == -- Equality operator for palette objects. * 40 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 41 42 #ifndef NOINITCLASS 43 #define NOINITCLASS 44 struct NoInitClass { 45 public: 46 void operator () (void) const {}; 47 }; 48 #endif 49 50 void __cdecl Set_Palette(void * palette); 51 52 53 #ifndef BITMAPCLASS 54 #define BITMAPCLASS 55 class BitmapClass 56 { 57 public: 58 BitmapClass(int w, int h, unsigned char * data) : 59 Width(w), Height(h), Data(data) {}; 60 61 int Width; 62 int Height; 63 unsigned char * Data; 64 }; 65 66 class TPoint2D 67 { 68 public: 69 TPoint2D(int xx, int yy) : x(xx), y(yy) {}; 70 TPoint2D(void) : x(0), y(0) {}; 71 72 int x; 73 int y; 74 }; 75 #endif 76 77 #include "function.h" 78 #include "watcom.h" 79 #include "palette.h" 80 #include "palettec.h" 81 #include "ftimer.h" 82 //#define TIMER_H 83 #include "wwlib32.h" 84 //#include "timer.h" 85 #include <string.h> 86 87 #ifndef SYSTEM_TIMER_CLASS 88 #define SYSTEM_TIMER_CLASS 89 90 #ifdef WIN32 91 extern WinTimerClass * WindowsTimer; 92 #endif 93 94 class SystemTimerClass 95 { 96 public: 97 #ifdef WIN32 98 long operator () (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());}; 99 operator long (void) const {if (!WindowsTimer) return(0);return(WindowsTimer->Get_System_Tick_Count());}; 100 #else 101 long operator () (void) const {return(Get_System_Tick_Count());}; 102 operator long (void) const {return(Get_System_Tick_Count());}; 103 #endif 104 }; 105 #endif 106 107 108 //PaletteClass const PaletteClass::CurrentPalette; 109 extern "C" unsigned char CurrentPalette[]; 110 111 PaletteClass const & PaletteClass::CurrentPalette = *(PaletteClass *)&::CurrentPalette[0]; 112 113 114 /*********************************************************************************************** 115 * PaletteClass::PaletteClass -- Constructor that fills palette with color specified. * 116 * * 117 * This constructor will fill the palette with the color specified. * 118 * * 119 * INPUT: rgb -- Reference to the color to fill the entire palette with. * 120 * * 121 * OUTPUT: none * 122 * * 123 * WARNINGS: none * 124 * * 125 * HISTORY: * 126 * 12/02/1995 JLB : Created. * 127 *=============================================================================================*/ 128 PaletteClass::PaletteClass(RGBClass const & rgb) 129 { 130 for (int index = 0; index < COLOR_COUNT; index++) { 131 Palette[index] = rgb; 132 } 133 } 134 135 136 /*********************************************************************************************** 137 * PaletteClass::operator == -- Equality operator for palette objects. * 138 * * 139 * This is the comparison for equality operator. It will compare palette objects to * 140 * determine if they are identical. * 141 * * 142 * INPUT: palette -- Reference to the palette to compare to this palette. * 143 * * 144 * OUTPUT: Are the two palettes identical? * 145 * * 146 * WARNINGS: none * 147 * * 148 * HISTORY: * 149 * 12/02/1995 JLB : Created. * 150 *=============================================================================================*/ 151 int PaletteClass::operator == (PaletteClass const & palette) const 152 { 153 if (this == &palette) return(true); 154 return(memcmp(&Palette[0], &palette.Palette[0], sizeof(Palette)) == 0); 155 } 156 157 158 /*********************************************************************************************** 159 * PaletteClass::operator = -- Assignment operator for palette objects. * 160 * * 161 * This is the assignment operator for palette objects. Although the default C++ generated * 162 * assignment operator would function correctly, it would not check for self-assignment * 163 * and thus this routine can be faster. * 164 * * 165 * INPUT: palette -- Reference to that palette that will be copied into this palette. * 166 * * 167 * OUTPUT: Returns with a reference to the newly copied to palette. * 168 * * 169 * WARNINGS: none * 170 * * 171 * HISTORY: * 172 * 12/02/1995 JLB : Created. * 173 *=============================================================================================*/ 174 PaletteClass & PaletteClass::operator = (PaletteClass const & palette) 175 { 176 if (this == &palette) return(*this); 177 178 memcpy(&Palette[0], &palette.Palette[0], sizeof(Palette)); 179 return(*this); 180 } 181 182 183 /*********************************************************************************************** 184 * PaletteClass::Adjust -- Adjusts this palette toward black. * 185 * * 186 * This routine is used to adjust this palette toward black. Typical use of this routine * 187 * is when fading the palette to black. * 188 * * 189 * INPUT: ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255 * 190 * means 100% faded to black. * 191 * * 192 * OUTPUT: none * 193 * * 194 * WARNINGS: This routine doesn't actually set the palette to the video card. Use the Set() * 195 * function to achieve that purpose. * 196 * * 197 * HISTORY: * 198 * 12/02/1995 JLB : Created. * 199 *=============================================================================================*/ 200 void PaletteClass::Adjust(int ratio) 201 { 202 for (int index = 0; index < COLOR_COUNT; index++) { 203 Palette[index].Adjust(ratio, BlackColor); 204 } 205 } 206 207 208 /*********************************************************************************************** 209 * PaletteClass::Adjust -- Adjusts the palette toward another palette. * 210 * * 211 * This routine is used to adjust a palette toward a destination palette by the ratio * 212 * specified. This is primarily used by the palette fading routines. * 213 * * 214 * INPUT: palette -- Reference to the destination palette. * 215 * * 216 * ratio -- The ratio to adjust this palette toward the destination palette. A * 217 * value of 0 means no adjustment at all. A value of 255 means 100% * 218 * adjustment. * 219 * * 220 * OUTPUT: none * 221 * * 222 * WARNINGS: none * 223 * * 224 * HISTORY: * 225 * 12/02/1995 JLB : Created. * 226 *=============================================================================================*/ 227 void PaletteClass::Adjust(int ratio, PaletteClass const & palette) 228 { 229 for (int index = 0; index < COLOR_COUNT; index++) { 230 231 //if (index == 1) { 232 // Mono_Printf("From R=%d,G=%d,B=%d ", Palette[index].Red_Component(), Palette[index].Green_Component(), Palette[index].Blue_Component()); 233 // Mono_Printf("To R=%d,G=%d,B=%d [%d] ", palette[index].Red_Component(), palette[index].Green_Component(), palette[index].Blue_Component(), ratio); 234 //} 235 Palette[index].Adjust(ratio, palette[index]); 236 237 //if (index == 1) { 238 // Mono_Printf("Equals R=%d,G=%d,B=%d.\n", Palette[index].Red_Component(), Palette[index].Green_Component(), Palette[index].Blue_Component()); 239 //} 240 241 } 242 } 243 244 245 /*********************************************************************************************** 246 * PaletteClass::Partial_Adjust -- Adjusts the specified parts of this palette toward black. * 247 * * 248 * This routine is used to adjust this palette toward black. Typical use of this routine * 249 * is when fading the palette to black. The input lookup table is used to determine * 250 * which entries should fade and which should stay the same * 251 * * 252 * INPUT: ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255 * 253 * means 100% faded to black. * 254 * * 255 * lookup -- ptr to lookup table * 256 * * 257 * OUTPUT: none * 258 * * 259 * WARNINGS: This routine doesn't actually set the palette to the video card. Use the Set() * 260 * function to achieve that purpose. * 261 * * 262 * HISTORY: * 263 * 12/02/1995 JLB : Created. * 264 *=============================================================================================*/ 265 void PaletteClass::Partial_Adjust(int ratio, char *lut) 266 { 267 for (int index = 0; index < COLOR_COUNT; index++) { 268 if (lut[index]) { 269 Palette[index].Adjust(ratio, BlackColor); 270 } 271 } 272 } 273 274 275 /*********************************************************************************************** 276 * PaletteClass::Partial_Adjust -- Adjusts the palette toward another palette. * 277 * * 278 * This routine is used to adjust a palette toward a destination palette by the ratio * 279 * specified. This is primarily used by the palette fading routines. The input lookup * 280 * table is used to determine which entries should fade and which should stay the same * 281 * * 282 * * 283 * INPUT: palette -- Reference to the destination palette. * 284 * * 285 * ratio -- The ratio to adjust this palette toward the destination palette. A * 286 * value of 0 means no adjustment at all. A value of 255 means 100% * 287 * adjustment. * 288 * * 289 * lookup -- ptr to lookup table * 290 * * 291 * * 292 * OUTPUT: none * 293 * * 294 * WARNINGS: none * 295 * * 296 * HISTORY: * 297 * 12/02/1995 JLB : Created. * 298 *=============================================================================================*/ 299 void PaletteClass::Partial_Adjust(int ratio, PaletteClass const & palette, char *lut) 300 { 301 for (int index = 0; index < COLOR_COUNT; index++) { 302 if (lut[index]) { 303 Palette[index].Adjust(ratio, palette[index]); 304 } 305 } 306 } 307 308 309 /*********************************************************************************************** 310 * PaletteClass::Closest_Color -- Finds closest match to color specified. * 311 * * 312 * This routine will examine the palette and return with the color index number for the * 313 * color that most closely matches the color specified. Remap operations rely heavily on * 314 * this routine to allow working with a constant palette. * 315 * * 316 * INPUT: rgb -- Reference to a color to search for in the current palette. * 317 * * 318 * OUTPUT: Returns with a color index value to most closely matches the specified color. * 319 * * 320 * WARNINGS: This routine will quite likely not find an exact match. * 321 * * 322 * HISTORY: * 323 * 12/02/1995 JLB : Created. * 324 *=============================================================================================*/ 325 int PaletteClass::Closest_Color(RGBClass const & rgb) const 326 { 327 int closest = 0; 328 int value = -1; 329 330 RGBClass const * ptr = &Palette[0]; 331 for (int index = 0; index < COLOR_COUNT; index++) { 332 int difference = rgb.Difference(*ptr++); 333 if (value == -1 || difference < value) { 334 value = difference; 335 closest = index; 336 } 337 } 338 return(closest); 339 } 340 341 342 #ifndef WIN32 343 extern void Vsync(void); 344 #pragma aux Vsync modify [edx ebx eax] = \ 345 "mov edx,03DAh" \ 346 "mov ebx,[VertBlank]" \ 347 "and bl,001h" \ 348 "shl bl,3" \ 349 "in_vbi:" \ 350 "in al,dx" \ 351 "and al,008h" \ 352 "xor al,bl" \ 353 "je in_vbi" \ 354 "out_vbi:" \ 355 "in al,dx" \ 356 "and al,008h" \ 357 "xor al,bl" \ 358 "jne out_vbi" 359 #endif //WIN32 360 361 362 /*********************************************************************************************** 363 * PaletteClass::Set -- Fade the display palette to this palette. * 364 * * 365 * This routine will fade the display palette to match this palette over the time period * 366 * specified. For smooth palette transitions, this is the routine to call. * 367 * * 368 * INPUT: time -- The time period (in system tick increments) to fade the display palette * 369 * to match this palette. * 370 * * 371 * callback -- Optional pointer to callback function that, if non-null, will be * 372 * called as often as possible during the fading process. * 373 * * 374 * OUTPUT: none * 375 * * 376 * WARNINGS: This routine will not return until the palette is completely faded to the * 377 * destination palette. * 378 * * 379 * HISTORY: * 380 * 12/02/1995 JLB : Created. * 381 * 02/05/1996 JLB : Uses new timer system. * 382 *=============================================================================================*/ 383 void PaletteClass::Set(int time, void (* callback)(void)) const 384 { 385 CDTimerClass<SystemTimerClass> timer = time; 386 PaletteClass original = CurrentPalette; 387 388 while (timer) { 389 390 /* 391 ** Build an intermediate palette that is as close to the destination palette 392 ** as the current time is proportional to the ending time. 393 */ 394 PaletteClass palette = original; 395 int adjust = ((time - timer) * 256) / time; 396 palette.Adjust(adjust, *this); 397 398 /* 399 ** Remember the current time so that multiple palette sets within the same game 400 ** time tick won't occur. This is probably unnecessary since the palette setting 401 ** code, at the time of this writing, delays at least one game tick in the process 402 ** of setting the palette. 403 */ 404 long holdtime = timer; 405 406 /* 407 ** Set the palette to this intermediate palette and then loop back 408 ** to calculate and set a new intermediate palette. 409 */ 410 #ifdef WIN32 411 Set_Palette((void*)&palette[0]); 412 #else 413 palette.Set(); 414 #endif //WIN32 415 416 /* 417 ** If the callback routine was specified, then call it once per palette 418 ** setting loop. 419 */ 420 if (callback) { 421 callback(); 422 } 423 424 /* 425 ** This loop ensures that the palette won't be set more than once per game tick. Setting 426 ** the palette more than once per game tick will have no effect since the calculation will 427 ** result in the same intermediate palette that was previously calculated. 428 */ 429 while (timer == holdtime && holdtime != 0) { 430 if (callback) callback(); 431 } 432 } 433 434 /* 435 ** Ensure that the final palette exactly matches the requested 436 ** palette before exiting the fading routine. 437 */ 438 #ifndef WIN32 439 Vsync(); 440 RGBClass const * rgbptr = &Palette[0]; 441 RGBClass::Raw_Color_Prep(0); 442 for (int index = 0; index < COLOR_COUNT; index++) { 443 rgbptr->Raw_Set(); 444 rgbptr++; 445 } 446 ((PaletteClass &)CurrentPalette) = *this; 447 #else //WIN32 448 Set_Palette((void*)&Palette[0]); 449 #endif 450 }