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