1 /**
2 * @file handler_display.cc
3 * @briefi Handle displaying and updating with SDL
4 * @created 2002-08-17
5 * @date 2014-08-15
6 * @copyright 1991-2014 TLK Games
7 * @author Bruno Ethvignot
8 * @version $Revision: 24 $
9 */
10 /*
11 * copyright (c) 1991-2014 TLK Games all rights reserved
12 * $Id: handler_display.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
13 *
14 * TecnoballZ is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * TecnoballZ is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 * MA 02110-1301, USA.
28 */
29 #include "../include/handler_display.h"
30 #include "../include/handler_keyboard.h"
31 #include "../include/handler_audio.h"
32 #include "../include/handler_resources.h"
33
34 char
35 handler_display::window_title[25] = "TecnoballZ by TLK Games\0";
36 bool handler_display::optionfull = false;
37 bool handler_display::optionsync = true;
38
39 /**
40 * Create the object
41 */
handler_display()42 handler_display::handler_display ()
43 {
44 sdl_screen = (SDL_Surface *) NULL;
45 game_surface = (SDL_Surface *) NULL;
46 sdl_ticks_amount = 0;
47 frames_counter_modulo = 0;
48 tilt_offset = 0;
49 /* 1000 / 50 = 20 */
50 game_speed = 20;
51 delay_change_counter = 0;
52 delay_ticks_amount = 0;
53 delay_change_counter = DELAY_CHANGE_MAX;
54 }
55
56 /**
57 * Release the display handler object
58 */
~handler_display()59 handler_display::~handler_display ()
60 {
61 if (NULL != game_screen)
62 {
63 delete game_screen;
64 game_screen = NULL;
65 }
66 if (NULL != background_screen)
67 {
68 delete background_screen;
69 background_screen = NULL;
70 }
71 if (SDL_WasInit (SDL_INIT_VIDEO) != 0)
72 {
73 if (is_verbose)
74 {
75 std::
76 cout << ">handler_display::~handler_display() SDL_VideoQuit()" <<
77 std::endl;
78 }
79 SDL_VideoQuit ();
80 }
81 SDL_Quit ();
82 }
83
84 /**
85 * Initialize the SDL display and allocate surfaces
86 */
87 void
initialize()88 handler_display::initialize ()
89 {
90 set_video_mode ();
91 Uint32 height = window_height + offsetplus * 2;
92 /** Create the main game offscreen */
93 game_screen =
94 new offscreen_surface (window_width, height, bitspixels, offsetplus);
95 game_surface = game_screen->get_surface ();
96 game_screen_pitch = game_surface->pitch;
97 game_screen_pixels =
98 (char *) game_surface->pixels + game_screen_pitch * offsetplus;
99 /** Create the background offscreen */
100 background_screen =
101 new offscreen_surface (window_width, height, bitspixels, offsetplus);
102 SDL_Surface *surface = background_screen->get_surface ();
103 background_pixels = (char *) surface->pixels + surface->pitch * offsetplus;
104 previous_sdl_ticks = SDL_GetTicks ();
105 delay_value = 0;
106 }
107
108 /**
109 * Initializes the video with SDL
110 */
111 void
set_video_mode()112 handler_display::set_video_mode ()
113 {
114 window_width = 320 * resolution;
115 window_height = 240 * resolution;
116 offsetplus = 64 * resolution;
117 if (is_verbose)
118 {
119 std::cout << ">handler_display::set_video_mode() " << window_width
120 << "x" << window_height << std::endl;
121 }
122
123 /* initializes SDL */
124 if (SDL_Init
125 (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE |
126 SDL_INIT_JOYSTICK) < 0)
127 {
128 std::cerr << "!handler_display::set_video_mode() " <<
129 "SDL_Init() return " << SDL_GetError () << std::endl;
130 throw std::runtime_error ("!handler_display::set_video_mode() "
131 "SDL_Init() failed!");
132 }
133
134 /* test if the video mode is available */
135 Uint32 flag = SDL_ANYFORMAT;
136 #ifdef TECNOBALLZ_HANDHELD_CONSOLE
137 flag = SDL_SWSURFACE | SDL_FULLSCREEN;
138 #endif
139 if (optionfull)
140 {
141 flag = flag | SDL_FULLSCREEN;
142 }
143 Uint32 bpp =
144 SDL_VideoModeOK (window_width, window_height, bitspixels, flag);
145 if (0 == bpp)
146 {
147 std::cerr << "!handler_display::set_video_mode() " <<
148 "SDL_VideoModeOK() " << "return " << SDL_GetError () << std::endl;
149 throw std::runtime_error ("!handler_display::set_video_mode() "
150 "SDL_VideoModeOK() failed!");
151 }
152
153 /* initialize the video mode */
154 sdl_screen =
155 SDL_SetVideoMode (window_width, window_height, bitspixels, flag);
156 if (NULL == sdl_screen)
157 {
158 std::cerr << "!handler_display::set_video_mode() " <<
159 "SDL_SetVideoMode() " << "return " << SDL_GetError () << std::endl;
160 throw std::runtime_error ("!handler_display::set_video_mode() "
161 "SDL_SetVideoMode() failed!");
162 }
163 SDL_WM_SetCaption (window_title, window_title);
164
165 #ifdef UNDER_DEVELOPMENT
166 SDL_ShowCursor (SDL_ENABLE);
167 #else
168 SDL_ShowCursor (SDL_DISABLE);
169 #endif
170 SDL_EnableUNICODE (1);
171 }
172
173 /**
174 * Return the screen's width
175 * @return the width of the screen in pixels
176 */
177 Uint32
get_width()178 handler_display::get_width ()
179 {
180 return sdl_screen->w;
181 }
182
183 /**
184 * Return the screen's height
185 * @return the height of the screen in lines
186 */
187 Uint32
get_height()188 handler_display::get_height ()
189 {
190 return sdl_screen->h;
191 }
192
193 /**
194 * Lock surfaces of the game offscreen and the background offscreen
195 */
196 void
lock_surfaces()197 handler_display::lock_surfaces ()
198 {
199 game_screen->lock_surface ();
200 background_screen->lock_surface ();
201 }
202
203 /**
204 * Unlock surfaces of the game offscreen and background offscreen
205 */
206 void
unlock_surfaces()207 handler_display::unlock_surfaces ()
208 {
209 game_screen->unlock_surface ();
210 background_screen->unlock_surface ();
211 }
212
213 /**
214 * Return the number of bits per pixel
215 * @return then number of bits per pixel, 8 for 256 colors
216 */
217 Uint32
get_bits_per_pixel()218 handler_display::get_bits_per_pixel ()
219 {
220 return bitspixels;
221 }
222
223 /**
224 * Display some SDL infos
225 */
226 void
get_info()227 handler_display::get_info ()
228 {
229 const SDL_VideoInfo *vi;
230 char namebuf[32] = { "123456789012345678901234567890\0" };
231 SDL_Rect **modes;
232 Sint32 i;
233 modes = SDL_ListModes (NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
234 if (modes == (SDL_Rect **) 0)
235 {
236 printf ("No modes available!\n");
237 return;
238 }
239 if (modes == (SDL_Rect **) - 1)
240 printf ("All resolutions available.\n");
241 else
242 {
243 printf ("Available Modes\n");
244 for (i = 0; modes[i]; ++i)
245 printf (" %d x %d\n", modes[i]->w, modes[i]->h);
246 }
247 SDL_WM_SetCaption ("TecnoballZ", 0);
248 vi = SDL_GetVideoInfo ();
249 printf
250 ("The number of bits used to represent each pixel in a surface.Usually 8, 16, 24 or 32. BitsPerPixel=%d \n",
251 vi->vfmt->BitsPerPixel);
252 printf
253 ("The number of bytes used to represent each pixel in a surface. Usually one to four BytesPerPixel=%d\n",
254 vi->vfmt->BytesPerPixel);
255 printf ("Rmask=%i Gmask=%i Bmask=%i Amask=%i \n", vi->vfmt->Rmask,
256 vi->vfmt->Gmask, vi->vfmt->Bmask, vi->vfmt->Amask);
257 printf ("Rshift=%i Gshift=%i Bshift=%i Ashift=%i \n", vi->vfmt->Rshift,
258 vi->vfmt->Gshift, vi->vfmt->Bshift, vi->vfmt->Ashift);
259 printf ("Rloss=%i Gloss=%i Bloss=%i Aloss=%i \n", vi->vfmt->Rloss,
260 vi->vfmt->Gloss, vi->vfmt->Bloss, vi->vfmt->Aloss);
261 printf ("Pixel value of transparent pixels. colorkey=%i \n",
262 vi->vfmt->colorkey);
263 printf ("Overall surface alpha value. alpha=%i \n", vi->vfmt->alpha);
264 printf ("Is it possible to create hardware surfaces? hw_available=%i \n",
265 vi->hw_available);
266 printf ("Is there a window manager available wm_available=%i \n",
267 vi->wm_available);
268 printf ("Are hardware to hardware blits accelerated? blit_hw=%i \n",
269 vi->blit_hw);
270 printf
271 ("Are hardware to hardware colorkey blits accelerated? blit_hw_CC=%i \n",
272 vi->blit_hw_CC);
273 printf ("Are hardware to hardware alpha blits accelerated? blit_hw_A=%i\n",
274 vi->blit_hw_A);
275 printf ("Are software to hardware blits accelerated? blit_sw=%i \n",
276 vi->blit_sw);
277 printf
278 ("Are software to hardware colorkey blits accelerated? blit_sw_CC=%i \n",
279 vi->blit_sw_CC);
280 printf ("Are software to hardware alpha blits accelerated? blit_sw_A=%i \n",
281 vi->blit_sw_A);
282 printf ("Are color fills accelerated? blit_fill=%i \n", vi->blit_fill);
283 printf ("Total amount of video memory in Kilobytes. video_mem=%i\n",
284 vi->video_mem);
285 char *c = SDL_VideoDriverName (namebuf, 32);
286 printf ("the name of the video driver=%s\n", c);
287 }
288
289
290 /**
291 * Switch to fullscreen or windows mode
292 */
293 void
check_if_toggle_fullscreen()294 handler_display::check_if_toggle_fullscreen ()
295 {
296 if (keyboard->command_is_pressed (handler_keyboard::TOGGLE_FULLSCREEN) &&
297 keyboard->get_input_cursor_pos () < 0)
298 {
299 if (optionfull)
300 {
301 optionfull = false;
302 }
303 else
304 {
305 optionfull = true;
306 }
307 display->set_video_mode ();
308 display->enable_palette (sdl_palette);
309 }
310 }
311
312 /**
313 * Synchronize the game's speed to the machine it's running on
314 */
315 void
wait_frame()316 handler_display::wait_frame ()
317 {
318
319 frame_counter++;
320
321 /* Get the number of milliseconds since the SDL library initialization */
322 Uint32 sdl_ticks = SDL_GetTicks () - previous_sdl_ticks;
323 optionsync = true;
324 if (optionsync)
325 {
326 delay_ticks_amount += sdl_ticks;
327 if (--delay_change_counter <= 0)
328 {
329 delay_value =
330 ((game_speed * DELAY_CHANGE_MAX) -
331 delay_ticks_amount) / DELAY_CHANGE_MAX;
332 delay_change_counter = DELAY_CHANGE_MAX;
333 delay_ticks_amount = 0;
334 if (delay_value <= 0)
335 {
336 delay_value = 1;
337 }
338 }
339 if (delay_value > 0)
340 {
341 SDL_Delay (delay_value);
342 }
343 }
344 previous_sdl_ticks = SDL_GetTicks ();
345
346 /** Calculate the number of frames per second */
347 sdl_ticks_amount += sdl_ticks;
348 if (++frames_counter_modulo >= 100)
349 {
350 if (0 != sdl_ticks_amount)
351 {
352 frames_per_second = 1000 * frames_counter_modulo / sdl_ticks_amount;
353 }
354 frames_counter_modulo = 0;
355 sdl_ticks_amount = 0;
356 }
357
358 keyboard->read_events ();
359 check_if_toggle_fullscreen ();
360 #ifndef SOUNDISOFF
361 audio->run ();
362 #endif
363 return;
364 }
365
366 /**
367 * Return tne number of frames per second
368 * @return the frame frequency
369 */
370 Uint32
get_frames_per_second()371 handler_display::get_frames_per_second ()
372 {
373 return frames_per_second;
374 }
375
376 //------------------------------------------------------------------------------
377 // buffer & tampon: convert (x,y) to offset
378 // input => zbase: start offset
379 // => offsx: x coordinate
380 // => offsy: y coordinate
381 //------------------------------------------------------------------------------
382 Sint32
ecran_next(Sint32 zbase,Sint32 offsx,Sint32 offsy)383 handler_display::ecran_next (Sint32 zbase, Sint32 offsx, Sint32 offsy)
384 {
385 return (zbase + offsy * game_screen_pitch + offsx);
386 }
387
388 /**
389 * Initialize color palette for the current screen
390 * @param pal pointer to color components
391 */
392 void
enable_palette(unsigned char * pal)393 handler_display::enable_palette (unsigned char *pal)
394 {
395 if (is_verbose)
396 {
397 std::cout << "handler_display::enable_palette() " << std::endl;
398 }
399 unsigned char *p = pal;
400 SDL_Color *color = &sdl_palette[0];
401 Uint32 k = 0;
402 for (Uint32 i = 0; i < 256; i++)
403 {
404 color->r = p[k++];
405 color->g = p[k++];
406 color->b = p[k++];
407 color++;
408 }
409
410 game_screen->set_palette (sdl_palette);
411 background_screen->set_palette (sdl_palette);
412 SDL_SetPalette (sdl_screen, SDL_LOGPAL | SDL_PHYSPAL, sdl_palette, 0, 256);
413 }
414
415 /**
416 * Initialize color palette for the current screen
417 * @param pal pointer to color components of a SDL_Color structure
418 */
419 void
enable_palette(SDL_Color * pal)420 handler_display::enable_palette (SDL_Color * pal)
421 {
422 if (is_verbose)
423 {
424 std::cout << "handler_display::enable_palette(SDL) " << std::endl;
425 }
426 game_screen->set_palette (pal);
427 background_screen->set_palette (pal);
428 SDL_SetPalette (sdl_screen, SDL_LOGPAL | SDL_PHYSPAL, pal, 0, 256);
429 }
430
431 /**
432 * Return the current SDL palette
433 * @return a pointer to a SDL_Color structure
434 */
435 SDL_Color *
get_palette()436 handler_display::get_palette ()
437 {
438 return sdl_palette;
439 }
440
441 /**
442 * Recopy the game offscreen in the main window
443 */
444 void
window_update()445 handler_display::window_update ()
446 {
447 SDL_Rect source =
448 {
449 0,
450 (Sint16) (offsetplus + tilt_offset),
451 (Uint16) window_width,
452 (Uint16) (window_height + offsetplus + tilt_offset)
453 };
454 SDL_Rect destination =
455 {
456 0, 0,
457 (Uint16) window_width, (Uint16) window_height
458 };
459 if (SDL_BlitSurface (game_surface, &source, sdl_screen, &destination) < 0)
460 {
461 std::cerr << "(!)handler_display::window_update():" <<
462 "BlitSurface() return " << SDL_GetError () << std::endl;
463 }
464 SDL_UpdateRect (sdl_screen, 0, 0, sdl_screen->w, sdl_screen->h);
465 if (tilt_offset > 0)
466 {
467 tilt_offset--;
468 }
469 }
470
471 //-------------------------------------------------------------------------------
472 // buffer & tampon: clear shadow box
473 // input => offst: offset adresse ecran
474 // large: width box in pixels
475 // haute: height box en pixels
476 //-------------------------------------------------------------------------------
477 void
clr_shadow(Sint32 offst,Sint32 large,Sint32 haute)478 handler_display::clr_shadow (Sint32 offst, Sint32 large, Sint32 haute)
479 {
480 char zmask = 0x7F;
481 char *bffer = game_screen_pixels + offst;
482 char *tmpon = background_pixels + offst;
483 Sint32 a = large;
484 Sint32 b = haute;
485 Sint32 n = game_screen_pitch - a;
486 for (Sint32 j = 0; j < b; j++, bffer += n, tmpon += n)
487 {
488 for (Sint32 i = 0; i < a; i++)
489 {
490 char pixel = *bffer;
491 pixel &= zmask;
492 *(bffer++) = pixel;
493 pixel = *tmpon;
494 pixel &= zmask;
495 *(tmpon++) = pixel;
496 }
497 }
498 }
499
500 /**
501 * Clear a shadow region
502 * @param xcoord
503 * @param ycoord
504 * @param width
505 * @param height
506 */
507 void
clr_shadow(Sint32 xcoord,Sint32 ycoord,Sint32 width,Sint32 height)508 handler_display::clr_shadow (Sint32 xcoord, Sint32 ycoord, Sint32 width,
509 Sint32 height)
510 {
511 char zmask = 0x7F;
512 char *screen = background_screen->get_pixel_data (xcoord, ycoord);
513 char *bkgd = game_screen->get_pixel_data (xcoord, ycoord);
514
515 Sint32 h = width;
516 Sint32 v = height;
517 Sint32 n = game_screen_pitch - h;
518 for (Sint32 j = 0; j < v; j++, screen += n, bkgd += n)
519 {
520 for (Sint32 i = 0; i < h; i++)
521 {
522 char pixel = *screen;
523 pixel &= zmask;
524 *(screen++) = pixel;
525 pixel = *bkgd;
526 pixel &= zmask;
527 *(bkgd++) = pixel;
528 }
529 }
530 }
531
532 //------------------------------------------------------------------------------
533 // buffer & tampon: display shadow box
534 // input => offst: buffer offset in bytes
535 // => large: width box in pixels
536 // => haute: height box en pixels
537 //------------------------------------------------------------------------------
538 void
set_shadow(Sint32 offst,Sint32 large,Sint32 haute)539 handler_display::set_shadow (Sint32 offst, Sint32 large, Sint32 haute)
540 {
541 char zmask = (char) (0x80);
542 char *bffer = game_screen_pixels + offst;
543 char *tmpon = background_pixels + offst;
544 Sint32 a = large;
545 Sint32 b = haute;
546 Sint32 n = game_screen_pitch - a;
547 for (Sint32 j = 0; j < b; j++, bffer += n, tmpon += n)
548 {
549 for (Sint32 i = 0; i < a; i++)
550 {
551 char pixel = *bffer;
552 pixel |= zmask;
553 *(bffer++) = pixel;
554 pixel = *tmpon;
555 pixel |= zmask;
556 *(tmpon++) = pixel;
557 }
558 }
559 }
560
561 //------------------------------------------------------------------------------
562 // buffer: copy an image of 32 width pixels into buffer memory
563 //------------------------------------------------------------------------------
564 void
buf_affx32(char * srcPT,char * desPT,Sint32 width,Sint32 heigh)565 handler_display::buf_affx32 (char *srcPT, char *desPT, Sint32 width,
566 Sint32 heigh)
567 {
568 Sint32 *d = (Sint32 *) desPT;
569 Sint32 *s = (Sint32 *) srcPT;
570 Sint32 j = heigh;
571 Sint32 ms = width;
572 Sint32 md = game_screen_pitch;
573 for (Sint32 i = 0; i < j; i++)
574 {
575 d[0] = s[0];
576 d[1] = s[1];
577 d[2] = s[2];
578 d[3] = s[3];
579 d[4] = s[4];
580 d[5] = s[5];
581 d[6] = s[6];
582 d[7] = s[7];
583 s = (Sint32 *) ((char *) s + ms);
584 d = (Sint32 *) ((char *) d + md);
585 }
586 }
587
588 //------------------------------------------------------------------------------
589 // buffer: copy an image of 64 width pixels into buffer memory
590 //------------------------------------------------------------------------------
591 void
buf_affx64(char * srcPT,char * desPT,Sint32 width,Sint32 heigh)592 handler_display::buf_affx64 (char *srcPT, char *desPT, Sint32 width,
593 Sint32 heigh)
594 {
595 double *d = (double *) desPT;
596 double *s = (double *) srcPT;
597 Sint32 j = heigh;
598 Sint32 ms = width;
599 Sint32 md = game_screen_pitch;
600 for (Sint32 i = 0; i < j; i++)
601 {
602 d[0] = s[0];
603 d[1] = s[1];
604 d[2] = s[2];
605 d[3] = s[3];
606 d[4] = s[4];
607 d[5] = s[5];
608 d[6] = s[6];
609 d[7] = s[7];
610 s = (double *) ((char *) s + ms);
611 d = (double *) ((char *) d + md);
612 }
613 }
614
615 //------------------------------------------------------------------------------
616 // copy an image
617 //------------------------------------------------------------------------------
618 /*
619 void
620 handler_display::genericGFX (char *sAdre, Sint32 sLarg, Sint32 sHaut,
621 Sint32 sNext, char *dAdre, Sint32 dLarg,
622 Sint32 dHaut, Sint32 dNext)
623 {
624 Sint32 h, l;
625 Sint32 a = sNext;
626 Sint32 b = dNext;
627 if (sLarg > dLarg)
628 l = sLarg;
629 else
630 l = dLarg;
631 if (sHaut > dHaut)
632 h = dHaut;
633 else
634 h = sHaut;
635 char *d = dAdre;
636 char *s = sAdre;
637 for (Sint32 i = 0; i < h; i++, s += a, d += b)
638 {
639 for (Sint32 j = 0; j < l; j++)
640 d[j] = s[j];
641 }
642 }
643 */
644
645 /**
646 * Tilt the screen 10 or 20 pixels upwards
647 */
648 void
tilt_screen()649 handler_display::tilt_screen ()
650 {
651 tilt_offset = 10 * resolution;
652 }
653
654 /**
655 * Select colour gradation
656 */
657 void
set_color_gradation()658 handler_display::set_color_gradation ()
659 {
660 SDL_Color *palette = display->get_palette ();
661 SDL_Color *pal = palette + 239;
662 Sint32 i = random_counter & 0x0F;
663 if (i >= 10)
664 {
665 i = i - 10;
666 }
667 const Uint32 *color_scale = (handler_resources::color_gradations + i * 18);
668 for (i = 0; i < 17; i++)
669 {
670 Uint32 vacol = color_scale[i];
671 Uint32 vablu = vacol & 0x000000ff;
672 Uint32 vagre = vacol & 0x0000ff00;
673 vagre = vagre >> 8;
674 Uint32 vared = vacol & 0x00ff0000;
675 vared = vared >> 16;
676 pal->r = vared;
677 pal->g = vagre;
678 pal->b = vablu;
679 pal++;
680 }
681 display->enable_palette (palette);
682 }
683