1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ultima/ultima8/graphics/palette_fader_process.h"
24 #include "ultima/ultima8/kernel/kernel.h"
25 #include "ultima/ultima8/ultima8.h"
26
27 namespace Ultima {
28 namespace Ultima8 {
29
30 PaletteFaderProcess *PaletteFaderProcess::_fader = nullptr;
31
32 // p_dynamic_class stuff
DEFINE_RUNTIME_CLASSTYPE_CODE(PaletteFaderProcess)33 DEFINE_RUNTIME_CLASSTYPE_CODE(PaletteFaderProcess)
34
35 PaletteFaderProcess::PaletteFaderProcess() : Process(), _priority(0),
36 _counter(0), _maxCounter(0) {
37 }
38
PaletteFaderProcess(PalTransforms trans,int priority,int frames)39 PaletteFaderProcess::PaletteFaderProcess(PalTransforms trans,
40 int priority, int frames) : _priority(priority),
41 _counter(frames), _maxCounter(frames) {
42 PaletteManager *pm = PaletteManager::get_instance();
43 Palette *pal = pm->getPalette(PaletteManager::Pal_Game);
44 for (int i = 0; i < 12; i++) _oldMatrix[i] = pal->_matrix[i];
45 pm->getTransformMatrix(_newMatrix, trans);
46 pal->_transform = trans;
47 }
48
PaletteFaderProcess(uint32 col32,bool from,int priority,int frames,bool current)49 PaletteFaderProcess::PaletteFaderProcess(uint32 col32, bool from,
50 int priority, int frames, bool current) : _priority(priority),
51 _counter(frames), _maxCounter(frames) {
52 PaletteManager *pm = PaletteManager::get_instance();
53 Palette *pal = pm->getPalette(PaletteManager::Pal_Game);
54 if (!from) {
55 if (current)
56 for (int i = 0; i < 12; i++) _oldMatrix[i] = pal->_matrix[i];
57 else
58 pm->getTransformMatrix(_oldMatrix, pal->_transform);
59 pm->getTransformMatrix(_newMatrix, col32);
60 } else {
61 pm->getTransformMatrix(_oldMatrix, col32);
62 if (current)
63 for (int i = 0; i < 12; i++) _newMatrix[i] = pal->_matrix[i];
64 else
65 pm->getTransformMatrix(_newMatrix, pal->_transform);
66 }
67 }
68
PaletteFaderProcess(const int16 from[12],const int16 to[12],int priority,int frames)69 PaletteFaderProcess::PaletteFaderProcess(const int16 from[12], const int16 to[12],
70 int priority, int frames) : _priority(priority),
71 _counter(frames), _maxCounter(frames) {
72 int i;
73 for (i = 0; i < 12; i++) _oldMatrix[i] = from[i];
74 for (i = 0; i < 12; i++) _newMatrix[i] = to[i];
75 }
76
~PaletteFaderProcess(void)77 PaletteFaderProcess::~PaletteFaderProcess(void) {
78 if (_fader == this)
79 _fader = nullptr;
80 }
81
run()82 void PaletteFaderProcess::run() {
83 int16 matrix[12];
84
85 for (int i = 0; i < 12; i++) {
86 int32 o = _oldMatrix[i] * _counter;
87 int32 n = _newMatrix[i] * (_maxCounter - _counter);
88 matrix[i] = static_cast<int16>((o + n) / _maxCounter);
89 }
90
91 PaletteManager::get_instance()->transformPalette(
92 PaletteManager::Pal_Game,
93 matrix);
94
95 if (!_counter--) terminate();
96 }
97
saveData(Common::WriteStream * ws)98 void PaletteFaderProcess::saveData(Common::WriteStream *ws) {
99 Process::saveData(ws);
100
101 ws->writeUint32LE(static_cast<uint32>(_priority));
102 ws->writeUint32LE(static_cast<uint32>(_counter));
103 ws->writeUint32LE(static_cast<uint32>(_maxCounter));
104 unsigned int i;
105 for (i = 0; i < 12; ++i)
106 ws->writeUint16LE(_oldMatrix[i]);
107 for (i = 0; i < 12; ++i)
108 ws->writeUint16LE(_newMatrix[i]);
109 }
110
loadData(Common::ReadStream * rs,uint32 version)111 bool PaletteFaderProcess::loadData(Common::ReadStream *rs, uint32 version) {
112 if (!Process::loadData(rs, version)) return false;
113
114 _priority = static_cast<int>(rs->readUint32LE());
115 _counter = static_cast<int>(rs->readUint32LE());
116 _maxCounter = static_cast<int>(rs->readUint32LE());
117
118 unsigned int i;
119 for (i = 0; i < 12; ++i)
120 _oldMatrix[i] = rs->readUint16LE();
121 for (i = 0; i < 12; ++i)
122 _newMatrix[i] = rs->readUint16LE();
123
124 _fader = this; //static
125 return true;
126 }
127
I_fadeToPaletteTransform(const uint8 * args,unsigned int)128 uint32 PaletteFaderProcess::I_fadeToPaletteTransform(const uint8 *args,
129 unsigned int /*argsize*/) {
130 ARG_UINT16(transform);
131 ARG_UINT16(priority);
132
133 // If current _fader has higher _priority, we do nothing
134 if (_fader && _fader->_priority > priority)
135 return 0;
136 else if (_fader && !_fader->is_terminated())
137 _fader->terminate();
138
139 _fader = new PaletteFaderProcess(static_cast<PalTransforms>(transform),
140 priority, 45);
141
142 return Kernel::get_instance()->addProcess(_fader);
143 }
144
I_fadeToBlack(const uint8 * args,unsigned int argsize)145 uint32 PaletteFaderProcess::I_fadeToBlack(const uint8 *args,
146 unsigned int argsize) {
147 if (_fader && _fader->_priority > 0x7FFF)
148 return 0;
149 else if (_fader && !_fader->is_terminated())
150 _fader->terminate();
151
152 int nsteps = (GAME_IS_U8 ? 30 : 40);
153 if (argsize > 0) {
154 ARG_UINT16(n);
155 nsteps = n;
156 if (argsize > 2) {
157 ARG_UINT16(unk);
158 warning("PaletteFaderProcess::I_fadeToBlackWithParam: Ignoring param %d", unk);
159 }
160 }
161
162 _fader = new PaletteFaderProcess(0x00000000, false, 0x7FFF, nsteps, true);
163 return Kernel::get_instance()->addProcess(_fader);
164 }
165
I_fadeFromBlack(const uint8 * args,unsigned int argsize)166 uint32 PaletteFaderProcess::I_fadeFromBlack(const uint8 *args,
167 unsigned int argsize) {
168 if (_fader && _fader->_priority > 0x7FFF)
169 return 0;
170 else if (_fader && !_fader->is_terminated())
171 _fader->terminate();
172
173 int nsteps = (GAME_IS_U8 ? 30 : 40);
174 if (argsize > 0) {
175 ARG_UINT16(n);
176 nsteps = n;
177 if (argsize > 2) {
178 ARG_UINT16(unk);
179 warning("PaletteFaderProcess::I_fadeFromBlackWithParam: Ignoring param %d", unk);
180 }
181 }
182
183 _fader = new PaletteFaderProcess(0x00000000, true, 0x7FFF, nsteps, false);
184 return Kernel::get_instance()->addProcess(_fader);
185 }
186
I_fadeToWhite(const uint8 *,unsigned int)187 uint32 PaletteFaderProcess::I_fadeToWhite(const uint8 * /*args*/,
188 unsigned int /*argsize*/) {
189 if (_fader && _fader->_priority > 0x7FFF)
190 return 0;
191 else if (_fader && !_fader->is_terminated())
192 _fader->terminate();
193
194 _fader = new PaletteFaderProcess(0x00FFFFFF, false, 0x7FFF, 30, true);
195 return Kernel::get_instance()->addProcess(_fader);
196 }
197
I_fadeFromWhite(const uint8 *,unsigned int)198 uint32 PaletteFaderProcess::I_fadeFromWhite(const uint8 * /*args*/,
199 unsigned int /*argsize*/) {
200 if (_fader && _fader->_priority > 0x7FFF)
201 return 0;
202 else if (_fader && !_fader->is_terminated())
203 _fader->terminate();
204
205 _fader = new PaletteFaderProcess(0x00FFFFFF, true, 0x7FFF, 30, false);
206 return Kernel::get_instance()->addProcess(_fader);
207 }
208
I_lightningBolt(const uint8 *,unsigned int)209 uint32 PaletteFaderProcess::I_lightningBolt(const uint8 * /*args*/,
210 unsigned int /*argsize*/) {
211 if (_fader && _fader->_priority > -1)
212 return 0;
213 else if (_fader && !_fader->is_terminated())
214 _fader->terminate();
215
216 _fader = new PaletteFaderProcess(0x3FCFCFCF, true, -1, 10, false);
217 return Kernel::get_instance()->addProcess(_fader);
218 }
219
220 static const int16 NoFadeMatrix[] = {0x800, 0, 0, 0,
221 0, 0x800, 0, 0,
222 0, 0, 0x800, 0
223 };
224 // Transform used in Crusader is Yib. We only care about Y:
225 // Y = (r * 0.299 + g * 0.587 + b * 0.114)
226 static const int16 GreyFadeMatrix[] = {612, 1202, 233, 0,
227 612, 1202, 233, 0,
228 612, 1202, 233, 0
229 };
230
231 static const int16 AllWhiteMatrix[] = {0, 0, 0, 0x7ff,
232 0, 0, 0, 0x7ff,
233 0, 0, 0, 0x7ff
234 };
235
236 static const int16 AllBlackMatrix[] = {0, 0, 0, 0,
237 0, 0, 0, 0,
238 0, 0, 0, 0
239 };
240
I_fadeToGreyScale(const uint8 *,unsigned int)241 uint32 PaletteFaderProcess::I_fadeToGreyScale(const uint8 * /*args*/,
242 unsigned int /*argsize*/) {
243 if (_fader && _fader->_priority > 0x7FFF) return 0;
244 else if (_fader) _fader->terminate();
245
246 _fader = new PaletteFaderProcess(NoFadeMatrix, GreyFadeMatrix, 0x7FFF, 1);
247 return Kernel::get_instance()->addProcess(_fader);
248 }
249
I_fadeToGivenColor(const uint8 * args,unsigned int)250 uint32 PaletteFaderProcess::I_fadeToGivenColor(const uint8 *args,
251 unsigned int /*argsize*/) {
252 if (_fader && _fader->_priority > 0x7FFF) return 0;
253 else if (_fader) _fader->terminate();
254
255 // TODO: guessing that color order should be same as other one below?
256 ARG_UINT8(r);
257 ARG_UINT8(g);
258 ARG_UINT8(b);
259 ARG_UINT16(nsteps);
260 ARG_UINT16(unk);
261
262 uint32 target = (r << 16) | (g << 8) | (b << 0);
263
264 warning("PaletteFaderProcess::I_fadeToGivenColor: Ignoring param %d", unk);
265
266 _fader = new PaletteFaderProcess(target, true, 0x7FFF, nsteps, false);
267 return Kernel::get_instance()->addProcess(_fader);
268 }
269
I_fadeToGamePal(const uint8 * args,unsigned int argsize)270 uint32 PaletteFaderProcess::I_fadeToGamePal(const uint8 *args,
271 unsigned int argsize) {
272 if (_fader && _fader->_priority > 0x7FFF)
273 return 0;
274 else if (_fader && !_fader->is_terminated())
275 _fader->terminate();
276
277 int nsteps = (GAME_IS_U8 ? 30 : 20);
278 if (argsize > 0) {
279 ARG_UINT16(n);
280 nsteps = n;
281 if (argsize > 2) {
282 ARG_UINT16(unk);
283 warning("PaletteFaderProcess::I_fadeToGamePalWithParam: Ignoring param %d", unk);
284 }
285 }
286
287 int16 curmatrix[12];
288 PaletteManager *pm = PaletteManager::get_instance();
289 pm->getTransformMatrix(curmatrix, PaletteManager::Pal_Game);
290 _fader = new PaletteFaderProcess(curmatrix, NoFadeMatrix, 0x7FFF, nsteps);
291 return Kernel::get_instance()->addProcess(_fader);
292 }
293
I_jumpToGreyScale(const uint8 *,unsigned int)294 uint32 PaletteFaderProcess::I_jumpToGreyScale(const uint8 * /*args*/,
295 unsigned int /*argsize*/) {
296 if (_fader && _fader->_priority > 0x7FFF) return 0;
297 else if (_fader) _fader->terminate();
298
299 PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
300 GreyFadeMatrix);
301 return 0;
302 }
303
I_jumpToAllBlack(const uint8 *,unsigned int)304 uint32 PaletteFaderProcess::I_jumpToAllBlack(const uint8 * /*args*/,
305 unsigned int /*argsize*/) {
306 if (_fader && _fader->_priority > 0x7FFF) return 0;
307 else if (_fader) _fader->terminate();
308
309 PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
310 AllBlackMatrix);
311 return 0;
312 }
313
I_jumpToAllWhite(const uint8 *,unsigned int)314 uint32 PaletteFaderProcess::I_jumpToAllWhite(const uint8 * /*args*/,
315 unsigned int /*argsize*/) {
316 if (_fader && _fader->_priority > 0x7FFF) return 0;
317 else if (_fader) _fader->terminate();
318
319 PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
320 AllWhiteMatrix);
321 return 0;
322 }
323
I_jumpToAllGivenColor(const uint8 * args,unsigned int)324 uint32 PaletteFaderProcess::I_jumpToAllGivenColor(const uint8 *args,
325 unsigned int /*argsize*/) {
326 if (_fader && _fader->_priority > 0x7FFF) return 0;
327 else if (_fader) _fader->terminate();
328
329 ARG_UINT8(r);
330 ARG_UINT8(g);
331 ARG_UINT8(b);
332
333 // Transform matrix goes 0~2048, scale 0-63 vals from input
334 const int16 r16 = static_cast<int16>(r) * 32;
335 const int16 g16 = static_cast<int16>(g) * 32;
336 const int16 b16 = static_cast<int16>(b) * 32;
337
338 const int16 color_matrix[] = {0, 0, 0, r16,
339 0, 0, 0, g16,
340 0, 0, 0, b16
341 };
342
343 PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
344 color_matrix);
345 return 0;
346 }
347
I_jumpToNormalPalette(const uint8 *,unsigned int)348 uint32 PaletteFaderProcess::I_jumpToNormalPalette(const uint8 * /*args*/,
349 unsigned int /*argsize*/) {
350 if (_fader && _fader->_priority > 0x7FFF) return 0;
351 else if (_fader) _fader->terminate();
352
353 PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
354 NoFadeMatrix);
355 return 0;
356 }
357
358 } // End of namespace Ultima8
359 } // End of namespace Ultima
360