17 #include "../stdafx.h"
18 #include "../openttd.h"
19 #include "../gfx_func.h"
21 #include "../blitter/factory.hpp"
22 #include "../network/network.h"
23 #include "../core/random_func.hpp"
24 #include "../core/math_func.hpp"
25 #include "../framerate_type.h"
26 #include "../thread.h"
30 #include "../safeguards.h"
40 static BITMAP *_allegro_screen;
42 #define MAX_DIRTY_RECTS 100
44 static int _num_dirty_rects;
48 if (_num_dirty_rects < MAX_DIRTY_RECTS) {
49 _dirty_rects[_num_dirty_rects].x = left;
50 _dirty_rects[_num_dirty_rects].y = top;
51 _dirty_rects[_num_dirty_rects].width =
width;
52 _dirty_rects[_num_dirty_rects].height =
height;
57 static void DrawSurfaceToScreen()
61 int n = _num_dirty_rects;
65 if (n > MAX_DIRTY_RECTS) {
66 blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
70 for (
int i = 0; i < n; i++) {
71 blit(_allegro_screen, screen, _dirty_rects[i].x, _dirty_rects[i].y, _dirty_rects[i].x, _dirty_rects[i].y, _dirty_rects[i].
width, _dirty_rects[i].
height);
76 static void UpdatePalette(uint start, uint count)
80 uint end = start + count;
81 for (uint i = start; i != end; i++) {
88 set_palette_range(pal, start, end - 1, 1);
91 static void InitPalette()
93 UpdatePalette(0, 256);
96 static void CheckPaletteAnim()
120 static const Dimension default_resolutions[] = {
134 static void GetVideoModes()
138 set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
142 GFX_MODE_LIST *mode_list = get_gfx_mode_list(gfx_driver->id);
143 if (mode_list ==
nullptr) {
144 _resolutions.assign(std::begin(default_resolutions), std::end(default_resolutions));
148 GFX_MODE *modes = mode_list->mode;
150 for (
int i = 0; modes[i].bpp != 0; i++) {
151 uint w = modes[i].width;
152 uint h = modes[i].height;
153 if (w < 640 || h < 480)
continue;
160 destroy_gfx_mode_list(mode_list);
163 static void GetAvailableVideoMode(uint *w, uint *h)
176 if (newdelta < delta) {
185 static bool CreateMainSurface(uint w, uint h)
188 if (bpp == 0)
usererror(
"Can't use a blitter that blits 0 bpp for normal visuals");
189 set_color_depth(bpp);
191 GetAvailableVideoMode(&w, &h);
192 if (set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, w, h, 0, 0) != 0) {
193 DEBUG(driver, 0,
"Allegro: Couldn't allocate a window to draw on '%s'", allegro_error);
199 _allegro_screen = create_bitmap_ex(bpp, screen->cr - screen->cl, screen->cb - screen->ct);
200 _screen.width = _allegro_screen->w;
201 _screen.height = _allegro_screen->h;
202 _screen.pitch = ((
byte*)screen->line[1] - (
byte*)screen->line[0]) / (bpp / 8);
203 _screen.dst_ptr = _allegro_screen->line[0];
206 memset(_screen.dst_ptr, 0, _screen.height * _screen.pitch);
210 _cursor.
pos.x = mouse_x;
211 _cursor.
pos.y = mouse_y;
218 seprintf(caption,
lastof(caption),
"OpenTTD %s", _openttd_revision);
219 set_window_title(caption);
221 enable_hardware_cursor();
222 select_mouse_cursor(MOUSE_CURSOR_ARROW);
223 show_mouse(_allegro_screen);
230 bool VideoDriver_Allegro::ClaimMousePointer()
232 select_mouse_cursor(MOUSE_CURSOR_NONE);
234 disable_hardware_cursor();
244 #define AS(x, z) {x, 0, z}
245 #define AM(x, y, z, w) {x, y - x, z}
249 AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN),
251 AS(KEY_DOWN, WKC_DOWN),
252 AS(KEY_LEFT, WKC_LEFT),
253 AS(KEY_RIGHT, WKC_RIGHT),
255 AS(KEY_HOME, WKC_HOME),
256 AS(KEY_END, WKC_END),
258 AS(KEY_INSERT, WKC_INSERT),
259 AS(KEY_DEL, WKC_DELETE),
262 AM(KEY_A, KEY_Z,
'A',
'Z'),
263 AM(KEY_0, KEY_9,
'0',
'9'),
265 AS(KEY_ESC, WKC_ESC),
266 AS(KEY_PAUSE, WKC_PAUSE),
267 AS(KEY_BACKSPACE, WKC_BACKSPACE),
269 AS(KEY_SPACE, WKC_SPACE),
270 AS(KEY_ENTER, WKC_RETURN),
271 AS(KEY_TAB, WKC_TAB),
274 AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12),
277 AM(KEY_0_PAD, KEY_9_PAD,
'0',
'9'),
278 AS(KEY_SLASH_PAD, WKC_NUM_DIV),
279 AS(KEY_ASTERISK, WKC_NUM_MUL),
280 AS(KEY_MINUS_PAD, WKC_NUM_MINUS),
281 AS(KEY_PLUS_PAD, WKC_NUM_PLUS),
282 AS(KEY_ENTER_PAD, WKC_NUM_ENTER),
283 AS(KEY_DEL_PAD, WKC_DELETE),
297 AS(KEY_TILDE, WKC_BACKQUOTE),
300 static uint32 ConvertAllegroKeyIntoMy(
WChar *character)
303 int unicode = ureadkey(&scancode);
308 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
309 if ((uint)(scancode - map->vk_from) <= map->vk_count) {
310 key = scancode - map->vk_from + map->map_to;
315 if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT;
316 if (key_shifts & KB_CTRL_FLAG) key |= WKC_CTRL;
317 if (key_shifts & KB_ALT_FLAG) key |= WKC_ALT;
319 DEBUG(driver, 0,
"Scancode character pressed %u", scancode);
320 DEBUG(driver, 0,
"Unicode character pressed %u", unicode);
323 *character = unicode;
327 static const uint LEFT_BUTTON = 0;
328 static const uint RIGHT_BUTTON = 1;
330 static void PollEvent()
334 bool mouse_action =
false;
337 static int prev_button_state;
338 if (prev_button_state != mouse_b) {
339 uint diff = prev_button_state ^ mouse_b;
343 if (
HasBit(mouse_b, button)) {
346 button = RIGHT_BUTTON;
347 ClrBit(diff, RIGHT_BUTTON);
369 }
else if (button == LEFT_BUTTON) {
372 }
else if (button == RIGHT_BUTTON) {
377 prev_button_state = mouse_b;
383 position_mouse(_cursor.
pos.x, _cursor.
pos.y);
385 if (_cursor.
delta.x != 0 || _cursor.
delta.y) mouse_action =
true;
387 static int prev_mouse_z = 0;
388 if (prev_mouse_z != mouse_z) {
389 _cursor.
wheel = (prev_mouse_z - mouse_z) < 0 ? -1 : 1;
390 prev_mouse_z = mouse_z;
397 if ((key_shifts & KB_ALT_FLAG) && (key[KEY_ENTER] || key[KEY_F])) {
398 ToggleFullScreen(!_fullscreen);
399 }
else if (keypressed()) {
401 uint keycode = ConvertAllegroKeyIntoMy(&character);
410 int _allegro_instance_count = 0;
414 if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno,
nullptr)) {
415 DEBUG(driver, 0,
"allegro: install_allegro failed '%s'", allegro_error);
416 return "Failed to set up Allegro";
418 _allegro_instance_count++;
429 signal(SIGABRT,
nullptr);
430 signal(SIGSEGV,
nullptr);
435 return "Failed to set up Allegro video";
438 set_close_button_callback(HandleExitGameRequest);
445 if (--_allegro_instance_count == 0) allegro_exit();
448 #if defined(UNIX) || defined(__OS2__)
449 # include <sys/time.h>
451 static uint32 GetTime()
455 gettimeofday(&tim,
nullptr);
456 return tim.tv_usec / 1000 + tim.tv_sec * 1000;
459 static uint32 GetTime()
461 return GetTickCount();
468 uint32 cur_ticks = GetTime();
469 uint32 last_cur_ticks = cur_ticks;
475 uint32 prev_cur_ticks = cur_ticks;
479 if (_exit_game)
return;
486 if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
489 if (!
_networking && _game_mode != GM_MENU) _fast_forward |= 2;
490 }
else if (_fast_forward & 2) {
494 cur_ticks = GetTime();
495 if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
497 last_cur_ticks = cur_ticks;
507 (key[KEY_LEFT] ? 1 : 0) |
508 (key[KEY_UP] ? 2 : 0) |
509 (key[KEY_RIGHT] ? 4 : 0) |
510 (key[KEY_DOWN] ? 8 : 0);
518 DrawSurfaceToScreen();
523 DrawSurfaceToScreen();
530 return CreateMainSurface(w, h);
547 return CreateMainSurface(_screen.width, _screen.height);