1 /*  DreamChess
2 **
3 **  DreamChess is the legal property of its developers, whose names are too
4 **  numerous to list here. Please refer to the AUTHORS.txt file distributed
5 **  with this source distribution.
6 **
7 **  This program is free software: you can redistribute it and/or modify
8 **  it under the terms of the GNU General Public License as published by
9 **  the Free Software Foundation, either version 3 of the License, or
10 **  (at your option) any later version.
11 **
12 **  This program is distributed in the hope that it will be useful,
13 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 **  GNU General Public License for more details.
16 **
17 **  You should have received a copy of the GNU General Public License
18 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "ui_sdlgl.h"
22 #include "git_rev.h"
23 
24 #ifdef _WIN32
25 #include <direct.h>
26 #else
27 #include <unistd.h>
28 #endif
29 
30 #include "audio.h"
31 #include "dialogs.h"
32 #include "options.h"
33 #include "system_config.h"
34 #include "theme.h"
35 #include <GL/glew.h>
36 #include <SDL2/SDL_syswm.h>
37 
38 static int turn_counter_start = 0;
39 static texture_t menu_title_tex;
40 static int game_in_stalemate;
41 static int white_in_check;
42 static int black_in_check;
43 static int white_in_checkmate;
44 static int black_in_checkmate;
45 static board_t board;
46 static int pgn_slot;
47 static int quit_to_menu = FALSE;
48 static int title_process_retval;
49 static int set_loading = FALSE;
50 static int dialog_promote_piece;
51 static int show_egg;
52 static int egg_req1 = FALSE;
53 static int screen_width = 640;
54 static int screen_height = 480;
55 static int screen_fs = 0;
56 static int screen_ms = 0;
57 static int reflections = 1;
58 static int mode_set_failed = 0;
59 static int engine_error_shown;
60 SDL_Window *sdl_window;
61 static GLuint screen_fb, screen_temp_fb, screen_tex, screen_color_rb, screen_temp_color_rb, screen_depth_stencil_rb;
62 static int max_samples;
63 
music_callback(char * title,char * artist,char * album)64 static void music_callback(char *title, char *artist, char *album) {
65 	DBG_LOG("Now playing: %s - %s", artist, title);
66 }
67 
get_screen_width(void)68 int get_screen_width(void) {
69 	return screen_width;
70 }
71 
get_screen_height(void)72 int get_screen_height(void) {
73 	return screen_height;
74 }
75 
76 static int menu_state;
77 enum { MENU_STATE_FADE_IN, MENU_STATE_IN_MENU, MENU_STATE_LOAD, MENU_STATE_FADE_OUT, MENU_STATE_RETURN };
78 
79 static void poll_move(void);
80 
get_egg_req(void)81 int get_egg_req(void) {
82 	return egg_req1;
83 }
84 
set_show_egg(int set)85 void set_show_egg(int set) {
86 	show_egg = set;
87 }
88 
get_show_egg(void)89 int get_show_egg(void) {
90 	return show_egg;
91 }
92 
get_dialog_promote_piece(void)93 int get_dialog_promote_piece(void) {
94 	return dialog_promote_piece;
95 }
96 
set_dialog_promote_piece(int piece)97 void set_dialog_promote_piece(int piece) {
98 	dialog_promote_piece = piece;
99 }
100 
set_title_process_retval(int ret)101 void set_title_process_retval(int ret) {
102 	title_process_retval = ret;
103 }
104 
set_set_loading(int set)105 void set_set_loading(int set) {
106 	set_loading = set;
107 }
108 
set_quit_to_menu(int menu)109 void set_quit_to_menu(int menu) {
110 	quit_to_menu = menu;
111 }
112 
set_pgn_slot(int slot)113 void set_pgn_slot(int slot) {
114 	pgn_slot = slot;
115 }
116 
get_board(void)117 board_t *get_board(void) {
118 	return &board;
119 }
120 
121 config_t config;
122 
get_config(void)123 config_t *get_config(void) {
124 	return &config;
125 }
126 
127 static int switch_to_menu = FALSE;
128 static int fading_out = FALSE;
129 
set_switch_to_menu(int sw)130 void set_switch_to_menu(int sw) {
131 	switch_to_menu = sw;
132 }
133 
get_fading_out(void)134 int get_fading_out(void) {
135 	return fading_out;
136 }
137 
set_fading_out(int fade)138 void set_fading_out(int fade) {
139 	fading_out = fade;
140 }
get_game_stalemate(void)141 int get_game_stalemate(void) {
142 	return game_in_stalemate;
143 }
144 
get_white_in_check(void)145 int get_white_in_check(void) {
146 	return white_in_check;
147 }
148 
get_black_in_check(void)149 int get_black_in_check(void) {
150 	return black_in_check;
151 }
get_white_in_checkmate(void)152 int get_white_in_checkmate(void) {
153 	return white_in_checkmate;
154 }
155 
get_black_in_checkmate(void)156 int get_black_in_checkmate(void) {
157 	return black_in_checkmate;
158 }
159 
get_turn_counter(void)160 int get_turn_counter(void) {
161 	return turn_counter_start;
162 }
163 
reset_turn_counter(void)164 static void reset_turn_counter(void) {
165 	turn_counter_start = SDL_GetTicks();
166 }
167 
poll_event(gg_event_t * event)168 static int poll_event(gg_event_t *event) {
169 	gg_event_t gg_event;
170 	SDL_Event sdl_event;
171 
172 	audio_poll(1);
173 
174 	while (SDL_PollEvent(&sdl_event)) {
175 
176 		if (sdl_event.type == SDL_QUIT)
177 			/* FIXME */
178 			exit(0);
179 
180 		if ((sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.mod & KMOD_ALT &&
181 			 sdl_event.key.keysym.sym == SDLK_RETURN) ||
182 			(sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.sym == SDLK_F11)) {
183 			DBG_LOG("Toggled fullscreen");
184 			toggle_fullscreen();
185 			continue;
186 		}
187 
188 		if ((sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.mod & KMOD_CTRL &&
189 			 sdl_event.key.keysym.sym == SDLK_f)) {
190 			DBG_LOG("Toggled fps counter");
191 			toggle_show_fps();
192 			continue;
193 		}
194 
195 		gg_event = convert_event(&sdl_event);
196 
197 		*event = gg_event;
198 		return 1;
199 	}
200 
201 	return 0;
202 }
203 
init_screen_fbo_ms(int width,int height,int ms)204 static void init_screen_fbo_ms(int width, int height, int ms) {
205 	glBindFramebuffer(GL_FRAMEBUFFER, screen_fb);
206 
207 	glBindRenderbuffer(GL_RENDERBUFFER, screen_color_rb);
208 	glRenderbufferStorageMultisample(GL_RENDERBUFFER, ms, GL_RGBA8, width, height);
209 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, screen_color_rb);
210 
211 	glBindRenderbuffer(GL_RENDERBUFFER, screen_depth_stencil_rb);
212 	glRenderbufferStorageMultisample(GL_RENDERBUFFER, ms, GL_DEPTH24_STENCIL8, width, height);
213 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, screen_depth_stencil_rb);
214 
215 	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
216 		DBG_ERROR("Failed to set up screen FBO with %dx multisampling", ms);
217 		exit(1);
218 	}
219 }
220 
init_screen_temp_fbo(int width,int height)221 static void init_screen_temp_fbo(int width, int height) {
222 	glBindFramebuffer(GL_FRAMEBUFFER, screen_temp_fb);
223 
224 	glBindRenderbuffer(GL_RENDERBUFFER, screen_temp_color_rb);
225 	glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
226 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, screen_temp_color_rb);
227 
228 	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
229 		DBG_ERROR("Failed to set up temp FBO");
230 		exit(1);
231 	}
232 }
233 
init_screen_fbo(int width,int height,int ms)234 static void init_screen_fbo(int width, int height, int ms) {
235 	glGenFramebuffers(1, &screen_fb); // Our default-bound framebuffer
236 	glGenRenderbuffers(1, &screen_color_rb);
237 	glGenRenderbuffers(1, &screen_depth_stencil_rb);
238 	init_screen_fbo_ms(width, height, ms);
239 
240 	glGenFramebuffers(1, &screen_temp_fb);
241 	glGenRenderbuffers(1, &screen_temp_color_rb);
242 	init_screen_temp_fbo(width, height);
243 
244 	glBindFramebuffer(GL_FRAMEBUFFER, screen_fb);
245 }
246 
blit_fbo()247 void blit_fbo() {
248 	int width, height;
249 	SDL_GetWindowSize(sdl_window, &width, &height);
250 
251 	const int fbo_width = get_screen_width();
252 	const int fbo_height = get_screen_height();
253 
254 	// Letterboxing for fullscreen
255 	int start_x = 0, start_y = 0;
256 	int new_width = width;
257 	int new_height = height;
258 
259 	if (screen_fs) {
260 		if (width * fbo_height > fbo_width * height) {
261 			new_width = fbo_width * height / fbo_height;
262 			start_x = (width - new_width) >> 1;
263 		} else {
264 			new_height = fbo_height * width / fbo_width;
265 			start_y = (height - new_height) >> 1;
266 		}
267 	}
268 
269 	// Multisampled buffer requires a same-dimension blit to resolve
270 	if (screen_ms && (new_width != fbo_width || new_height != fbo_height)) {
271 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen_temp_fb);
272 		glBlitFramebuffer(0, 0, fbo_width, fbo_height, 0, 0, fbo_width, fbo_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
273 		glBindFramebuffer(GL_READ_FRAMEBUFFER, screen_temp_fb);
274 	}
275 
276 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
277 	glClear(GL_COLOR_BUFFER_BIT);
278 	glBlitFramebuffer(0, 0, fbo_width, fbo_height, start_x, start_y, new_width + start_x, new_height + start_y,
279 					  GL_COLOR_BUFFER_BIT, GL_LINEAR);
280 
281 	SDL_GL_SwapWindow(sdl_window);
282 
283 	glBindFramebuffer(GL_FRAMEBUFFER, screen_fb);
284 }
285 
286 /** Implements ui_driver::menu */
do_menu(int * pgn)287 static config_t *do_menu(int *pgn) {
288 	title_process_retval = 2;
289 
290 	resize_window(screen_width, screen_height);
291 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
292 	glEnable(GL_BLEND);
293 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
294 	engine_error_shown = 0;
295 	set_loading = FALSE;
296 	draw_credits(1);
297 	open_title_root_dialog();
298 	if (mode_set_failed) {
299 		gg_dialog_open(
300 			dialog_error_create(gg_dialog_get_active(), "Error: failed to set video mode; using defaults", NULL));
301 		mode_set_failed = 0;
302 	}
303 
304 	set_fade_start(gg_system_get_ticks());
305 	set_show_egg(FALSE);
306 
307 	DBG_LOG("Entering title menu");
308 
309 	while (1) {
310 		const Uint8 *keystate;
311 		gg_event_t event;
312 
313 		keystate = SDL_GetKeyboardState(NULL);
314 
315 		egg_req1 = FALSE;
316 
317 		gg_dialog_cleanup();
318 
319 		/* Draw the menu.. */
320 		glDisable(GL_BLEND);
321 		glDisable(GL_DEPTH_TEST);
322 		draw_texture_fullscreen(&menu_title_tex, 1.0f);
323 		glEnable(GL_BLEND);
324 		glEnable(GL_DEPTH_TEST);
325 		text_draw_string_right(get_gl_width() - 20, 20, g_version, 0.75f, get_col(COL_WHITE));
326 
327 		/*if (get_show_egg())
328 			text_draw_string(560, 440, "Egg!", 1, get_col(COL_WHITE));*/
329 
330 		switch (menu_state) {
331 		case MENU_STATE_FADE_IN:
332 			while (poll_event(&event))
333 				;
334 			gg_dialog_render_all();
335 
336 			if (!draw_fade(FADE_IN)) {
337 				menu_state = MENU_STATE_IN_MENU;
338 				draw_credits(1);
339 			}
340 			break;
341 
342 		case MENU_STATE_IN_MENU:
343 
344 			if (keystate[SDL_SCANCODE_UP])
345 				egg_req1 = TRUE;
346 
347 			while (poll_event(&event))
348 				gg_dialog_input_current(event);
349 
350 			if (title_process_retval == 1)
351 				return NULL;
352 
353 			if (set_loading) {
354 				gg_widget_t *widget = gg_label_create("Loading, please wait...");
355 				widget = gg_dialog_create(widget, NULL, NULL, 0);
356 				gg_dialog_set_style(GG_DIALOG(widget), get_menu_style());
357 				gg_dialog_open(GG_DIALOG(widget));
358 				menu_state = MENU_STATE_LOAD;
359 			} else
360 				draw_credits(0);
361 
362 			gg_dialog_render_all();
363 			break;
364 
365 		case MENU_STATE_LOAD: {
366 			option_t *option = config_get_option("theme");
367 			struct theme_struct *theme = option->selected->data;
368 
369 			load_theme(theme);
370 			reset_transition(TRUE);
371 		}
372 
373 			*pgn = pgn_slot;
374 			if (pgn_slot >= 0)
375 				config = *get_config_save(pgn_slot);
376 
377 			reset_3d(config.player[WHITE] == PLAYER_ENGINE);
378 
379 			set_fade_start(gg_system_get_ticks());
380 			gg_dialog_close();
381 
382 			menu_state = MENU_STATE_FADE_OUT;
383 			break;
384 
385 		case MENU_STATE_FADE_OUT:
386 			while (poll_event(&event))
387 				;
388 			if ((get_show_egg() && !draw_sonic_fade(FADE_OUT)) || (!get_show_egg() && !draw_fade(FADE_OUT))) {
389 				set_fade_start(gg_system_get_ticks());
390 				menu_state = MENU_STATE_RETURN;
391 				return &config;
392 			}
393 			break;
394 
395 		case MENU_STATE_RETURN:
396 			while (poll_event(&event))
397 				;
398 			gg_dialog_render_all();
399 
400 			if (!draw_fade(FADE_IN))
401 				menu_state = MENU_STATE_IN_MENU;
402 			break;
403 		}
404 
405 		/* Draw mouse cursor.. */
406 		draw_texture(get_menu_mouse_cursor(), get_mouse_x(), (479 - get_mouse_y() - 32), 32, 32, 1.0f,
407 					 get_col(COL_WHITE));
408 
409 		gl_swap();
410 	}
411 }
412 
free_menu_tex(void)413 static void free_menu_tex(void) {
414 	glDeleteTextures(1, &menu_title_tex.id);
415 	glDeleteTextures(1, &get_menu_mouse_cursor()->id);
416 	glDeleteTextures(1, &get_menu_border()->id);
417 	glDeleteTextures(1, &get_text_character(0)->id);
418 }
419 
load_menu_tex(void)420 static void load_menu_tex(void) {
421 	ch_datadir();
422 	/* For the menu.. */
423 	load_texture_png(&menu_title_tex, "menu_title.png", 0, 1);
424 	/* New text stuff. */
425 	generate_text_chars();
426 
427 	chdir("styles");
428 	chdir("default");
429 	load_border(get_menu_border(), "border.png");
430 	load_texture_png(get_menu_mouse_cursor(), "mouse_cursor.png", 1, 1);
431 }
432 
set_fullscreen(int fullscreen)433 static int set_fullscreen(int fullscreen) {
434 	if (SDL_SetWindowFullscreen(sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) > 0) {
435 		DBG_ERROR("Failed to set fullscreen to %s: %s", fullscreen ? "on" : "off", SDL_GetError());
436 		return 1;
437 	}
438 
439 	return 0;
440 }
441 
resize(int width,int height,int fullscreen,int ms)442 static int resize(int width, int height, int fullscreen, int ms) {
443 	DBG_LOG("Resizing video mode to %ix%i; fullscreen %s; %ix multisampling", width, height, fullscreen ? "on" : "off",
444 			ms);
445 
446 	if (ms > max_samples)
447 		return 1;
448 
449 	if (fullscreen != screen_fs && set_fullscreen(fullscreen))
450 		return 1;
451 
452 	if (screen_width != width || screen_height != height || screen_fs != fullscreen) {
453 		SDL_SetWindowSize(sdl_window, width, height);
454 		init_screen_temp_fbo(width, height);
455 	}
456 
457 	if (screen_ms != ms || screen_width != width || screen_height != height)
458 		init_screen_fbo_ms(width, height, ms);
459 
460 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
461 	glClear(GL_COLOR_BUFFER_BIT);
462 	glBindFramebuffer(GL_FRAMEBUFFER, screen_temp_fb);
463 	glClear(GL_COLOR_BUFFER_BIT);
464 	glBindFramebuffer(GL_FRAMEBUFFER, screen_fb);
465 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
466 
467 	screen_width = width;
468 	screen_height = height;
469 	screen_fs = fullscreen;
470 	screen_ms = ms;
471 	resize_window(screen_width, screen_height);
472 
473 	return 0;
474 }
475 
476 /** Implements ui_driver::create_window. */
create_window(int width,int height,int fullscreen,int ms)477 static int create_window(int width, int height, int fullscreen, int ms) {
478 	int i, err;
479 
480 	screen_width = width;
481 	screen_height = height;
482 	screen_fs = fullscreen;
483 	screen_ms = ms;
484 
485 	int video_flags = SDL_WINDOW_OPENGL;
486 
487 	DBG_LOG("Setting video mode to %ix%i; fullscreen %s; %ix multisampling", width, height, fullscreen ? "on" : "off",
488 			ms);
489 
490 	if (fullscreen)
491 		video_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
492 
493 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
494 	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
495 
496 	sdl_window =
497 		SDL_CreateWindow("DreamChess", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, video_flags);
498 
499 	if (!sdl_window) {
500 		DBG_ERROR("Failed to set video mode: %ix%i; fullscreen %s; %ix multisampling: %s", width, height,
501 				  fullscreen ? "on" : "off", ms, SDL_GetError());
502 		mode_set_failed = 1;
503 		return 1;
504 	}
505 
506 	if (!SDL_GL_CreateContext(sdl_window)) {
507 		DBG_ERROR("Failed to create GL context: %s", SDL_GetError());
508 		SDL_DestroyWindow(sdl_window);
509 		mode_set_failed = 1;
510 		return 1;
511 	}
512 
513 	err = glewInit();
514 	if (err != GLEW_OK) {
515 		DBG_ERROR("Failed to initialize GLEW: %s", glewGetErrorString(err));
516 		exit(1);
517 	}
518 
519 	if (!glewIsSupported("GL_ARB_framebuffer_object")) {
520 		DBG_ERROR("OpenGL extension GL_ARB_framebuffer_object not supported");
521 		exit(1);
522 	}
523 
524 	if (!glewIsSupported("GL_ARB_texture_non_power_of_two")) {
525 		DBG_ERROR("OpenGL extension GL_ARB_texture_non_power_of_two not supported");
526 		exit(1);
527 	}
528 
529 	glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
530 	init_fbo();
531 
532 	if (ms > max_samples) {
533 		SDL_DestroyWindow(sdl_window);
534 		mode_set_failed = 1;
535 		return 1;
536 	}
537 
538 	init_screen_fbo(width, height, ms);
539 
540 	init_gl();
541 	load_menu_tex();
542 
543 	SDL_ShowCursor(SDL_DISABLE);
544 
545 	// SDL_WM_SetCaption( "DreamChess", NULL );
546 
547 	gg_system_init(get_gg_driver_sdlgl());
548 	get_ingame_style()->fade_col = gg_colour(0.0f, 0.0f, 0.0f, 0.5f);
549 	get_ingame_style()->hor_pad = 20;
550 	get_ingame_style()->vert_pad = 10;
551 
552 	for (i = 0; i < 9; i++)
553 		get_ingame_style()->border.image[i] = &get_border()[i];
554 
555 	get_menu_style()->textured = 1;
556 	get_menu_style()->fade_col = gg_colour(0.0f, 0.0f, 0.0f, 0.0f);
557 	get_menu_style()->hor_pad = 20;
558 	get_menu_style()->vert_pad = 10;
559 
560 	for (i = 0; i < 9; i++)
561 		get_menu_style()->border.image[i] = &get_menu_border()[i];
562 
563 	ch_datadir();
564 	audio_init();
565 
566 	/* Make virtual keyboard table? */
567 	populate_key_table();
568 
569 	update_fps_time();
570 
571 	/* Register music callback */
572 	audio_set_music_callback(music_callback);
573 
574 	return 0;
575 }
576 
577 /** Implements ui_driver::update. */
update(board_t * b,move_t * move)578 static void update(board_t *b, move_t *move) {
579 	board = *b;
580 
581 	if (move != NULL)
582 		start_piece_move(move->source, move->destination);
583 	if (board.state == BOARD_STALEMATE) {
584 		game_in_stalemate = TRUE;
585 	} else
586 		game_in_stalemate = FALSE;
587 
588 	black_in_check = FALSE;
589 	white_in_check = FALSE;
590 	if (board.state == BOARD_CHECK) {
591 		if (IS_WHITE(board.turn))
592 			white_in_check = TRUE;
593 		else
594 			black_in_check = TRUE;
595 	}
596 	black_in_checkmate = FALSE;
597 	white_in_checkmate = FALSE;
598 	if (board.state == BOARD_CHECKMATE) {
599 		if (IS_WHITE(board.turn))
600 			white_in_checkmate = TRUE;
601 		else
602 			black_in_checkmate = TRUE;
603 	}
604 
605 	/* FIXME */
606 	while (get_piece_moving_done() == 0)
607 		poll_move();
608 }
609 
610 /** Implements ui_driver::show_result. */
show_result(result_t * res)611 static void show_result(result_t *res) {
612 	gg_dialog_open(dialog_victory_create(res));
613 }
614 
615 /** Implements ui_driver::init. */
sdlgl_init(void)616 static void sdlgl_init(void) {
617 	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) {
618 		DBG_ERROR("SDL initialization failed: %s", SDL_GetError());
619 		exit(1);
620 	}
621 
622 	ch_datadir();
623 }
624 
625 /** Implements ui_driver::exit. */
sdlgl_exit(void)626 static int sdlgl_exit(void) {
627 	audio_set_music_callback(NULL);
628 
629 	gg_system_exit();
630 	free_menu_tex();
631 	deinit_fbo();
632 
633 	SDL_Quit();
634 	return 0;
635 }
636 
637 /** Implements ui_driver::show_message. */
show_message(char * msg)638 static void show_message(char *msg) {
639 	gg_dialog_open(dialog_message_create(msg));
640 }
641 
642 /** Implements ui_driver::poll. */
poll_move(void)643 static void poll_move(void) {
644 	static int source = -1, dest = -1, needprom = 0;
645 	/* board_t *board = history->play->board; */
646 	move_t move;
647 	int input;
648 
649 	audio_poll(0);
650 	draw_scene(&board, screen_fb, reflections);
651 	gl_swap();
652 
653 	if (switch_to_menu == TRUE) {
654 		quit_to_menu = 0;
655 		switch_to_menu = FALSE;
656 		fading_out = FALSE;
657 		needprom = 0;
658 		source = -1;
659 		dest = -1;
660 		unload_theme();
661 		game_quit();
662 		return;
663 	} else if (quit_to_menu) {
664 		DBG_LOG("Returning to title menu");
665 		set_fading_out(TRUE);
666 		reset_transition(FALSE);
667 		set_fade_start(gg_system_get_ticks());
668 		quit_to_menu = FALSE;
669 	}
670 	input = get_move();
671 	/* FIXME */
672 	if (!engine_error_shown && game_get_engine_error()) {
673 		gg_dialog_open(dialog_engine_error_create());
674 		engine_error_shown = 1;
675 		return;
676 	}
677 
678 	if (!game_want_move()) {
679 		source = -1;
680 		dest = -1;
681 		needprom = 0;
682 	}
683 
684 	if (source == -1) {
685 		source = input;
686 		/* Only allow piece of current player to be moved. */
687 		if ((source >= 0) && ((PIECE(board.square[source]) == NONE) || (COLOUR(board.square[source]) != board.turn)))
688 			source = -1;
689 		return;
690 	}
691 
692 	if (dest == -1) {
693 		dest = input;
694 		if (dest >= 0) {
695 			/* Destination square must not contain piece of current player. */
696 			if ((PIECE(board.square[dest]) != NONE) && (COLOUR(board.square[dest]) == board.turn)) {
697 				dest = -1;
698 				/* We use currently selected square as source. */
699 				source = input;
700 			} else
701 				select_piece(-1);
702 		}
703 		return;
704 	}
705 
706 	if (needprom == 1) {
707 		if (dialog_promote_piece != NONE)
708 			needprom = 2;
709 		return;
710 	}
711 
712 	if ((needprom == 0) && (((board.square[source] == WHITE_PAWN) && (dest >= 56)) ||
713 							((board.square[source] == BLACK_PAWN) && (dest <= 7)))) {
714 		gg_dialog_open(dialog_promote_create(COLOUR(board.square[source])));
715 		needprom = 1;
716 		return;
717 	}
718 
719 	move.source = source;
720 	move.destination = dest;
721 	if (needprom == 2)
722 		move.promotion_piece = dialog_promote_piece;
723 	else
724 		move.promotion_piece = NONE;
725 	needprom = 0;
726 
727 	/* start_piece_move( source, dest ); */
728 
729 	source = -1;
730 	dest = -1;
731 	game_make_move(&move, 1);
732 	reset_turn_counter();
733 }
734 
735 /** SDL + OpenGL driver. */
736 ui_driver_t ui_sdlgl = {"sdlgl", sdlgl_init, create_window, resize,		  sdlgl_exit,
737 						do_menu, update,	 poll_move,		show_message, show_result};
738