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/nuvie/core/nuvie_defs.h"
24 #include "ultima/nuvie/misc/u6_misc.h"
25 #include "ultima/nuvie/conf/configuration.h"
26 #include "ultima/nuvie/screen/surface.h"
27 #include "ultima/nuvie/screen/scale.h"
28 #include "ultima/nuvie/screen/screen.h"
29 #include "ultima/nuvie/gui/widgets/map_window.h"
30 #include "ultima/nuvie/gui/widgets/background.h"
31 #include "common/system.h"
32 #include "engines/util.h"
33 
34 namespace Ultima {
35 namespace Nuvie {
36 
37 #define sqr(a) ((a)*(a))
38 
39 //Ultima 6 light globe sizes.
40 #define NUM_GLOBES 5
41 #define SHADING_BORDER 2 // should be the same as MapWindow's TMP_MAP_BORDER
42 static const sint32 globeradius[]   = { 36, 112, 148, 192, 448 };
43 static const sint32 globeradius_2[] = { 18, 56, 74, 96, 224 };
44 
Screen(Configuration * cfg)45 Screen::Screen(Configuration *cfg) {
46 	config = cfg;
47 
48 	_rawSurface = NULL;
49 	_renderSurface = NULL;
50 	scaler = NULL;
51 	shading_data = NULL;
52 	scaler_index = 0;
53 	scale_factor = 2;
54 	doubleBuffer = false;
55 	is_no_darkness = false;
56 	non_square_pixels = false;
57 	shading_ambient = 255;
58 	width = 320;
59 	height = 200;
60 
61 	Std::string str_lighting_style;
62 	config->value("config/general/lighting", str_lighting_style);
63 
64 	if (str_lighting_style == "none")
65 		lighting_style = LIGHTING_STYLE_NONE;
66 	else if (str_lighting_style == "smooth")
67 		lighting_style = LIGHTING_STYLE_SMOOTH;
68 	else
69 		lighting_style = LIGHTING_STYLE_ORIGINAL;
70 	old_lighting_style = lighting_style;
71 	memset(shading_globe, 0, sizeof(shading_globe));
72 }
73 
~Screen()74 Screen::~Screen() {
75 	delete _renderSurface;
76 	delete _rawSurface;
77 
78 	if (shading_data)
79 		free(shading_data);
80 
81 	for (int i = 0; i < NUM_GLOBES; i++) {
82 		if (shading_globe[i])
83 			free(shading_globe[i]);
84 	}
85 }
86 
init()87 bool Screen::init() {
88 	Std::string str;
89 
90 	int new_width, new_height;
91 	config->value("config/video/screen_width", new_width, 320);
92 	config->value("config/video/screen_height", new_height, 200);
93 
94 	if (new_width < 320)
95 		new_width = 320;
96 
97 	if (new_height < 200)
98 		new_height = 200;
99 
100 	width = (uint16)new_width;
101 	height = (uint16)new_height;
102 
103 	config->value("config/video/scale_method", str, "---");
104 	scaler_index = scaler_reg.GetIndexForName(str);
105 	if (scaler_index == -1) {
106 		//config.set("config/video/scale_method","SuperEagle",true);
107 		scaler_index = scaler_reg.GetIndexForName("SuperEagle");
108 	}
109 
110 	config->value("config/video/scale_factor", scale_factor, 1);
111 
112 	config->value("config/video/non_square_pixels", non_square_pixels, false);
113 
114 	set_screen_mode();
115 
116 	return true;
117 }
118 
set_lighting_style(int lighting)119 void Screen::set_lighting_style(int lighting) {
120 	lighting_style = lighting;
121 	old_lighting_style = lighting;
122 }
123 
toggle_darkness_cheat()124 bool Screen::toggle_darkness_cheat() {
125 	is_no_darkness = !is_no_darkness;
126 	if (is_no_darkness) {
127 		old_lighting_style = lighting_style;
128 		lighting_style = LIGHTING_STYLE_NONE;
129 	} else
130 		lighting_style = old_lighting_style;
131 	return is_no_darkness;
132 }
133 
134 
set_palette(uint8 * p)135 bool Screen::set_palette(uint8 *p) {
136 	if (_renderSurface == NULL || p == NULL)
137 		return false;
138 
139 //SDL_SetColors(scaled_surface,palette,0,256);
140 	for (int i = 0; i < 256; ++i) {
141 		uint32  r = p[i * 3];
142 		uint32  g = p[i * 3 + 1];
143 		uint32  b = p[i * 3 + 2];
144 
145 		uint32  c = ((r >> RenderSurface::Rloss) << RenderSurface::Rshift) | ((g >> RenderSurface::Gloss) << RenderSurface::Gshift) | ((b >> RenderSurface::Bloss) << RenderSurface::Bshift);
146 
147 		_renderSurface->colour32[i] = c;
148 	}
149 
150 	return true;
151 }
152 
set_palette_entry(uint8 idx,uint8 r,uint8 g,uint8 b)153 bool Screen::set_palette_entry(uint8 idx, uint8 r, uint8 g, uint8 b) {
154 	if (_renderSurface == NULL)
155 		return false;
156 
157 	uint32 c = ((((uint32)r) >> RenderSurface::Rloss) << RenderSurface::Rshift) | ((((uint32)g) >> RenderSurface::Gloss) << RenderSurface::Gshift) | ((((uint32)b) >> RenderSurface::Bloss) << RenderSurface::Bshift);
158 
159 	_renderSurface->colour32[idx] = c;
160 
161 	return true;
162 }
163 
rotate_palette(uint8 pos,uint8 length)164 bool Screen::rotate_palette(uint8 pos, uint8 length) {
165 	uint32 tmp_colour;
166 	uint8 i;
167 
168 	tmp_colour = _renderSurface->colour32[pos + length - 1];
169 
170 	for (i = length - 1; i > 0; i--)
171 		_renderSurface->colour32[pos + i] = _renderSurface->colour32[pos + i - 1];
172 
173 	_renderSurface->colour32[pos] = tmp_colour;
174 
175 	return true;
176 }
177 
get_translated_x(uint16 x)178 uint16 Screen::get_translated_x(uint16 x) {
179 	if (scale_factor != 1)
180 		x /= scale_factor;
181 
182 	return x;
183 }
184 
get_translated_y(uint16 y)185 uint16 Screen::get_translated_y(uint16 y) {
186 	if (scale_factor != 1)
187 		y /= scale_factor;
188 
189 	return y;
190 }
clear(sint16 x,sint16 y,sint16 w,sint16 h,Common::Rect * clip_rect)191 bool Screen::clear(sint16 x, sint16 y, sint16 w, sint16 h, Common::Rect *clip_rect) {
192 	uint8 *pixels;
193 	uint16 i;
194 	uint16 x1, y1;
195 
196 	pixels = (uint8 *)_renderSurface->pixels;
197 
198 	if (x >= width || y >= height)
199 		return false;
200 
201 	if (x < 0) {
202 		if (x + w <= 0)
203 			return false;
204 		else
205 			w += x;
206 
207 		x = 0;
208 	}
209 
210 	if (y < 0) {
211 		if (y + h <= 0)
212 			return false;
213 		else
214 			h += y;
215 
216 		y = 0;
217 	}
218 
219 	if (x + w >= width)
220 		w = width - x;
221 
222 	if (y + h >= height)
223 		h = height - y;
224 
225 	if (clip_rect) {
226 		x1 = x;
227 		y1 = y;
228 		if (x < clip_rect->left)
229 			x = clip_rect->left;
230 
231 		if (y < clip_rect->top)
232 			y = clip_rect->top;
233 
234 		if (x1 + w > clip_rect->left + clip_rect->width()) {
235 			w -= (x1 + w) - (clip_rect->left + clip_rect->width());
236 			if (w <= 0)
237 				return false;
238 		}
239 
240 		if (y1 + h > clip_rect->top + clip_rect->height()) {
241 			h -= (y1 + h) - (clip_rect->top + clip_rect->height());
242 			if (h <= 0)
243 				return false;
244 		}
245 	}
246 
247 	pixels += y * _renderSurface->pitch + (x * _renderSurface->bytes_per_pixel);
248 
249 	for (i = 0; i < h; i++) {
250 		memset(pixels, 0, w * _renderSurface->bytes_per_pixel);
251 		pixels += _renderSurface->pitch;
252 	}
253 
254 	return true;
255 }
256 
fill(uint8 colour_num,uint16 x,uint16 y,sint16 w,sint16 h)257 bool Screen::fill(uint8 colour_num, uint16 x, uint16 y, sint16 w, sint16 h) {
258 	if (x >= _renderSurface->w || y >= _renderSurface->h) {
259 		return true;
260 	}
261 
262 	if ((uint32)(y + h) > _renderSurface->h) {
263 		h = _renderSurface->h - y;
264 	}
265 
266 	if ((uint32)(x + w) > _renderSurface->w) {
267 		w = _renderSurface->w - x;
268 	}
269 
270 	if (_renderSurface->bits_per_pixel == 16)
271 		return fill16(colour_num, x, y, w, h);
272 
273 	return fill32(colour_num, x, y, w, h);
274 }
275 
fill16(uint8 colour_num,uint16 x,uint16 y,sint16 w,sint16 h)276 bool Screen::fill16(uint8 colour_num, uint16 x, uint16 y, sint16 w, sint16 h) {
277 	uint16 *pixels;
278 	uint16 i, j;
279 
280 	pixels = (uint16 *)_renderSurface->pixels;
281 
282 	pixels += y * _renderSurface->w + x;
283 
284 	for (i = 0; i < h; i++) {
285 		for (j = 0; j < w; j++)
286 			pixels[j] = (uint16)_renderSurface->colour32[colour_num];
287 
288 		pixels += _renderSurface->w;
289 	}
290 
291 	return true;
292 }
293 
fill32(uint8 colour_num,uint16 x,uint16 y,sint16 w,sint16 h)294 bool Screen::fill32(uint8 colour_num, uint16 x, uint16 y, sint16 w, sint16 h) {
295 	uint32 *pixels;
296 	uint16 i, j;
297 
298 
299 	pixels = (uint32 *)_renderSurface->pixels;
300 
301 	pixels += y * _renderSurface->w + x;
302 
303 	for (i = 0; i < h; i++) {
304 		for (j = 0; j < w; j++)
305 			pixels[j] = _renderSurface->colour32[colour_num];
306 
307 		pixels += _renderSurface->w;
308 	}
309 
310 	return true;
311 }
fade(uint16 dest_x,uint16 dest_y,uint16 src_w,uint16 src_h,uint8 opacity,uint8 fade_bg_color)312 void Screen::fade(uint16 dest_x, uint16 dest_y, uint16 src_w, uint16 src_h, uint8 opacity, uint8 fade_bg_color) {
313 	if (_renderSurface->bits_per_pixel == 16)
314 		fade16(dest_x, dest_y, src_w, src_h, opacity, fade_bg_color);
315 	else
316 		fade32(dest_x, dest_y, src_w, src_h, opacity, fade_bg_color);
317 }
318 
fade16(uint16 dest_x,uint16 dest_y,uint16 src_w,uint16 src_h,uint8 opacity,uint8 fade_bg_color)319 void Screen::fade16(uint16 dest_x, uint16 dest_y, uint16 src_w, uint16 src_h, uint8 opacity, uint8 fade_bg_color) {
320 	uint16 bg = (uint16)_renderSurface->colour32[fade_bg_color];
321 	uint16 *pixels;
322 	uint16 i, j;
323 
324 	pixels = (uint16 *)_renderSurface->pixels;
325 
326 	pixels += dest_y * _renderSurface->w + dest_x;
327 
328 	for (i = 0; i < src_h; i++) {
329 		for (j = 0; j < src_w; j++) {
330 			pixels[j] = blendpixel16(bg, pixels[j], opacity);
331 		}
332 
333 		pixels += _renderSurface->w; //_renderSurface->pitch;
334 	}
335 
336 	return;
337 }
338 
fade32(uint16 dest_x,uint16 dest_y,uint16 src_w,uint16 src_h,uint8 opacity,uint8 fade_bg_color)339 void Screen::fade32(uint16 dest_x, uint16 dest_y, uint16 src_w, uint16 src_h, uint8 opacity, uint8 fade_bg_color) {
340 	uint32 bg = _renderSurface->colour32[fade_bg_color];
341 	uint32 *pixels;
342 	uint16 i, j;
343 
344 	pixels = (uint32 *)_renderSurface->pixels;
345 
346 	pixels += dest_y * _renderSurface->w + dest_x;
347 
348 	for (i = 0; i < src_h; i++) {
349 		for (j = 0; j < src_w; j++) {
350 			pixels[j] = blendpixel32(bg, pixels[j], opacity);
351 		}
352 
353 		pixels += _renderSurface->w; //_renderSurface->pitch;
354 	}
355 
356 	return;
357 }
358 
stipple_8bit(uint8 color_num)359 void Screen::stipple_8bit(uint8 color_num) {
360 	stipple_8bit(color_num, 0, 0, _renderSurface->w, _renderSurface->h);
361 }
362 
stipple_8bit(uint8 color_num,uint16 x,uint16 y,uint16 w,uint16 h)363 void Screen::stipple_8bit(uint8 color_num, uint16 x, uint16 y, uint16 w, uint16 h) {
364 	uint32 i, j;
365 
366 	if (x >= _renderSurface->w || y >= _renderSurface->h) {
367 		return;
368 	}
369 
370 	if ((uint32)(y + h) > _renderSurface->h) {
371 		h = _renderSurface->h - y;
372 	}
373 
374 	if ((uint32)(x + w) > _renderSurface->w) {
375 		w = _renderSurface->w - x;
376 	}
377 
378 	if (_renderSurface->bits_per_pixel == 16) {
379 		uint16 color = (uint16)_renderSurface->colour32[color_num];
380 		uint16 *pixels = (uint16 *)_renderSurface->pixels;
381 
382 		pixels += y * _renderSurface->w + x;
383 
384 		for (i = y; i < (uint32)(y + h); i++) {
385 			for (j = x; j < (uint32)(x + w); j += 2) {
386 				*pixels = color;
387 				pixels += 2;
388 			}
389 			pixels += (_renderSurface->w - j) + x;
390 			if (i % 2) {
391 				pixels--;
392 			} else {
393 				pixels++;
394 			}
395 		}
396 	} else {
397 		uint32 color = _renderSurface->colour32[color_num];
398 		uint32 *pixels = (uint32 *)_renderSurface->pixels;
399 
400 		pixels += y * _renderSurface->w + x;
401 
402 		for (i = 0; i < h; i++) {
403 			for (j = x; j < (uint32)(x + w); j += 2) {
404 				*pixels = color;
405 				pixels += 2;
406 			}
407 			pixels += (_renderSurface->w - j) + x;
408 			if (i % 2) {
409 				pixels--;
410 			} else {
411 				pixels++;
412 			}
413 		}
414 	}
415 }
put_pixel(uint8 colour_num,uint16 x,uint16 y)416 void Screen::put_pixel(uint8 colour_num, uint16 x, uint16 y) {
417 	if (_renderSurface->bits_per_pixel == 16) {
418 		uint16 *pixel = (uint16 *)_renderSurface->pixels + y * _renderSurface->w + x;
419 		*pixel = (uint16)_renderSurface->colour32[colour_num];
420 	} else {
421 		uint32 *pixel = (uint32 *)_renderSurface->pixels + y * _renderSurface->w + x;
422 		*pixel = (uint32)_renderSurface->colour32[colour_num];
423 	}
424 }
425 
get_pixels()426 void *Screen::get_pixels() {
427 //if(scaled_surface == NULL)
428 //   return NULL;
429 
430 //return scaled_surface->pixels;
431 	return NULL;
432 }
433 
get_sdl_surface()434 Graphics::ManagedSurface *Screen::get_sdl_surface() {
435 	if (_renderSurface)
436 		return _renderSurface->get_sdl_surface();
437 
438 	return NULL;
439 }
440 
blit(int32 dest_x,int32 dest_y,const byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch,bool trans,Common::Rect * clip_rect,uint8 opacity)441 bool Screen::blit(int32 dest_x, int32 dest_y, const byte *src_buf, uint16 src_bpp,
442 		uint16 src_w, uint16 src_h, uint16 src_pitch, bool trans,
443 		Common::Rect *clip_rect, uint8 opacity) {
444 	uint16 src_x = 0;
445 	uint16 src_y = 0;
446 
447 // clip to screen.
448 
449 	if (dest_x >= width || dest_y >= height)
450 		return false;
451 
452 	if (dest_x < 0) {
453 		if (dest_x + src_w <= 0)
454 			return false;
455 		else
456 			src_w += dest_x;
457 
458 		src_buf += -dest_x;
459 		dest_x = 0;
460 	}
461 
462 	if (dest_y < 0) {
463 		if (dest_y + src_h <= 0)
464 			return false;
465 		else
466 			src_h += dest_y;
467 
468 		src_buf += src_pitch * -dest_y;
469 		dest_y = 0;
470 	}
471 
472 	if (dest_x + src_w >= width)
473 		src_w = width - dest_x;
474 
475 	if (dest_y + src_h >= height)
476 		src_h = height - dest_y;
477 
478 //clip to rect if required.
479 
480 	if (clip_rect) {
481 		if (dest_x + src_w < clip_rect->left || dest_y + src_h < clip_rect->top)
482 			return false;
483 
484 		if (clip_rect->left > dest_x) {
485 			src_x = clip_rect->left - dest_x;
486 			src_w -= src_x;
487 			dest_x = clip_rect->left;
488 		}
489 
490 		if (clip_rect->top > dest_y) {
491 			src_y = clip_rect->top - dest_y;
492 			src_h -= src_y;
493 			dest_y = clip_rect->top;
494 		}
495 
496 		if (dest_x + src_w > clip_rect->left + clip_rect->width()) {
497 			if (clip_rect->left + clip_rect->width() - dest_x <= 0)
498 				return false;
499 
500 			src_w = clip_rect->left + clip_rect->width() - dest_x;
501 		}
502 
503 		if (dest_y + src_h > clip_rect->top + clip_rect->height()) {
504 			if (clip_rect->top + clip_rect->height() - dest_y <= 0)
505 				return false;
506 
507 			src_h = clip_rect->top + clip_rect->height() - dest_y;
508 		}
509 
510 		src_buf += src_y * src_pitch + src_x;
511 	}
512 
513 	if (_renderSurface->bits_per_pixel == 16) {
514 		if (opacity < 255)
515 			return blit16WithOpacity(dest_x, dest_y, src_buf, src_bpp, src_w, src_h, src_pitch, trans, opacity);
516 
517 		return blit16(dest_x, dest_y, src_buf, src_bpp, src_w, src_h, src_pitch, trans);
518 	}
519 
520 	if (opacity < 255)
521 		return blit32WithOpacity(dest_x, dest_y, src_buf, src_bpp, src_w, src_h, src_pitch, trans, opacity);
522 
523 	return blit32(dest_x, dest_y, src_buf, src_bpp, src_w, src_h, src_pitch, trans);
524 }
525 
526 
blendpixel16(uint16 p,uint16 p1,uint8 opacity)527 inline uint16 Screen::blendpixel16(uint16 p, uint16 p1, uint8 opacity) {
528 	return (((uint8)(((float)((p1 & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Rshift) |     //R
529 	       (((uint8)(((float)((p1 & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Gshift) |    //G
530 	       (((uint8)(((float)((p1 & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Bshift);     //B
531 }
532 
blendpixel32(uint32 p,uint32 p1,uint8 opacity)533 inline uint32 Screen::blendpixel32(uint32 p, uint32 p1, uint8 opacity) {
534 	return (((uint8)(((float)((p1 & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Rshift) |     //R
535 	       (((uint8)(((float)((p1 & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Gshift) |    //G
536 	       (((uint8)(((float)((p1 & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(opacity) / 255.0f) + (uint8)(((float)((p & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(255 - opacity) / 255.0f)) << _renderSurface->Bshift);     //B
537 }
538 
blit16(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch,bool trans)539 inline bool Screen::blit16(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_bpp, uint16 src_w, uint16 src_h, uint16 src_pitch, bool trans) {
540 	uint16 *pixels;
541 	uint16 i, j;
542 
543 	pixels = (uint16 *)_renderSurface->pixels;
544 
545 	pixels += dest_y * _renderSurface->w + dest_x;
546 
547 	if (trans) {
548 		for (i = 0; i < src_h; i++) {
549 			for (j = 0; j < src_w; j++) {
550 				if (src_buf[j] != 0xff)
551 					pixels[j] = (uint16)_renderSurface->colour32[src_buf[j]];
552 			}
553 			src_buf += src_pitch;
554 			pixels += _renderSurface->w; //pitch;
555 		}
556 	} else {
557 		for (i = 0; i < src_h; i++) {
558 			for (j = 0; j < src_w; j++) {
559 				pixels[j] = (uint16)_renderSurface->colour32[src_buf[j]];
560 			}
561 			src_buf += src_pitch;
562 			pixels += _renderSurface->w; //_renderSurface->pitch;
563 		}
564 	}
565 
566 	return true;
567 }
568 
blit16WithOpacity(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch,bool trans,uint8 opacity)569 inline bool Screen::blit16WithOpacity(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_bpp, uint16 src_w, uint16 src_h, uint16 src_pitch, bool trans, uint8 opacity) {
570 	uint16 *pixels;
571 	uint16 i, j;
572 
573 	pixels = (uint16 *)_renderSurface->pixels;
574 
575 	pixels += dest_y * _renderSurface->w + dest_x;
576 
577 	if (trans) {
578 		for (i = 0; i < src_h; i++) {
579 			for (j = 0; j < src_w; j++) {
580 				if (src_buf[j] != 0xff)
581 					pixels[j] = blendpixel16(pixels[j], (uint16)_renderSurface->colour32[src_buf[j]], opacity);
582 			}
583 			src_buf += src_pitch;
584 			pixels += _renderSurface->w; //pitch;
585 		}
586 	} else {
587 		for (i = 0; i < src_h; i++) {
588 			for (j = 0; j < src_w; j++) {
589 				pixels[j] = blendpixel16(pixels[j], (uint16)_renderSurface->colour32[src_buf[j]], opacity);
590 			}
591 			src_buf += src_pitch;
592 			pixels += _renderSurface->w; //_renderSurface->pitch;
593 		}
594 	}
595 
596 	return true;
597 }
598 
blit32(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch,bool trans)599 bool Screen::blit32(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_bpp, uint16 src_w, uint16 src_h, uint16 src_pitch, bool trans) {
600 	uint32 *pixels;
601 	uint16 i, j;
602 
603 	pixels = (uint32 *)_renderSurface->pixels;
604 
605 	pixels += dest_y * _renderSurface->w + dest_x;
606 
607 
608 	if (trans) {
609 		for (i = 0; i < src_h; i++) {
610 			for (j = 0; j < src_w; j++) {
611 				if (src_buf[j] != 0xff)
612 					pixels[j] = _renderSurface->colour32[src_buf[j]];
613 			}
614 			src_buf += src_pitch;
615 			pixels += _renderSurface->w; //pitch;
616 		}
617 	} else {
618 		for (i = 0; i < src_h; i++) {
619 			for (j = 0; j < src_w; j++) {
620 				pixels[j] = _renderSurface->colour32[src_buf[j]];
621 			}
622 			src_buf += src_pitch;
623 			pixels += _renderSurface->w; //_renderSurface->pitch;
624 		}
625 	}
626 
627 	return true;
628 }
629 
blit32WithOpacity(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch,bool trans,uint8 opacity)630 bool Screen::blit32WithOpacity(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_bpp, uint16 src_w, uint16 src_h, uint16 src_pitch, bool trans, uint8 opacity) {
631 	uint32 *pixels;
632 	uint16 i, j;
633 
634 	pixels = (uint32 *)_renderSurface->pixels;
635 
636 	pixels += dest_y * _renderSurface->w + dest_x;
637 
638 
639 	if (trans) {
640 		for (i = 0; i < src_h; i++) {
641 			for (j = 0; j < src_w; j++) {
642 				if (src_buf[j] != 0xff)
643 					pixels[j] = blendpixel32(pixels[j], _renderSurface->colour32[src_buf[j]], opacity);
644 			}
645 			src_buf += src_pitch;
646 			pixels += _renderSurface->w; //pitch;
647 		}
648 	} else {
649 		for (i = 0; i < src_h; i++) {
650 			for (j = 0; j < src_w; j++) {
651 				pixels[j] = blendpixel32(pixels[j], _renderSurface->colour32[src_buf[j]], opacity);
652 			}
653 			src_buf += src_pitch;
654 			pixels += _renderSurface->w; //_renderSurface->pitch;
655 		}
656 	}
657 
658 	return true;
659 }
660 
blitbitmap(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_w,uint16 src_h,uint8 fg_color,uint8 bg_color)661 void Screen::blitbitmap(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_w, uint16 src_h, uint8 fg_color, uint8 bg_color) {
662 	if (_renderSurface->bits_per_pixel == 16)
663 		blitbitmap16(dest_x, dest_y, src_buf, src_w, src_h, fg_color, bg_color);
664 	else
665 		blitbitmap32(dest_x, dest_y, src_buf, src_w, src_h, fg_color, bg_color);
666 
667 	return;
668 }
669 
blitbitmap16(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_w,uint16 src_h,uint8 fg_color,uint8 bg_color)670 void Screen::blitbitmap16(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_w, uint16 src_h, uint8 fg_color, uint8 bg_color) {
671 	uint16 *pixels;
672 	uint16 i, j;
673 
674 	pixels = (uint16 *)_renderSurface->pixels;
675 
676 	pixels += dest_y * _renderSurface->w + dest_x;
677 
678 	for (i = 0; i < src_h; i++) {
679 		for (j = 0; j < src_w; j++) {
680 			if (src_buf[j])
681 				pixels[j] = (uint16)_renderSurface->colour32[fg_color];
682 			else
683 				pixels[j] = (uint16)_renderSurface->colour32[bg_color];
684 		}
685 		src_buf += src_w;
686 		pixels += _renderSurface->w; //_renderSurface->pitch;
687 	}
688 
689 	return;
690 }
691 
blitbitmap32(uint16 dest_x,uint16 dest_y,const byte * src_buf,uint16 src_w,uint16 src_h,uint8 fg_color,uint8 bg_color)692 void Screen::blitbitmap32(uint16 dest_x, uint16 dest_y, const byte *src_buf, uint16 src_w, uint16 src_h, uint8 fg_color, uint8 bg_color) {
693 	uint32 *pixels;
694 	uint16 i, j;
695 
696 	pixels = (uint32 *)_renderSurface->pixels;
697 
698 	pixels += dest_y * _renderSurface->w + dest_x;
699 
700 	for (i = 0; i < src_h; i++) {
701 		for (j = 0; j < src_w; j++) {
702 			if (src_buf[j])
703 				pixels[j] = _renderSurface->colour32[fg_color];
704 			else
705 				pixels[j] = _renderSurface->colour32[bg_color];
706 		}
707 		src_buf += src_w;
708 		pixels += _renderSurface->w; //_renderSurface->pitch;
709 	}
710 
711 	return;
712 }
713 
714 //4 is pure-light
715 //0 is pitch-black
716 //Globe of r 1 is just a single tile of 2
717 
718 static const char TileGlobe[][11 * 11] = {
719 	{
720 		// 1 - magic items
721 		1
722 	},
723 	{
724 		// 2- candle, heatsource, fire field, cookfire, stove
725 		1, 1, 1,
726 		1, 2, 1,
727 		1, 1, 1
728 	},
729 	{
730 		// 3 - torch, brazier, campfire, lamppost, candelabra, moongate
731 		0, 1, 1, 1, 0,
732 		1, 2, 2, 2, 1,
733 		1, 2, 3, 2, 1,
734 		1, 2, 2, 2, 1,
735 		0, 1, 1, 1, 0
736 	},
737 	{
738 		// 4 - 20:00, eclipse, dungeon
739 		0, 0, 1, 1, 1, 0, 0,
740 		0, 1, 2, 2, 2, 1, 0,
741 		1, 2, 3, 3, 3, 2, 1,
742 		1, 2, 3, 4, 3, 2, 1,
743 		1, 2, 3, 3, 3, 2, 1,
744 		0, 1, 2, 2, 2, 1, 0,
745 		0, 0, 1, 1, 1, 0, 0
746 	},
747 	{
748 		// 5 - 5:00, 19:50
749 		0, 0, 0, 1, 1, 1, 0, 0, 0,
750 		0, 1, 1, 2, 2, 2, 1, 1, 0,
751 		0, 1, 2, 3, 3, 3, 2, 1, 0,
752 		1, 2, 3, 4, 4, 4, 3, 2, 1,
753 		1, 2, 3, 4, 4, 4, 3, 2, 1,
754 		1, 2, 3, 4, 4, 4, 3, 2, 1,
755 		0, 1, 2, 3, 3, 3, 2, 1, 0,
756 		0, 1, 1, 2, 2, 2, 1, 1, 0,
757 		0, 0, 0, 1, 1, 1, 0, 0, 0,
758 	},
759 	{
760 		// 6 - 5:10, 19:40
761 		0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
762 		0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0,
763 		0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0,
764 		0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0,
765 		1, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1,
766 		1, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1,
767 		1, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1,
768 		0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0,
769 		0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0,
770 		0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0,
771 		0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0
772 	},
773 	{
774 		// 7 - 5:20, 19:30
775 		0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0,
776 		0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0,
777 		1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1,
778 		1, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1,
779 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
780 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
781 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
782 		1, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1,
783 		1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1,
784 		0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0,
785 		0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0
786 	},
787 	{
788 		// 8- 5:30, 19:20, torch equipped, light spell
789 		2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2,
790 		2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2,
791 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
792 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
793 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
794 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
795 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
796 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
797 		2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2,
798 		2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2,
799 		2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2
800 	},
801 	{
802 		// 9 - 5:40, 19:10
803 		3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3,
804 		3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3,
805 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
806 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
807 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
808 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
809 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
810 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
811 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
812 		3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3,
813 		3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3
814 	},
815 	{
816 		// 10 - 5:50 19:00
817 		3, 3, 3, 4, 4, 4, 4, 4, 3, 3, 3,
818 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
819 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
820 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
821 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
822 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
823 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
824 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
825 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
826 		3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
827 		3, 3, 3, 4, 4, 4, 4, 4, 3, 3, 3
828 	}
829 };
830 
clearalphamap8(uint16 x,uint16 y,uint16 w,uint16 h,uint8 opacity,bool party_light_source)831 void Screen::clearalphamap8(uint16 x, uint16 y, uint16 w, uint16 h, uint8 opacity, bool party_light_source) {
832 	switch (lighting_style) {
833 	default:
834 	case LIGHTING_STYLE_NONE:
835 		return;
836 	case LIGHTING_STYLE_SMOOTH:
837 		shading_ambient = opacity;
838 		break;
839 	case LIGHTING_STYLE_ORIGINAL:
840 		if (opacity < 0xFF)
841 			shading_ambient = 0;
842 		else
843 			shading_ambient = 0xFF;
844 		break;
845 	}
846 
847 	if (shading_data == NULL) {
848 		shading_rect.left = x;
849 		shading_rect.top = y;
850 		if (lighting_style == LIGHTING_STYLE_ORIGINAL) {
851 			shading_rect.setWidth(w + (SHADING_BORDER * 2));
852 			shading_rect.setHeight(h + (SHADING_BORDER * 2));
853 		} else { // LIGHTING_STYLE_SMOOTH
854 			shading_rect.setWidth((w + (SHADING_BORDER * 2)) * 16 + 8);
855 			shading_rect.setHeight((h + (SHADING_BORDER * 2)) * 16 + 8);
856 		}
857 		shading_data = (byte *)malloc(sizeof(byte) * shading_rect.width() * shading_rect.height());
858 		if (shading_data == NULL) {
859 			/* We couldn't allocate memory for the opacity map, so just disable lighting */
860 			shading_ambient = 0xFF;
861 			return;
862 		}
863 		buildalphamap8();
864 	}
865 	if (shading_ambient == 0xFF) {
866 	} else {
867 		memset(shading_data, shading_ambient, sizeof(char)*shading_rect.width() * shading_rect.height());
868 	}
869 	sint16 x_off;
870 	if (Game::get_game()->is_original_plus_full_map())
871 		x_off = - Game::get_game()->get_background()->get_border_width();
872 	else
873 		x_off = 0;
874 	//Light globe around the avatar
875 	if (lighting_style == LIGHTING_STYLE_ORIGINAL)
876 		drawalphamap8globe((shading_rect.width() - 1 + x_off / 16) / 2 - SHADING_BORDER, (shading_rect.height() - 1) / 2 - SHADING_BORDER, opacity / 20 + 4); //range 4 - 10
877 	else if (lighting_style == LIGHTING_STYLE_SMOOTH)
878 		drawalphamap8globe((((shading_rect.width() - 8 + x_off) / 16) - 1) / 2 - SHADING_BORDER, (((shading_rect.height() - 8) / 16) - 1) / 2 - SHADING_BORDER, party_light_source ? 5 : 4);
879 }
880 
buildalphamap8()881 void Screen::buildalphamap8() {
882 	//Build three globes for 5 intensities
883 	for (int i = 0; i < NUM_GLOBES; i++) {
884 		shading_globe[i] = (uint8 *)malloc(sqr(globeradius[i]));
885 		for (int y = 0; y < globeradius[i]; y++) {
886 			for (int x = 0; x < globeradius[i]; x++) {
887 				float r;
888 				//Distance from center
889 				r  = sqrtf(sqr((y - globeradius_2[i])) + sqr((x - globeradius_2[i])));
890 				//Unitize
891 				r /= sqrtf(sqr(globeradius_2[i]) + sqr(globeradius_2[i]));
892 				//Calculate brightness
893 				r  = (float)exp(-(10 * r * r));
894 				//Fit into a byte
895 				r *= 255;
896 				//Place it
897 				shading_globe[i][y * globeradius[i] + x] = (uint8)r;
898 			}
899 		}
900 	}
901 
902 	//Get the three shading tiles (for original-style dithered lighting)
903 	Game *game = Game::get_game();
904 	int game_type;
905 	config->value("config/GameType", game_type);
906 
907 	if (game_type == NUVIE_GAME_U6 || game_type == NUVIE_GAME_SE) {
908 		shading_tile[0] = game->get_map_window()->get_tile_manager()->get_tile(444)->data;
909 		shading_tile[1] = game->get_map_window()->get_tile_manager()->get_tile(445)->data;
910 		shading_tile[2] = game->get_map_window()->get_tile_manager()->get_tile(446)->data;
911 		shading_tile[3] = game->get_map_window()->get_tile_manager()->get_tile(447)->data;
912 	} else { //NUVIE_GAME_MD
913 		shading_tile[0] = game->get_map_window()->get_tile_manager()->get_tile(268)->data;
914 		shading_tile[1] = game->get_map_window()->get_tile_manager()->get_tile(269)->data;
915 		shading_tile[2] = game->get_map_window()->get_tile_manager()->get_tile(270)->data;
916 		shading_tile[3] = game->get_map_window()->get_tile_manager()->get_tile(271)->data;
917 	}
918 }
919 
920 
drawalphamap8globe(sint16 x,sint16 y,uint16 r)921 void Screen::drawalphamap8globe(sint16 x, sint16 y, uint16 r) {
922 	sint16 i, j;
923 // check shouldn't be needed since items only have 3 intensites
924 	//Clamp lighting globe size to 0-4 (5 levels) // 4 - 10 (7 levels) now in orig_style now like original
925 //    if( r > NUM_GLOBES && lighting_style != LIGHTING_STYLE_ORIGINAL)
926 //        r = NUM_GLOBES;
927 	if (r < 1)
928 		return;
929 	if (shading_ambient == 0xFF)
930 		return;
931 	if (lighting_style == LIGHTING_STYLE_NONE)
932 		return;
933 	if (lighting_style == LIGHTING_STYLE_ORIGINAL) {
934 		uint8 rad;
935 		if (r < 6)
936 			rad = r - 1;
937 		else
938 			rad = 5;
939 		x += SHADING_BORDER;
940 		y += SHADING_BORDER;
941 		//Draw using "original" lighting
942 		for (j = 0; j <= rad * 2; j++)
943 			for (i = 0; i <= rad * 2; i++) {
944 				if (x + i - rad < 0 || x + i - rad >= shading_rect.width())
945 					continue;
946 				if (y + j - rad < 0 || y + j - rad >= shading_rect.height())
947 					continue;
948 				shading_data[(y + j - rad)*shading_rect.width() + (x + i - rad)] = MIN(shading_data[(y + j - rad) * shading_rect.width() + (x + i - rad)] + TileGlobe[r - 1][j * (rad * 2 + 1) + i], 4);
949 			}
950 		return;
951 	}
952 	x = (x + SHADING_BORDER) * 16 + 8;
953 	y = (y + SHADING_BORDER) * 16 + 8;
954 
955 	//Draw using "smooth" lighting
956 	//The x and y are relative to (0,0) of the mapwindow itself, and are absolute coordinates, so are i and j
957 	r--;
958 	for (i = -globeradius_2[r]; i < globeradius_2[r]; i++)
959 		for (j = -globeradius_2[r]; j < globeradius_2[r]; j++) {
960 			if ((y + i) - 1 < 0 ||
961 			        (x + j) - 1 < 0 ||
962 			        (y + i) + 1 > shading_rect.height() ||
963 			        (x + j) + 1 > shading_rect.width())
964 				continue;
965 			shading_data[(y + i)*shading_rect.width() + (x + j)] = MIN(shading_data[(y + i) * shading_rect.width() + (x + j)] + shading_globe[r][(i + globeradius_2[r]) * globeradius[r] + (j + globeradius_2[r])], 255);
966 		}
967 }
968 
969 
blitalphamap8(sint16 x,sint16 y,Common::Rect * clip_rect)970 void Screen::blitalphamap8(sint16 x, sint16 y, Common::Rect *clip_rect) {
971 	//pixel = (dst*(1-alpha))+(src*alpha)   for an interpolation
972 	//pixel = pixel * alpha                 for a reduction
973 	//We use a reduction here
974 
975 	if (shading_ambient == 0xFF)
976 		return;
977 	if (lighting_style == LIGHTING_STYLE_NONE)
978 		return;
979 
980 	uint16 i, j;
981 	Game *game = Game::get_game();
982 
983 	if (lighting_style == LIGHTING_STYLE_ORIGINAL) {
984 
985 		for (j = SHADING_BORDER; j < shading_rect.height() - SHADING_BORDER; j++) {
986 			for (i = SHADING_BORDER; i < shading_rect.width() - SHADING_BORDER; i++) {
987 				if (shading_data[j * shading_rect.width() + i] < 4)
988 					blit(x + (i - SHADING_BORDER) * 16, y + (j - SHADING_BORDER) * 16, shading_tile[shading_data[j * shading_rect.width() + i]], 8, 16, 16, 16, true, game->get_map_window()->get_clip_rect());
989 			}
990 		}
991 		return;
992 	}
993 
994 	uint16 src_w = shading_rect.width() - (SHADING_BORDER * 2 * 16);
995 	uint16 src_h = shading_rect.height() - (SHADING_BORDER * 2 * 16);
996 
997 	uint16 src_x = SHADING_BORDER * 16;
998 	uint16 src_y = SHADING_BORDER * 16;
999 
1000 	uint8 *src_buf = shading_data;
1001 
1002 	// clip to screen.
1003 
1004 	//if(x >= width || y >= height)
1005 	//  return;
1006 
1007 	if (x < 0) {
1008 		//if(x + src_w <= 0)
1009 		//  return;
1010 		//else
1011 		src_w += x;
1012 
1013 		src_buf += -x;
1014 		x = 0;
1015 	}
1016 
1017 	if (y < 0) {
1018 		//if(y + src_h <= 0)
1019 		//  return;
1020 		//else
1021 		src_h += y;
1022 
1023 		src_buf += shading_rect.width() * -y;
1024 		y = 0;
1025 	}
1026 
1027 	if (x + src_w >= width)
1028 		src_w = width - x;
1029 
1030 	if (y + src_h >= height)
1031 		src_h = height - y;
1032 
1033 	//clip to rect if required.
1034 
1035 	if (clip_rect) {
1036 		//if(x + src_w < clip_rect->left || y + src_h < clip_rect->top)
1037 		//   return;
1038 
1039 		if (clip_rect->left > x) {
1040 			src_x += (clip_rect->left - x);
1041 			src_w -= (clip_rect->left - x);
1042 			x = clip_rect->left;
1043 		}
1044 
1045 		if (clip_rect->top > y) {
1046 			src_y += (clip_rect->top - y);
1047 			src_h -= (clip_rect->top - y);
1048 			y = clip_rect->top;
1049 		}
1050 
1051 		if (x + src_w > clip_rect->left + clip_rect->width()) {
1052 			//if(clip_rect->left + clip_rect->width() - x <= 0)
1053 			//  return;
1054 
1055 			src_w = clip_rect->left + clip_rect->width() - x;
1056 		}
1057 
1058 		if (y + src_h > clip_rect->top + clip_rect->height()) {
1059 			//if(clip_rect->top + clip_rect->height() - y <= 0)
1060 			//  return;
1061 
1062 			src_h = clip_rect->top + clip_rect->height() - y;
1063 		}
1064 
1065 		src_buf += src_y * shading_rect.width() + src_x;
1066 	}
1067 
1068 
1069 	switch (_renderSurface->bits_per_pixel) {
1070 	case 16:
1071 		uint16 *pixels16;
1072 		pixels16 = (uint16 *)_renderSurface->pixels;
1073 
1074 		pixels16 += y * _renderSurface->w + x;
1075 
1076 		for (i = 0; i < src_h; i++) {
1077 			for (j = 0; j < src_w; j++) {
1078 				pixels16[j] = (((unsigned char)(((float)((pixels16[j] & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Rshift) |      //R
1079 				              (((unsigned char)(((float)((pixels16[j] & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Gshift) |      //G
1080 				              (((unsigned char)(((float)((pixels16[j] & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Bshift);       //B
1081 			}
1082 			pixels16 += _renderSurface->w;
1083 			src_buf += shading_rect.width();
1084 		}
1085 		return;
1086 		break;
1087 	case 24:
1088 	case 32:
1089 		uint32 *pixels;
1090 		pixels = (uint32 *)_renderSurface->pixels;
1091 
1092 		pixels += y * _renderSurface->w + x;
1093 
1094 		for (i = 0; i < src_h; i++) {
1095 			for (j = 0; j < src_w; j++) {
1096 				pixels[j] = (((unsigned char)(((float)((pixels[j] & _renderSurface->Rmask) >> _renderSurface->Rshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Rshift) |      //R
1097 				            (((unsigned char)(((float)((pixels[j] & _renderSurface->Gmask) >> _renderSurface->Gshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Gshift) |      //G
1098 				            (((unsigned char)(((float)((pixels[j] & _renderSurface->Bmask) >> _renderSurface->Bshift)) * (float)(src_buf[j]) / 255.0f)) << _renderSurface->Bshift);       //B
1099 			}
1100 			pixels += _renderSurface->w;
1101 			src_buf += shading_rect.width();
1102 		}
1103 		return;
1104 		break;
1105 	default:
1106 		DEBUG(0, LEVEL_ERROR, "Screen::blitalphamap8() cannot handle your screen _renderSurface depth of %d\n", _renderSurface->bits_per_pixel);
1107 		break;
1108 		return;
1109 	}
1110 
1111 }
1112 
1113 
1114 /* Return an 8bit _renderSurface. Source format is assumed to be identical to screen. */
create_sdl_surface_8(byte * src_buf,uint16 src_w,uint16 src_h)1115 Graphics::ManagedSurface *Screen::create_sdl_surface_8(byte *src_buf, uint16 src_w, uint16 src_h) {
1116 	Graphics::ManagedSurface *new_surface = new Graphics::ManagedSurface(src_w, src_h,
1117 		Graphics::PixelFormat::createFormatCLUT8());
1118 	byte *pixels = (byte *)new_surface->getPixels();
1119 
1120 	if (_renderSurface->bits_per_pixel == 16) {
1121 		uint16 *src = (uint16 *)src_buf;
1122 		for (int p = 0; p < (src_w * src_h); p++)
1123 			for (int i = 0; i < 256; i++) // convert to 8bpp
1124 				if (src[p] == (uint16)_renderSurface->colour32[i]) {
1125 					pixels[p] = i;
1126 					break;
1127 				}
1128 	} else {
1129 		uint32 *src = (uint32 *)src_buf;
1130 		for (int p = 0; p < (src_w * src_h); p++)
1131 			for (int i = 0; i < 256; i++)
1132 				if (src[p] == _renderSurface->colour32[i]) {
1133 					pixels[p] = i;
1134 					break;
1135 				}
1136 	}
1137 	return (new_surface);
1138 }
1139 
1140 
create_sdl_surface_from(byte * src_buf,uint16 src_bpp,uint16 src_w,uint16 src_h,uint16 src_pitch)1141 Graphics::ManagedSurface *Screen::create_sdl_surface_from(byte *src_buf, uint16 src_bpp, uint16 src_w, uint16 src_h, uint16 src_pitch) {
1142 	Graphics::ManagedSurface *new_surface;
1143 	uint16 i, j;
1144 
1145 	new_surface = RenderSurface::createSurface(src_w, src_h,
1146 		_renderSurface->getFormat());
1147 
1148 	if (_renderSurface->bits_per_pixel == 16) {
1149 		uint16 *pixels = (uint16 *)new_surface->getPixels();
1150 
1151 		for (i = 0; i < src_h; i++) {
1152 			for (j = 0; j < src_w; j++) {
1153 				pixels[j] = (uint16)_renderSurface->colour32[src_buf[j]];
1154 			}
1155 			src_buf += src_pitch;
1156 			pixels += src_pitch; //_renderSurface->pitch;
1157 		}
1158 	} else {
1159 		uint32 *pixels = (uint32 *)new_surface->getPixels();
1160 
1161 		for (i = 0; i < src_h; i++) {
1162 			for (j = 0; j < src_w; j++) {
1163 				pixels[j] = _renderSurface->colour32[src_buf[j]];
1164 			}
1165 			src_buf += src_pitch;
1166 			pixels += src_w;
1167 		}
1168 	}
1169 
1170 	return new_surface;
1171 
1172 }
1173 
get_pitch()1174 uint16 Screen::get_pitch() {
1175 	return (uint16)_renderSurface->pitch;
1176 }
1177 
get_bpp()1178 uint16 Screen::get_bpp() {
1179 	return _renderSurface->bits_per_pixel;
1180 }
1181 
update()1182 void Screen::update() {
1183 	_rawSurface->markAllDirty();
1184 	_rawSurface->update();
1185 }
1186 
1187 
update(int x,int y,uint16 w,uint16 h)1188 void Screen::update(int x, int y, uint16 w, uint16 h) {
1189 	if (x < 0)
1190 		x = 0;
1191 	if (y < 0)
1192 		y = 0;
1193 	if (x > width)
1194 		return;
1195 	if (y > height)
1196 		return;
1197 	if ((x + w) > width)
1198 		w = width - x;
1199 	if ((y + h) > height)
1200 		h = height - y;
1201 
1202 	// Get the subarea, which internally adds a dirty rect for the given area
1203 	_rawSurface->getSubArea(Common::Rect(x, y, x + width, y + height));
1204 }
1205 
preformUpdate()1206 void Screen::preformUpdate() {
1207 	_rawSurface->update();
1208 }
1209 
lock()1210 void Screen::lock() {
1211 // SDL_LockSurface(scaled_surface);
1212 
1213 	return;
1214 }
1215 
unlock()1216 void Screen::unlock() {
1217 //SDL_UnlockSurface(scaled_surface);
1218 
1219 	return;
1220 }
1221 
initScaler()1222 bool Screen::initScaler() {
1223 	Std::string scaler_name;
1224 
1225 	return true;
1226 }
1227 
get_screen_bpp()1228 int Screen::get_screen_bpp() {
1229 	// Get info. about video.
1230 	Graphics::PixelFormat pf = g_system->getScreenFormat();
1231 	return pf.bpp();
1232 }
1233 
set_screen_mode()1234 void Screen::set_screen_mode() {
1235 	if (scale_factor == 0) scale_factor = 1;
1236 	scaler = 0;
1237 	scale_factor = 1;
1238 
1239 	Graphics::PixelFormat SCREEN_FORMAT(2, 5, 6, 5, 0, 11, 5, 0, 0);
1240 	initGraphics(width, height, &SCREEN_FORMAT);
1241 	_rawSurface = new Graphics::Screen(width, height, SCREEN_FORMAT);
1242 
1243 	_renderSurface = CreateRenderSurface(_rawSurface);
1244 }
1245 
is_fullscreen() const1246 bool Screen::is_fullscreen() const {
1247 	return g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
1248 }
1249 
toggle_fullscreen()1250 bool Screen::toggle_fullscreen() {
1251 	set_fullscreen(!is_fullscreen());
1252 	return true;
1253 }
1254 
set_fullscreen(bool value)1255 bool Screen::set_fullscreen(bool value) {
1256 	g_system->beginGFXTransaction();
1257 	g_system->setFeatureState(OSystem::kFeatureFullscreenMode, value);
1258 	g_system->endGFXTransaction();
1259 
1260 	return true;
1261 }
1262 
1263 //Note! assumes area divides evenly by down_scale factor
copy_area(Common::Rect * area,uint16 down_scale)1264 byte *Screen::copy_area(Common::Rect *area, uint16 down_scale) {
1265 	if (_renderSurface->bits_per_pixel == 16)
1266 		return (copy_area16(area, down_scale));
1267 
1268 	return (copy_area32(area, down_scale));
1269 }
1270 
copy_area16(Common::Rect * area,uint16 down_scale)1271 byte *Screen::copy_area16(Common::Rect *area, uint16 down_scale) {
1272 	Graphics::PixelFormat *fmt;
1273 	Graphics::ManagedSurface *main_surface = get_sdl_surface();
1274 	byte *dst_pixels = NULL;
1275 	byte *ptr;
1276 	const uint16 *src_pixels;
1277 	uint32 r, g, b;
1278 	uint32 ra, ga, ba;
1279 	uint16 x, y;
1280 	uint8 x1, y1;
1281 
1282 	dst_pixels = new unsigned char[((area->width() / down_scale) * (area->height() / down_scale)) * 3];
1283 	ptr = dst_pixels;
1284 
1285 	fmt = &main_surface->format;
1286 
1287 	for (y = 0; y < area->height(); y += down_scale) {
1288 		for (x = 0; x < area->width(); x += down_scale) {
1289 			r = 0;
1290 			g = 0;
1291 			b = 0;
1292 
1293 			src_pixels = (const uint16 *)main_surface->getPixels();
1294 			src_pixels += ((area->top + y) * _renderSurface->w + (area->left + x));
1295 
1296 			for (y1 = 0; y1 < down_scale; y1++) {
1297 				for (x1 = 0; x1 < down_scale; x1++) {
1298 					ra = *src_pixels & fmt->rMax();
1299 					ra >>= fmt->rShift;
1300 					ra <<= fmt->rLoss;
1301 
1302 					ga = *src_pixels & fmt->gMax();
1303 					ga >>= fmt->gShift;
1304 					ga <<= fmt->gLoss;
1305 
1306 					ba = *src_pixels & fmt->bMax();
1307 					ba >>= fmt->bShift;
1308 					ba <<= fmt->bLoss;
1309 
1310 					r += ra;
1311 					g += ga;
1312 					b += ba;
1313 
1314 					src_pixels++;
1315 				}
1316 				src_pixels += _renderSurface->w;
1317 			}
1318 
1319 			ptr[0] = (uint8)(r / (down_scale * down_scale));
1320 			ptr[1] = (uint8)(g / (down_scale * down_scale));
1321 			ptr[2] = (uint8)(b / (down_scale * down_scale));
1322 			ptr += 3;
1323 		}
1324 	}
1325 
1326 	return dst_pixels;
1327 }
1328 
copy_area32(Common::Rect * area,uint16 down_scale)1329 byte *Screen::copy_area32(Common::Rect *area, uint16 down_scale) {
1330 	Graphics::PixelFormat *fmt;
1331 	Graphics::ManagedSurface *main_surface = get_sdl_surface();
1332 	byte *dst_pixels = NULL;
1333 	byte *ptr;
1334 	const uint32 *src_pixels;
1335 	uint32 r, g, b;
1336 	uint32 ra, ga, ba;
1337 	uint16 x, y;
1338 	uint8 x1, y1;
1339 
1340 	dst_pixels = new unsigned char[((area->width() / down_scale) * (area->height() / down_scale)) * 3];
1341 	ptr = dst_pixels;
1342 
1343 	fmt = &main_surface->format;
1344 
1345 	for (y = 0; y < area->height(); y += down_scale) {
1346 		for (x = 0; x < area->width(); x += down_scale) {
1347 			r = 0;
1348 			g = 0;
1349 			b = 0;
1350 
1351 			src_pixels = (const uint32 *)main_surface->getPixels();
1352 			src_pixels += ((area->top + y) * _renderSurface->w + (area->left + x));
1353 
1354 			for (y1 = 0; y1 < down_scale; y1++) {
1355 				for (x1 = 0; x1 < down_scale; x1++) {
1356 					ra = *src_pixels & fmt->rMax();
1357 					ra >>= fmt->rShift;
1358 					ra <<= fmt->rLoss;
1359 
1360 					ga = *src_pixels & fmt->gMax();
1361 					ga >>= fmt->gShift;
1362 					ga <<= fmt->gLoss;
1363 
1364 					ba = *src_pixels & fmt->bMax();
1365 					ba >>= fmt->bShift;
1366 					ba <<= fmt->bLoss;
1367 
1368 					r += ra;
1369 					g += ga;
1370 					b += ba;
1371 
1372 					src_pixels++;
1373 				}
1374 				src_pixels += _renderSurface->w;
1375 			}
1376 
1377 			ptr[0] = (uint8)(r / (down_scale * down_scale));
1378 			ptr[1] = (uint8)(g / (down_scale * down_scale));
1379 			ptr[2] = (uint8)(b / (down_scale * down_scale));
1380 			ptr += 3;
1381 		}
1382 	}
1383 
1384 	return dst_pixels;
1385 }
1386 
1387 // _renderSurface -> byte *
1388 // (NULL area = entire screen)
copy_area(Common::Rect * area,byte * buf)1389 byte *Screen::copy_area(Common::Rect *area, byte *buf) {
1390 	Common::Rect screen_area(0, 0, _renderSurface->w, _renderSurface->h);
1391 	if (!area)
1392 		area = &screen_area;
1393 
1394 	if (_renderSurface->bits_per_pixel == 16)
1395 		return (copy_area16(area, buf));
1396 	return (copy_area32(area, buf));
1397 }
1398 
1399 
1400 // byte * -> _renderSurface
1401 // byte * -> target (src area still means location on screen, not relative to target)
1402 // (NULL area = entire screen)
restore_area(byte * pixels,Common::Rect * area,byte * target,Common::Rect * target_area,bool free_src)1403 void Screen::restore_area(byte *pixels, Common::Rect *area,
1404 						  byte *target, Common::Rect *target_area, bool free_src) {
1405 	Common::Rect screen_area(0, 0, _renderSurface->w, _renderSurface->h);
1406 	if (!area)
1407 		area = &screen_area;
1408 
1409 	if (_renderSurface->bits_per_pixel == 16)
1410 		restore_area16(pixels, area, target, target_area, free_src);
1411 	else
1412 		restore_area32(pixels, area, target, target_area, free_src);
1413 }
1414 
1415 
copy_area32(Common::Rect * area,byte * buf)1416 byte *Screen::copy_area32(Common::Rect *area, byte *buf) {
1417 	uint32 *copied = (uint32 *)buf;
1418 	if (buf == NULL) {
1419 		copied = (uint32 *)malloc(area->width() * area->height() * 4);
1420 	}
1421 	uint32 *dest = copied;
1422 	uint32 *src = (uint32 *)_renderSurface->pixels;
1423 	uint16 src_x_off = ABS(area->left);
1424 	uint16 src_y_off = ABS(area->top);
1425 	uint16 src_w = area->width();
1426 	uint16 src_h = area->height();
1427 
1428 	if (area->left < 0) {
1429 		src_x_off = 0;
1430 		src_w += area->left;
1431 		dest += ABS(area->left);
1432 	}
1433 
1434 	if (area->top < 0) {
1435 		src_y_off = 0;
1436 		src_h += area->top;
1437 		dest += (area->width() * ABS(area->top));
1438 	}
1439 
1440 	if (src_x_off + src_w > (int)_renderSurface->w) {
1441 		src_w -= ((src_x_off + src_w) - _renderSurface->w);
1442 	}
1443 
1444 	if (src_y_off + src_h > (int)_renderSurface->h) {
1445 		src_h -= ((src_y_off + src_h) - _renderSurface->h);
1446 	}
1447 
1448 	src += src_y_off * _renderSurface->w + src_x_off;
1449 
1450 	for (uint32 i = 0; i < src_h; i++) {
1451 		for (uint32 j = 0; j < src_w; j++)
1452 			dest[j] = src[j];
1453 		dest += area->width();
1454 		src += _renderSurface->w;
1455 	}
1456 	return ((byte *)copied);
1457 }
1458 
1459 
restore_area32(byte * pixels,Common::Rect * area,byte * target,Common::Rect * target_area,bool free_src)1460 void Screen::restore_area32(byte *pixels, Common::Rect *area,
1461 							byte *target, Common::Rect *target_area, bool free_src) {
1462 	uint32 *src = (uint32 *)pixels;
1463 	uint32 *dest = (uint32 *)_renderSurface->pixels;
1464 	dest += area->top * _renderSurface->w + area->left;
1465 	if (target) { // restore to target instead of screen
1466 		dest = (uint32 *)target;
1467 		dest += (area->top - target_area->top) * target_area->width() + (area->left - target_area->left);
1468 	}
1469 	for (int i = 0; i < area->height(); i++) {
1470 		for (int j = 0; j < area->width(); j++)
1471 			dest[j] = src[j];
1472 		src += area->width();
1473 		dest += target ? target_area->width() : _renderSurface->w;
1474 	}
1475 	if (free_src) {
1476 		free(pixels);
1477 	}
1478 }
1479 
1480 
copy_area16(Common::Rect * area,byte * buf)1481 byte *Screen::copy_area16(Common::Rect *area, byte *buf) {
1482 	uint16 *copied = (uint16 *)buf;
1483 	if (buf == NULL) {
1484 		copied = (uint16 *)malloc(area->width() * area->height() * 2);
1485 	}
1486 	uint16 *dest = copied;
1487 	uint16 *src = (uint16 *)_renderSurface->pixels;
1488 	uint16 src_x_off = ABS(area->left);
1489 	uint16 src_y_off = ABS(area->top);
1490 	uint16 src_w = area->width();
1491 	uint16 src_h = area->height();
1492 
1493 	if (area->left < 0) {
1494 		src_x_off = 0;
1495 		src_w += area->left;
1496 		dest += ABS(area->left);
1497 	}
1498 
1499 	if (area->top < 0) {
1500 		src_y_off = 0;
1501 		src_h += area->top;
1502 		dest += (area->width() * ABS(area->top));
1503 	}
1504 
1505 	if (src_x_off + src_w > (int)_renderSurface->w) {
1506 		src_w -= ((src_x_off + src_w) - _renderSurface->w);
1507 	}
1508 
1509 	if (src_y_off + src_h > (int)_renderSurface->h) {
1510 		src_h -= ((src_y_off + src_h) - _renderSurface->h);
1511 	}
1512 
1513 	src += src_y_off * _renderSurface->w + src_x_off;
1514 
1515 	for (uint32 i = 0; i < src_h; i++) {
1516 		for (uint32 j = 0; j < src_w; j++)
1517 			dest[j] = src[j];
1518 		dest += area->width();
1519 		src += _renderSurface->w;
1520 	}
1521 	return ((byte *)copied);
1522 }
1523 
1524 
restore_area16(byte * pixels,Common::Rect * area,byte * target,Common::Rect * target_area,bool free_src)1525 void Screen::restore_area16(byte *pixels, Common::Rect *area,
1526 							byte *target, Common::Rect *target_area, bool free_src) {
1527 	uint16 *src = (uint16 *)pixels;
1528 	uint16 *dest = (uint16 *)_renderSurface->pixels;
1529 	dest += area->top * _renderSurface->w + area->left;
1530 	if (target) { // restore to target instead of screen
1531 		dest = (uint16 *)target;
1532 		dest += (area->top - target_area->top) * target_area->width() + (area->left - target_area->left);
1533 	}
1534 
1535 	for (int i = 0; i < area->height(); i++) {
1536 		for (int j = 0; j < area->width(); j++)
1537 			dest[j] = src[j];
1538 		src += area->width();
1539 		dest += target ? target_area->width() : _renderSurface->w;
1540 	}
1541 	if (free_src) {
1542 		free(pixels);
1543 	}
1544 }
1545 
draw_line(int sx,int sy,int ex,int ey,uint8 color)1546 void Screen::draw_line(int sx, int sy, int ex, int ey, uint8 color) {
1547 	if (_renderSurface == NULL)
1548 		return;
1549 
1550 	_renderSurface->draw_line(sx, sy, ex, ey, color);
1551 
1552 	return;
1553 }
1554 
1555 
get_mouse_location(int * x,int * y)1556 void Screen::get_mouse_location(int *x, int *y) {
1557 	Common::Point pt = Events::get()->getMousePos();
1558 	*x = pt.x;
1559 	*y = pt.y;
1560 }
1561 
set_non_square_pixels(bool value)1562 void Screen::set_non_square_pixels(bool value) {
1563 	// No implementation
1564 }
1565 
1566 } // End of namespace Nuvie
1567 } // End of namespace Ultima
1568