17 #include "../stdafx.h"
18 #include "../openttd.h"
19 #include "../error_func.h"
20 #include "../gfx_func.h"
21 #include "../blitter/factory.hpp"
22 #include "../core/random_func.hpp"
23 #include "../core/math_func.hpp"
24 #include "../framerate_type.h"
25 #include "../progress.h"
26 #include "../thread.h"
27 #include "../window_func.h"
31 #include "../safeguards.h"
41 static BITMAP *_allegro_screen;
43 #define MAX_DIRTY_RECTS 100
45 static int _num_dirty_rects;
50 if (_num_dirty_rects < MAX_DIRTY_RECTS) {
51 _dirty_rects[_num_dirty_rects].x = left;
52 _dirty_rects[_num_dirty_rects].y = top;
53 _dirty_rects[_num_dirty_rects].width = width;
54 _dirty_rects[_num_dirty_rects].height = height;
63 int n = _num_dirty_rects;
67 if (n > MAX_DIRTY_RECTS) {
68 blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
72 for (
int i = 0; i < n; i++) {
73 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);
78 static void UpdatePalette(uint start, uint count)
82 uint end = start + count;
83 for (uint i = start; i != end; i++) {
90 set_palette_range(pal, start, end - 1, 1);
93 static void InitPalette()
95 UpdatePalette(0, 256);
121 static const Dimension default_resolutions[] = {
135 static void GetVideoModes()
139 set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
143 GFX_MODE_LIST *mode_list = get_gfx_mode_list(gfx_driver->id);
144 if (mode_list ==
nullptr) {
145 _resolutions.assign(std::begin(default_resolutions), std::end(default_resolutions));
149 GFX_MODE *modes = mode_list->mode;
151 for (
int i = 0; modes[i].bpp != 0; i++) {
152 uint w = modes[i].width;
153 uint h = modes[i].height;
154 if (w < 640 || h < 480)
continue;
161 destroy_gfx_mode_list(mode_list);
164 static void GetAvailableVideoMode(uint *w, uint *h)
177 if (newdelta < delta) {
186 static bool CreateMainSurface(uint w, uint h)
189 if (bpp == 0) UserError(
"Can't use a blitter that blits 0 bpp for normal visuals");
190 set_color_depth(bpp);
192 GetAvailableVideoMode(&w, &h);
193 if (set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, w, h, 0, 0) != 0) {
194 Debug(driver, 0,
"Allegro: Couldn't allocate a window to draw on '{}'", allegro_error);
200 _allegro_screen = create_bitmap_ex(bpp, screen->cr - screen->cl, screen->cb - screen->ct);
201 _screen.width = _allegro_screen->w;
202 _screen.height = _allegro_screen->h;
203 _screen.pitch = ((uint8_t*)screen->line[1] - (uint8_t*)screen->line[0]) / (bpp / 8);
204 _screen.dst_ptr = _allegro_screen->line[0];
207 memset(_screen.dst_ptr, 0,
static_cast<size_t>(_screen.height) * _screen.pitch);
211 _cursor.
pos.x = mouse_x;
212 _cursor.
pos.y = mouse_y;
219 set_window_title(caption.c_str());
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();
240 std::vector<int> rates = {};
242 int refresh_rate = get_refresh_rate();
243 if (refresh_rate != 0) rates.push_back(refresh_rate);
248 struct AllegroVkMapping {
254 #define AS(x, z) {x, 1, z}
255 #define AM(x, y, z, w) {x, y - x + 1, z}
257 static const AllegroVkMapping _vk_mapping[] = {
259 AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN),
261 AS(KEY_DOWN, WKC_DOWN),
262 AS(KEY_LEFT, WKC_LEFT),
263 AS(KEY_RIGHT, WKC_RIGHT),
265 AS(KEY_HOME, WKC_HOME),
266 AS(KEY_END, WKC_END),
268 AS(KEY_INSERT, WKC_INSERT),
269 AS(KEY_DEL, WKC_DELETE),
272 AM(KEY_A, KEY_Z,
'A',
'Z'),
273 AM(KEY_0, KEY_9,
'0',
'9'),
275 AS(KEY_ESC, WKC_ESC),
276 AS(KEY_PAUSE, WKC_PAUSE),
277 AS(KEY_BACKSPACE, WKC_BACKSPACE),
279 AS(KEY_SPACE, WKC_SPACE),
280 AS(KEY_ENTER, WKC_RETURN),
281 AS(KEY_TAB, WKC_TAB),
284 AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12),
287 AM(KEY_0_PAD, KEY_9_PAD,
'0',
'9'),
288 AS(KEY_SLASH_PAD, WKC_NUM_DIV),
289 AS(KEY_ASTERISK, WKC_NUM_MUL),
290 AS(KEY_MINUS_PAD, WKC_NUM_MINUS),
291 AS(KEY_PLUS_PAD, WKC_NUM_PLUS),
292 AS(KEY_ENTER_PAD, WKC_NUM_ENTER),
293 AS(KEY_DEL_PAD, WKC_DELETE),
307 AS(KEY_TILDE, WKC_BACKQUOTE),
310 static uint32_t ConvertAllegroKeyIntoMy(char32_t *character)
313 int unicode = ureadkey(&scancode);
317 for (
const auto &map : _vk_mapping) {
318 if (
IsInsideBS(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 {}", scancode);
329 Debug(driver, 0,
"Unicode character pressed {}", unicode);
332 *character = unicode;
336 static const uint LEFT_BUTTON = 0;
337 static const uint RIGHT_BUTTON = 1;
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);
421 int _allegro_instance_count = 0;
425 if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno,
nullptr)) {
426 Debug(driver, 0,
"allegro: install_allegro failed '{}'", allegro_error);
427 return "Failed to set up Allegro";
429 _allegro_instance_count++;
440 signal(SIGABRT,
nullptr);
441 signal(SIGSEGV,
nullptr);
446 return "Failed to set up Allegro video";
449 set_close_button_callback(HandleExitGameRequest);
458 if (--_allegro_instance_count == 0) allegro_exit();
474 (key[KEY_LEFT] ? 1 : 0) |
475 (key[KEY_UP] ? 2 : 0) |
476 (key[KEY_RIGHT] ? 4 : 0) |
477 (key[KEY_DOWN] ? 8 : 0);
487 if (_exit_game)
break;
498 return CreateMainSurface(w, h);
503 _fullscreen = fullscreen;
515 return CreateMainSurface(_screen.width, _screen.height);