1 /*
2 FADES.C
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(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 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 Friday, June 10, 1994 6:59:04 PM
22 
23 Saturday, June 11, 1994 12:49:19 AM
24 	not doing signed math on the color deltas resulted in some very cool static-ish effects
25 	resulting from integer overflow.
26 Saturday, July 9, 1994 1:06:20 PM
27 	fade_finished() was acting like fade_not_finished().
28 Sunday, September 25, 1994 12:50:34 PM  (Jason')
29 	cool new fades.
30 Monday, April 3, 1995 11:22:58 AM  (Jason')
31 	fade effects for underwater/lava/goo/sewage.
32 Monday, July 10, 1995 8:23:03 PM  (Jason)
33 	random transparencies
34 Thursday, August 24, 1995 6:20:06 PM  (Jason)
35 	removed macintosh dependencies
36 Monday, October 30, 1995 8:02:12 PM  (Jason)
37 	fade prioritites for juggernaut flash
38 
39 Jan 30, 2000 (Loren Petrich):
40 	Removed some "static" declarations that conflict with "extern"
41 
42 May 17, 2000 (Loren Petrich):
43 	Added separate under-JjaroGoo fade effects
44 
45 May 20, 2000 (Loren Petrich):
46 	Added XML-parser support.
47 	Note: "transparency" here should be called the opacity,
48 	since if it is zero, then colors will be unmodified.
49 
50 May 29, 2000 (Loren Petrich):
51 	Extended the ranges of the opacities (values > 1 and < 0 now OK)
52 
53 May 30, 2000 (Loren Petrich):
54 	Added stuff for transmitting fader info to OpenGL
55 
56 Jul 1, 2000 (Loren Petrich):
57 	Added some idiot-proofing to the fader accessors
58 
59 Jan 31, 2001 (Loren Petrich):
60 	Added delayed action for the fader effect, so as to get around certain MacOS oddities
61 */
62 
63 #include "cseries.h"
64 #include "fades.h"
65 #include "screen.h"
66 #include "interface.h"
67 #include "map.h" // for TICKS_PER_SECOND
68 #include "InfoTree.h"
69 
70 #include <string.h>
71 #include <stdlib.h>
72 #include <math.h>
73 #include <limits.h>
74 
75 // LP additions:
76 #include <string.h>
77 #include "OGL_Faders.h"
78 
79 #include "Music.h"
80 #include "Movie.h"
81 
82 /* ---------- constants */
83 
84 #define ADJUSTED_TRANSPARENCY_DOWNSHIFT 8
85 
86 #define MINIMUM_FADE_RESTART (MACHINE_TICKS_PER_SECOND/2)
87 
88 /* ---------- macros */
89 
90 #define FADES_RANDOM() ((fades_random_seed&1) ? (fades_random_seed= (fades_random_seed>>1)^0xb400) : (fades_random_seed>>= 1))
91 
92 /* ---------- types */
93 
94 typedef void (*fade_proc)(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
95 
96 /* ---------- structures */
97 
98 /* an effect is something which is applied to the original color table before a fade begins */
99 struct fade_effect_definition
100 {
101 	short fade_type;
102 	_fixed transparency;
103 };
104 
105 enum
106 {
107 	_full_screen_flag= 0x0001,
108 	_random_transparency_flag= 0x0002
109 };
110 
111 struct fade_definition
112 {
113 	fade_proc proc;
114 	struct rgb_color color;
115 	_fixed initial_transparency, final_transparency; /* in [0,FIXED_ONE] */
116 
117 	short period;
118 
119 	uint16 flags;
120 	short priority; // higher is higher
121 };
122 
123 #define FADE_IS_ACTIVE(f) ((f)->flags&(uint16)0x8000)
124 #define SET_FADE_ACTIVE_STATUS(f,s) ((void)((s)?((f)->flags|=(uint16)0x8000):((f)->flags&=(uint16)~0x8000)))
125 
126 struct fade_data
127 {
128 	uint16 flags; /* [active.1] [unused.15] */
129 
130 	short type;
131 	short fade_effect_type;
132 
133 	uint32 last_update_tick;
134 	uint32 last_update_game_tick;
135 
136 	struct color_table *original_color_table;
137 	struct color_table *animated_color_table;
138 };
139 
140 /* ---------- globals */
141 
142 static struct fade_data *fade = NULL;
143 static short last_fade_type = NUMBER_OF_FADE_TYPES;
144 
145 static uint16 fades_random_seed= 0x1;
146 
147 // LP addition: pointer to OpenGL fader to be used in the color-table functions below
148 // It is NULL if OpenGL is inactive
149 static OGL_Fader *CurrentOGLFader = NULL;
150 
151 static int FadeEffectDelay = 0;
152 
153 /* ---------- fade definitions */
154 
155 static void tint_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
156 static void randomize_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
157 static void negate_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
158 static void dodge_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
159 static void burn_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
160 static void soft_tint_color_table(struct color_table *original_color_table, struct color_table *animated_color_table, struct rgb_color *color, _fixed transparency);
161 
162 static struct fade_definition fade_definitions[NUMBER_OF_FADE_TYPES]=
163 {
164 	{tint_color_table, {0, 0, 0}, FIXED_ONE, FIXED_ONE, 0, _full_screen_flag, 0}, /* _start_cinematic_fade_in */
165 	{tint_color_table, {0, 0, 0}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/2, _full_screen_flag, 0}, /* _cinematic_fade_in */
166 	{tint_color_table, {0, 0, 0}, FIXED_ONE, 0, 3*MACHINE_TICKS_PER_SECOND/2, _full_screen_flag, 0}, /* _long_cinematic_fade_in */
167 	{tint_color_table, {0, 0, 0}, 0, FIXED_ONE, MACHINE_TICKS_PER_SECOND/2, _full_screen_flag, 0}, /* _cinematic_fade_out */
168 	{tint_color_table, {0, 0, 0}, 0, 0, 0, _full_screen_flag, 0}, /* _end_cinematic_fade_out */
169 
170 	{tint_color_table, {65535, 0, 0}, (3*FIXED_ONE)/4, 0, MACHINE_TICKS_PER_SECOND/4, 0, 0}, /* _fade_red */
171 	{tint_color_table, {65535, 0, 0}, FIXED_ONE, 0, (3*MACHINE_TICKS_PER_SECOND)/4, 0, 0}, /* _fade_big_red */
172 	{tint_color_table, {0, 65535, 0}, FIXED_ONE_HALF, 0, MACHINE_TICKS_PER_SECOND/4, 0, 0}, /* _fade_bonus */
173 	{tint_color_table, {65535, 65535, 50000}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/3, 0, 0}, /* _fade_bright */
174 	{tint_color_table, {65535, 65535, 50000}, FIXED_ONE, 0, 4*MACHINE_TICKS_PER_SECOND, 0, 1}, /* _fade_long_bright */
175 	{tint_color_table, {65535, 65535, 0}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/2, 0, 0}, /* _fade_yellow */
176 	{tint_color_table, {65535, 65535, 0}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_big_yellow */
177 	{tint_color_table, {215*256, 107*256, 65535}, (3*FIXED_ONE)/4, 0, MACHINE_TICKS_PER_SECOND/4, 0, 0}, /* _fade_purple */
178 	{tint_color_table, {169*256, 65535, 224*256}, (3*FIXED_ONE)/4, 0, MACHINE_TICKS_PER_SECOND/2, 0, 0}, /* _fade_cyan */
179 	{tint_color_table, {65535, 65535, 65535}, FIXED_ONE_HALF, 0, MACHINE_TICKS_PER_SECOND/4, 0, 0}, /* _fade_white */
180 	{tint_color_table, {65535, 65535, 65535}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/2, 0, 0}, /* _fade_big_white */
181 	{tint_color_table, {65535, 32768, 0}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/4, 0, 0}, /* _fade_orange */
182 	{tint_color_table, {65535, 32768, 0}, FIXED_ONE/4, 0, 3*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_long_orange */
183 	{tint_color_table, {0, 65535, 0}, 3*FIXED_ONE/4, 0, MACHINE_TICKS_PER_SECOND/2, 0, 0}, /* _fade_green */
184 	{tint_color_table, {65535, 0, 65535}, FIXED_ONE/4, 0, 3*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_long_green */
185 
186 	{randomize_color_table, {0, 0, 0}, FIXED_ONE, 0, (3*MACHINE_TICKS_PER_SECOND)/8, 0, 0}, /* _fade_static */
187 	{negate_color_table, {65535, 65535, 65535}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/2, 0, 0}, /* _fade_negative */
188 	{negate_color_table, {65535, 65535, 65535}, FIXED_ONE, 0, (3*MACHINE_TICKS_PER_SECOND)/2, 0, 0}, /* _fade_big_negative */
189 	{negate_color_table, {0, 65535, 0}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND/2, _random_transparency_flag, 0}, /* _fade_flicker_negative */
190 	{dodge_color_table, {0, 65535, 0}, FIXED_ONE, 0, (3*MACHINE_TICKS_PER_SECOND)/4, 0, 0}, /* _fade_dodge_purple */
191 	{burn_color_table, {0, 65535, 65535}, FIXED_ONE, 0, MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_burn_cyan */
192 	{dodge_color_table, {0, 0, 65535}, FIXED_ONE, 0, (3*MACHINE_TICKS_PER_SECOND)/2, 0, 0}, /* _fade_dodge_yellow */
193 	{burn_color_table, {0, 65535, 0}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_burn_green */
194 
195 	{soft_tint_color_table, {137*256, 0, 137*256}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_tint_purple */
196 	{soft_tint_color_table, {0, 0, 65535}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_tint_blue */
197 	{soft_tint_color_table, {65535, 16384, 0}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_tint_orange */
198 	{soft_tint_color_table, {32768, 65535, 0}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_tint_gross */
199 
200 	// LP addition: underneath JjaroGoo (default: like sewage)
201 	{soft_tint_color_table, {32768, 65535, 0}, FIXED_ONE, 0, 2*MACHINE_TICKS_PER_SECOND, 0, 0}, /* _fade_tint_gross */
202 };
203 
204 // LP change: rearranged to get order: water, lava, sewage, jjaro, pfhor
205 struct fade_effect_definition fade_effect_definitions[NUMBER_OF_FADE_EFFECT_TYPES]=
206 {
207 	{_fade_tint_blue, 3*FIXED_ONE/4}, /* _effect_under_water */
208 	{_fade_tint_orange, 3*FIXED_ONE/4}, /* _effect_under_lava */
209 	{_fade_tint_gross, 3*FIXED_ONE/4}, /* _effect_under_sewage */
210 	{_fade_tint_jjaro, 3*FIXED_ONE/4}, /* _effect_under_jjaro */ // LP addition
211 	{_fade_tint_green, 3*FIXED_ONE/4}, /* _effect_under_goo */
212 };
213 
214 static float actual_gamma_values[NUMBER_OF_GAMMA_LEVELS]=
215 {
216 	1.3F,
217 	1.15F,
218 	1.0F, // default
219 	0.95F,
220 	0.90F,
221 	0.85F,
222 	0.77F,
223 	0.70F
224 };
225 
226 /* ---------- private prototypes */
227 
228 static fade_definition *get_fade_definition(
229 	const short index);
230 
231 static fade_effect_definition *get_fade_effect_definition(
232 	const short index);
233 
234 static void recalculate_and_display_color_table(short type, _fixed transparency,
235 	struct color_table *original_color_table, struct color_table *animated_color_table, bool fade_active);
236 
237 // LP additions for OpenGL fader support; both of them use the pointer to the current
238 // OpenGL fader defined above.
239 
240 // Set up OpenGL fader-queue entry -- arg is which one (liquid or other);
241 // the fader type is set to NONE.
242 static void SetOGLFader(int Index);
243 
244 // Translate the color and opacity values
245 static void TranslateToOGLFader(rgb_color &Color, _fixed Opacity);
246 
247 /* ---------- code */
248 
249 // Accessors:
get_fade_definition(const short index)250 fade_definition *get_fade_definition(
251 	const short index)
252 {
253 	return GetMemberWithBounds(fade_definitions,index,NUMBER_OF_FADE_TYPES);
254 }
255 
get_fade_effect_definition(const short index)256 fade_effect_definition *get_fade_effect_definition(
257 	const short index)
258 {
259 	return GetMemberWithBounds(fade_effect_definitions,index,NUMBER_OF_FADE_EFFECT_TYPES);
260 }
261 
initialize_fades(void)262 void initialize_fades(
263 	void)
264 {
265 	/* allocate and initialize space for our fade_data structure */
266 	fade= new fade_data;
267 	assert(fade);
268 	fade->flags = 0;
269 
270 	SET_FADE_ACTIVE_STATUS(fade, false);
271 	fade->fade_effect_type= NONE;
272 }
273 
update_fades(bool game_in_progress)274 bool update_fades(
275 	bool game_in_progress)
276 {
277   if (FADE_IS_ACTIVE(fade))
278 	{
279 		struct fade_definition *definition= get_fade_definition(fade->type);
280 		// LP change: idiot-proofing
281 		if (!definition) return false;
282 
283 		_fixed transparency;
284 		short phase;
285 		if (game_in_progress)
286 		{
287 			phase = (dynamic_world->tick_count - fade->last_update_game_tick) * MACHINE_TICKS_PER_SECOND/TICKS_PER_SECOND;
288 		}
289 		else
290 		{
291 			phase = machine_tick_count() - fade->last_update_tick;
292 		}
293 
294 		if (phase>=definition->period)
295 		{
296 			transparency= definition->final_transparency;
297 			SET_FADE_ACTIVE_STATUS(fade, false);
298 		}
299 		else
300 		{
301 			transparency= definition->initial_transparency + (phase*(definition->final_transparency-definition->initial_transparency))/definition->period;
302 			if (definition->flags&_random_transparency_flag) transparency+= FADES_RANDOM()%(definition->final_transparency-transparency);
303 		}
304 
305 		recalculate_and_display_color_table(fade->type, transparency, fade->original_color_table, fade->animated_color_table, FADE_IS_ACTIVE(fade));
306 		Movie::instance()->AddFrame(Movie::FRAME_FADE);
307 	}
308 
309 	return FADE_IS_ACTIVE(fade) ? true : false;
310 }
311 
SetFadeEffectDelay(int _FadeEffectDelay)312 void SetFadeEffectDelay(int _FadeEffectDelay)
313 {
314 	FadeEffectDelay = _FadeEffectDelay;
315 }
316 
set_fade_effect(short type)317 void set_fade_effect(
318 	short type)
319 {
320 	bool ForceFEUpdate = false;
321 	if (FadeEffectDelay > 0)
322 	{
323 		ForceFEUpdate = true;
324 		FadeEffectDelay--;
325 	}
326 
327 	if (ForceFEUpdate || fade->fade_effect_type!=type)
328 	{
329 		fade->fade_effect_type= type;
330 
331 		if (!FADE_IS_ACTIVE(fade))
332 		{
333 			if (type==NONE)
334 			{
335 				// LP addition: OpenGL-fader handling
336 				for (int f=0; f<NUMBER_OF_FADER_QUEUE_ENTRIES; f++)
337 					SetOGLFader(f);
338 
339 				// Only do the video-card fader if the OpenGL fader is inactive
340 #ifdef HAVE_OPENGL
341 				if (!OGL_FaderActive())
342 #endif
343 					animate_screen_clut(world_color_table, false);
344 			}
345 			else
346 			{
347 				recalculate_and_display_color_table(NONE, 0, world_color_table, visible_color_table, false);
348 			}
349 		}
350 	}
351 }
352 
start_fade(short type)353 void start_fade(
354 	short type)
355 {
356 	explicit_start_fade(type, world_color_table, visible_color_table, true);
357 }
358 
explicit_start_fade(short type,struct color_table * original_color_table,struct color_table * animated_color_table,bool game_in_progress)359 void explicit_start_fade(
360 	short type,
361 	struct color_table *original_color_table,
362 	struct color_table *animated_color_table,
363 	bool game_in_progress)
364 {
365 	struct fade_definition *definition= get_fade_definition(type);
366 	// LP change: idiot-proofing
367 	if (!definition) return;
368 
369 	uint32 machine_ticks= machine_tick_count();
370 	bool do_fade= true;
371 
372 	if (FADE_IS_ACTIVE(fade))
373 	{
374 		struct fade_definition *old_definition= get_fade_definition(fade->type);
375 		// LP change: idiot-proofing
376 		if (old_definition)
377 		{
378 			if (old_definition->priority>definition->priority) do_fade= false;
379 			if (fade->type==type)
380 			{
381 				short phase;
382 				if (game_in_progress)
383 				{
384 					phase = (dynamic_world->tick_count - fade->last_update_game_tick) * MACHINE_TICKS_PER_SECOND/TICKS_PER_SECOND;
385 				}
386 				else
387 				{
388 					phase = machine_ticks - fade->last_update_tick;
389 				}
390 				if (phase<MINIMUM_FADE_RESTART) do_fade= false;
391 			}
392 		}
393 	}
394 
395 	if (do_fade)
396 	{
397 		SET_FADE_ACTIVE_STATUS(fade, false);
398 		last_fade_type = type;
399 
400 		recalculate_and_display_color_table(type, definition->initial_transparency, original_color_table, animated_color_table, definition->period);
401 		if (definition->period)
402 		{
403 			fade->type= type;
404 			fade->last_update_tick= machine_ticks;
405 			fade->last_update_game_tick = game_in_progress ? dynamic_world->tick_count : 0;
406 			fade->original_color_table= original_color_table;
407 			fade->animated_color_table= animated_color_table;
408 			SET_FADE_ACTIVE_STATUS(fade, true);
409 		}
410 	}
411 }
412 
stop_fade(void)413 void stop_fade(
414 	void)
415 {
416 	if (FADE_IS_ACTIVE(fade))
417 	{
418 		struct fade_definition *definition= get_fade_definition(fade->type);
419 		// LP change: idiot-proofing
420 		if (!definition) return;
421 
422 		recalculate_and_display_color_table(fade->type, definition->final_transparency,
423 			fade->original_color_table, fade->animated_color_table, false);
424 
425 		SET_FADE_ACTIVE_STATUS(fade, false);
426 	}
427 }
428 
fade_finished(void)429 bool fade_finished(
430 	void)
431 {
432 	return FADE_IS_ACTIVE(fade) ? false : true;
433 }
434 
full_fade(short type,struct color_table * original_color_table)435 void full_fade(
436 	short type,
437 	struct color_table *original_color_table)
438 {
439 	struct color_table animated_color_table;
440 
441 	obj_copy(animated_color_table, *original_color_table);
442 
443 	explicit_start_fade(type, original_color_table, &animated_color_table);
444 	while (update_fades())
445 		Music::instance()->Idle();
446 		;
447 }
448 
get_fade_period(short type)449 short get_fade_period(
450 	short type)
451 {
452 	struct fade_definition *definition= get_fade_definition(type);
453 	// LP change: idiot-proofing
454 	if (!definition) return 0;
455 
456 	return definition->period;
457 }
458 
gamma_correct_color_table(struct color_table * uncorrected_color_table,struct color_table * corrected_color_table,short gamma_level)459 void gamma_correct_color_table(
460 	struct color_table *uncorrected_color_table,
461 	struct color_table *corrected_color_table,
462 	short gamma_level)
463 {
464 	short i;
465 	float gamma;
466 	struct rgb_color *uncorrected= uncorrected_color_table->colors;
467 	struct rgb_color *corrected= corrected_color_table->colors;
468 
469 	assert(gamma_level>=0 && gamma_level<NUMBER_OF_GAMMA_LEVELS);
470 	gamma= actual_gamma_values[gamma_level];
471 	if (Movie::instance()->IsRecording())
472 		gamma = 1.0;
473 	if (gamma > 0.999F && gamma < 1.001F) {
474 		memcpy(corrected_color_table, uncorrected_color_table, sizeof(struct color_table));
475 		return;
476 	}
477 
478 	corrected_color_table->color_count= uncorrected_color_table->color_count;
479 	for (i= 0; i<uncorrected_color_table->color_count; ++i, ++corrected, ++uncorrected)
480 	{
481 		corrected->red = static_cast<uint16>(pow(static_cast<float>(uncorrected->red/65535.0), gamma)*65535.0);
482 		corrected->green = static_cast<uint16>(pow(static_cast<float>(uncorrected->green/65535.0), gamma)*65535.0);
483 		corrected->blue = static_cast<uint16>(pow(static_cast<float>(uncorrected->blue/65535.0), gamma)*65535.0);
484 	}
485 }
486 
get_actual_gamma_adjust(short gamma_level)487 float get_actual_gamma_adjust(short gamma_level)
488 {
489 	return actual_gamma_values[gamma_level];
490 }
491 
fade_blacked_screen(void)492 bool fade_blacked_screen(void)
493 {
494 	return (!FADE_IS_ACTIVE(fade) &&
495 			(last_fade_type == _start_cinematic_fade_in ||
496 			 last_fade_type == _cinematic_fade_out));
497 }
498 
499 /* ---------- private code */
500 
501 /*
502 struct fade_definition *get_fade_definition(
503 	short index)
504 {
505 	assert(index>=0 && index<NUMBER_OF_FADE_TYPES);
506 
507 	return fade_definitions + index;
508 }
509 
510 static struct fade_effect_definition *get_fade_effect_definition(
511 	short index)
512 {
513 	assert(index>=0 && index<NUMBER_OF_FADE_EFFECT_TYPES);
514 
515 	return fade_effect_definitions + index;
516 }
517 */
518 
519 //void draw_intro_screen(void); // from screen.cpp
520 
recalculate_and_display_color_table(short type,_fixed transparency,struct color_table * original_color_table,struct color_table * animated_color_table,bool fade_active)521 static void recalculate_and_display_color_table(
522 	short type,
523 	_fixed transparency,
524 	struct color_table *original_color_table,
525 	struct color_table *animated_color_table,
526 	bool fade_active)
527 {
528 	bool full_screen= false;
529 
530 	// LP addition: set up the OGL queue entry for the liquid effects
531 	SetOGLFader(FaderQueue_Liquid);
532 
533 	/* if a fade effect is active, apply it first */
534 	if (fade->fade_effect_type!=NONE)
535 	{
536 		struct fade_effect_definition *effect_definition= get_fade_effect_definition(fade->fade_effect_type);
537 		// LP change: idiot-proofing
538 		if (!effect_definition) return;
539 
540 		struct fade_definition *definition= get_fade_definition(effect_definition->fade_type);
541 		// LP change: idiot-proofing
542 		if (!definition) return;
543 
544 		definition->proc(original_color_table, animated_color_table, &definition->color, effect_definition->transparency);
545 		original_color_table= animated_color_table;
546 	}
547 
548 	// LP addition: set up the OGL queue entry for the other effects
549 	SetOGLFader(FaderQueue_Other);
550 
551 	if (type!=NONE)
552 	{
553 		struct fade_definition *definition= get_fade_definition(type);
554 
555 		definition->proc(original_color_table, animated_color_table, &definition->color, transparency);
556 		full_screen= (definition->flags&_full_screen_flag) ? true : false;
557 
558 		// cancel OGL fader if we've reached the end point for this fade
559 		if (!fade_active)
560 			SetOGLFader(FaderQueue_Other);
561 	}
562 
563 	// Only do the video-card fader if the OpenGL fader is inactive
564 #ifdef HAVE_OPENGL
565 	if (!OGL_FaderActive())
566 #endif
567 		animate_screen_clut(animated_color_table, full_screen);
568 
569 	if (get_game_state() < _game_in_progress)  // main menu or chapter screen
570 		draw_intro_screen();
571 }
572 
573 /* ---------- fade functions */
574 
tint_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)575 static void tint_color_table(
576 	struct color_table *original_color_table,
577 	struct color_table *animated_color_table,
578 	struct rgb_color *color,
579 	_fixed transparency)
580 {
581 	// LP addition: support for OpenGL faders
582 	if (CurrentOGLFader)
583 	{
584 		CurrentOGLFader->Type = _tint_fader_type;
585 		TranslateToOGLFader(*color,transparency);
586 		return;
587 	}
588 
589 	short i;
590 	struct rgb_color *unadjusted= original_color_table->colors;
591 	struct rgb_color *adjusted= animated_color_table->colors;
592 	short adjusted_transparency= transparency>>ADJUSTED_TRANSPARENCY_DOWNSHIFT;
593 
594 	animated_color_table->color_count= original_color_table->color_count;
595 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
596 	{
597 		adjusted->red= unadjusted->red + (((color->red-unadjusted->red)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
598 		adjusted->green= unadjusted->green + (((color->green-unadjusted->green)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
599 		adjusted->blue= unadjusted->blue + (((color->blue-unadjusted->blue)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
600 	}
601 }
602 
randomize_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)603 static void randomize_color_table(
604 	struct color_table *original_color_table,
605 	struct color_table *animated_color_table,
606 	struct rgb_color *color,
607 	_fixed transparency)
608 {
609 	// LP addition: support for OpenGL faders
610 	if (CurrentOGLFader)
611 	{
612 		CurrentOGLFader->Type = _randomize_fader_type;
613 		// Create random colors, but transmit the opacity
614 		CurrentOGLFader->Color[0] = FADES_RANDOM()/float(SHRT_MAX);
615 		CurrentOGLFader->Color[1] = FADES_RANDOM()/float(SHRT_MAX);
616 		CurrentOGLFader->Color[2] = FADES_RANDOM()/float(SHRT_MAX);
617 		CurrentOGLFader->Color[3] = transparency/float(FIXED_ONE);
618 		return;
619 	}
620 
621 	short i;
622 	struct rgb_color *unadjusted= original_color_table->colors;
623 	struct rgb_color *adjusted= animated_color_table->colors;
624 	uint16 mask, adjusted_transparency= PIN(transparency, 0, 0xffff);
625 
626 	(void) (color);
627 
628 	/* calculate a mask which has all bits including and lower than the high-bit in the
629 		transparency set */
630 	for (mask= 0; ~mask & adjusted_transparency; mask= (mask<<1)|1)
631 		;
632 
633 	animated_color_table->color_count= original_color_table->color_count;
634 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
635 	{
636 		adjusted->red= unadjusted->red + (FADES_RANDOM()&mask);
637 		adjusted->green= unadjusted->green + (FADES_RANDOM()&mask);
638 		adjusted->blue= unadjusted->blue + (FADES_RANDOM()&mask);
639 	}
640 }
641 
642 /* unlike pathways, all colors won�t pass through 50% gray at the same time */
negate_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)643 static void negate_color_table(
644 	struct color_table *original_color_table,
645 	struct color_table *animated_color_table,
646 	struct rgb_color *color,
647 	_fixed transparency)
648 {
649 	// LP addition: support for OpenGL faders
650 	if (CurrentOGLFader)
651 	{
652 		CurrentOGLFader->Type = _negate_fader_type;
653 		TranslateToOGLFader(*color,transparency);
654 		return;
655 	}
656 
657 	short i;
658 	struct rgb_color *unadjusted= original_color_table->colors;
659 	struct rgb_color *adjusted= animated_color_table->colors;
660 
661 	transparency= FIXED_ONE-transparency;
662 	animated_color_table->color_count= original_color_table->color_count;
663 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
664 	{
665 		adjusted->red= (unadjusted->red>0x8000) ?
666 			CEILING((unadjusted->red^color->red)+transparency, (int32)unadjusted->red) :
667 			FLOOR((unadjusted->red^color->red)-transparency, (int32)unadjusted->red);
668 		adjusted->green= (unadjusted->green>0x8000) ?
669 			CEILING((unadjusted->green^color->green)+transparency, (int32)unadjusted->green) :
670 			FLOOR((unadjusted->green^color->green)-transparency, (int32)unadjusted->green);
671 		adjusted->blue= (unadjusted->blue>0x8000) ?
672 			CEILING((unadjusted->blue^color->blue)+transparency, (int32)unadjusted->blue) :
673 			FLOOR((unadjusted->blue^color->blue)-transparency, (int32)unadjusted->blue);
674 	}
675 }
676 
dodge_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)677 static void dodge_color_table(
678 	struct color_table *original_color_table,
679 	struct color_table *animated_color_table,
680 	struct rgb_color *color,
681 	_fixed transparency)
682 {
683 	// LP addition: support for OpenGL faders
684 	if (CurrentOGLFader)
685 	{
686 		CurrentOGLFader->Type = _dodge_fader_type;
687 		TranslateToOGLFader(*color,transparency);
688 		return;
689 	}
690 
691 	short i;
692 	struct rgb_color *unadjusted= original_color_table->colors;
693 	struct rgb_color *adjusted= animated_color_table->colors;
694 
695 	animated_color_table->color_count= original_color_table->color_count;
696 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
697 	{
698 		int32 component;
699 
700 		component= 0xffff - (int32(1LL*(color->red^0xffff)*unadjusted->red)>>FIXED_FRACTIONAL_BITS) - transparency, adjusted->red= CEILING(component, unadjusted->red);
701 		component= 0xffff - (int32(1LL*(color->green^0xffff)*unadjusted->green)>>FIXED_FRACTIONAL_BITS) - transparency, adjusted->green= CEILING(component, unadjusted->green);
702 		component= 0xffff - (int32(1LL*(color->blue^0xffff)*unadjusted->blue)>>FIXED_FRACTIONAL_BITS) - transparency, adjusted->blue= CEILING(component, unadjusted->blue);
703 	}
704 }
705 
burn_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)706 static void burn_color_table(
707 	struct color_table *original_color_table,
708 	struct color_table *animated_color_table,
709 	struct rgb_color *color,
710 	_fixed transparency)
711 {
712 	// LP addition: support for OpenGL faders
713 	if (CurrentOGLFader)
714 	{
715 		CurrentOGLFader->Type = _burn_fader_type;
716 		TranslateToOGLFader(*color,transparency);
717 		return;
718 	}
719 
720 	short i;
721 	struct rgb_color *unadjusted= original_color_table->colors;
722 	struct rgb_color *adjusted= animated_color_table->colors;
723 
724 	transparency= FIXED_ONE-transparency;
725 	animated_color_table->color_count= original_color_table->color_count;
726 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
727 	{
728 		int32 component;
729 
730 		component= (int32(1LL*color->red*unadjusted->red)>>FIXED_FRACTIONAL_BITS) + transparency, adjusted->red= CEILING(component, unadjusted->red);
731 		component= (int32(1LL*color->green*unadjusted->green)>>FIXED_FRACTIONAL_BITS) + transparency, adjusted->green= CEILING(component, unadjusted->green);
732 		component= (int32(1LL*color->blue*unadjusted->blue)>>FIXED_FRACTIONAL_BITS) + transparency, adjusted->blue= CEILING(component, unadjusted->blue);
733 	}
734 }
735 
soft_tint_color_table(struct color_table * original_color_table,struct color_table * animated_color_table,struct rgb_color * color,_fixed transparency)736 static void soft_tint_color_table(
737 	struct color_table *original_color_table,
738 	struct color_table *animated_color_table,
739 	struct rgb_color *color,
740 	_fixed transparency)
741 {
742 	// LP addition: support for OpenGL faders
743 	if (CurrentOGLFader)
744 	{
745 		CurrentOGLFader->Type = _soft_tint_fader_type;
746 		TranslateToOGLFader(*color,transparency);
747 		return;
748 	}
749 
750 	short i;
751 	struct rgb_color *unadjusted= original_color_table->colors;
752 	struct rgb_color *adjusted= animated_color_table->colors;
753 	uint16 adjusted_transparency= transparency>>ADJUSTED_TRANSPARENCY_DOWNSHIFT;
754 
755 	animated_color_table->color_count= original_color_table->color_count;
756 	for (i= 0; i<original_color_table->color_count; ++i, ++adjusted, ++unadjusted)
757 	{
758 		uint16 intensity;
759 
760 		intensity= MAX(unadjusted->red, unadjusted->green);
761 		intensity= MAX(intensity, unadjusted->blue)>>ADJUSTED_TRANSPARENCY_DOWNSHIFT;
762 
763 		adjusted->red= unadjusted->red + (((((color->red*intensity)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT))-unadjusted->red)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
764 		adjusted->green= unadjusted->green + (((((color->green*intensity)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT))-unadjusted->green)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
765 		adjusted->blue= unadjusted->blue + (((((color->blue*intensity)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT))-unadjusted->blue)*adjusted_transparency)>>(FIXED_FRACTIONAL_BITS-ADJUSTED_TRANSPARENCY_DOWNSHIFT));
766 	}
767 }
768 
769 
770 // Arg is location in the OpenGL fader queue
SetOGLFader(int Index)771 void SetOGLFader(int Index)
772 {
773 #ifdef HAVE_OPENGL
774 	if (OGL_FaderActive())
775 	{
776 		CurrentOGLFader = GetOGL_FaderQueueEntry(Index);
777 		CurrentOGLFader->Type = NONE;
778 	} else
779 #endif
780 		CurrentOGLFader = NULL;
781 }
782 
783 // Translate the color and opacity values
TranslateToOGLFader(rgb_color & Color,_fixed Opacity)784 static void TranslateToOGLFader(rgb_color &Color, _fixed Opacity)
785 {
786 	assert(CurrentOGLFader);
787 	CurrentOGLFader->Color[0] = Color.red/float(FIXED_ONE-1);
788 	CurrentOGLFader->Color[1] = Color.green/float(FIXED_ONE-1);
789 	CurrentOGLFader->Color[2] = Color.blue/float(FIXED_ONE-1);
790 	CurrentOGLFader->Color[3] = Opacity/float(FIXED_ONE);
791 }
792 
793 
794 struct fade_definition *original_fade_definitions = NULL;
795 struct fade_effect_definition *original_fade_effect_definitions = NULL;
796 
reset_mml_faders()797 void reset_mml_faders()
798 {
799 	if (original_fade_definitions) {
800 		for (int i = 0; i < NUMBER_OF_FADE_TYPES; i++)
801 			fade_definitions[i] = original_fade_definitions[i];
802 		free(original_fade_definitions);
803 		original_fade_definitions = NULL;
804 	}
805 
806 	if (original_fade_effect_definitions) {
807 		for (int i = 0; i < NUMBER_OF_FADE_EFFECT_TYPES; i++)
808 			fade_effect_definitions[i] = original_fade_effect_definitions[i];
809 		free(original_fade_effect_definitions);
810 		original_fade_effect_definitions = NULL;
811 	}
812 }
813 
parse_mml_faders(const InfoTree & root)814 void parse_mml_faders(const InfoTree& root)
815 {
816 	// back up old values first
817 	if (!original_fade_definitions) {
818 		original_fade_definitions = (struct fade_definition *) malloc(sizeof(struct fade_definition) * NUMBER_OF_FADE_TYPES);
819 		assert(original_fade_definitions);
820 		for (int i = 0; i < NUMBER_OF_FADE_TYPES; i++)
821 			original_fade_definitions[i] = fade_definitions[i];
822 	}
823 
824 	if (!original_fade_effect_definitions) {
825 		original_fade_effect_definitions = (struct fade_effect_definition *) malloc(sizeof(struct fade_effect_definition) * NUMBER_OF_FADE_EFFECT_TYPES);
826 		assert(original_fade_effect_definitions);
827 		for (int i = 0; i < NUMBER_OF_FADE_EFFECT_TYPES; i++)
828 			original_fade_effect_definitions[i] = fade_effect_definitions[i];
829 	}
830 
831 	BOOST_FOREACH(InfoTree ftree, root.children_named("fader"))
832 	{
833 		int16 index;
834 		if (!ftree.read_indexed("index", index, NUMBER_OF_FADE_TYPES))
835 			continue;
836 
837 		fade_definition& def = fade_definitions[index];
838 		int16 fade_type;
839 		if (ftree.read_indexed("type", fade_type, NUMBER_OF_FADER_FUNCTIONS))
840 		{
841 			switch (fade_type) {
842 				case _tint_fader_type:
843 					def.proc = tint_color_table;
844 					break;
845 				case _randomize_fader_type:
846 					def.proc = randomize_color_table;
847 					break;
848 				case _negate_fader_type:
849 					def.proc = negate_color_table;
850 					break;
851 				case _dodge_fader_type:
852 					def.proc = dodge_color_table;
853 					break;
854 				case _burn_fader_type:
855 					def.proc = burn_color_table;
856 					break;
857 				case _soft_tint_fader_type:
858 					def.proc = soft_tint_color_table;
859 					break;
860 				default:
861 					break;
862 			}
863 		}
864 
865 		ftree.read_fixed("initial_opacity", def.initial_transparency);
866 		ftree.read_fixed("final_opacity", def.final_transparency);
867 		ftree.read_attr("flags", def.flags);
868 		ftree.read_attr("priority", def.priority);
869 		int16 period;
870 		if (ftree.read_attr("period", period))
871 			def.period = static_cast<int32>(period) * 1000 / MACHINE_TICKS_PER_SECOND;
872 
873 		BOOST_FOREACH(InfoTree color, ftree.children_named("color"))
874 			color.read_color(def.color);
875 	}
876 
877 	BOOST_FOREACH(InfoTree ltree, root.children_named("liquid"))
878 	{
879 		int16 index;
880 		if (!ltree.read_indexed("index", index, NUMBER_OF_FADE_EFFECT_TYPES))
881 			continue;
882 
883 		fade_effect_definition& def = fade_effect_definitions[index];
884 		ltree.read_indexed("fader", def.fade_type, NUMBER_OF_FADE_TYPES, true);
885 		ltree.read_fixed("opacity", def.transparency);
886 	}
887 }
888