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 * Additional copyright for this file:
8 * Copyright (C) 1994-1998 Revolution Software Ltd.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 // high level layer initializing
26
27 // the system supports:
28 // 1 optional background parallax layer
29 // 1 not optional normal backdrop layer
30 // 3 normal sorted layers
31 // up to 2 foreground parallax layers
32
33
34 #include "common/rect.h"
35 #include "common/textconsole.h"
36
37 #include "sword2/sword2.h"
38 #include "sword2/defs.h"
39 #include "sword2/header.h"
40 #include "sword2/logic.h"
41 #include "sword2/mouse.h"
42 #include "sword2/resman.h"
43 #include "sword2/screen.h"
44 #include "sword2/sound.h"
45
46 namespace Sword2 {
47
48 /**
49 * This function is called when entering a new room.
50 * @param res resource id of the normal background layer
51 * @param new_palette 1 for new palette, otherwise 0
52 */
53
initBackground(int32 res,int32 new_palette)54 void Screen::initBackground(int32 res, int32 new_palette) {
55 int i;
56
57 assert(res);
58
59 _vm->_sound->clearFxQueue(false);
60 waitForFade();
61
62 debug(1, "CHANGED TO LOCATION \"%s\"", _vm->_resman->fetchName(res));
63
64 // We have to clear this. Otherwise, if an exit warps back to the same
65 // room (e.g. the jungle maze), clicking on the same exit again will be
66 // misinterpreted as a double-click, and that only works if we're
67 // actually walking towards that exit. Otherwise, the game would hang.
68
69 _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
70
71 // if last screen was using a shading mask (see below)
72 if (_thisScreen.mask_flag) {
73 if (closeLightMask() != RD_OK)
74 error("Could not close light mask");
75 }
76
77 // Close the previous screen, if one is open
78 if (_thisScreen.background_layer_id)
79 closeBackgroundLayer();
80
81 _thisScreen.background_layer_id = res;
82 _thisScreen.new_palette = new_palette;
83
84 // ok, now read the resource and pull out all the normal sort layer
85 // info/and set them up at the beginning of the sort list - why do it
86 // each cycle
87
88 byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
89 ScreenHeader screen_head;
90
91 screen_head.read(_vm->fetchScreenHeader(file));
92
93 // set number of special sort layers
94 _thisScreen.number_of_layers = screen_head.noLayers;
95 _thisScreen.screen_wide = screen_head.width;
96 _thisScreen.screen_deep = screen_head.height;
97
98 debug(2, "layers=%d width=%d depth=%d", screen_head.noLayers, screen_head.width, screen_head.height);
99
100 // initialize the driver back buffer
101 setLocationMetrics(screen_head.width, screen_head.height);
102
103 for (i = 0; i < screen_head.noLayers; i++) {
104 debug(3, "init layer %d", i);
105
106 LayerHeader layer;
107
108 layer.read(_vm->fetchLayerHeader(file, i));
109
110 // Add the layer to the sort list. We only provide just enough
111 // information so that it's clear that it's a layer, and where
112 // to sort it in relation to other things in the list.
113
114 _sortList[i].layer_number = i + 1;
115 _sortList[i].sort_y = layer.y + layer.height;
116 }
117
118 // reset scroll offsets
119 _thisScreen.scroll_offset_x = 0;
120 _thisScreen.scroll_offset_y = 0;
121
122 if (screen_head.width > _screenWide || screen_head.height > _screenDeep) {
123 // The layer is larger than the physical screen. Switch on
124 // scrolling. (2 means first time on screen)
125 _thisScreen.scroll_flag = 2;
126
127 // Note: if we've already set the player up then we could do
128 // the initial scroll set here
129
130 // Calculate the maximum scroll offsets to prevent scrolling
131 // off the edge. The minimum offsets are both 0.
132
133 _thisScreen.max_scroll_offset_x = screen_head.width - _screenWide;
134 _thisScreen.max_scroll_offset_y = screen_head.height - (_screenDeep - (MENUDEEP * 2));
135 } else {
136 // The later fits on the phyiscal screen. Switch off scrolling.
137 _thisScreen.scroll_flag = 0;
138 }
139
140 resetRenderEngine();
141
142 // These are the physical screen coords where the system will try to
143 // maintain George's actual feet coords.
144
145 _thisScreen.feet_x = 320;
146 _thisScreen.feet_y = 340;
147
148 // shading mask
149
150 MultiScreenHeader screenLayerTable;
151
152 screenLayerTable.read(file + ResHeader::size());
153
154 if (screenLayerTable.maskOffset) {
155 SpriteInfo spriteInfo;
156
157 spriteInfo.x = 0;
158 spriteInfo.y = 0;
159 spriteInfo.w = screen_head.width;
160 spriteInfo.h = screen_head.height;
161 spriteInfo.scale = 0;
162 spriteInfo.scaledWidth = 0;
163 spriteInfo.scaledHeight = 0;
164 spriteInfo.type = 0;
165 spriteInfo.blend = 0;
166 spriteInfo.data = _vm->fetchShadingMask(file);
167 spriteInfo.colorTable = 0;
168
169 if (openLightMask(&spriteInfo) != RD_OK)
170 error("Could not open light mask");
171
172 // so we know to close it later! (see above)
173 _thisScreen.mask_flag = true;
174 } else {
175 // no need to close a mask later
176 _thisScreen.mask_flag = false;
177 }
178
179 // Background parallax layers
180
181 for (i = 0; i < 2; i++) {
182 if (screenLayerTable.bg_parallax[i])
183 initializeBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i));
184 else
185 initializeBackgroundLayer(NULL);
186 }
187
188 // Normal backround layer
189
190 initializeBackgroundLayer(_vm->fetchBackgroundLayer(file));
191
192 // Foreground parallax layers
193
194 for (i = 0; i < 2; i++) {
195 if (screenLayerTable.fg_parallax[i])
196 initializeBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i));
197 else
198 initializeBackgroundLayer(NULL);
199 }
200
201 _vm->_resman->closeResource(_thisScreen.background_layer_id);
202 }
203
204 /**
205 * This function is called when entering a new room, PSX edition
206 * @param res resource id of the normal background layer
207 * @param new_palette 1 for new palette, otherwise 0
208 */
209
initPsxBackground(int32 res,int32 new_palette)210 void Screen::initPsxBackground(int32 res, int32 new_palette) {
211 int i;
212
213 assert(res);
214
215 _vm->_sound->clearFxQueue(false);
216 waitForFade();
217
218 debug(1, "CHANGED TO LOCATION \"%s\"", _vm->_resman->fetchName(res));
219
220 _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
221
222 // Close the previous screen, if one is open
223 if (_thisScreen.background_layer_id)
224 closeBackgroundLayer();
225
226 _thisScreen.background_layer_id = res;
227 _thisScreen.new_palette = new_palette;
228
229 // ok, now read the resource and pull out all the normal sort layer
230 // info/and set them up at the beginning of the sort list - why do it
231 // each cycle
232
233 byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
234 ScreenHeader screen_head;
235
236 screen_head.read(_vm->fetchScreenHeader(file));
237 screen_head.height *= 2;
238
239 // set number of special sort layers
240 _thisScreen.number_of_layers = screen_head.noLayers;
241 _thisScreen.screen_wide = screen_head.width;
242 _thisScreen.screen_deep = screen_head.height;
243
244 debug(2, "layers=%d width=%d depth=%d", screen_head.noLayers, screen_head.width, screen_head.height);
245
246 // initialize the driver back buffer
247 setLocationMetrics(screen_head.width, screen_head.height);
248
249 for (i = 0; i < screen_head.noLayers; i++) {
250 debug(3, "init layer %d", i);
251
252 LayerHeader layer;
253
254 layer.read(_vm->fetchLayerHeader(file, i));
255 _sortList[i].layer_number = i + 1;
256 _sortList[i].sort_y = layer.y + layer.height;
257 }
258
259 // reset scroll offsets
260 _thisScreen.scroll_offset_x = 0;
261 _thisScreen.scroll_offset_y = 0;
262
263 if (screen_head.width > _screenWide || screen_head.height > _screenDeep) {
264 _thisScreen.scroll_flag = 2;
265
266 _thisScreen.max_scroll_offset_x = screen_head.width - _screenWide;
267 _thisScreen.max_scroll_offset_y = screen_head.height - (_screenDeep - (MENUDEEP * 2));
268 } else {
269 // The later fits on the phyiscal screen. Switch off scrolling.
270 _thisScreen.scroll_flag = 0;
271 }
272
273 resetRenderEngine();
274
275 // These are the physical screen coords where the system will try to
276 // maintain George's actual feet coords.
277
278 _thisScreen.feet_x = 320;
279 _thisScreen.feet_y = 340;
280
281 // Background parallax layers
282 initializePsxParallaxLayer(_vm->fetchBackgroundParallaxLayer(file, 0));
283 initializePsxParallaxLayer(NULL);
284
285 // Normal backround layer
286 initializePsxBackgroundLayer(_vm->fetchBackgroundLayer(file));
287
288 // Foreground parallax layers
289 initializePsxParallaxLayer(_vm->fetchForegroundParallaxLayer(file, 1));
290 initializePsxParallaxLayer(NULL);
291
292 _vm->_resman->closeResource(_thisScreen.background_layer_id);
293
294 }
295
296 } // End of namespace Sword2
297