1 /*
2  * This file is released under the GNU General Public Licence
3  *
4  * authors:
5  * Richard Ashbury       <richard.asbury@btinternet.com>
6  * Jean-Christophe Hoelt <jeko@ios-software.com>
7  */
8 
9 #include "corona_palette.h"
10 
11 #include <cstdlib>
12 #include <cstring>
13 using namespace std;
14 
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 
18 // Palette stored in compressed format (just checkpoints)
19 class CompressedPalette
20 {
21   public:
22   ColorRGB m_col[16];
23   int      m_ind[16];
24   int      m_nb;
25 
CompressedPalette()26   CompressedPalette() : m_nb(0) {}
push_color(int i,ColorRGB col)27   void push_color(int i, ColorRGB col) { m_col[m_nb] = col; m_ind[m_nb++] = i; }
28 
29   void expand(Palette pal) const;
30 };
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 
PaletteCycler(const int palettes[][NB_PALETTES],int nbPalettes)34 PaletteCycler::PaletteCycler(const int palettes[][NB_PALETTES], int nbPalettes)
35   : m_palettes(palettes, nbPalettes)
36 {
37   for (int i=0;i<256;++i) {
38     m_curpal[i].rgbBlue  = 0;
39     m_curpal[i].rgbGreen = 0;
40     m_curpal[i].rgbRed   = 0;
41   }
42   startPaletteTransition();
43   affectPaletteTransition(1);
44   m_transferring  = false;
45   m_srcnum        = m_destnum;
46 }
47 
startPaletteTransition()48 void PaletteCycler::startPaletteTransition()
49 {
50   if (m_palettes.size() > 0)
51   {
52     // Copy the current palette to the "source palette"
53     memcpy(m_srcpal, m_curpal, sizeof(m_srcpal));
54 
55     // Create a new palette as the "destination palette"
56     m_srcnum  = m_destnum;
57     m_destnum = rand() % (int) m_palettes.size();
58     m_palettes.expandPalette(m_destnum, m_destpal);
59 
60     // Begin the transition
61     m_transferring = true;
62     m_progress     = 0;
63   }
64 }
65 
update(TimedLevel * pLevels)66 void PaletteCycler::update(TimedLevel *pLevels)
67 {
68   // Randomly change the destination palette
69   if (pLevels->timeStamp - pLevels->lastbeat > 10000000) {
70     if (rand() % 100 == 0) startPaletteTransition();
71   }
72   else {
73     if (rand() % 400 == 0) startPaletteTransition();
74   }
75 
76   // Continue any current palette transtion
77   if (m_transferring) {
78     if (pLevels->timeStamp - pLevels->lastbeat > 10000000) m_progress += 0.01;
79     else m_progress += 0.005;
80     if (m_progress >= 1) {
81       m_transferring = false;
82       m_progress = 1;
83       m_srcnum = m_destnum;
84     }
85     // Use an inverse sigmoid transition to emphasise the midway palette
86     double x;
87     if (m_progress < 0.5) x = 2 * m_progress * (1 - m_progress);
88     else x = 2 * m_progress * (m_progress - 1) + 1;
89     affectPaletteTransition(x);
90   }
91 }
92 
affectPaletteTransition(double p)93 void PaletteCycler::affectPaletteTransition(double p)
94 {
95   for (int i = 0; i < 256; ++i)
96   {
97     ColorRGB c1 = m_srcpal[i];
98     ColorRGB c2 = m_destpal[i];
99     m_curpal[i].rgbRed   = (unsigned char) ((1 - p) * c1.rgbRed   + p * c2.rgbRed);
100     m_curpal[i].rgbGreen = (unsigned char) ((1 - p) * c1.rgbGreen + p * c2.rgbGreen);
101     m_curpal[i].rgbBlue  = (unsigned char) ((1 - p) * c1.rgbBlue  + p * c2.rgbBlue);
102   }
103 }
104 
105 
106 
107 ///////////////////////////////////////////////////////////////////////////////
108 
expand(Palette dest) const109 void CompressedPalette::expand(Palette dest) const
110 {
111   ColorRGB col;
112   int entry = 0;
113   col.rgbBlue = col.rgbGreen = col.rgbRed = 0;
114 
115   int i = 0;
116   for (; i < m_nb; ++i)
117   {
118     int j = entry;
119     for (; j < m_ind[i]; ++j)
120     {
121       double t = (double) (j - entry) / (m_ind[i] - entry);
122       dest[j].rgbRed   = (unsigned char) ((1 - t) * col.rgbRed   + t * m_col[i].rgbRed);
123       dest[j].rgbGreen = (unsigned char) ((1 - t) * col.rgbGreen + t * m_col[i].rgbGreen);
124       dest[j].rgbBlue  = (unsigned char) ((1 - t) * col.rgbBlue  + t * m_col[i].rgbBlue);
125     }
126     entry = j;
127     col = m_col[i];
128   }
129   for (; entry < 256; ++entry) dest[entry] = col;
130 }
131 
132 ///////////////////////////////////////////////////////////////////////////////
133 
PaletteCollection(const int palettes[][NB_PALETTES],int nbPalettes)134 PaletteCollection::PaletteCollection(const int palettes[][NB_PALETTES], int nbPalettes)
135 {
136   m_cpal = new CompressedPalette[nbPalettes];
137   m_nbPalettes = nbPalettes;
138 
139 	// Set up the palettes from the array
140 	for (int i = 0; i < nbPalettes; ++i)
141   {
142     CompressedPalette newpal;
143 		const int* pal = palettes[i];
144 		for (int j = 1; j < pal[0] * 2; j += 2)
145     {
146 			ColorRGB rgb;
147 			rgb.rgbRed   = (pal[j + 1] & 0xff0000) >> 16;
148 			rgb.rgbGreen = (pal[j + 1] & 0xff00) >> 8;
149 			rgb.rgbBlue  = pal[j + 1] & 0xff;
150 			newpal.push_color(pal[j], rgb);
151 		}
152     m_cpal[i] = newpal;
153 	}
154 }
155 
~PaletteCollection()156 PaletteCollection::~PaletteCollection()
157 {
158   delete[] m_cpal;
159 }
160 
expandPalette(int i,Palette dest) const161 void PaletteCollection::expandPalette(int i, Palette dest) const
162 {
163   m_cpal[i].expand(dest);
164 }
165 
166 ///////////////////////////////////////////////////////////////////////////////
167 
blitSurface8To32(unsigned char * byteSurf,int * colorSurf,int palette[256],int size)168 void blitSurface8To32(unsigned char *byteSurf, int *colorSurf, int palette[256], int size)
169 {
170   int i = 0;
171   while(size--) {
172     colorSurf[i++] = palette[byteSurf[size]];
173   }
174 }
175 
paletteToRGBA(int dest[256],const Palette src)176 void paletteToRGBA(int dest[256], const Palette src)
177 {
178   for (int i=0; i<256; ++i) {
179     int alpha = (i<128?i*2:255);
180     dest[i] = (alpha << 24) | ((int)src[i].rgbRed << 16) | ((int)src[i].rgbGreen << 8) | (int)src[i].rgbBlue;
181 /*    dest[i] = ((int)i << 24) | ((int)src[i].rgbRed << 0) | ((int)src[i].rgbGreen << 8) | ((int)src[i].rgbBlue << 16); */
182   }
183 }
184