// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /*************************************************************************** ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** *************************************************************************** * * * Project Name : WWLIB * * * * File Name : PALETTE.C * * * * Programmer : BILL STOKES * * * * Start Date : 6/20/91 * * * * Last Update : August 2, 1994 [SKB] * * * *-------------------------------------------------------------------------* * Note: This module contains dependencies upon the video system, * * specifically Get_Video_Mode(). * *-------------------------------------------------------------------------* * Functions: * * Set_Palette -- sets the current palette * * Set_Palette_Color -- Set a color number in a palette to the data. * * Fade_Palette_To -- Fades the current palette into another * * Determine_Bump_Rate -- determines desired bump rate for fading * * Bump_Palette -- increments the palette one step, for fading * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* ********************************* Includes ********************************** */ //#include #include "palette.h" #include "timer.h" #include "wwstd.h" /* ********************************* Constants ********************************* */ /* ********************************** Globals ********************************** */ extern "C" extern unsigned char CurrentPalette[]; /* in pal.asm */ /* ******************************** Prototypes ********************************* */ PRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks, short *rate); PRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step); /* ******************************** Code ********************************* */ /*************************************************************************** * Set_Palette -- sets the current palette * * * * INPUT: * * void *palette - palette to set * * * * OUTPUT: * * none * * * * WARNINGS: * * * * HISTORY: * * 04/25/1994 SKB : Created. * * 04/27/1994 BR : Converted to 32-bit * *=========================================================================*/ void __cdecl Set_Palette(void *palette) { #if(IBM) Set_Palette_Range(palette); #else Copy_Palette(palette,CurrentPalette); LoadRGB4(&Main_Screen->ViewPort,palette,32L); LoadRGB4(AltVPort,palette,32L); #endif } /* end of Set_Palette */ /*************************************************************************** * Set_Palette_Color -- Set a color number in a palette to the data. * * * * * * INPUT: * * void *palette - palette to set color in * * int color - which color index to set * * void *data - RGB data for color * * * * OUTPUT: * * none * * * * WARNINGS: * * * * HISTORY: * * 04/25/1994 SKB : Created. * * 04/27/1994 BR : Converted to 32-bit * *=========================================================================*/ void __cdecl Set_Palette_Color(void *palette, int color, void *data) { /* ---------------------- Return if 'palette' is NULL ----------------------- */ if (!palette) return; /* ------------------- Change the color & set the palette ------------------- */ #if(IBM) memcpy(&((unsigned char *)palette)[color * RGB_BYTES], data, RGB_BYTES); Set_Palette_Range(palette); #else palette[color] = *(unsigned short*)data; Set_Palette(palette); #endif } /* end of Set_Palette */ /*************************************************************************** * Fade_Palette_To -- Fades the current palette into another * * * * This will allow the palette to fade from current palette into the * * palette that was passed in. This can be used to fade in and fade out. * * * * INPUT: * * char *palette1 - this is the palette to fade to. * * unsigned int delay - fade with this timer count down * * void *callback - user-defined callback function * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 06/20/1991 BS : Created. * *=========================================================================*/ void Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() ) { BOOL changed; // Flag that palette has changed this tick. short jump; // Gun values to jump per palette set. unsigned long timer; // Tick count timer used for timing. short ticksper; // The ticks (fixed point) per bit jump. int tickaccum; extern void (*cb_ptr)(void); // callback function pointer // (void *)cb_ptr = callback; cb_ptr = callback; /* ---------------------- Return if 'palette1' is NULL ---------------------- */ if (!palette1) return; /* --------------------------- Get the bump rate ---------------------------- */ Determine_Bump_Rate(palette1, delay, &ticksper, &jump); tickaccum = 0; // init accumulated elapsed time timer = TickCount.Time(); // timer = current time do { changed = FALSE; tickaccum += ticksper; // tickaccum = time of next change * 256 timer += (tickaccum >> 8); // timer = time of next change (rounded) tickaccum &= 0x0FF; // shave off high byte, keep roundoff bits changed = Bump_Palette(palette1, jump); // increment palette /* .................. Wait for time increment to elapse .................. */ if (changed) { while (TickCount.Time() < (int)timer) { /* ................. Update callback while waiting ................. */ if (callback) { #if LIB_EXTERNS_RESOLVED Sound_Callback(); // should be removed! #endif (*cb_ptr)(); } } } #if LIB_EXTERNS_RESOLVED Sound_Callback(); // should be removed! #endif if (callback) { (*cb_ptr)(); } } while (changed); } /* end of Fade_Palette_To */ /*************************************************************************** * Determine_Bump_Rate -- determines desired bump rate for fading * * * * INPUT: * * unsigned char *palette - palette to fade to * * int delay - desired time delay in 60ths of a second * * short *ticks - output: loop ticks per color jump * * short *rate - output: color gun increment rate * * * * OUTPUT: * * none * * * * WARNINGS: * * * * HISTORY: * * 04/27/1994 BR : Converted to 32-bit * * 08/02/1994 SKB : Made private * *=========================================================================*/ PRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks, short *rate) { int gun1; // Palette 1 gun value. int gun2; // Palette 2 gun value. int diff; // Maximum color gun difference. int tp; // Temporary tick accumulator. int index; // Color gun working index. long t; // Working tick intermediate value. int adiff; // Absolute difference between guns. /* ------------------------ Find max gun difference ------------------------- */ diff = 0; for (index = 0; index < PALETTE_BYTES; index++) { gun1 = ((unsigned char *)palette)[index]; gun2 = CurrentPalette[index]; adiff = ABS(gun1-gun2); diff = MAX(diff, adiff); } /*------------------------------------------------------------------------ ticks = (total time delay ) / (max gun diff) The value is computed based on (delay * 256), for fixed-point math; the lower bits represent the leftover from the division; 'ticks' is returned still shifted, so the low bits can be used to accumulate the time more accurately; the caller must shift the accumulated value down 8 bits to determine the actual elapsed time! ------------------------------------------------------------------------*/ t = ((long)delay) << 8; if (diff) { t /= diff; t = MIN((long)t, (long)0x7FFF); } *ticks = (short)t; /*------------------------------------------------------------------------ Adjust the color gun rate value if the time to fade is faster than can reasonably be performed given the palette change, ie if (ticks>>8)==0, and thus less than 1/60 of a second ------------------------------------------------------------------------*/ tp = *ticks; *rate = 1; while (*rate <= diff && *ticks < 256) { *ticks += tp; *rate += 1; } } /* end of Determine_Bump_Rate */ /*************************************************************************** * Bump_Palette -- increments the palette one step, for fading * * * * INPUT: * * palette1 - palette to fade towards * * step - max step amount, determined by Determine_Bump_Rate * * * * OUTPUT: * * FALSE = no change, TRUE = changed * * * * WARNINGS: * * * * HISTORY: * * 04/27/1994 BR : Created. * * 08/02/1994 SKB : Made private * *=========================================================================*/ #if(IBM) PRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step) { BOOL changed=FALSE; // Flag that palette has changed this tick. int index; // Index to DAC register gun. int gun1,gun2; // Palette 1 gun value. unsigned char palette[PALETTE_BYTES]; // copy of current palette /* ---------------------- Return if 'palette1' is NULL ---------------------- */ if (!palette1) return (FALSE); /* ------------------------ Copy the current palette ------------------------ */ memcpy(palette, CurrentPalette, 768); /* ----------------------- Loop through palette bytes ----------------------- */ for (index = 0; index < PALETTE_BYTES; index++) { gun1 = ((unsigned char *)palette1)[index]; gun2 = palette[index]; /* ............. If the colors match, go on to the next one .............. */ if (gun1 == gun2) continue; changed = TRUE; /* .................. Increment current palette's color .................. */ if (gun2 < gun1) { gun2 += step; gun2 = MIN(gun2, gun1); // make sure we didn't overshoot it } /* .................. Decrement current palette's color .................. */ else { gun2 -= step; gun2 = MAX(gun2, gun1); // make sure we didn't overshoot it } palette[index] = (unsigned char)gun2; } /* ----------------- Set current palette to the new palette ----------------- */ if (changed) { Set_Palette(&palette[0]); } return (changed); } /* end of Bump_Palette */ #else /* This is already implemented in asm on the Amiga */ #endif void (*cb_ptr)(void); // callback function pointer /**************************** End of palette.cpp ***************************/