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" 27 #include "../framerate_type.h" 28 #include "../thread.h" 33 #include "../safeguards.h" 43 static BITMAP *_allegro_screen;
45 #define MAX_DIRTY_RECTS 100 47 static int _num_dirty_rects;
51 if (_num_dirty_rects < MAX_DIRTY_RECTS) {
52 _dirty_rects[_num_dirty_rects].x = left;
53 _dirty_rects[_num_dirty_rects].y = top;
54 _dirty_rects[_num_dirty_rects].width = width;
55 _dirty_rects[_num_dirty_rects].height = height;
60 static void DrawSurfaceToScreen()
64 int n = _num_dirty_rects;
68 if (n > MAX_DIRTY_RECTS) {
69 blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
73 for (
int i = 0; i < n; i++) {
74 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);
79 static void UpdatePalette(uint start, uint count)
83 uint end = start + count;
84 for (uint i = start; i != end; i++) {
91 set_palette_range(pal, start, end - 1, 1);
94 static void InitPalette()
96 UpdatePalette(0, 256);
99 static void CheckPaletteAnim()
123 static const Dimension default_resolutions[] = {
137 static void GetVideoModes()
141 set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
145 GFX_MODE_LIST *mode_list = get_gfx_mode_list(gfx_driver->id);
146 if (mode_list ==
nullptr) {
147 _resolutions.assign(std::begin(default_resolutions), std::end(default_resolutions));
151 GFX_MODE *modes = mode_list->mode;
153 for (
int i = 0; modes[i].bpp != 0; i++) {
154 uint w = modes[i].width;
155 uint h = modes[i].height;
156 if (w < 640 || h < 480)
continue;
163 destroy_gfx_mode_list(mode_list);
166 static void GetAvailableVideoMode(uint *w, uint *h)
179 if (newdelta < delta) {
188 static bool CreateMainSurface(uint w, uint h)
191 if (bpp == 0)
usererror(
"Can't use a blitter that blits 0 bpp for normal visuals");
192 set_color_depth(bpp);
194 GetAvailableVideoMode(&w, &h);
195 if (set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, w, h, 0, 0) != 0) {
196 DEBUG(driver, 0,
"Allegro: Couldn't allocate a window to draw on '%s'", allegro_error);
202 _allegro_screen = create_bitmap_ex(bpp, screen->cr - screen->cl, screen->cb - screen->ct);
203 _screen.width = _allegro_screen->w;
204 _screen.height = _allegro_screen->h;
205 _screen.pitch = ((byte*)screen->line[1] - (byte*)screen->line[0]) / (bpp / 8);
206 _screen.dst_ptr = _allegro_screen->line[0];
209 memset(_screen.dst_ptr, 0, _screen.height * _screen.pitch);
213 _cursor.
pos.x = mouse_x;
214 _cursor.
pos.y = mouse_y;
221 seprintf(caption,
lastof(caption),
"OpenTTD %s", _openttd_revision);
222 set_window_title(caption);
224 enable_hardware_cursor();
225 select_mouse_cursor(MOUSE_CURSOR_ARROW);
226 show_mouse(_allegro_screen);
233 bool VideoDriver_Allegro::ClaimMousePointer()
235 select_mouse_cursor(MOUSE_CURSOR_NONE);
237 disable_hardware_cursor();
247 #define AS(x, z) {x, 0, z} 248 #define AM(x, y, z, w) {x, y - x, z} 252 AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN),
254 AS(KEY_DOWN, WKC_DOWN),
255 AS(KEY_LEFT, WKC_LEFT),
256 AS(KEY_RIGHT, WKC_RIGHT),
258 AS(KEY_HOME, WKC_HOME),
259 AS(KEY_END, WKC_END),
261 AS(KEY_INSERT, WKC_INSERT),
262 AS(KEY_DEL, WKC_DELETE),
265 AM(KEY_A, KEY_Z,
'A',
'Z'),
266 AM(KEY_0, KEY_9,
'0',
'9'),
268 AS(KEY_ESC, WKC_ESC),
269 AS(KEY_PAUSE, WKC_PAUSE),
270 AS(KEY_BACKSPACE, WKC_BACKSPACE),
272 AS(KEY_SPACE, WKC_SPACE),
273 AS(KEY_ENTER, WKC_RETURN),
274 AS(KEY_TAB, WKC_TAB),
277 AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12),
280 AM(KEY_0_PAD, KEY_9_PAD,
'0',
'9'),
281 AS(KEY_SLASH_PAD, WKC_NUM_DIV),
282 AS(KEY_ASTERISK, WKC_NUM_MUL),
283 AS(KEY_MINUS_PAD, WKC_NUM_MINUS),
284 AS(KEY_PLUS_PAD, WKC_NUM_PLUS),
285 AS(KEY_ENTER_PAD, WKC_NUM_ENTER),
286 AS(KEY_DEL_PAD, WKC_DELETE),
300 AS(KEY_TILDE, WKC_BACKQUOTE),
303 static uint32 ConvertAllegroKeyIntoMy(
WChar *character)
306 int unicode = ureadkey(&scancode);
311 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
312 if ((uint)(scancode - map->vk_from) <= map->vk_count) {
313 key = scancode - map->vk_from + map->map_to;
318 if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT;
319 if (key_shifts & KB_CTRL_FLAG) key |= WKC_CTRL;
320 if (key_shifts & KB_ALT_FLAG) key |= WKC_ALT;
322 DEBUG(driver, 0,
"Scancode character pressed %u", scancode);
323 DEBUG(driver, 0,
"Unicode character pressed %u", unicode);
326 *character = unicode;
330 static const uint LEFT_BUTTON = 0;
331 static const uint RIGHT_BUTTON = 1;
333 static void PollEvent()
337 bool mouse_action =
false;
340 static int prev_button_state;
341 if (prev_button_state != mouse_b) {
342 uint diff = prev_button_state ^ mouse_b;
346 if (
HasBit(mouse_b, button)) {
349 button = RIGHT_BUTTON;
350 ClrBit(diff, RIGHT_BUTTON);
372 }
else if (button == LEFT_BUTTON) {
375 }
else if (button == RIGHT_BUTTON) {
380 prev_button_state = mouse_b;
386 position_mouse(_cursor.
pos.x, _cursor.
pos.y);
388 if (_cursor.
delta.x != 0 || _cursor.
delta.y) mouse_action =
true;
390 static int prev_mouse_z = 0;
391 if (prev_mouse_z != mouse_z) {
392 _cursor.
wheel = (prev_mouse_z - mouse_z) < 0 ? -1 : 1;
393 prev_mouse_z = mouse_z;
400 if ((key_shifts & KB_ALT_FLAG) && (key[KEY_ENTER] || key[KEY_F])) {
401 ToggleFullScreen(!_fullscreen);
402 }
else if (keypressed()) {
404 uint keycode = ConvertAllegroKeyIntoMy(&character);
413 int _allegro_instance_count = 0;
417 if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno,
nullptr)) {
418 DEBUG(driver, 0,
"allegro: install_allegro failed '%s'", allegro_error);
419 return "Failed to set up Allegro";
421 _allegro_instance_count++;
430 signal(SIGABRT,
nullptr);
431 signal(SIGSEGV,
nullptr);
436 return "Failed to set up Allegro video";
439 set_close_button_callback(HandleExitGameRequest);
446 if (--_allegro_instance_count == 0) allegro_exit();
449 #if defined(UNIX) || defined(__OS2__) 450 # include <sys/time.h> 452 static uint32 GetTime()
456 gettimeofday(&tim,
nullptr);
457 return tim.tv_usec / 1000 + tim.tv_sec * 1000;
460 static uint32 GetTime()
462 return GetTickCount();
469 uint32 cur_ticks = GetTime();
470 uint32 last_cur_ticks = cur_ticks;
476 uint32 prev_cur_ticks = cur_ticks;
480 if (_exit_game)
return;
487 if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
490 if (!
_networking && _game_mode != GM_MENU) _fast_forward |= 2;
491 }
else if (_fast_forward & 2) {
495 cur_ticks = GetTime();
496 if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
498 last_cur_ticks = cur_ticks;
508 (key[KEY_LEFT] ? 1 : 0) |
509 (key[KEY_UP] ? 2 : 0) |
510 (key[KEY_RIGHT] ? 4 : 0) |
511 (key[KEY_DOWN] ? 8 : 0);
519 DrawSurfaceToScreen();
524 DrawSurfaceToScreen();
531 return CreateMainSurface(w, h);
536 _fullscreen = fullscreen;
548 return CreateMainSurface(_screen.width, _screen.height);
bool _networking
are we in networking mode?
uint32 _realtime_tick
The real time in the game.
Point pos
logical mouse position
Factory for the allegro video driver.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
bool _right_button_down
Is right mouse button pressed?
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
Dimension _cur_resolution
The current resolution.
#define lastof(x)
Get the last element of an fixed size array.
How all blitters should look like.
void MainLoop() override
Perform the actual drawing.
virtual void PostResize()
Post resize event.
Palette animation should be done by video backend (8bpp only!)
bool _left_button_clicked
Is left mouse button clicked?
Base of the Allegro video driver.
std::vector< Dimension > _resolutions
List of resolutions.
bool _ctrl_pressed
Is Ctrl pressed?
bool ChangeResolution(int w, int h) override
Change the resolution of the window.
bool _right_button_clicked
Is right mouse button clicked?
void MakeDirty(int left, int top, int width, int height) override
Mark a particular area dirty.
The blitter takes care of the palette animation.
virtual void PaletteAnimate(const Palette &palette)=0
Called when the 8bpp palette is changed; you should redraw all pixels on the screen that are equal to...
bool _left_button_down
Is left mouse button pressed?
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
int wheel
mouse wheel movement
bool UpdateCursorPosition(int x, int y, bool queued_warp)
Update cursor position on mouse movement.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
void HandleKeypress(uint keycode, WChar key)
Handle keyboard input.
bool ToggleFullscreen(bool fullscreen) override
Change the full screen setting.
byte _dirkeys
1 = left, 2 = up, 4 = right, 8 = down
void HandleMouseEvents()
Handle a mouse event from the video driver.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
int first_dirty
The first dirty element.
PauseMode _pause_mode
The current pause mode.
Palette _cur_palette
Current palette.
bool AfterBlitterChange() override
Callback invoked after the blitter was changed.
bool _shift_pressed
Is Shift pressed?
void Stop() override
Stop this driver.
#define DEBUG(name, level,...)
Output a line of debugging information.
uint8 FindFirstBit(uint32 x)
Search the first set bit in a 32 bit variable.
virtual Blitter::PaletteAnimation UsePaletteAnimation()=0
Check if the blitter uses palette animation at all.
void HandleCtrlChanged()
State of CONTROL key has changed.
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Specification of a rectangle with an absolute top-left coordinate and a (relative) width/height...
Speed of painting drawn video buffer.
const char * Start(const char *const *param) override
Start this driver.
void NetworkDrawChatMessage()
Draw the chat message-box.
#define endof(x)
Get the end element of an fixed size array.
virtual uint8 GetScreenDepth()=0
Get the screen depth this blitter works for.
#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise, maint_cost, ttdpatch_type, class_id, name, preview)
AirportSpec definition for airports with at least one depot.
bool _rightclick_emulate
Whether right clicking is emulated.
void GameSizeChanged()
Size of the application screen changed.
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Point delta
relative mouse movement in this tick
int count_dirty
The number of dirty elements.
static T Delta(const T a, const T b)
Returns the (absolute) difference between two (scalar) variables.
uint32 WChar
Type for wide characters, i.e.
Dimensions (a width and height) of a rectangle in 2D.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
void UpdateWindows()
Update the continuously changing contents of the windows, such as the viewports.