[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Oh, and here's the attachment I forgot.
On Sat, Jul 5, 2014 at 9:59 PM, Elias Pschernig
<elias.pschernig@xxxxxxxxxx> wrote:
> I've been working on an SDL2 port for a while (unlike fixing actual
> bugs, this is something I could do with only having 30 minutes or so
> at a time). I started with it a few years ago, my main motivation back
> then was that SDL2 already worked with emscripten and so it would have
> been a way to get Allegro to work in a web browser as well. Of course
> that's not necessary anymore as we do have a patch for that. So now I
> just see this sort of as a reference port, mostly every Allegro
> function will get to call an SDL function without having to actually
> implement anything. And it might be useful for testing - if something
> works with this port but not the "native" Allegro, we know the bug
> must be in how our implementation differs from SDL's.
>
> It's still very incomplete and probably always will be, but I figure
> it wouldn't hurt committing it. It only works on Linux, there's no
> sound (it will use Allegro's audio), no input devices other than
> keyboard/mouse, and no graphics (it will use Allegro's OpenGL driver).
>
> Also, there is one fundamental difference between how Allegro and SDL2
> events works[1]:
>
> SDL_PumpEvents documentation: "This should only be run in the thread
> that initialized the video subsystem, and for extra safety, you should
> consider only doing those things on the main thread in any case. "
>
> So there was no easy way of making the Allegro way work where we can
> receive events even when the user calls no Allegro functions at all. I
> was considering adding an SDL specific function which would call
> SDL_PumpEvents - but then figured we could just as well add a
> mechanism for Allegro to call a system driver function which does
> that. I made it get called from these functions:
>
> sdl_get_keyboard_state
> sdl_get_mouse_state
> al_is_event_queue_empty
> al_get_next_event
> al_peek_next_event
> al_drop_next_event
> al_flush_event_queue
> al_wait_for_event
> al_wait_for_event_timed
> al_wait_for_event_until
>
> So at least in a typical game everything will work without changes. If
> you have a loop without any of these functions (or wait on an event
> queue which has no timer events) the application will freeze however.
>
> My next steps will probably be implementing audio with SDL and getting
> it to run under Windows and OSX (and maybe Android and IOS).
>
> [1] http://wiki.libsdl.org/SDL_PumpEvents
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a66030d..bec512b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,6 +32,7 @@ option(WANT_GLES2 "Compile with GLES2 support" ON)
if(WANT_ANDROID)
include(${CMAKE_SOURCE_DIR}/cmake/Toolchain-android.cmake)
endif(WANT_ANDROID)
+option(ALLEGRO_SDL "Build using the SDL backend (experimental)" OFF)
# Set the project name.
# We use C++ in a few cases.
@@ -314,6 +315,12 @@ if(ALLEGRO_RASPBERRYPI)
set(ALLEGRO_CFG_PTHREADS_TLS 1)
endif(ALLEGRO_RASPBERRYPI)
+if(ALLEGRO_SDL)
+ set(ALLEGRO_UNIX 0)
+ set(WANT_X11 off)
+ include(FindSDL2)
+endif(ALLEGRO_SDL)
+
# Tell the compiler it can use SSE instructions on x86 architectures.
# If compatibility with Pentium 2's and below is required then the user
# should switch WANT_ALLOW_SSE off.
@@ -808,6 +815,12 @@ foreach(genfile ${ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES_GENERATED})
)
endforeach(genfile)
+if(ALLEGRO_SDL)
+ list(APPEND LIBRARY_SOURCES ${ALLEGRO_SRC_SDL_FILES})
+ list(APPEND PLATFORM_LIBS ${SDL2_LIBRARIES} pthread dl m)
+ include_directories(${SDL2_INCLUDE_DIR})
+endif(ALLEGRO_SDL)
+
set_our_header_properties(${ALLEGRO_PUBLIC_HEADERS})
if(NOT WANT_MONOLITH)
diff --git a/cmake/FileList.cmake b/cmake/FileList.cmake
index af72772..ede9c57 100644
--- a/cmake/FileList.cmake
+++ b/cmake/FileList.cmake
@@ -181,6 +181,15 @@ set(ALLEGRO_SRC_RASPBERRYPI_FILES
src/raspberrypi/pidisplay.c
)
+set(ALLEGRO_SRC_SDL_FILES
+ src/sdl/sdl_system.c
+ src/sdl/sdl_time.c
+ src/sdl/sdl_thread.c
+ src/sdl/sdl_display.c
+ src/sdl/sdl_keyboard.c
+ src/sdl/sdl_mouse.c
+ )
+
set(ALLEGRO_INCLUDE_ALLEGRO_FILES
include/allegro5/allegro5.h
include/allegro5/allegro.h
diff --git a/include/allegro5/internal/aintern_system.h b/include/allegro5/internal/aintern_system.h
index c30a651..4ad698f 100644
--- a/include/allegro5/internal/aintern_system.h
+++ b/include/allegro5/internal/aintern_system.h
@@ -45,6 +45,8 @@ struct ALLEGRO_SYSTEM_INTERFACE
void *(*open_library)(const char *filename);
void *(*import_symbol)(void *library, const char *symbol);
void (*close_library)(void *handle);
+ void (*heartbeat)(void);
+ void (*heartbeat_init)(void);
};
struct ALLEGRO_SYSTEM
diff --git a/include/allegro5/internal/alconfig.h b/include/allegro5/internal/alconfig.h
index 0835321..3647569 100644
--- a/include/allegro5/internal/alconfig.h
+++ b/include/allegro5/internal/alconfig.h
@@ -47,6 +47,8 @@
#include "allegro5/platform/alraspberrypicfg.h"
#elif defined ALLEGRO_UNIX
#include "allegro5/platform/alucfg.h"
+#elif defined ALLEGRO_SDL
+ #include "allegro5/platform/allegro_sdl_config.h"
#else
#error platform not supported
#endif
diff --git a/include/allegro5/platform/allegro_internal_sdl.h b/include/allegro5/platform/allegro_internal_sdl.h
new file mode 100644
index 0000000..6fa189e
--- /dev/null
+++ b/include/allegro5/platform/allegro_internal_sdl.h
@@ -0,0 +1,41 @@
+#include "SDL.h"
+
+#include "allegro5/internal/aintern_display.h"
+#include "allegro5/internal/aintern_keyboard.h"
+#include "allegro5/internal/aintern_mouse.h"
+#include "allegro5/internal/aintern_bitmap.h"
+#include "allegro5/internal/aintern_system.h"
+
+typedef struct
+{
+ ALLEGRO_SYSTEM system;
+ ALLEGRO_MUTEX *mutex;
+} ALLEGRO_SYSTEM_SDL;
+
+typedef struct ALLEGRO_DISPLAY_SDL
+{
+ ALLEGRO_DISPLAY display; /* This must be the first member. */
+
+ int x, y;
+ SDL_Window *window;
+ char *title;
+ SDL_Renderer *renderer;
+ SDL_GLContext context;
+} ALLEGRO_DISPLAY_SDL;
+
+typedef struct ALLEGRO_SYSTEM_INTERFACE ALLEGRO_SYSTEM_INTERFACE;
+ALLEGRO_SYSTEM_INTERFACE *_al_sdl_system_driver(void);
+ALLEGRO_DISPLAY_INTERFACE *_al_sdl_display_driver(void);
+ALLEGRO_KEYBOARD_DRIVER *_al_sdl_keyboard_driver(void);
+ALLEGRO_MOUSE_DRIVER *_al_sdl_mouse_driver(void);
+ALLEGRO_BITMAP_INTERFACE *_al_sdl_bitmap_driver(void);
+
+void _al_sdl_keyboard_event(SDL_Event *e);
+void _al_sdl_mouse_event(SDL_Event *e);
+void _al_sdl_display_event(SDL_Event *e);
+
+int _al_sdl_get_allegro_pixel_format(int sdl_format);
+int _al_sdl_get_sdl_pixel_format(int allegro_format);
+
+ALLEGRO_DISPLAY *_al_sdl_find_display(uint32_t window_id);
+
diff --git a/include/allegro5/platform/allegro_sdl_config.h b/include/allegro5/platform/allegro_sdl_config.h
new file mode 100644
index 0000000..79e98d1
--- /dev/null
+++ b/include/allegro5/platform/allegro_sdl_config.h
@@ -0,0 +1,8 @@
+#define ALLEGRO_PLATFORM_STR "SDL"
+
+#define ALLEGRO_INTERNAL_HEADER "allegro5/platform/allegro_internal_sdl.h"
+#define ALLEGRO_INTERNAL_THREAD_HEADER "allegro5/platform/allegro_sdl_thread.h"
+
+// FIXME: remove once we don't use Unix specifics anymore
+#include <fcntl.h>
+#include <unistd.h>
diff --git a/include/allegro5/platform/allegro_sdl_thread.h b/include/allegro5/platform/allegro_sdl_thread.h
new file mode 100644
index 0000000..1a4a796
--- /dev/null
+++ b/include/allegro5/platform/allegro_sdl_thread.h
@@ -0,0 +1,101 @@
+#ifndef __al_included_allegro5_allegro_sdl_thread_h
+#define __al_included_allegro5_allegro_sdl_thread_h
+
+#include "SDL.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+struct _AL_MUTEX
+{
+ SDL_mutex *mutex;
+ SDL_TLSID lock_count;
+};
+
+struct _AL_THREAD
+{
+ /* private: */
+ SDL_Thread *thread;
+ bool should_stop;
+ void (*proc)(struct _AL_THREAD *self, void *arg);
+ void *arg;
+};
+
+#define _AL_MUTEX_UNINITED { NULL }
+#define _AL_MARK_MUTEX_UNINITED(M) do { M.mutex = NULL; } while (0)
+
+struct _AL_COND
+{
+ SDL_cond *cond;
+};
+
+typedef struct ALLEGRO_TIMEOUT_SDL ALLEGRO_TIMEOUT_SDL;
+struct ALLEGRO_TIMEOUT_SDL
+{
+ int ms;
+};
+
+AL_INLINE(bool, _al_get_thread_should_stop, (struct _AL_THREAD *t),
+{
+ return t->should_stop;
+})
+
+
+AL_FUNC(void, _al_mutex_init, (struct _AL_MUTEX*));
+AL_FUNC(void, _al_mutex_destroy, (struct _AL_MUTEX*));
+AL_INLINE(void, _al_mutex_lock, (struct _AL_MUTEX *m),
+{
+ if (m->lock_count) {
+ int *v = (int *)SDL_TLSGet(m->lock_count);
+ (*v)++;
+ if (*v > 1)
+ return;
+ }
+ if (m->mutex)
+ SDL_LockMutex(m->mutex);
+})
+AL_INLINE(void, _al_mutex_unlock, (struct _AL_MUTEX *m),
+{
+ if (m->lock_count) {
+ int *v = (int *)SDL_TLSGet(m->lock_count);
+ (*v)--;
+ if (*v > 0)
+ return;
+ }
+ if (m->mutex)
+ SDL_UnlockMutex(m->mutex);
+})
+
+AL_INLINE(void, _al_cond_init, (struct _AL_COND *cond),
+{
+ cond->cond = SDL_CreateCond();
+})
+
+AL_INLINE(void, _al_cond_destroy, (struct _AL_COND *cond),
+{
+ SDL_DestroyCond(cond->cond);
+})
+
+AL_INLINE(void, _al_cond_wait, (struct _AL_COND *cond, struct _AL_MUTEX *mutex),
+{
+ SDL_CondWait(cond->cond, mutex->mutex);
+})
+
+AL_INLINE(void, _al_cond_broadcast, (struct _AL_COND *cond),
+{
+ SDL_CondBroadcast(cond->cond);
+})
+
+AL_INLINE(void, _al_cond_signal, (struct _AL_COND *cond),
+{
+ SDL_CondSignal(cond->cond);
+})
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/include/allegro5/platform/alplatf.h.cmake b/include/allegro5/platform/alplatf.h.cmake
index 01775d1..24831a5 100644
--- a/include/allegro5/platform/alplatf.h.cmake
+++ b/include/allegro5/platform/alplatf.h.cmake
@@ -98,5 +98,8 @@
/* Define if target platform is linux. */
#cmakedefine ALLEGRO_LINUX
+/* Define if we are building with SDL backend. */
+#cmakedefine ALLEGRO_SDL
+
/*---------------------------------------------------------------------------*/
/* vi: set ft=c ts=3 sts=3 sw=3 et: */
diff --git a/src/events.c b/src/events.c
index 3bf5579..0d95a96 100644
--- a/src/events.c
+++ b/src/events.c
@@ -213,13 +213,31 @@ bool al_is_event_queue_paused(const ALLEGRO_EVENT_QUEUE *queue)
+static void heartbeat(void)
+{
+ ALLEGRO_SYSTEM *system = al_get_system_driver();
+ if (system->vt->heartbeat)
+ system->vt->heartbeat();
+}
+
+
+
+static bool is_event_queue_empty(ALLEGRO_EVENT_QUEUE *queue)
+{
+ return (queue->events_head == queue->events_tail);
+}
+
+
+
/* Function: al_is_event_queue_empty
*/
bool al_is_event_queue_empty(ALLEGRO_EVENT_QUEUE *queue)
{
ASSERT(queue);
- return (queue->events_head == queue->events_tail);
+ heartbeat();
+
+ return is_event_queue_empty(queue);
}
@@ -246,7 +264,7 @@ static ALLEGRO_EVENT *get_next_event_if_any(ALLEGRO_EVENT_QUEUE *queue,
{
ALLEGRO_EVENT *event;
- if (al_is_event_queue_empty(queue)) {
+ if (is_event_queue_empty(queue)) {
return NULL;
}
@@ -267,6 +285,8 @@ bool al_get_next_event(ALLEGRO_EVENT_QUEUE *queue, ALLEGRO_EVENT *ret_event)
ASSERT(queue);
ASSERT(ret_event);
+ heartbeat();
+
_al_mutex_lock(&queue->mutex);
next_event = get_next_event_if_any(queue, true);
@@ -290,6 +310,8 @@ bool al_peek_next_event(ALLEGRO_EVENT_QUEUE *queue, ALLEGRO_EVENT *ret_event)
ASSERT(queue);
ASSERT(ret_event);
+ heartbeat();
+
_al_mutex_lock(&queue->mutex);
next_event = get_next_event_if_any(queue, false);
@@ -312,6 +334,8 @@ bool al_drop_next_event(ALLEGRO_EVENT_QUEUE *queue)
ALLEGRO_EVENT *next_event;
ASSERT(queue);
+ heartbeat();
+
_al_mutex_lock(&queue->mutex);
next_event = get_next_event_if_any(queue, true);
@@ -333,6 +357,8 @@ void al_flush_event_queue(ALLEGRO_EVENT_QUEUE *queue)
unsigned int i;
ASSERT(queue);
+ heartbeat();
+
_al_mutex_lock(&queue->mutex);
/* Decrement reference counts on all user events. */
@@ -358,9 +384,11 @@ void al_wait_for_event(ALLEGRO_EVENT_QUEUE *queue, ALLEGRO_EVENT *ret_event)
ASSERT(queue);
+ heartbeat();
+
_al_mutex_lock(&queue->mutex);
{
- while (al_is_event_queue_empty(queue)) {
+ while (is_event_queue_empty(queue)) {
_al_cond_wait(&queue->cond, &queue->mutex);
}
@@ -385,6 +413,8 @@ bool al_wait_for_event_timed(ALLEGRO_EVENT_QUEUE *queue,
ASSERT(queue);
ASSERT(secs >= 0);
+ heartbeat();
+
if (secs < 0.0)
al_init_timeout(&timeout, 0);
else
@@ -402,6 +432,8 @@ bool al_wait_for_event_until(ALLEGRO_EVENT_QUEUE *queue,
{
ASSERT(queue);
+ heartbeat();
+
return do_wait_for_event(queue, ret_event, timeout);
}
@@ -421,7 +453,7 @@ static bool do_wait_for_event(ALLEGRO_EVENT_QUEUE *queue,
* variable, which will be signaled when an event is placed into
* the queue.
*/
- while (al_is_event_queue_empty(queue) && (result != -1)) {
+ while (is_event_queue_empty(queue) && (result != -1)) {
result = _al_cond_timedwait(&queue->cond, &queue->mutex, timeout);
}
diff --git a/src/opengl/extensions.c b/src/opengl/extensions.c
index a16a4be..2ac5f43 100644
--- a/src/opengl/extensions.c
+++ b/src/opengl/extensions.c
@@ -340,6 +340,16 @@ static void load_extensions(ALLEGRO_OGL_EXT_API *ext)
#undef AGL_API
+#elif defined ALLEGRO_SDL
+
+#define AGL_API(type, name, args) \
+ ext->name = (_ALLEGRO_gl##name##_t)SDL_GL_GetProcAddress(("gl" # name)); \
+ if (ext->name) { ALLEGRO_DEBUG("gl" #name " successfully loaded\n"); }
+
+ #include "allegro5/opengl/GLext/gl_ext_api.h"
+
+ #undef AGL_API
+
#endif
}
diff --git a/src/sdl/sdl_display.c b/src/sdl/sdl_display.c
new file mode 100644
index 0000000..17ecfd6
--- /dev/null
+++ b/src/sdl/sdl_display.c
@@ -0,0 +1,256 @@
+#include "allegro5/allegro.h"
+#include "allegro5/allegro_opengl.h"
+#include "allegro5/system.h"
+#include "allegro5/internal/aintern.h"
+#include "allegro5/internal/aintern_bitmap.h"
+#include "allegro5/internal/aintern_opengl.h"
+#include "allegro5/internal/aintern_vector.h"
+#include "allegro5/internal/aintern_system.h"
+#include "allegro5/platform/allegro_internal_sdl.h"
+
+ALLEGRO_DEBUG_CHANNEL("display")
+
+int _al_win_determine_adapter(void);
+
+static ALLEGRO_DISPLAY_INTERFACE *vt;
+
+ALLEGRO_DISPLAY *_al_sdl_find_display(uint32_t window_id) {
+ unsigned int i;
+ ALLEGRO_SYSTEM *s = al_get_system_driver();
+ for (i = 0; i < _al_vector_size(&s->displays); i++) {
+ void **v = (void **)_al_vector_ref(&s->displays, i);
+ ALLEGRO_DISPLAY_SDL *d = *v;
+ if (SDL_GetWindowID(d->window) == window_id) {
+ return &d->display;
+ break;
+ }
+ }
+ return NULL;
+}
+
+void _al_sdl_display_event(SDL_Event *e)
+{
+ ALLEGRO_EVENT event;
+ event.display.timestamp = al_get_time();
+
+ ALLEGRO_DISPLAY *d = NULL;
+
+ if (e->type == SDL_WINDOWEVENT) {
+ if (e->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
+ event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN;
+ }
+ if (e->window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
+ event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT;
+ }
+ if (e->window.event == SDL_WINDOWEVENT_CLOSE) {
+ event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE;
+ }
+ d = _al_sdl_find_display(e->window.windowID);
+ }
+ if (e->type == SDL_QUIT) {
+ event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE;
+ /* Use the first display as event source if we have any displays. */
+ ALLEGRO_SYSTEM *s = al_get_system_driver();
+ if (_al_vector_size(&s->displays) > 0) {
+ void **v = (void **)_al_vector_ref(&s->displays, 0);
+ d = *v;
+ }
+ }
+
+ if (!d)
+ return;
+ ALLEGRO_EVENT_SOURCE *es = &d->es;
+ _al_event_source_lock(es);
+ _al_event_source_emit_event(es, &event);
+ _al_event_source_unlock(es);
+}
+
+static ALLEGRO_DISPLAY *sdl_create_display_locked(int w, int h)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = al_calloc(1, sizeof *sdl);
+ ALLEGRO_DISPLAY *d = (void *)sdl;
+ d->w = w;
+ d->h = h;
+ d->flags = al_get_new_display_flags();
+ d->flags |= ALLEGRO_OPENGL;
+ int flags = SDL_WINDOW_OPENGL;
+ if (d->flags & ALLEGRO_FULLSCREEN)
+ flags |= SDL_WINDOW_FULLSCREEN;
+ if (d->flags & ALLEGRO_FULLSCREEN_WINDOW)
+ flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+ if (d->flags & ALLEGRO_FRAMELESS)
+ flags |= SDL_WINDOW_BORDERLESS;
+ sdl->window = SDL_CreateWindow(sdl->title, sdl->x, sdl->y,
+ d->w, d->h, flags);
+ if (!sdl->window) {
+ ALLEGRO_ERROR("SDL_CreateWindow failed: %s", SDL_GetError());
+ return NULL;
+ }
+ flags =
+ SDL_RENDERER_ACCELERATED |
+ SDL_RENDERER_PRESENTVSYNC |
+ SDL_RENDERER_TARGETTEXTURE;
+ sdl->renderer = SDL_CreateRenderer(sdl->window, -1, flags);
+ sdl->context = SDL_GL_CreateContext(sdl->window);
+ ALLEGRO_DISPLAY **add;
+ ALLEGRO_SYSTEM *system = al_get_system_driver();
+ add = _al_vector_alloc_back(&system->displays);
+ *add = d;
+
+ _al_event_source_init(&d->es);
+ d->vt = vt;
+
+ d->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = true;
+
+ d->ogl_extras = al_calloc(1, sizeof *d->ogl_extras);
+ _al_ogl_manage_extensions(d);
+ _al_ogl_set_extensions(d->ogl_extras->extension_api);
+
+ _al_ogl_setup_gl(d);
+
+ return d;
+}
+
+static ALLEGRO_DISPLAY *sdl_create_display(int w, int h)
+{
+ ALLEGRO_SYSTEM_SDL *s = (void *)al_get_system_driver();
+ al_lock_mutex(s->mutex);
+ ALLEGRO_DISPLAY *d = sdl_create_display_locked(w, h);
+ al_unlock_mutex(s->mutex);
+ return d;
+}
+
+static void sdl_destroy_display_locked(ALLEGRO_DISPLAY *d)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)d;
+ ALLEGRO_SYSTEM *system = al_get_system_driver();
+ _al_vector_find_and_delete(&system->displays, &d);
+ SDL_DestroyWindow(sdl->window);
+ al_free(sdl);
+}
+
+static void sdl_destroy_display(ALLEGRO_DISPLAY *d)
+{
+ ALLEGRO_SYSTEM_SDL *s = (void *)al_get_system_driver();
+ al_lock_mutex(s->mutex);
+ sdl_destroy_display_locked(d);
+ al_unlock_mutex(s->mutex);
+}
+
+static bool sdl_set_current_display(ALLEGRO_DISPLAY *d)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)d;
+ SDL_GL_MakeCurrent(sdl->window, sdl->context);
+ return true;
+}
+
+static void sdl_unset_current_display(ALLEGRO_DISPLAY *d)
+{
+}
+
+static void sdl_flip_display(ALLEGRO_DISPLAY *d)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)d;
+ SDL_RenderPresent(sdl->renderer);
+}
+
+static void sdl_update_display_region(ALLEGRO_DISPLAY *d, int x, int y,
+ int width, int height)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)d;
+ SDL_RenderPresent(sdl->renderer);
+}
+
+static bool sdl_is_compatible_bitmap(ALLEGRO_DISPLAY *display,
+ ALLEGRO_BITMAP *bitmap)
+{
+ return true;
+}
+
+static bool sdl_set_mouse_cursor(ALLEGRO_DISPLAY *display,
+ ALLEGRO_MOUSE_CURSOR *cursor)
+{
+ return false;
+}
+
+static bool sdl_set_system_mouse_cursor(ALLEGRO_DISPLAY *display,
+ ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id)
+{
+ return false;
+}
+
+static bool sdl_show_mouse_cursor(ALLEGRO_DISPLAY *display)
+{
+ return false;
+}
+
+static bool sdl_hide_mouse_cursor(ALLEGRO_DISPLAY *display)
+{
+ return false;
+}
+
+static void sdl_set_window_position(ALLEGRO_DISPLAY *display, int x, int y)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)display;
+ SDL_SetWindowPosition(sdl->window, x, y);
+}
+
+static void sdl_get_window_position(ALLEGRO_DISPLAY *display, int *x, int *y)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)display;
+ SDL_GetWindowPosition(sdl->window, x, y);
+}
+
+ALLEGRO_DISPLAY_INTERFACE *_al_sdl_display_driver(void)
+{
+ if (vt)
+ return vt;
+
+ vt = al_calloc(1, sizeof *vt);
+ vt->id = AL_ID('S', 'D', 'L', '2');
+ vt->create_display = sdl_create_display;
+ vt->destroy_display = sdl_destroy_display;
+ vt->set_current_display = sdl_set_current_display;
+ vt->unset_current_display = sdl_unset_current_display;
+ //vt->clear = GL
+ //vt->draw_pixel = GL
+ vt->flip_display = sdl_flip_display;
+ vt->update_display_region = sdl_update_display_region;
+ /*vt->acknowledge_resize = sdl_acknowledge_resize;
+ vt->resize_display = sdl_resize_display;
+ vt->quick_size = sdl_quick_size;
+ vt->get_orientation = sdl_get_orientation;*/
+ vt->create_bitmap = _al_ogl_create_bitmap;
+ vt->set_target_bitmap = _al_ogl_set_target_bitmap;
+ vt->get_backbuffer = _al_ogl_get_backbuffer;
+ vt->is_compatible_bitmap = sdl_is_compatible_bitmap;
+ /*vt->switch_out = sdl_switch_out;
+ vt->switch_in = sdl_switch_in;
+ vt->draw_memory_bitmap_region = sdl_draw_memory_bitmap_region;
+ vt->wait_for_vsync = sdl_wait_for_vsync;*/
+ vt->set_mouse_cursor = sdl_set_mouse_cursor;
+ vt->set_system_mouse_cursor = sdl_set_system_mouse_cursor;
+ vt->show_mouse_cursor = sdl_show_mouse_cursor;
+ vt->hide_mouse_cursor = sdl_hide_mouse_cursor;
+ /*vt->set_icons = sdl_set_icons;*/
+ vt->set_window_position = sdl_set_window_position;
+ vt->get_window_position = sdl_get_window_position;
+ /*vt->set_window_constraints = sdl_set_window_constraints;
+ vt->get_window_constraints = sdl_get_window_constraints;
+ vt->set_display_flag = sdl_set_display_flag;
+ vt->set_window_title = sdl_set_window_title;*/
+ //vt->flush_vertex_cache = GL
+ //vt->prepare_vertex_cache = GL
+ //vt->update_transformation = GL
+ //vt->set_projection = GL
+ /*vt->shutdown = sdl_shutdown;
+ vt->acknowledge_drawing_halt = sdl_acknowledge_drawing_halt;
+ vt->acknowledge_drawing_resume = sdl_acknowledge_drawing_resume;
+ vt->set_display_option = sdl_set_display_option;*/
+ //vt->clear_depth_buffer = GL
+ vt->update_render_state = _al_ogl_update_render_state;
+
+ _al_ogl_add_drawing_functions(vt);
+
+ return vt;
+}
diff --git a/src/sdl/sdl_keyboard.c b/src/sdl/sdl_keyboard.c
new file mode 100644
index 0000000..93a332a
--- /dev/null
+++ b/src/sdl/sdl_keyboard.c
@@ -0,0 +1,404 @@
+#include "allegro5/allegro.h"
+#include "allegro5/internal/aintern_system.h"
+#include "allegro5/platform/allegro_internal_sdl.h"
+
+ALLEGRO_DEBUG_CHANNEL("SDL")
+
+typedef struct ALLEGRO_KEYBOARD_SDL
+{
+ ALLEGRO_KEYBOARD keyboard;
+ int table[1024];
+ int inverse[1024];
+ int unicode[1024];
+ int inverse_unicode[1024];
+ bool create_extra_char[1024];
+ ALLEGRO_DISPLAY *display;
+} ALLEGRO_KEYBOARD_SDL;
+
+static ALLEGRO_KEYBOARD_DRIVER *vt;
+static ALLEGRO_KEYBOARD_SDL *keyboard;
+
+void _al_sdl_keyboard_event(SDL_Event *e)
+{
+ if (!keyboard)
+ return;
+ if (e->type == SDL_WINDOWEVENT) {
+ if (e->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
+ keyboard->display = _al_sdl_find_display(e->window.windowID);
+ }
+ else {
+ keyboard->display = NULL;
+ }
+ return;
+ }
+ ALLEGRO_EVENT event;
+ ALLEGRO_EVENT_SOURCE *es = &keyboard->keyboard.es;
+ _al_event_source_lock(es);
+ event.keyboard.timestamp = al_get_time();
+ event.keyboard.display = NULL;
+ event.keyboard.modifiers = 0;
+ event.keyboard.repeat = false;
+
+ if (e->type == SDL_TEXTINPUT) {
+ ALLEGRO_USTR_INFO info;
+ ALLEGRO_USTR const *u = al_ref_cstr(&info, e->text.text);
+ int pos = 0;
+ while (true) {
+ int32_t c = al_ustr_get_next(u, &pos);
+ if (c <= 0)
+ break;
+ event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR;
+ event.keyboard.keycode = c < 1024 ? keyboard->inverse_unicode[c] : 0;
+ event.keyboard.unichar = c;
+ event.keyboard.display = _al_sdl_find_display(e->text.windowID);
+ _al_event_source_emit_event(es, &event);
+ }
+
+ }
+ else if (e->type == SDL_KEYDOWN) {
+ event.keyboard.type = ALLEGRO_EVENT_KEY_DOWN;
+ event.keyboard.keycode = keyboard->table[e->key.keysym.scancode];
+ event.keyboard.unichar = keyboard->unicode[e->key.keysym.scancode];
+ event.keyboard.display = _al_sdl_find_display(e->key.windowID);
+ _al_event_source_emit_event(es, &event);
+
+ if (keyboard->create_extra_char[e->key.keysym.scancode]) {
+ event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR;
+ _al_event_source_emit_event(es, &event);
+ }
+ }
+ else if (e->type == SDL_KEYUP) {
+ event.keyboard.type = ALLEGRO_EVENT_KEY_UP;
+ event.keyboard.keycode = keyboard->table[e->key.keysym.scancode];
+ event.keyboard.unichar = keyboard->unicode[e->key.keysym.scancode];
+ event.keyboard.display = _al_sdl_find_display(e->key.windowID);
+ _al_event_source_emit_event(es, &event);
+ }
+
+ keyboard->display = event.keyboard.display;
+
+ _al_event_source_unlock(es);
+}
+
+static void adde(int sdl_scancode, int allegro_keycode, int unicode, bool extra)
+{
+ if (sdl_scancode >= 1024) {
+ ALLEGRO_WARN("Cannot map SDL scancode %d.\n", sdl_scancode);
+ return;
+ }
+ keyboard->table[sdl_scancode] = allegro_keycode;
+ keyboard->inverse[allegro_keycode] = sdl_scancode;
+ keyboard->unicode[sdl_scancode] = unicode;
+ keyboard->inverse_unicode[unicode] = allegro_keycode;
+ keyboard->create_extra_char[sdl_scancode] = extra;
+}
+
+static void add(int sdl_scancode, int allegro_keycode, int unicode)
+{
+ adde(sdl_scancode, allegro_keycode, unicode, false);
+}
+
+#define ADD_SAME(X, c) add(SDL_SCANCODE_##X, ALLEGRO_KEY_##X, c)
+#define ADD_SAMEC(X) add(SDL_SCANCODE_##X, ALLEGRO_KEY_##X, tolower(#X[0]))
+#define ADD_SAMEE(X, c) adde(SDL_SCANCODE_##X, ALLEGRO_KEY_##X, c, true)
+
+static bool sdl_init_keyboard(void)
+{
+ keyboard = al_calloc(1, sizeof *keyboard);
+ _al_event_source_init(&keyboard->keyboard.es);
+
+ add(SDL_SCANCODE_UNKNOWN, 0, 0);
+ ADD_SAMEC(A);
+ ADD_SAMEC(B);
+ ADD_SAMEC(C);
+ ADD_SAMEC(D);
+ ADD_SAMEC(E);
+ ADD_SAMEC(F);
+ ADD_SAMEC(G);
+ ADD_SAMEC(H);
+ ADD_SAMEC(I);
+ ADD_SAMEC(J);
+ ADD_SAMEC(K);
+ ADD_SAMEC(L);
+ ADD_SAMEC(M);
+ ADD_SAMEC(N);
+ ADD_SAMEC(O);
+ ADD_SAMEC(P);
+ ADD_SAMEC(Q);
+ ADD_SAMEC(R);
+ ADD_SAMEC(S);
+ ADD_SAMEC(T);
+ ADD_SAMEC(U);
+ ADD_SAMEC(V);
+ ADD_SAMEC(W);
+ ADD_SAMEC(X);
+ ADD_SAMEC(Y);
+ ADD_SAMEC(Z);
+ ADD_SAMEC(1);
+ ADD_SAMEC(2);
+ ADD_SAMEC(3);
+ ADD_SAMEC(4);
+ ADD_SAMEC(5);
+ ADD_SAMEC(6);
+ ADD_SAMEC(7);
+ ADD_SAMEC(8);
+ ADD_SAMEC(9);
+ ADD_SAMEC(0);
+ adde(SDL_SCANCODE_RETURN, ALLEGRO_KEY_ENTER, 13, true);
+ ADD_SAMEE(ESCAPE, 27);
+ ADD_SAMEE(BACKSPACE, 8);
+ ADD_SAMEE(TAB, 9);
+ ADD_SAME(SPACE, ' ');
+ ADD_SAME(MINUS, '-');
+ ADD_SAME(EQUALS, '=');
+ add(SDL_SCANCODE_LEFTBRACKET, ALLEGRO_KEY_OPENBRACE, '[');
+ add(SDL_SCANCODE_RIGHTBRACKET, ALLEGRO_KEY_CLOSEBRACE, ']');
+ ADD_SAME(BACKSLASH, '\\');
+ add(SDL_SCANCODE_NONUSHASH, 0, '#');
+ ADD_SAME(SEMICOLON, ';');
+ add(SDL_SCANCODE_APOSTROPHE, 0, '\'');
+ add(SDL_SCANCODE_GRAVE, 0, 0);
+ ADD_SAME(COMMA, ',');
+ add(SDL_SCANCODE_PERIOD, ALLEGRO_KEY_FULLSTOP, '.');
+ ADD_SAME(SLASH, '/');
+ ADD_SAME(CAPSLOCK, 0);
+ ADD_SAMEE(F1, 0);
+ ADD_SAMEE(F2, 0);
+ ADD_SAMEE(F3, 0);
+ ADD_SAMEE(F4, 0);
+ ADD_SAMEE(F5, 0);
+ ADD_SAMEE(F6, 0);
+ ADD_SAMEE(F7, 0);
+ ADD_SAMEE(F8, 0);
+ ADD_SAMEE(F9, 0);
+ ADD_SAMEE(F10, 0);
+ ADD_SAMEE(F11, 0);
+ ADD_SAMEE(F12, 0);
+ ADD_SAME(PRINTSCREEN, 0);
+ ADD_SAME(SCROLLLOCK, 0);
+ ADD_SAME(PAUSE, 0);
+ ADD_SAMEE(INSERT, 0);
+ ADD_SAMEE(HOME, 0);
+ add(SDL_SCANCODE_PAGEUP, ALLEGRO_KEY_PGUP, 0);
+ ADD_SAMEE(DELETE, 0);
+ ADD_SAMEE(END, 0);
+ add(SDL_SCANCODE_PAGEDOWN, ALLEGRO_KEY_PGDN, 0);
+ ADD_SAMEE(RIGHT, 0);
+ ADD_SAMEE(LEFT, 0);
+ ADD_SAMEE(DOWN, 0);
+ ADD_SAMEE(UP, 0);
+ add(SDL_SCANCODE_NUMLOCKCLEAR, ALLEGRO_KEY_NUMLOCK, 0);
+ add(SDL_SCANCODE_KP_DIVIDE, ALLEGRO_KEY_PAD_SLASH, '/');
+ add(SDL_SCANCODE_KP_MULTIPLY, ALLEGRO_KEY_PAD_ASTERISK, '*');
+ add(SDL_SCANCODE_KP_MINUS, ALLEGRO_KEY_PAD_MINUS, '-');
+ add(SDL_SCANCODE_KP_PLUS, ALLEGRO_KEY_PAD_PLUS, '+');
+ add(SDL_SCANCODE_KP_ENTER, ALLEGRO_KEY_PAD_ENTER, 13);
+ add(SDL_SCANCODE_KP_1, ALLEGRO_KEY_PAD_1, '1');
+ add(SDL_SCANCODE_KP_2, ALLEGRO_KEY_PAD_2, '2');
+ add(SDL_SCANCODE_KP_3, ALLEGRO_KEY_PAD_3, '3');
+ add(SDL_SCANCODE_KP_4, ALLEGRO_KEY_PAD_4, '4');
+ add(SDL_SCANCODE_KP_5, ALLEGRO_KEY_PAD_5, '5');
+ add(SDL_SCANCODE_KP_6, ALLEGRO_KEY_PAD_6, '6');
+ add(SDL_SCANCODE_KP_7, ALLEGRO_KEY_PAD_7, '7');
+ add(SDL_SCANCODE_KP_8, ALLEGRO_KEY_PAD_8, '8');
+ add(SDL_SCANCODE_KP_9, ALLEGRO_KEY_PAD_9, '9');
+ add(SDL_SCANCODE_KP_0, ALLEGRO_KEY_PAD_0, '0');
+ add(SDL_SCANCODE_KP_PERIOD, ALLEGRO_KEY_PAD_DELETE, 0);
+ add(SDL_SCANCODE_NONUSBACKSLASH, 0, '\\');
+ add(SDL_SCANCODE_APPLICATION, 0, 0);
+ add(SDL_SCANCODE_POWER, 0, 0);
+ add(SDL_SCANCODE_KP_EQUALS, ALLEGRO_KEY_PAD_EQUALS, '=');
+ add(SDL_SCANCODE_F13, 0, 0);
+ add(SDL_SCANCODE_F14, 0, 0);
+ add(SDL_SCANCODE_F15, 0, 0);
+ add(SDL_SCANCODE_F16, 0, 0);
+ add(SDL_SCANCODE_F17, 0, 0);
+ add(SDL_SCANCODE_F18, 0, 0);
+ add(SDL_SCANCODE_F19, 0, 0);
+ add(SDL_SCANCODE_F20, 0, 0);
+ add(SDL_SCANCODE_F21, 0, 0);
+ add(SDL_SCANCODE_F22, 0, 0);
+ add(SDL_SCANCODE_F23, 0, 0);
+ add(SDL_SCANCODE_F24, 0, 0);
+ add(SDL_SCANCODE_EXECUTE, 0, 0);
+ add(SDL_SCANCODE_HELP, 0, 0);
+ ADD_SAME(MENU, 0);
+ add(SDL_SCANCODE_SELECT, 0, 0);
+ add(SDL_SCANCODE_STOP, 0, 0);
+ add(SDL_SCANCODE_AGAIN, 0, 0);
+ add(SDL_SCANCODE_UNDO, 0, 0);
+ add(SDL_SCANCODE_CUT, 0, 0);
+ add(SDL_SCANCODE_COPY, 0, 0);
+ add(SDL_SCANCODE_PASTE, 0, 0);
+ add(SDL_SCANCODE_FIND, 0, 0);
+ add(SDL_SCANCODE_MUTE, 0, 0);
+ add(SDL_SCANCODE_VOLUMEUP, 0, 0);
+ add(SDL_SCANCODE_VOLUMEDOWN, 0, 0);
+ add(SDL_SCANCODE_KP_COMMA, 0, ',');
+ add(SDL_SCANCODE_KP_EQUALSAS400, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL1, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL2, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL3, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL4, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL5, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL6, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL7, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL8, 0, 0);
+ add(SDL_SCANCODE_INTERNATIONAL9, 0, 0);
+ add(SDL_SCANCODE_LANG1, 0, 0);
+ add(SDL_SCANCODE_LANG2, 0, 0);
+ add(SDL_SCANCODE_LANG3, 0, 0);
+ add(SDL_SCANCODE_LANG4, 0, 0);
+ add(SDL_SCANCODE_LANG5, 0, 0);
+ add(SDL_SCANCODE_LANG6, 0, 0);
+ add(SDL_SCANCODE_LANG7, 0, 0);
+ add(SDL_SCANCODE_LANG8, 0, 0);
+ add(SDL_SCANCODE_LANG9, 0, 0);
+ add(SDL_SCANCODE_ALTERASE, 0, 0);
+ add(SDL_SCANCODE_SYSREQ, 0, 0);
+ add(SDL_SCANCODE_CANCEL, 0, 0);
+ add(SDL_SCANCODE_CLEAR, 0, 0);
+ add(SDL_SCANCODE_PRIOR, 0, 0);
+ add(SDL_SCANCODE_RETURN2, 0, 0);
+ add(SDL_SCANCODE_SEPARATOR, 0, 0);
+ add(SDL_SCANCODE_OUT, 0, 0);
+ add(SDL_SCANCODE_OPER, 0, 0);
+ add(SDL_SCANCODE_CLEARAGAIN, 0, 0);
+ add(SDL_SCANCODE_CRSEL, 0, 0);
+ add(SDL_SCANCODE_EXSEL, 0, 0);
+ add(SDL_SCANCODE_KP_00, 0, 0);
+ add(SDL_SCANCODE_KP_000, 0, 0);
+ add(SDL_SCANCODE_THOUSANDSSEPARATOR, 0, 0);
+ add(SDL_SCANCODE_DECIMALSEPARATOR, 0, 0);
+ add(SDL_SCANCODE_CURRENCYUNIT, 0, 0);
+ add(SDL_SCANCODE_CURRENCYSUBUNIT, 0, 0);
+ add(SDL_SCANCODE_KP_LEFTPAREN, 0, 0);
+ add(SDL_SCANCODE_KP_RIGHTPAREN, 0, 0);
+ add(SDL_SCANCODE_KP_LEFTBRACE, 0, '{');
+ add(SDL_SCANCODE_KP_RIGHTBRACE, 0, '}');
+ add(SDL_SCANCODE_KP_TAB, 0, 9);
+ add(SDL_SCANCODE_KP_BACKSPACE, 0, 8);
+ add(SDL_SCANCODE_KP_A, 0, 0);
+ add(SDL_SCANCODE_KP_B, 0, 0);
+ add(SDL_SCANCODE_KP_C, 0, 0);
+ add(SDL_SCANCODE_KP_D, 0, 0);
+ add(SDL_SCANCODE_KP_E, 0, 0);
+ add(SDL_SCANCODE_KP_F, 0, 0);
+ add(SDL_SCANCODE_KP_XOR, 0, 0);
+ add(SDL_SCANCODE_KP_POWER, 0, 0);
+ add(SDL_SCANCODE_KP_PERCENT, 0, 0);
+ add(SDL_SCANCODE_KP_LESS, 0, '<');
+ add(SDL_SCANCODE_KP_GREATER, 0, '>');
+ add(SDL_SCANCODE_KP_AMPERSAND, 0, '&');
+ add(SDL_SCANCODE_KP_DBLAMPERSAND, 0, 0);
+ add(SDL_SCANCODE_KP_VERTICALBAR, 0, '|');
+ add(SDL_SCANCODE_KP_DBLVERTICALBAR, 0, 0);
+ add(SDL_SCANCODE_KP_COLON, 0, ':');
+ add(SDL_SCANCODE_KP_HASH, 0, '#');
+ add(SDL_SCANCODE_KP_SPACE, 0, 0);
+ add(SDL_SCANCODE_KP_AT, 0, '@');
+ add(SDL_SCANCODE_KP_EXCLAM, 0, '!');
+ add(SDL_SCANCODE_KP_MEMSTORE, 0, 0);
+ add(SDL_SCANCODE_KP_MEMRECALL, 0, 0);
+ add(SDL_SCANCODE_KP_MEMCLEAR, 0, 0);
+ add(SDL_SCANCODE_KP_MEMADD, 0, 0);
+ add(SDL_SCANCODE_KP_MEMSUBTRACT, 0, 0);
+ add(SDL_SCANCODE_KP_MEMMULTIPLY, 0, 0);
+ add(SDL_SCANCODE_KP_MEMDIVIDE, 0, 0);
+ add(SDL_SCANCODE_KP_PLUSMINUS, 0, 0);
+ add(SDL_SCANCODE_KP_CLEAR, 0, 0);
+ add(SDL_SCANCODE_KP_CLEARENTRY, 0, 0);
+ add(SDL_SCANCODE_KP_BINARY, 0, 0);
+ add(SDL_SCANCODE_KP_OCTAL, 0, 0);
+ add(SDL_SCANCODE_KP_DECIMAL, 0, 0);
+ add(SDL_SCANCODE_KP_HEXADECIMAL, 0, 0);
+ ADD_SAME(LCTRL, 0);
+ ADD_SAME(LSHIFT, 0);
+ add(SDL_SCANCODE_LALT, ALLEGRO_KEY_ALT, 0);
+ add(SDL_SCANCODE_LGUI, ALLEGRO_KEY_LWIN, 0);
+ ADD_SAME(RCTRL, 0);
+ ADD_SAME(RSHIFT, 0);
+ add(SDL_SCANCODE_RALT, ALLEGRO_KEY_ALTGR, 0);
+ add(SDL_SCANCODE_RGUI, ALLEGRO_KEY_RWIN, 0);
+ add(SDL_SCANCODE_MODE, 0, 0);
+ add(SDL_SCANCODE_AUDIONEXT, 0, 0);
+ add(SDL_SCANCODE_AUDIOPREV, 0, 0);
+ add(SDL_SCANCODE_AUDIOSTOP, 0, 0);
+ add(SDL_SCANCODE_AUDIOPLAY, 0, 0);
+ add(SDL_SCANCODE_AUDIOMUTE, 0, 0);
+ add(SDL_SCANCODE_MEDIASELECT, 0, 0);
+ add(SDL_SCANCODE_WWW, 0, 0);
+ add(SDL_SCANCODE_MAIL, 0, 0);
+ add(SDL_SCANCODE_CALCULATOR, 0, 0);
+ add(SDL_SCANCODE_COMPUTER, 0, 0);
+ add(SDL_SCANCODE_AC_SEARCH, 0, 0);
+ add(SDL_SCANCODE_AC_HOME, 0, 0);
+ add(SDL_SCANCODE_AC_BACK, 0, 0);
+ add(SDL_SCANCODE_AC_FORWARD, 0, 0);
+ add(SDL_SCANCODE_AC_STOP, 0, 0);
+ add(SDL_SCANCODE_AC_REFRESH, 0, 0);
+ add(SDL_SCANCODE_AC_BOOKMARKS, 0, 0);
+ add(SDL_SCANCODE_BRIGHTNESSDOWN, 0, 0);
+ add(SDL_SCANCODE_BRIGHTNESSUP, 0, 0);
+ add(SDL_SCANCODE_DISPLAYSWITCH, 0, 0);
+ add(SDL_SCANCODE_KBDILLUMTOGGLE, 0, 0);
+ add(SDL_SCANCODE_KBDILLUMDOWN, 0, 0);
+ add(SDL_SCANCODE_KBDILLUMUP, 0, 0);
+ add(SDL_SCANCODE_EJECT, 0, 0);
+ add(SDL_SCANCODE_SLEEP, 0, 0);
+
+ return true;
+}
+
+static void sdl_exit_keyboard(void)
+{
+}
+
+static ALLEGRO_KEYBOARD *sdl_get_keyboard(void)
+{
+ return &keyboard->keyboard;
+}
+
+static bool sdl_set_keyboard_leds(int leds)
+{
+ return false;
+}
+
+static char const *sdl_keycode_to_name(int keycode)
+{
+ return SDL_GetScancodeName(keyboard->inverse[keycode]);
+}
+
+static void sdl_get_keyboard_state(ALLEGRO_KEYBOARD_STATE *ret_state)
+{
+ int i, n;
+ ALLEGRO_SYSTEM_INTERFACE *sdl = _al_sdl_system_driver();
+ sdl->heartbeat();
+ const Uint8 *s = SDL_GetKeyboardState(&n);
+ for (i = 0; i < n; i++) {
+ if (s[i])
+ _AL_KEYBOARD_STATE_SET_KEY_DOWN(*ret_state, keyboard->table[i]);
+ else
+ _AL_KEYBOARD_STATE_CLEAR_KEY_DOWN(*ret_state, keyboard->table[i]);
+ }
+ ret_state->display = keyboard->display;
+}
+
+ALLEGRO_KEYBOARD_DRIVER *_al_sdl_keyboard_driver(void)
+{
+ if (vt)
+ return vt;
+
+ vt = al_calloc(1, sizeof *vt);
+ vt->keydrv_id = AL_ID('S','D','L','2');
+ vt->keydrv_name = "SDL2 Keyboard";
+ vt->keydrv_desc = "SDL2 Keyboard";
+ vt->keydrv_ascii_name = "SDL2 Keyboard";
+ vt->init_keyboard = sdl_init_keyboard;
+ vt->exit_keyboard = sdl_exit_keyboard;
+ vt->get_keyboard = sdl_get_keyboard;
+ vt->set_keyboard_leds = sdl_set_keyboard_leds;
+ vt->keycode_to_name = sdl_keycode_to_name;
+ vt->get_keyboard_state = sdl_get_keyboard_state;
+ return vt;
+}
diff --git a/src/sdl/sdl_mouse.c b/src/sdl/sdl_mouse.c
new file mode 100644
index 0000000..5bf32db
--- /dev/null
+++ b/src/sdl/sdl_mouse.c
@@ -0,0 +1,167 @@
+#include "allegro5/allegro.h"
+#include "allegro5/internal/aintern_system.h"
+#include "allegro5/platform/allegro_internal_sdl.h"
+
+ALLEGRO_DEBUG_CHANNEL("SDL")
+
+typedef struct ALLEGRO_MOUSE_SDL
+{
+ ALLEGRO_MOUSE mouse;
+ int x, y, z, w;
+ ALLEGRO_DISPLAY *display;
+ int buttons;
+} ALLEGRO_MOUSE_SDL;
+
+static ALLEGRO_MOUSE_DRIVER *vt;
+static ALLEGRO_MOUSE_SDL *mouse;
+
+void _al_sdl_mouse_event(SDL_Event *e)
+{
+ if (!mouse)
+ return;
+
+ ALLEGRO_EVENT_SOURCE *es = &mouse->mouse.es;
+ _al_event_source_lock(es);
+ ALLEGRO_EVENT event;
+ memset(&event, 0, sizeof event);
+
+ event.mouse.timestamp = al_get_time();
+
+ ALLEGRO_DISPLAY *d = NULL;
+
+ if (e->type == SDL_WINDOWEVENT) {
+ if (e->window.event == SDL_WINDOWEVENT_ENTER) {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY;
+ SDL_GetMouseState(&event.mouse.x, &event.mouse.y );
+ }
+ else {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY;
+ event.mouse.x = mouse->x;
+ event.mouse.y = mouse->y;
+ }
+ d = _al_sdl_find_display(e->window.windowID);
+ mouse->display = e->window.event == SDL_WINDOWEVENT_ENTER ? d : NULL;
+ }
+ else if (e->type == SDL_MOUSEMOTION) {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_AXES;
+ event.mouse.x = e->motion.x;
+ event.mouse.y = e->motion.y;
+ event.mouse.dx = e->motion.xrel;
+ event.mouse.dy = e->motion.yrel;
+ mouse->x = e->motion.x;
+ mouse->y = e->motion.y;
+ d = _al_sdl_find_display(e->motion.windowID);
+ }
+ else if (e->type == SDL_MOUSEWHEEL) {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_AXES;
+ mouse->z += e->wheel.y;
+ mouse->w += e->wheel.x;
+ event.mouse.z = mouse->z;
+ event.mouse.w = mouse->w;
+ event.mouse.dz = e->wheel.y;
+ event.mouse.dw = e->wheel.x;
+ d = _al_sdl_find_display(e->wheel.windowID);
+ }
+ else {
+ switch (e->button.button) {
+ case SDL_BUTTON_LEFT: event.mouse.button = 1; break;
+ case SDL_BUTTON_RIGHT: event.mouse.button = 2; break;
+ case SDL_BUTTON_MIDDLE: event.mouse.button = 3; break;
+ case SDL_BUTTON_X1: event.mouse.button = 4; break;
+ case SDL_BUTTON_X2: event.mouse.button = 5; break;
+ }
+ event.mouse.x = e->button.x;
+ event.mouse.y = e->button.y;
+ if (e->type == SDL_MOUSEBUTTONDOWN) {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN;
+ mouse->buttons |= 1 << (event.mouse.button - 1);
+ }
+ if (e->type == SDL_MOUSEBUTTONUP) {
+ event.mouse.type = ALLEGRO_EVENT_MOUSE_BUTTON_UP;
+ mouse->buttons &= ~(1 << (event.mouse.button - 1));
+ }
+ d = _al_sdl_find_display(e->button.windowID);
+ }
+
+ event.mouse.display = d;
+
+ _al_event_source_emit_event(es, &event);
+ _al_event_source_unlock(es);
+}
+
+static bool sdl_init_mouse(void)
+{
+ mouse = al_calloc(1, sizeof *mouse);
+ _al_event_source_init(&mouse->mouse.es);
+ return true;
+}
+
+static void sdl_exit_mouse(void)
+{
+}
+
+static ALLEGRO_MOUSE *sdl_get_mouse(void)
+{
+ return &mouse->mouse;
+}
+
+static unsigned int sdl_get_mouse_num_buttons(void)
+{
+ return 5;
+}
+
+static unsigned int sdl_get_mouse_num_axes(void)
+{
+ return 4;
+}
+
+static bool sdl_set_mouse_xy(ALLEGRO_DISPLAY *display, int x, int y)
+{
+ ALLEGRO_DISPLAY_SDL *sdl = (void *)display;
+ SDL_WarpMouseInWindow(sdl->window, x, y);
+ return true;
+}
+
+static bool sdl_set_mouse_axis(int which, int value)
+{
+ return false;
+}
+
+static void sdl_get_mouse_state(ALLEGRO_MOUSE_STATE *ret_state)
+{
+ int x, y, i;
+ ALLEGRO_SYSTEM_INTERFACE *sdl = _al_sdl_system_driver();
+ sdl->heartbeat();
+ SDL_GetMouseState(&x, &y);
+ ret_state->x = x;
+ ret_state->y = y;
+ ret_state->z = 0;
+ ret_state->w = 0;
+ for (i = 0; i < ALLEGRO_MOUSE_MAX_EXTRA_AXES; i++)
+ ret_state->more_axes[i] = 0;
+ ret_state->buttons = mouse->buttons;
+ ret_state->pressure = 0;
+ ret_state->display = mouse->display;
+}
+
+ALLEGRO_MOUSE_DRIVER *_al_sdl_mouse_driver(void)
+{
+ if (vt)
+ return vt;
+
+ vt = al_calloc(1, sizeof *vt);
+ vt->msedrv_id = AL_ID('S','D','L','2');
+ vt->msedrv_name = "SDL2 Mouse";
+ vt->msedrv_desc = "SDL2 Mouse";
+ vt->msedrv_ascii_name = "SDL2 Mouse";
+ vt->init_mouse = sdl_init_mouse;
+ vt->exit_mouse = sdl_exit_mouse;
+ vt->get_mouse = sdl_get_mouse;
+ vt->get_mouse_num_buttons = sdl_get_mouse_num_buttons;
+ vt->get_mouse_num_axes = sdl_get_mouse_num_axes;
+ vt->set_mouse_xy = sdl_set_mouse_xy;
+ vt->set_mouse_axis = sdl_set_mouse_axis;
+ vt->get_mouse_state = sdl_get_mouse_state;
+
+ return vt;
+}
diff --git a/src/sdl/sdl_system.c b/src/sdl/sdl_system.c
new file mode 100644
index 0000000..ca51f4c
--- /dev/null
+++ b/src/sdl/sdl_system.c
@@ -0,0 +1,285 @@
+#include "allegro5/allegro.h"
+#include "allegro5/internal/aintern_system.h"
+#include "allegro5/platform/allegro_internal_sdl.h"
+
+ALLEGRO_DEBUG_CHANNEL("SDL")
+
+static ALLEGRO_SYSTEM_INTERFACE *vt;
+
+#define _E(x) if (type == x) return #x;
+static char const *event_name(int type)
+{
+ _E(SDL_FIRSTEVENT)
+ _E(SDL_QUIT)
+ _E(SDL_APP_TERMINATING)
+ _E(SDL_APP_LOWMEMORY)
+ _E(SDL_APP_WILLENTERBACKGROUND)
+ _E(SDL_APP_DIDENTERBACKGROUND)
+ _E(SDL_APP_WILLENTERFOREGROUND)
+ _E(SDL_APP_DIDENTERFOREGROUND)
+ _E(SDL_WINDOWEVENT)
+ _E(SDL_SYSWMEVENT)
+ _E(SDL_KEYDOWN)
+ _E(SDL_KEYUP)
+ _E(SDL_TEXTEDITING)
+ _E(SDL_TEXTINPUT)
+ _E(SDL_MOUSEMOTION)
+ _E(SDL_MOUSEBUTTONDOWN)
+ _E(SDL_MOUSEBUTTONUP)
+ _E(SDL_MOUSEWHEEL)
+ _E(SDL_JOYAXISMOTION)
+ _E(SDL_JOYBALLMOTION)
+ _E(SDL_JOYHATMOTION)
+ _E(SDL_JOYBUTTONDOWN)
+ _E(SDL_JOYBUTTONUP)
+ _E(SDL_JOYDEVICEADDED)
+ _E(SDL_JOYDEVICEREMOVED)
+ _E(SDL_CONTROLLERAXISMOTION)
+ _E(SDL_CONTROLLERBUTTONDOWN)
+ _E(SDL_CONTROLLERBUTTONUP)
+ _E(SDL_CONTROLLERDEVICEADDED)
+ _E(SDL_CONTROLLERDEVICEREMOVED)
+ _E(SDL_CONTROLLERDEVICEREMAPPED)
+ _E(SDL_FINGERDOWN)
+ _E(SDL_FINGERUP)
+ _E(SDL_FINGERMOTION)
+ _E(SDL_DOLLARGESTURE)
+ _E(SDL_DOLLARRECORD)
+ _E(SDL_MULTIGESTURE)
+ _E(SDL_CLIPBOARDUPDATE)
+ _E(SDL_DROPFILE)
+ _E(SDL_RENDER_TARGETS_RESET)
+ _E(SDL_USEREVENT)
+ return "(unknown)";
+}
+#undef _E
+
+static void sdl_heartbeat(void)
+{
+ ALLEGRO_SYSTEM_SDL *s = (void *)al_get_system_driver();
+ al_lock_mutex(s->mutex);
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ //printf("event %s\n", event_name(event.type));
+ switch (event.type) {
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ case SDL_TEXTINPUT:
+ _al_sdl_keyboard_event(&event);
+ break;
+ case SDL_MOUSEMOTION:
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEWHEEL:
+ _al_sdl_mouse_event(&event);
+ break;
+ case SDL_QUIT:
+ _al_sdl_display_event(&event);
+ break;
+ case SDL_WINDOWEVENT:
+ switch (event.window.event) {
+ case SDL_WINDOWEVENT_ENTER:
+ case SDL_WINDOWEVENT_LEAVE:
+ _al_sdl_mouse_event(&event);
+ break;
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ case SDL_WINDOWEVENT_FOCUS_LOST:
+ _al_sdl_display_event(&event);
+ _al_sdl_keyboard_event(&event);
+ break;
+ case SDL_WINDOWEVENT_CLOSE:
+ _al_sdl_display_event(&event);
+ break;
+ }
+ }
+ }
+ al_unlock_mutex(s->mutex);
+}
+
+static ALLEGRO_SYSTEM *sdl_initialize(int flags)
+{
+ (void)flags;
+ ALLEGRO_SYSTEM_SDL *s = al_calloc(1, sizeof *s);
+ s->system.vt = vt;
+
+ SDL_Init(SDL_INIT_EVERYTHING);
+
+ _al_vector_init(&s->system.displays, sizeof (ALLEGRO_DISPLAY_SDL *));
+
+ return &s->system;
+}
+
+static void sdl_heartbeat_init(void)
+{
+ ALLEGRO_SYSTEM_SDL *s = (void *)al_get_system_driver();
+
+ /* This cannot be done in sdl_initialize because the threading system
+ * requires a completed ALLEGRO_SYSTEM which only exists after the
+ * function returns. This function on the other hand will get called
+ * once the system was created.
+ */
+ s->mutex = al_create_mutex();
+}
+
+static void sdl_shutdown_system(void)
+{
+ ALLEGRO_SYSTEM_SDL *s = (void *)al_get_system_driver();
+
+ al_destroy_mutex(s->mutex);
+ al_free(s);
+ SDL_Quit();
+}
+
+static ALLEGRO_PATH *sdl_get_path(int id)
+{
+ ALLEGRO_PATH *p = NULL;
+ switch (id) {
+ case ALLEGRO_TEMP_PATH:
+ case ALLEGRO_USER_DOCUMENTS_PATH:
+ case ALLEGRO_USER_DATA_PATH:
+ case ALLEGRO_USER_SETTINGS_PATH:
+ p = al_create_path_for_directory(SDL_GetPrefPath(
+ al_get_org_name(), al_get_app_name()));
+ if (id == ALLEGRO_TEMP_PATH) {
+ al_append_path_component(p, "tmp");
+ }
+ break;
+ case ALLEGRO_RESOURCES_PATH:
+ case ALLEGRO_EXENAME_PATH:
+ case ALLEGRO_USER_HOME_PATH:
+ p = al_create_path_for_directory(SDL_GetBasePath());
+ if (id == ALLEGRO_EXENAME_PATH) {
+ al_set_path_filename(p, al_get_app_name());
+ }
+ break;
+ }
+ return p;
+}
+
+static ALLEGRO_DISPLAY_INTERFACE *sdl_get_display_driver(void)
+{
+ return _al_sdl_display_driver();
+}
+
+static ALLEGRO_KEYBOARD_DRIVER *sdl_get_keyboard_driver(void)
+{
+ return _al_sdl_keyboard_driver();
+}
+
+static ALLEGRO_MOUSE_DRIVER *sdl_get_mouse_driver(void)
+{
+ return _al_sdl_mouse_driver();
+}
+
+#define ADD(allegro, sdl) if (sdl_format == \
+ SDL_PIXELFORMAT_##sdl) return ALLEGRO_PIXEL_FORMAT_##allegro;
+int _al_sdl_get_allegro_pixel_format(int sdl_format) {
+ ADD(ARGB_8888, ARGB8888)
+ ADD(RGBA_8888, RGBA8888)
+ ADD(ABGR_8888, ABGR8888)
+ return 0;
+}
+#undef ADD
+
+#define ADD(allegro, sdl) if (allegro_format == \
+ ALLEGRO_PIXEL_FORMAT_##allegro) return SDL_PIXELFORMAT_##sdl;
+int _al_sdl_get_sdl_pixel_format(int allegro_format) {
+ ADD(ANY, ABGR8888)
+ ADD(ANY_NO_ALPHA, ABGR8888)
+ ADD(ANY_WITH_ALPHA, ABGR8888)
+ ADD(ANY_32_NO_ALPHA, ABGR8888)
+ ADD(ANY_32_WITH_ALPHA, ABGR8888)
+ ADD(ARGB_8888, ARGB8888)
+ ADD(RGBA_8888, RGBA8888)
+ ADD(ABGR_8888, ABGR8888)
+ ADD(ABGR_8888_LE, ABGR8888)
+ return 0;
+}
+#undef ADD
+
+
+static int sdl_get_num_video_adapters(void)
+{
+ return SDL_GetNumVideoDisplays();
+}
+
+static bool sdl_get_monitor_info(int adapter, ALLEGRO_MONITOR_INFO *info)
+{
+ SDL_Rect rect;
+ if (SDL_GetDisplayBounds(adapter, &rect) < 0)
+ return false;
+ info->x1 = rect.x;
+ info->y1 = rect.y;
+ info->x2 = rect.x + rect.w;
+ info->y2 = rect.y + rect.h;
+ return true;
+}
+
+static int sdl_get_num_display_modes(void)
+{
+ int i = al_get_new_display_adapter();
+ if (i < 0)
+ i = 0;
+ return SDL_GetNumDisplayModes(i);
+}
+
+static ALLEGRO_DISPLAY_MODE *sdl_get_display_mode(int index, ALLEGRO_DISPLAY_MODE *mode)
+{
+ SDL_DisplayMode sdl_mode;
+ int i = al_get_new_display_adapter();
+ if (i < 0)
+ i = 0;
+ if (SDL_GetDisplayMode(i, index, &sdl_mode) < 0)
+ return NULL;
+ mode->width = sdl_mode.w;
+ mode->height = sdl_mode.h;
+ mode->format = _al_sdl_get_allegro_pixel_format(sdl_mode.format);
+ mode->refresh_rate = sdl_mode.refresh_rate;
+ return mode;
+}
+
+/* Internal function to get a reference to this driver. */
+ALLEGRO_SYSTEM_INTERFACE *_al_sdl_system_driver(void)
+{
+ if (vt)
+ return vt;
+
+ vt = al_calloc(1, sizeof *vt);
+ vt->id = AL_ID('S', 'D', 'L', '2');
+ vt->initialize = sdl_initialize;
+ vt->get_display_driver = sdl_get_display_driver;
+ vt->get_keyboard_driver = sdl_get_keyboard_driver;
+ vt->get_mouse_driver = sdl_get_mouse_driver;
+ /*
+ vt->get_touch_input_driver = sdl_get_touch_input_driver;
+ vt->get_joystick_driver = sdl_get_joystick_driver;
+ vt->get_haptic_driver = sdl_get_haptic_driver;*/
+ vt->get_num_display_modes = sdl_get_num_display_modes;
+ vt->get_display_mode = sdl_get_display_mode;
+ vt->shutdown_system = sdl_shutdown_system;
+ vt->get_num_video_adapters = sdl_get_num_video_adapters;
+ vt->get_monitor_info = sdl_get_monitor_info;
+ /*vt->create_mouse_cursor = sdl_create_mouse_cursor;
+ vt->destroy_mouse_cursor = sdl_destroy_mouse_cursor;
+ vt->get_cursor_position = sdl_get_cursor_position;
+ vt->grab_mouse = sdl_grab_mouse;
+ vt->ungrab_mouse = sdl_ungrab_mouse;*/
+ vt->get_path = sdl_get_path;
+ /*vt->inhibit_screensaver = sdl_inhibit_screensaver;
+ vt->thread_init = sdl_thread_init;
+ vt->thread_exit = sdl_thread_exit;
+ vt->open_library = sdl_open_library;
+ vt->import_symbol = sdl_import_symbol;
+ vt->close_library = sdl_close_library;*/
+ vt->heartbeat = sdl_heartbeat;
+ vt->heartbeat_init = sdl_heartbeat_init;
+
+ return vt;
+}
+
+void _al_register_system_interfaces(void)
+{
+ ALLEGRO_SYSTEM_INTERFACE **add;
+ add = _al_vector_alloc_back(&_al_system_interfaces);
+ *add = _al_sdl_system_driver();
+}
diff --git a/src/sdl/sdl_thread.c b/src/sdl/sdl_thread.c
new file mode 100644
index 0000000..1d90071
--- /dev/null
+++ b/src/sdl/sdl_thread.c
@@ -0,0 +1,89 @@
+#include "allegro5/allegro.h"
+#include "allegro5/internal/aintern.h"
+#include "allegro5/internal/aintern_thread.h"
+#include "allegro5/platform/allegro_internal_sdl.h"
+
+static int thread_trampoline(void* data)
+{
+ _AL_THREAD *thread = data;
+ (*thread->proc)(thread, thread->arg);
+ return 0;
+}
+
+void _al_thread_create(_AL_THREAD *thread, void (*proc)(_AL_THREAD*, void*),
+ void *arg)
+{
+ ASSERT(thread);
+ ASSERT(proc);
+ thread->should_stop = false;
+ thread->proc = proc;
+ thread->arg = arg;
+ thread->thread = SDL_CreateThread(thread_trampoline, "allegro", thread);
+}
+
+void _al_thread_set_should_stop(_AL_THREAD *thread)
+{
+ ASSERT(thread);
+ thread->should_stop = true;
+}
+
+void _al_thread_join(_AL_THREAD *thread)
+{
+ ASSERT(thread);
+ _al_thread_set_should_stop(thread);
+ int r;
+ SDL_WaitThread(thread->thread, &r);
+}
+
+void _al_thread_detach(_AL_THREAD *thread)
+{
+ ASSERT(thread);
+ SDL_DetachThread(thread->thread);
+}
+
+/* mutexes */
+
+void _al_mutex_init(_AL_MUTEX *mutex)
+{
+ ASSERT(mutex);
+
+ mutex->mutex = SDL_CreateMutex();
+ mutex->lock_count = 0;
+}
+
+static void free_tls(void *v)
+{
+ al_free(v);
+}
+
+void _al_mutex_init_recursive(_AL_MUTEX *mutex)
+{
+ ASSERT(mutex);
+
+ mutex->mutex = SDL_CreateMutex();
+ mutex->lock_count = SDL_TLSCreate();
+ int *v = al_calloc(1, sizeof *v);
+ SDL_TLSSet(mutex->lock_count, v, free_tls);
+}
+
+void _al_mutex_destroy(_AL_MUTEX *mutex)
+{
+ ASSERT(mutex);
+
+ if (mutex->mutex) {
+ SDL_DestroyMutex(mutex->mutex);
+ mutex->mutex = NULL;
+ }
+}
+
+/* condition variables */
+/* most of the condition variable implementation is actually inline */
+
+int _al_cond_timedwait(_AL_COND *cond, _AL_MUTEX *mutex,
+ const ALLEGRO_TIMEOUT *timeout)
+{
+ ALLEGRO_TIMEOUT_SDL *timeout_sdl = (void *)timeout;
+ int r = SDL_CondWaitTimeout(cond->cond, mutex->mutex, timeout_sdl->ms);
+
+ return (r == SDL_MUTEX_TIMEDOUT) ? -1 : 0;
+}
diff --git a/src/sdl/sdl_time.c b/src/sdl/sdl_time.c
new file mode 100644
index 0000000..cdfc5f3
--- /dev/null
+++ b/src/sdl/sdl_time.c
@@ -0,0 +1,35 @@
+#include "SDL.h"
+
+#include "allegro5/altime.h"
+#include "allegro5/platform/allegro_sdl_thread.h"
+#include "allegro5/debug.h"
+
+ALLEGRO_DEBUG_CHANNEL("SDL")
+
+/* Function: al_get_time
+ */
+double al_get_time(void)
+{
+ return 1.0 * SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency();
+}
+
+
+
+/* Function: al_rest
+ */
+void al_rest(double seconds)
+{
+ SDL_Delay(seconds * 1000);
+}
+
+
+
+/* Function: al_init_timeout
+ */
+void al_init_timeout(ALLEGRO_TIMEOUT *timeout, double seconds)
+{
+ ALLEGRO_TIMEOUT_SDL *timeout_sdl = (void *)timeout;
+ timeout_sdl->ms = seconds * 1000;
+}
+
+/* vim: set sts=3 sw=3 et */
diff --git a/src/system.c b/src/system.c
index ce47a88..66f9f9b 100644
--- a/src/system.c
+++ b/src/system.c
@@ -104,6 +104,8 @@ static ALLEGRO_PATH *early_get_exename_path(void)
return _al_unix_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_ANDROID)
return _al_android_get_path(ALLEGRO_EXENAME_PATH);
+#elif defined(ALLEGRO_SDL)
+ return al_create_path_for_directory(SDL_GetBasePath());
#else
#error early_get_exename_path not implemented
#endif
@@ -271,6 +273,9 @@ bool al_install_system(int version, int (*atexit_ptr)(void (*)(void)))
_al_init_timers();
+ if (active_sysdrv->vt->heartbeat_init)
+ active_sysdrv->vt->heartbeat_init();
+
if (atexit_ptr && atexit_virgin) {
atexit_ptr(al_uninstall_system);
atexit_virgin = false;