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);
bool _networking
are we in networking mode?
void MakeDirty(int left, int top, int width, int height)
Mark a particular area dirty.
uint32 _realtime_tick
The real time in the game.
Point pos
logical mouse position
bool ChangeResolution(int w, int h)
Change the resolution of the window.
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 MainLoop()
Perform the actual drawing.
Dimension _cur_resolution
The current resolution.
int _num_resolutions
The number of resolutions.
#define lastof(x)
Get the last element of an fixed size array.
How all blitters should look like.
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.
bool _ctrl_pressed
Is Ctrl pressed?
bool _right_button_clicked
Is right mouse button clicked?
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.
bool AfterBlitterChange()
Callback invoked after the blitter was changed.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
void HandleKeypress(uint keycode, WChar key)
Handle keyboard input.
byte _dirkeys
1 = left, 2 = up, 4 = right, 8 = down
void HandleMouseEvents()
Handle a mouse event from the video driver.
#define lengthof(x)
Return the length of an fixed size array.
PauseModeByte _pause_mode
The current pause mode.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
int first_dirty
The first dirty element.
bool ToggleFullscreen(bool fullscreen)
Change the full screen setting.
Palette _cur_palette
Current palette.
bool _shift_pressed
Is Shift pressed?
#define DEBUG(name, level,...)
Output a line of debugging information.
uint8 FindFirstBit(uint32 x)
Search the first set bit in a 32 bit variable.
Dimension _resolutions[32]
List of resolutions.
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.
void Stop()
Stop this driver.
Specification of a rectangle with an absolute top-left coordinate and a (relative) width/height...
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.
const char * Start(const char *const *param)
Start this driver.
#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.