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