PALETTEC.CPP 24 KB

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