diff --git a/Makefile.emscripten b/Makefile.emscripten
new file mode 100644
index 0000000000..79f77f2c56
--- /dev/null
+++ b/Makefile.emscripten
@@ -0,0 +1,152 @@
+TARGET = retroarch.html
+
+OBJ = frontend/frontend_emscripten.o \
+ retroarch.o \
+ file.o \
+ file_path.o \
+ driver.o \
+ conf/config_file.o \
+ settings.o \
+ hash.o \
+ dynamic.o \
+ dynamic_dummy.o \
+ message.o \
+ rewind.o \
+ movie.o \
+ gfx/gfx_common.o \
+ input/input_common.o \
+ core_options.o \
+ patch.o \
+ compat/compat.o \
+ screenshot.o \
+ cheats.o \
+ audio/utils.o \
+ input/overlay.o \
+ fifo_buffer.o \
+ gfx/scaler/scaler.o \
+ gfx/scaler/pixconv.o \
+ gfx/scaler/scaler_int.o \
+ gfx/scaler/filter.o \
+ gfx/state_tracker.o \
+ gfx/shader_parse.o \
+ gfx/fonts/fonts.o \
+ gfx/fonts/bitmapfont.o \
+ gfx/image.o \
+ audio/resampler.o \
+ audio/sinc.o \
+ audio/null.o \
+ performance.o
+
+HAVE_OPENGL = 1
+HAVE_RGUI = 1
+HAVE_SDL = 1
+HAVE_SDL_IMAGE = 1
+HAVE_FREETYPE = 1
+HAVE_ZLIB = 1
+HAVE_FBO = 1
+
+libretro ?= -lretro
+
+LIBS = -lm
+DEFINES = -I. -DHAVE_SCREENSHOTS -DHAVE_NULLAUDIO -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.9.3\"
+LDFLAGS = -L. -static-libgcc -s TOTAL_MEMORY=268435456 -s FULL_ES2=1
+
+ifeq ($(SCALER_NO_SIMD), 1)
+ DEFINES += -DSCALER_NO_SIMD
+endif
+
+ifeq ($(PERF_TEST), 1)
+ DEFINES += -DPERF_TEST
+endif
+
+ifeq ($(HAVE_RGUI), 1)
+ DEFINES += -DHAVE_RGUI
+ OBJ += frontend/menu/menu_common.o frontend/menu/rgui.o frontend/menu/history.o
+endif
+
+ifeq ($(HAVE_SDL), 1)
+ OBJ += input/sdl_input.o
+ LIBS += -lSDL
+ DEFINES += -ISDL -DHAVE_SDL
+endif
+
+ifeq ($(HAVE_THREADS), 1)
+ OBJ += autosave.o thread.o gfx/thread_wrapper.o
+ DEFINES += -DHAVE_THREADS
+endif
+
+ifeq ($(HAVE_OPENGL), 1)
+ OBJ += gfx/gl.o gfx/math/matrix.o gfx/fonts/gl_font.o gfx/fonts/gl_raster_font.o gfx/gfx_context.o gfx/context/emscriptenegl_ctx.o gfx/shader_glsl.o
+ DEFINES += -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_EGL -DHAVE_OVERLAY -DHAVE_GLSL
+endif
+
+ifeq ($(HAVE_ZLIB), 1)
+ OBJ += gfx/rpng/rpng.o file_extract.o
+ DEFINES += -DHAVE_ZLIB
+ ifeq ($(WANT_MINIZ), 1)
+ OBJ += deps/miniz/miniz.o
+ DEFINES += -DWANT_MINIZ
+ else
+ LIBS += -lz
+ DEFINES += -DHAVE_ZLIB_DEFLATE
+ endif
+endif
+
+LIBS += $(libretro)
+
+ifeq ($(HAVE_FBO), 1)
+ DEFINES += -DHAVE_FBO
+endif
+
+ifneq ($(V), 1)
+ Q := @
+endif
+
+ifeq ($(DEBUG), 1)
+ LDFLAGS += -O0 -g -s LABEL_DEBUG=1
+else
+ LDFLAGS += -O2 -ffast-math
+endif
+
+CFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I. -std=gnu99
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+ @$(if $(Q), $(shell echo echo LD $@),)
+ $(Q)$(LD) -o $@ $(OBJ) $(LIBS) $(LDFLAGS)
+
+%.o: %.c
+ @$(if $(Q), $(shell echo echo CC $<),)
+ $(Q)$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+
+%.o: %.cpp
+ @$(if $(Q), $(shell echo echo CXX $<),)
+ $(Q)$(CXX) $(CXXFLAGS) $(DEFINES) -c -o $@ $<
+
+clean:
+ rm -f *.o
+ rm -f deps/miniz/*.o
+ rm -f frontend/*.o
+ rm -f frontend/menu/*.o
+ rm -f audio/*.o
+ rm -f audio/xaudio-c/*.o
+ rm -f compat/*.o
+ rm -f compat/rxml/*.o
+ rm -f conf/*.o
+ rm -f gfx/scaler/*.o
+ rm -f gfx/*.o
+ rm -f gfx/d3d9/*.o
+ rm -f gfx/context/*.o
+ rm -f gfx/math/*.o
+ rm -f gfx/fonts/*.o
+ rm -f gfx/py_state/*.o
+ rm -f gfx/rpng/*.o
+ rm -f record/*.o
+ rm -f input/*.o
+ rm -f $(TARGET)
+ rm -f retroarch-joyconfig.exe
+ rm -f tools/*.o
+
+.PHONY: all clean
+
diff --git a/config.def.h b/config.def.h
index c11957648c..ae2f7523b7 100644
--- a/config.def.h
+++ b/config.def.h
@@ -128,6 +128,8 @@ enum
#define AUDIO_DEFAULT_DRIVER AUDIO_SL
#elif defined(HAVE_DSOUND)
#define AUDIO_DEFAULT_DRIVER AUDIO_DSOUND
+#elif defined(EMSCRIPTEN)
+#define AUDIO_DEFAULT_DRIVER AUDIO_NULL
#elif defined(HAVE_SDL)
#define AUDIO_DEFAULT_DRIVER AUDIO_SDL
#elif defined(HAVE_XAUDIO)
@@ -195,6 +197,8 @@ enum
#define EXT_EXECUTABLES "xex|XEX"
#elif defined(GEKKO)
#define EXT_EXECUTABLES "dol|DOL"
+#else
+#define EXT_EXECUTABLES "???"
#endif
#endif
diff --git a/driver.c b/driver.c
index 790e23e1f6..338dd28ff6 100644
--- a/driver.c
+++ b/driver.c
@@ -62,7 +62,7 @@ static const audio_driver_t *audio_drivers[] = {
#ifdef HAVE_JACK
&audio_jack,
#endif
-#ifdef HAVE_SDL
+#if defined(HAVE_SDL) && !defined(EMSCRIPTEN)
&audio_sdl,
#endif
#ifdef HAVE_XAUDIO
diff --git a/frontend/frontend_emscripten.c b/frontend/frontend_emscripten.c
new file mode 100644
index 0000000000..949870e0c5
--- /dev/null
+++ b/frontend/frontend_emscripten.c
@@ -0,0 +1,127 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2013 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2013 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include "../general.h"
+#include "../conf/config_file.h"
+#include "../file.h"
+
+#ifdef HAVE_RGUI
+#include "../frontend/menu/rgui.h"
+#endif
+
+#if defined(HAVE_RGUI) || defined(HAVE_RMENU) || defined(HAVE_RMENU_XUI)
+#define HAVE_MENU
+#else
+#undef HAVE_MENU
+#endif
+
+static bool menuloop;
+
+void mainloop(void)
+{
+ if (g_extern.system.shutdown)
+ {
+ RARCH_ERR("Exit...\n");
+ emscripten_cancel_main_loop();
+ }
+ else if (menuloop)
+ {
+ if (!menu_iterate())
+ {
+ menuloop = false;
+ driver_set_nonblock_state(driver.nonblock_state);
+
+ if (driver.audio_data && !audio_start_func())
+ {
+ RARCH_ERR("Failed to resume audio driver. Will continue without audio.\n");
+ g_extern.audio_active = false;
+ }
+
+ g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU);
+ }
+ }
+ else if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME))
+ {
+ load_menu_game_prepare();
+
+ // If ROM load fails, we exit RetroArch. On console it might make more sense to go back to menu though ...
+ if (load_menu_game())
+ g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME);
+ else
+ {
+#ifdef RARCH_CONSOLE
+ g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU);
+#else
+ return;
+#endif
+ }
+
+ g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME);
+ }
+ else if (g_extern.lifecycle_mode_state & (1ULL << MODE_GAME))
+ {
+ bool r;
+ if (g_extern.is_paused && !g_extern.is_oneshot)
+ r = rarch_main_idle_iterate();
+ else
+ r = rarch_main_iterate();
+ if (!r)
+ g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME);
+ }
+ else if (g_extern.lifecycle_mode_state & (1ULL << MODE_MENU))
+ {
+ g_extern.lifecycle_mode_state |= 1ULL << MODE_MENU_PREINIT;
+ // Menu should always run with vsync on.
+ video_set_nonblock_state_func(false);
+
+ if (driver.audio_data)
+ audio_stop_func();
+
+ menuloop = true;
+ }
+ else
+ {
+ g_extern.system.shutdown = true;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ emscripten_set_canvas_size(800, 600);
+
+ rarch_main_clear_state();
+ rarch_init_msg_queue();
+
+ char *_argv[] = { "retroarch", "--menu", "-v" };
+
+ int init_ret;
+ if ((init_ret = rarch_main_init(3, _argv))) return init_ret;
+
+#ifdef HAVE_MENU
+ menu_init();
+ g_extern.lifecycle_mode_state |= 1ULL << MODE_GAME;
+
+ // If we started a ROM directly from command line,
+ // push it to ROM history.
+ if (!g_extern.libretro_dummy)
+ menu_rom_history_push_current();
+#endif
+
+ emscripten_set_main_loop(mainloop, 0, 0);
+
+ return 0;
+}
diff --git a/gfx/context/emscriptenegl_ctx.c b/gfx/context/emscriptenegl_ctx.c
new file mode 100644
index 0000000000..2674e8bcc6
--- /dev/null
+++ b/gfx/context/emscriptenegl_ctx.c
@@ -0,0 +1,268 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2013 - Hans-Kristian Arntzen
+ * Copyright (C) 2012 - Michael Lelli
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+// VideoCore context, for Rasperry Pi.
+
+#include "../../driver.h"
+#include "../gfx_context.h"
+#include "../gl_common.h"
+#include "../gfx_common.h"
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+static EGLContext g_egl_ctx;
+static EGLSurface g_egl_surf;
+static EGLDisplay g_egl_dpy;
+static EGLConfig g_config;
+static bool g_quit;
+
+static bool g_inited;
+
+static unsigned g_fb_width;
+static unsigned g_fb_height;
+
+static void gfx_ctx_swap_interval(unsigned interval)
+{
+ // no way to control vsync in WebGL
+ (void)interval;
+}
+
+static void gfx_ctx_check_window(bool *quit,
+ bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
+{
+ (void)frame_count;
+ (void)width;
+ (void)height;
+
+ *resize = false;
+ *quit = g_quit;
+}
+
+static void gfx_ctx_swap_buffers(void)
+{
+ eglSwapBuffers(g_egl_dpy, g_egl_surf);
+}
+
+static void gfx_ctx_set_resize(unsigned width, unsigned height)
+{
+ (void)width;
+ (void)height;
+}
+
+static void gfx_ctx_update_window_title(void)
+{
+ char buf[128];
+ gfx_get_fps(buf, sizeof(buf), false);
+}
+
+static void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
+{
+ *width = g_fb_width;
+ *height = g_fb_height;
+}
+
+static void gfx_ctx_destroy(void);
+
+static bool gfx_ctx_init(void)
+{
+ EGLint width;
+ EGLint height;
+
+ RARCH_LOG("[VC/EMSCRIPTEN]: Initializing...\n");
+ if (g_inited)
+ {
+ RARCH_ERR("[VC/EMSCRIPTEN]: Attempted to re-initialize driver.\n");
+ return true;
+ }
+
+ EGLint num_config;
+
+ static const EGLint attribute_list[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE
+ };
+
+ static const EGLint context_attributes[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ // get an EGL display connection
+ g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (!g_egl_dpy)
+ goto error;
+
+ // initialize the EGL display connection
+ if (!eglInitialize(g_egl_dpy, NULL, NULL))
+ goto error;
+
+ // get an appropriate EGL frame buffer configuration
+ if (!eglChooseConfig(g_egl_dpy, attribute_list, &g_config, 1, &num_config))
+ goto error;
+
+ // create an EGL rendering context
+ g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, context_attributes);
+ if (!g_egl_ctx)
+ goto error;
+
+ // create an EGL window surface
+ g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, 0, NULL);
+ if (!g_egl_surf)
+ goto error;
+
+ // connect the context to the surface
+ if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
+ goto error;
+
+ eglQuerySurface(g_egl_dpy, g_egl_surf, EGL_WIDTH, &width);
+ eglQuerySurface(g_egl_dpy, g_egl_surf, EGL_HEIGHT, &height);
+ g_fb_width = width;
+ g_fb_height = height;
+ RARCH_LOG("[VC/EMSCRIPTEN]: Dimensions: %ux%u\n", width, height);
+
+ return true;
+
+error:
+ gfx_ctx_destroy();
+ return false;
+}
+
+static bool gfx_ctx_set_video_mode(
+ unsigned width, unsigned height,
+ bool fullscreen)
+{
+ if (g_inited)
+ return false;
+
+ g_inited = true;
+ return true;
+}
+
+static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
+{
+ switch (api)
+ {
+ case GFX_CTX_OPENGL_ES_API:
+ return eglBindAPI(EGL_OPENGL_ES_API);
+ default:
+ return false;
+ }
+}
+
+static void gfx_ctx_destroy(void)
+{
+ if (g_egl_dpy)
+ {
+ if (g_egl_ctx)
+ {
+ eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(g_egl_dpy, g_egl_ctx);
+ }
+
+ if (g_egl_surf)
+ {
+ eglDestroySurface(g_egl_dpy, g_egl_surf);
+ }
+
+ eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(g_egl_dpy);
+ }
+
+ g_egl_ctx = NULL;
+ g_egl_surf = NULL;
+ g_egl_dpy = NULL;
+ g_config = 0;
+ g_inited = false;
+}
+
+static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
+{
+ *input = NULL;
+
+ if (SDL_Init(SDL_INIT_VIDEO) != 0)
+ return;
+
+ void *sdlinput = input_sdl.init();
+
+ if (sdlinput)
+ {
+ *input = &input_sdl;
+ *input_data = sdlinput;
+ }
+}
+
+static bool gfx_ctx_has_focus(void)
+{
+ return g_inited;
+}
+
+static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
+{
+ return SDL_GL_GetProcAddress(symbol);
+}
+
+static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
+{
+ return (float)width / height;
+}
+
+static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
+{
+ return false;
+}
+
+static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
+{
+ return false;
+}
+
+const gfx_ctx_driver_t gfx_ctx_emscripten = {
+ gfx_ctx_init,
+ gfx_ctx_destroy,
+ gfx_ctx_bind_api,
+ gfx_ctx_swap_interval,
+ gfx_ctx_set_video_mode,
+ gfx_ctx_get_video_size,
+ gfx_ctx_translate_aspect,
+ gfx_ctx_update_window_title,
+ gfx_ctx_check_window,
+ gfx_ctx_set_resize,
+ gfx_ctx_has_focus,
+ gfx_ctx_swap_buffers,
+ gfx_ctx_input_driver,
+ gfx_ctx_get_proc_address,
+ gfx_ctx_init_egl_image_buffer,
+ gfx_ctx_write_egl_image,
+ NULL,
+ "emscripten",
+};
diff --git a/gfx/gfx_context.c b/gfx/gfx_context.c
index 47745ca3f3..ba0aedd0fe 100644
--- a/gfx/gfx_context.c
+++ b/gfx/gfx_context.c
@@ -13,6 +13,7 @@
* If not, see .
*/
+#include "../general.h"
#include "gfx_context.h"
#include
@@ -51,14 +52,17 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
#if defined(IOS) || defined(OSX) //< Don't use __APPLE__ as it breaks basic SDL builds
&gfx_ctx_apple,
#endif
-#if defined(HAVE_SDL) && defined(HAVE_OPENGL)
+#if defined(HAVE_SDL) && defined(HAVE_OPENGL) && !defined(EMSCRIPTEN)
&gfx_ctx_sdl_gl,
#endif
+#ifdef EMSCRIPTEN
+ &gfx_ctx_emscripten,
+#endif
};
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident)
{
- for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(gfx_ctx_drivers); i++)
{
if (strcmp(gfx_ctx_drivers[i]->ident, ident) == 0)
return gfx_ctx_drivers[i];
@@ -69,7 +73,7 @@ const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident)
const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api)
{
- for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(gfx_ctx_drivers); i++)
{
if (gfx_ctx_drivers[i]->bind_api(api))
{
diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h
index fa70e76e73..6e0219f382 100644
--- a/gfx/gfx_context.h
+++ b/gfx/gfx_context.h
@@ -108,6 +108,7 @@ extern const gfx_ctx_driver_t gfx_ctx_wgl;
extern const gfx_ctx_driver_t gfx_ctx_videocore;
extern const gfx_ctx_driver_t gfx_ctx_bbqnx;
extern const gfx_ctx_driver_t gfx_ctx_apple;
+extern const gfx_ctx_driver_t gfx_ctx_emscripten;
extern const gfx_ctx_driver_t gfx_ctx_null;
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize.
diff --git a/input/input_common.c b/input/input_common.c
index 12be6eaf76..e58eede808 100644
--- a/input/input_common.c
+++ b/input/input_common.c
@@ -16,6 +16,7 @@
#include "input_common.h"
#include
#include
+#include
#include "../general.h"
#include "../driver.h"
@@ -47,7 +48,7 @@ static const rarch_joypad_driver_t *joypad_drivers[] = {
#if defined(__linux) && !defined(ANDROID)
&linuxraw_joypad,
#endif
-#ifdef HAVE_SDL
+#if defined(HAVE_SDL) && !defined(EMSCRIPTEN)
&sdl_joypad,
#endif
#endif
diff --git a/input/sdl_input.c b/input/sdl_input.c
index d438c3f8a5..1c332b8396 100644
--- a/input/sdl_input.c
+++ b/input/sdl_input.c
@@ -24,6 +24,10 @@
#include "../libretro.h"
#include "input_common.h"
+#if !(SDL_MAJOR_VERSION <= 1 && SDL_MINOR_VERSION <= 2)
+#define SDL_GetKeyState SDL_GetKeyboardState
+#endif
+
typedef struct sdl_input
{
const rarch_joypad_driver_t *joypad;
@@ -51,9 +55,8 @@ static bool sdl_key_pressed(int key)
int sym = input_translate_rk_to_keysym((enum retro_key)key);
- int num_keys;
+ int num_keys = 0xFFFF;
Uint8 *keymap = SDL_GetKeyState(&num_keys);
- if (sym < 0 || sym >= num_keys)
return false;
return keymap[sym];
@@ -216,16 +219,24 @@ static void sdl_input_free(void *data)
static void sdl_poll_mouse(sdl_input_t *sdl)
{
+ (void)sdl;
+#ifndef EMSCRIPTEN
Uint8 btn = SDL_GetRelativeMouseState(&sdl->mouse_x, &sdl->mouse_y);
SDL_GetMouseState(&sdl->mouse_abs_x, &sdl->mouse_abs_y);
sdl->mouse_l = SDL_BUTTON(SDL_BUTTON_LEFT) & btn ? 1 : 0;
sdl->mouse_r = SDL_BUTTON(SDL_BUTTON_RIGHT) & btn ? 1 : 0;
sdl->mouse_m = SDL_BUTTON(SDL_BUTTON_MIDDLE) & btn ? 1 : 0;
+#endif
}
static void sdl_input_poll(void *data)
{
+#ifdef EMSCRIPTEN
+ SDL_Event event;
+ while (SDL_PollEvent(&event));
+#else
SDL_PumpEvents();
+#endif
sdl_input_t *sdl = (sdl_input_t*)data;
input_joypad_poll(sdl->joypad);
diff --git a/performance.c b/performance.c
index 7829fe265d..faad97135d 100644
--- a/performance.c
+++ b/performance.c
@@ -58,6 +58,10 @@
#include
#endif
+#ifdef EMSCRIPTEN
+#include
+#endif
+
#ifdef PERF_TEST
#define MAX_COUNTERS 64
static struct rarch_perf_counter *perf_counters[MAX_COUNTERS];
@@ -145,6 +149,8 @@ rarch_time_t rarch_get_time_usec(void)
if (clock_gettime(CLOCK_MONOTONIC, &tv) < 0)
return 0;
return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000;
+#elif defined(EMSCRIPTEN)
+ return emscripten_get_now() * 1000;
#else
#error "Your platform does not have a timer function implemented in rarch_get_time_usec(). Cannot continue."
#endif