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" 31 #include "../safeguards.h" 41 static BITMAP *_allegro_screen;
43 #define MAX_DIRTY_RECTS 100 45 static int _num_dirty_rects;
49 if (_num_dirty_rects < MAX_DIRTY_RECTS) {
50 _dirty_rects[_num_dirty_rects].x = left;
51 _dirty_rects[_num_dirty_rects].y = top;
52 _dirty_rects[_num_dirty_rects].width = width;
53 _dirty_rects[_num_dirty_rects].height = height;
58 static void DrawSurfaceToScreen()
62 int n = _num_dirty_rects;
66 if (n > MAX_DIRTY_RECTS) {
67 blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
71 for (
int i = 0; i < n; i++) {
72 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);
77 static void UpdatePalette(uint start, uint count)
81 uint end = start + count;
82 for (uint i = start; i != end; i++) {
89 set_palette_range(pal, start, end - 1, 1);
92 static void InitPalette()
94 UpdatePalette(0, 256);
97 static void CheckPaletteAnim()
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 '%s'", 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 = ((byte*)screen->line[1] - (byte*)screen->line[0]) / (bpp / 8);
204 _screen.dst_ptr = _allegro_screen->line[0];
207 memset(_screen.dst_ptr, 0, _screen.height * _screen.pitch);
211 _cursor.
pos.x = mouse_x;
212 _cursor.
pos.y = mouse_y;
219 seprintf(caption,
lastof(caption),
"OpenTTD %s", _openttd_revision);
220 set_window_title(caption);
222 enable_hardware_cursor();
223 select_mouse_cursor(MOUSE_CURSOR_ARROW);
224 show_mouse(_allegro_screen);
231 bool VideoDriver_Allegro::ClaimMousePointer()
233 select_mouse_cursor(MOUSE_CURSOR_NONE);
235 disable_hardware_cursor();
245 #define AS(x, z) {x, 0, z} 246 #define AM(x, y, z, w) {x, y - x, z} 250 AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN),
252 AS(KEY_DOWN, WKC_DOWN),
253 AS(KEY_LEFT, WKC_LEFT),
254 AS(KEY_RIGHT, WKC_RIGHT),
256 AS(KEY_HOME, WKC_HOME),
257 AS(KEY_END, WKC_END),
259 AS(KEY_INSERT, WKC_INSERT),
260 AS(KEY_DEL, WKC_DELETE),
263 AM(KEY_A, KEY_Z,
'A',
'Z'),
264 AM(KEY_0, KEY_9,
'0',
'9'),
266 AS(KEY_ESC, WKC_ESC),
267 AS(KEY_PAUSE, WKC_PAUSE),
268 AS(KEY_BACKSPACE, WKC_BACKSPACE),
270 AS(KEY_SPACE, WKC_SPACE),
271 AS(KEY_ENTER, WKC_RETURN),
272 AS(KEY_TAB, WKC_TAB),
275 AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12),
278 AM(KEY_0_PAD, KEY_9_PAD,
'0',
'9'),
279 AS(KEY_SLASH_PAD, WKC_NUM_DIV),
280 AS(KEY_ASTERISK, WKC_NUM_MUL),
281 AS(KEY_MINUS_PAD, WKC_NUM_MINUS),
282 AS(KEY_PLUS_PAD, WKC_NUM_PLUS),
283 AS(KEY_ENTER_PAD, WKC_NUM_ENTER),
284 AS(KEY_DEL_PAD, WKC_DELETE),
298 AS(KEY_TILDE, WKC_BACKQUOTE),
301 static uint32 ConvertAllegroKeyIntoMy(
WChar *character)
304 int unicode = ureadkey(&scancode);
309 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
310 if ((uint)(scancode - map->vk_from) <= map->vk_count) {
311 key = scancode - map->vk_from + map->map_to;
316 if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT;
317 if (key_shifts & KB_CTRL_FLAG) key |= WKC_CTRL;
318 if (key_shifts & KB_ALT_FLAG) key |= WKC_ALT;
320 DEBUG(driver, 0,
"Scancode character pressed %u", scancode);
321 DEBUG(driver, 0,
"Unicode character pressed %u", unicode);
324 *character = unicode;
328 static const uint LEFT_BUTTON = 0;
329 static const uint RIGHT_BUTTON = 1;
331 static void PollEvent()
335 bool mouse_action =
false;
338 static int prev_button_state;
339 if (prev_button_state != mouse_b) {
340 uint diff = prev_button_state ^ mouse_b;
344 if (
HasBit(mouse_b, button)) {
347 button = RIGHT_BUTTON;
348 ClrBit(diff, RIGHT_BUTTON);
370 }
else if (button == LEFT_BUTTON) {
373 }
else if (button == RIGHT_BUTTON) {
378 prev_button_state = mouse_b;
384 position_mouse(_cursor.
pos.x, _cursor.
pos.y);
386 if (_cursor.
delta.x != 0 || _cursor.
delta.y) mouse_action =
true;
388 static int prev_mouse_z = 0;
389 if (prev_mouse_z != mouse_z) {
390 _cursor.
wheel = (prev_mouse_z - mouse_z) < 0 ? -1 : 1;
391 prev_mouse_z = mouse_z;
398 if ((key_shifts & KB_ALT_FLAG) && (key[KEY_ENTER] || key[KEY_F])) {
399 ToggleFullScreen(!_fullscreen);
400 }
else if (keypressed()) {
402 uint keycode = ConvertAllegroKeyIntoMy(&character);
411 int _allegro_instance_count = 0;
415 if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno,
nullptr)) {
416 DEBUG(driver, 0,
"allegro: install_allegro failed '%s'", allegro_error);
417 return "Failed to set up Allegro";
419 _allegro_instance_count++;
428 signal(SIGABRT,
nullptr);
429 signal(SIGSEGV,
nullptr);
434 return "Failed to set up Allegro video";
437 set_close_button_callback(HandleExitGameRequest);
444 if (--_allegro_instance_count == 0) allegro_exit();
447 #if defined(UNIX) || defined(__OS2__) 448 # include <sys/time.h> 450 static uint32 GetTime()
454 gettimeofday(&tim,
nullptr);
455 return tim.tv_usec / 1000 + tim.tv_sec * 1000;
458 static uint32 GetTime()
460 return GetTickCount();
467 uint32 cur_ticks = GetTime();
468 uint32 last_cur_ticks = cur_ticks;
474 uint32 prev_cur_ticks = cur_ticks;
478 if (_exit_game)
return;
485 if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
488 if (!
_networking && _game_mode != GM_MENU) _fast_forward |= 2;
489 }
else if (_fast_forward & 2) {
493 cur_ticks = GetTime();
494 if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
496 last_cur_ticks = cur_ticks;
506 (key[KEY_LEFT] ? 1 : 0) |
507 (key[KEY_UP] ? 2 : 0) |
508 (key[KEY_RIGHT] ? 4 : 0) |
509 (key[KEY_DOWN] ? 8 : 0);
517 DrawSurfaceToScreen();
522 DrawSurfaceToScreen();
529 return CreateMainSurface(w, h);
534 _fullscreen = fullscreen;
546 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.