1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "engines/icb/debug.h"
29 #include "engines/icb/mission.h"
30 #include "engines/icb/global_objects.h"
31
32 namespace ICB {
33
fx_narrow_screen(int32 & result,int32 * params)34 mcodeFunctionReturnCodes fx_narrow_screen(int32 &result, int32 *params) { return (MS->fx_narrow_screen(result, params)); }
35
fx_generic_fade(int32 & result,int32 * params)36 mcodeFunctionReturnCodes fx_generic_fade(int32 &result, int32 *params) { return (MS->fx_generic_fade(result, params)); }
37
fx_narrow_screen(int32 &,int32 * params)38 mcodeFunctionReturnCodes _game_session::fx_narrow_screen(int32 &, int32 *params) {
39 /* Parameters */
40 int32 mode = params[0]; // border mode
41 int32 red = params[1]; // red component of cover
42 int32 green = params[2]; // green component of cover
43 int32 blue = params[3]; // blue component of cover
44 int32 percent = params[4]; // 0 - 100 percentage screen to cover
45 int32 cycles = params[5]; // number of cycles to shirnk over
46
47 /* Function Storage */
48 static int32 heightStep = 0;
49 static int32 alphaStep = 0;
50 static int32 cycleCount = 0;
51
52 // Get access to the border rectangle
53 LRECT &border = surface_manager->BorderRect();
54
55 // Check if there is a set loaded. If not we want to ignore the cycles param
56 if (!MSS.OK())
57 cycles = 1;
58
59 // Calculate the fxtarget screen coverage
60 int32 fxtarget = (480 * percent) / 200;
61
62 if (cycleCount == 0) {
63 // First time through
64
65 // Set the border colour
66 surface_manager->BorderRed() = (uint8)red;
67 surface_manager->BorderGreen() = (uint8)green;
68 surface_manager->BorderBlue() = (uint8)blue;
69
70 // Semi-non-persistance(ish)... If percentage is not 0 make sure we start from 0
71 if (percent) {
72 border.top = 0;
73 border.bottom = SCREEN_DEPTH;
74 surface_manager->BorderAlpha() = 0;
75 } else
76 surface_manager->BorderAlpha() = 255;
77
78 // Calculate the per cycle height step
79 heightStep = (cycles) ? (fxtarget - border.top) / cycles : fxtarget;
80
81 // Calculate alpha step
82 alphaStep = (cycles) ? 255 / cycles : 255;
83
84 // Check if we are fading out
85 if (percent == 0)
86 alphaStep = 0 - alphaStep;
87
88 // Mode 0 has no fade so set alpha to solid
89 if (mode == 0) { // Solid Colour
90 alphaStep = 0;
91 surface_manager->BorderAlpha() = 255;
92 }
93
94 if (mode == 2) { // Just Fade no shrink so set height step to 0
95 heightStep = 0;
96
97 if (percent) {
98 border.top = fxtarget;
99 border.bottom = SCREEN_DEPTH - fxtarget;
100 }
101 }
102
103 // Set the mode
104 surface_manager->BorderMode() = mode;
105
106 // Check we actually need to move the borders or fade the screen
107 if (heightStep == 0 && alphaStep == 0)
108 return (IR_CONT);
109 }
110
111 // Check if we have reached the specified border size
112 if (cycleCount == cycles) {
113 cycleCount = 0;
114
115 if (percent) {
116 // We are leaving the screen with borders of one sort or another
117 // So stop blending and switch to solid borders
118 surface_manager->BorderMode() = 0;
119 } else {
120 // We were removing the borders, so stop drawing them now
121 border.top = 0;
122 border.bottom = SCREEN_DEPTH;
123 }
124 return (IR_CONT);
125 }
126
127 // Check we aren't going to over step the borders
128 if (abs(fxtarget - border.top) <= abs(heightStep)) {
129 border.bottom -= fxtarget - border.top;
130 border.top = fxtarget;
131 } else {
132 // Move the borders
133 border.top += heightStep;
134 border.bottom -= heightStep;
135 }
136
137 // Check the alpha isn't going to go too far
138 if ((alphaStep + surface_manager->BorderAlpha()) > 255) {
139 surface_manager->BorderAlpha() = (uint8)255;
140 } else if ((alphaStep + surface_manager->BorderAlpha()) < 0) {
141 surface_manager->BorderAlpha() = (uint8)0;
142 } else {
143 surface_manager->BorderAlpha() = (uint8)(alphaStep + surface_manager->BorderAlpha());
144 }
145
146 cycleCount++;
147
148 return (IR_REPEAT);
149 }
150
151 // the full monty effect, fx_generic_fade(mode (0,1,2), on/off, r, g, b, cycles)
152 // where mode is 0-brighten, 1-darken, 2-fade
153 // where on/off is equiverlant to to/from
154
fx_generic_fade(int32 &,int32 * params)155 mcodeFunctionReturnCodes _game_session::fx_generic_fade(int32 &, int32 *params) {
156 int32 mode = params[0];
157 int32 onOff = params[1];
158 int32 fromRed = params[2];
159 int32 fromGreen = params[3];
160 int32 fromBlue = params[4];
161 int32 toRed = params[5];
162 int32 toGreen = params[6];
163 int32 toBlue = params[7];
164 int32 cycles = params[8];
165
166 /* Function Storage */
167 static int32 alphaStep = 0;
168
169 // Is this the first time through ?
170 if (alphaStep == 0) {
171 // First time through
172 alphaStep = (cycles) ? 255 / cycles : 255;
173
174 // Set the colour components
175 surface_manager->FadeFromRed() = (uint8)fromRed;
176 surface_manager->FadeFromGreen() = (uint8)fromGreen;
177 surface_manager->FadeFromBlue() = (uint8)fromBlue;
178 surface_manager->FadeToRed() = (uint8)toRed;
179 surface_manager->FadeToGreen() = (uint8)toGreen;
180 surface_manager->FadeToBlue() = (uint8)toBlue;
181
182 // Set the initial alpha value
183 if (onOff)
184 surface_manager->FadeAlpha() = 0; // Fading in
185 else
186 surface_manager->FadeAlpha() = 255; // Fading out
187
188 // Set the fade mode
189 surface_manager->FadeMode() = mode + 1;
190 }
191
192 // Increment / Decrement the alpha value
193 int32 newAlpha = surface_manager->FadeAlpha();
194 if (onOff) {
195 // Fading in
196 newAlpha += alphaStep;
197 } else {
198 // Fading out
199 newAlpha -= alphaStep;
200 }
201
202 // Check the limits
203 if (newAlpha <= 0) {
204 // Finished fade out
205 surface_manager->FadeMode() = 0;
206 surface_manager->FadeAlpha() = 0;
207 alphaStep = 0;
208 return (IR_CONT);
209 }
210
211 if (newAlpha >= 255) {
212 // Finished fade in
213 surface_manager->FadeAlpha() = 255;
214 alphaStep = 0;
215 return (IR_CONT);
216 }
217
218 surface_manager->FadeAlpha() = (uint8)newAlpha;
219
220 return (IR_REPEAT);
221 }
222
223 } // End of namespace ICB
224