19 #include "../stdafx.h"
20 #include "../openttd.h"
21 #include "../gfx_func.h"
23 #include "../blitter/factory.hpp"
24 #include "../network/network.h"
25 #include "../core/random_func.hpp"
26 #include "../core/math_func.hpp"
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()
59 int n = _num_dirty_rects;
63 if (n > MAX_DIRTY_RECTS) {
64 blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
68 for (
int i = 0; i < n; i++) {
69 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);
74 static void UpdatePalette(uint start, uint count)
78 uint end = start + count;
79 for (uint i = start; i != end; i++) {
86 set_palette_range(pal, start, end - 1, 1);
89 static void InitPalette()
91 UpdatePalette(0, 256);
94 static void CheckPaletteAnim()
118 static const Dimension default_resolutions[] = {
132 static void GetVideoModes()
136 set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
138 GFX_MODE_LIST *mode_list = get_gfx_mode_list(gfx_driver->id);
139 if (mode_list == NULL) {
140 memcpy(
_resolutions, default_resolutions,
sizeof(default_resolutions));
145 GFX_MODE *modes = mode_list->mode;
148 for (
int i = 0; modes[i].bpp != 0; i++) {
149 uint w = modes[i].width;
150 uint h = modes[i].height;
151 if (w >= 640 && h >= 480) {
153 for (j = 0; j < n; j++) {
167 destroy_gfx_mode_list(mode_list);
170 static void GetAvailableVideoMode(uint *w, uint *h)
185 if (newdelta < delta) {
194 static bool CreateMainSurface(uint w, uint h)
197 if (bpp == 0)
usererror(
"Can't use a blitter that blits 0 bpp for normal visuals");
198 set_color_depth(bpp);
200 GetAvailableVideoMode(&w, &h);
201 if (set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, w, h, 0, 0) != 0) {
202 DEBUG(driver, 0,
"Allegro: Couldn't allocate a window to draw on '%s'", allegro_error);
208 _allegro_screen = create_bitmap_ex(bpp, screen->cr - screen->cl, screen->cb - screen->ct);
209 _screen.width = _allegro_screen->w;
210 _screen.height = _allegro_screen->h;
211 _screen.pitch = ((byte*)screen->line[1] - (byte*)screen->line[0]) / (bpp / 8);
212 _screen.dst_ptr = _allegro_screen->line[0];
215 memset(_screen.dst_ptr, 0, _screen.height * _screen.pitch);
219 _cursor.pos.x = mouse_x;
220 _cursor.pos.y = mouse_y;
227 seprintf(caption,
lastof(caption),
"OpenTTD %s", _openttd_revision);
228 set_window_title(caption);
230 enable_hardware_cursor();
231 select_mouse_cursor(MOUSE_CURSOR_ARROW);
232 show_mouse(_allegro_screen);
239 bool VideoDriver_Allegro::ClaimMousePointer()
241 select_mouse_cursor(MOUSE_CURSOR_NONE);
243 disable_hardware_cursor();
253 #define AS(x, z) {x, 0, z}
254 #define AM(x, y, z, w) {x, y - x, z}
258 AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN),
260 AS(KEY_DOWN, WKC_DOWN),
261 AS(KEY_LEFT, WKC_LEFT),
262 AS(KEY_RIGHT, WKC_RIGHT),
264 AS(KEY_HOME, WKC_HOME),
265 AS(KEY_END, WKC_END),
267 AS(KEY_INSERT, WKC_INSERT),
268 AS(KEY_DEL, WKC_DELETE),
271 AM(KEY_A, KEY_Z,
'A',
'Z'),
272 AM(KEY_0, KEY_9,
'0',
'9'),
274 AS(KEY_ESC, WKC_ESC),
275 AS(KEY_PAUSE, WKC_PAUSE),
276 AS(KEY_BACKSPACE, WKC_BACKSPACE),
278 AS(KEY_SPACE, WKC_SPACE),
279 AS(KEY_ENTER, WKC_RETURN),
280 AS(KEY_TAB, WKC_TAB),
283 AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12),
286 AM(KEY_0_PAD, KEY_9_PAD,
'0',
'9'),
287 AS(KEY_SLASH_PAD, WKC_NUM_DIV),
288 AS(KEY_ASTERISK, WKC_NUM_MUL),
289 AS(KEY_MINUS_PAD, WKC_NUM_MINUS),
290 AS(KEY_PLUS_PAD, WKC_NUM_PLUS),
291 AS(KEY_ENTER_PAD, WKC_NUM_ENTER),
292 AS(KEY_DEL_PAD, WKC_DELETE),
306 AS(KEY_TILDE, WKC_BACKQUOTE),
309 static uint32 ConvertAllegroKeyIntoMy(
WChar *character)
312 int unicode = ureadkey(&scancode);
317 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
318 if ((uint)(scancode - map->vk_from) <= map->vk_count) {
319 key = scancode - map->vk_from + map->map_to;
324 if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT;
325 if (key_shifts & KB_CTRL_FLAG) key |= WKC_CTRL;
326 if (key_shifts & KB_ALT_FLAG) key |= WKC_ALT;
328 DEBUG(driver, 0,
"Scancode character pressed %u", scancode);
329 DEBUG(driver, 0,
"Unicode character pressed %u", unicode);
332 *character = unicode;
336 static const uint LEFT_BUTTON = 0;
337 static const uint RIGHT_BUTTON = 1;
339 static void PollEvent()
343 bool mouse_action =
false;
346 static int prev_button_state;
347 if (prev_button_state != mouse_b) {
348 uint diff = prev_button_state ^ mouse_b;
352 if (
HasBit(mouse_b, button)) {
355 button = RIGHT_BUTTON;
356 ClrBit(diff, RIGHT_BUTTON);
378 }
else if (button == LEFT_BUTTON) {
381 }
else if (button == RIGHT_BUTTON) {
386 prev_button_state = mouse_b;
392 position_mouse(_cursor.pos.x, _cursor.pos.y);
394 if (_cursor.
delta.x != 0 || _cursor.
delta.y) mouse_action =
true;
396 static int prev_mouse_z = 0;
397 if (prev_mouse_z != mouse_z) {
398 _cursor.
wheel = (prev_mouse_z - mouse_z) < 0 ? -1 : 1;
399 prev_mouse_z = mouse_z;
406 if ((key_shifts & KB_ALT_FLAG) && (key[KEY_ENTER] || key[KEY_F])) {
407 ToggleFullScreen(!_fullscreen);
408 }
else if (keypressed()) {
410 uint keycode = ConvertAllegroKeyIntoMy(&character);
419 int _allegro_instance_count = 0;
423 if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno, NULL)) {
424 DEBUG(driver, 0,
"allegro: install_allegro failed '%s'", allegro_error);
425 return "Failed to set up Allegro";
427 _allegro_instance_count++;
436 signal(SIGABRT, NULL);
437 signal(SIGSEGV, NULL);
448 return "Failed to set up Allegro video";
451 set_close_button_callback(HandleExitGameRequest);
458 if (--_allegro_instance_count == 0) allegro_exit();
461 #if defined(UNIX) || defined(__OS2__) || defined(PSP) || defined(DOS)
462 # include <sys/time.h>
464 static uint32 GetTime()
468 gettimeofday(&tim, NULL);
469 return tim.tv_usec / 1000 + tim.tv_sec * 1000;
472 static uint32 GetTime()
474 return GetTickCount();
481 uint32 cur_ticks = GetTime();
482 uint32 last_cur_ticks = cur_ticks;
488 uint32 prev_cur_ticks = cur_ticks;
492 if (_exit_game)
return;
499 if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
502 if (!
_networking && _game_mode != GM_MENU) _fast_forward |= 2;
503 }
else if (_fast_forward & 2) {
507 cur_ticks = GetTime();
508 if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
510 last_cur_ticks = cur_ticks;
520 (key[KEY_LEFT] ? 1 : 0) |
521 (key[KEY_UP] ? 2 : 0) |
522 (key[KEY_RIGHT] ? 4 : 0) |
523 (key[KEY_DOWN] ? 8 : 0);
531 DrawSurfaceToScreen();
536 DrawSurfaceToScreen();
543 return CreateMainSurface(w, h);
551 _fullscreen = fullscreen;
564 return CreateMainSurface(_screen.width, _screen.height);