From fb5dcb4f8b69283d662155b6e1a3257f87aade65 Mon Sep 17 00:00:00 2001
From: Richard Janicek <r@janicek.co>
Date: Thu, 11 Jul 2013 00:36:10 -0400
Subject: [PATCH] Vice 2.4.4 Emscripten changes.

---
 configure.ac                             |  59 +++++-----
 configure.proto                          |  59 +++++-----
 src/arch/sdl/emscripten/coroutine.h      | 181 +++++++++++++++++++++++++++++++
 src/arch/sdl/emscripten/sdl_emscripten.h |   3 +
 src/arch/sdl/kbd.c                       |   4 +-
 src/arch/sdl/menu_help.c                 |   6 +-
 src/arch/sdl/ui.c                        |   4 +-
 src/arch/sdl/video.c                     |  10 +-
 src/arch/sdl/vsyncarch.c                 |  24 +++-
 src/main.c                               |   8 ++
 src/maincpu.c                            |  30 ++++-
 src/opencbm.h                            |   5 +
 src/vice_sdl.h                           |   2 +-
 13 files changed, 322 insertions(+), 73 deletions(-)
 create mode 100644 src/arch/sdl/emscripten/coroutine.h
 create mode 100644 src/arch/sdl/emscripten/sdl_emscripten.h

diff --git a/configure.ac b/configure.ac
index 6be2f83..40a892d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1860,30 +1860,33 @@ if test x"$with_sdlsound" = "xyes" -o x"$enable_sdlui" = "xyes"; then
             LIBS="$LIBS `$sdl_config --libs`"
         fi
 
-
-        AC_CHECK_HEADERS(SDL/SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
-                         [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
-                          use_sdl_prefix=yes;
-                          AC_DEFINE(USE_SDL_PREFIX,,[Enable SDL prefix for header inclusion.])
-                          AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
-                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
-                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
-
-        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
-            unset ac_cv_lib_SDL_SDL_OpenAudio
-            AC_CHECK_HEADERS(SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
-                             [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
-                              use_sdl_prefix=no;
-                              AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
-                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
-                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
-        fi
-
-        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
-            with_sdlsound=no
-        else
+      SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+      use_sdl_prefix=no;
+      AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])
+
+dnl        AC_CHECK_HEADERS(SDL/SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
+dnl                         [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+dnl                          use_sdl_prefix=yes;
+dnl                          AC_DEFINE(USE_SDL_PREFIX,,[Enable SDL prefix for header inclusion.])
+dnl                          AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
+dnl                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
+dnl                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
+
+dnl        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
+dnl            unset ac_cv_lib_SDL_SDL_OpenAudio
+dnl            AC_CHECK_HEADERS(SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
+dnl                             [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+dnl                              use_sdl_prefix=no;
+dnl                              AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
+dnl                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
+dnl                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
+dnl        fi
+
+dnl        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
+dnl            with_sdlsound=no
+dnl        else
             SOUND_LIBS="$SOUND_LIBS $EXTRA_SDL_LIBS"
-        fi
+dnl        fi
 
         if test x"$enable_sdlui" = "xyes"; then
             AC_CHECK_HEADERS(SDL/SDL.h,[AC_CHECK_LIB(SDL, SDL_SetVideoMode,
@@ -1902,11 +1905,11 @@ if test x"$with_sdlsound" = "xyes" -o x"$enable_sdlui" = "xyes"; then
                                  [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
             fi
 
-            if test x"$ac_cv_lib_SDL_SDL_SetVideoMode" != "xyes"; then
-                AC_MSG_ERROR([SDL headers and/or libraries missing])
-            else
-                AC_DEFINE(HAVE_FULLSCREEN,,[Enable Fullscreen support.])
-            fi
+dnl            if test x"$ac_cv_lib_SDL_SDL_SetVideoMode" != "xyes"; then
+dnl                AC_MSG_ERROR([SDL headers and/or libraries missing!])
+dnl            else
+                   AC_DEFINE(HAVE_FULLSCREEN,,[Enable Fullscreen support.])
+dnl            fi
 
             if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
                 LIBS="$LIBS $EXTRA_SDL_LIBS"
diff --git a/configure.proto b/configure.proto
index 6be2f83..40a892d 100644
--- a/configure.proto
+++ b/configure.proto
@@ -1860,30 +1860,33 @@ if test x"$with_sdlsound" = "xyes" -o x"$enable_sdlui" = "xyes"; then
             LIBS="$LIBS `$sdl_config --libs`"
         fi
 
-
-        AC_CHECK_HEADERS(SDL/SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
-                         [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
-                          use_sdl_prefix=yes;
-                          AC_DEFINE(USE_SDL_PREFIX,,[Enable SDL prefix for header inclusion.])
-                          AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
-                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
-                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
-
-        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
-            unset ac_cv_lib_SDL_SDL_OpenAudio
-            AC_CHECK_HEADERS(SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
-                             [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
-                              use_sdl_prefix=no;
-                              AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
-                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
-                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
-        fi
-
-        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
-            with_sdlsound=no
-        else
+      SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+      use_sdl_prefix=no;
+      AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])
+
+dnl        AC_CHECK_HEADERS(SDL/SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
+dnl                         [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+dnl                          use_sdl_prefix=yes;
+dnl                          AC_DEFINE(USE_SDL_PREFIX,,[Enable SDL prefix for header inclusion.])
+dnl                          AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
+dnl                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
+dnl                         [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
+
+dnl        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
+dnl            unset ac_cv_lib_SDL_SDL_OpenAudio
+dnl            AC_CHECK_HEADERS(SDL_audio.h,[AC_CHECK_LIB(SDL, SDL_OpenAudio,
+dnl                             [SOUND_DRIVERS="$SOUND_DRIVERS soundsdl.o";
+dnl                              use_sdl_prefix=no;
+dnl                              AC_DEFINE(USE_SDL_AUDIO,,[Enable SDL sound support.])],
+dnl                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break],$SOUND_LIBS $EXTRA_SDL_LIBS)],
+dnl                             [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
+dnl        fi
+
+dnl        if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
+dnl            with_sdlsound=no
+dnl        else
             SOUND_LIBS="$SOUND_LIBS $EXTRA_SDL_LIBS"
-        fi
+dnl        fi
 
         if test x"$enable_sdlui" = "xyes"; then
             AC_CHECK_HEADERS(SDL/SDL.h,[AC_CHECK_LIB(SDL, SDL_SetVideoMode,
@@ -1902,11 +1905,11 @@ if test x"$with_sdlsound" = "xyes" -o x"$enable_sdlui" = "xyes"; then
                                  [CFLAGS=$old_cflags; CXXFLAGS=$old_cxxflags; LIBS=$old_libs; break])
             fi
 
-            if test x"$ac_cv_lib_SDL_SDL_SetVideoMode" != "xyes"; then
-                AC_MSG_ERROR([SDL headers and/or libraries missing])
-            else
-                AC_DEFINE(HAVE_FULLSCREEN,,[Enable Fullscreen support.])
-            fi
+dnl            if test x"$ac_cv_lib_SDL_SDL_SetVideoMode" != "xyes"; then
+dnl                AC_MSG_ERROR([SDL headers and/or libraries missing!])
+dnl            else
+                   AC_DEFINE(HAVE_FULLSCREEN,,[Enable Fullscreen support.])
+dnl            fi
 
             if test x"$ac_cv_lib_SDL_SDL_OpenAudio" != "xyes"; then
                 LIBS="$LIBS $EXTRA_SDL_LIBS"
diff --git a/src/arch/sdl/emscripten/coroutine.h b/src/arch/sdl/emscripten/coroutine.h
new file mode 100644
index 0000000..d54a718
--- /dev/null
+++ b/src/arch/sdl/emscripten/coroutine.h
@@ -0,0 +1,181 @@
+/* coroutine.h
+ * 
+ * Coroutine mechanics, implemented on top of standard ANSI C. See
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html for
+ * a full discussion of the theory behind this.
+ * 
+ * To use these macros to define a coroutine, you need to write a
+ * function that looks something like this.
+ * 
+ * [Simple version using static variables (scr macros)]
+ * int ascending (void) {
+ *    static int i;
+ * 
+ *    scrBegin;
+ *    for (i=0; i<10; i++) {
+ *       scrReturn(i);
+ *    }
+ *    scrFinish(-1);
+ * }
+ * 
+ * [Re-entrant version using an explicit context structure (ccr macros)]
+ * int ascending (ccrContParam) {
+ *    ccrBeginContext;
+ *    int i;
+ *    ccrEndContext(foo);
+ *
+ *    ccrBegin(foo);
+ *    for (foo->i=0; foo->i<10; foo->i++) {
+ *       ccrReturn(foo->i);
+ *    }
+ *    ccrFinish(-1);
+ * }
+ * 
+ * In the static version, you need only surround the function body
+ * with `scrBegin' and `scrFinish', and then you can do `scrReturn'
+ * within the function and on the next call control will resume
+ * just after the scrReturn statement. Any local variables you need
+ * to be persistent across an `scrReturn' must be declared static.
+ * 
+ * In the re-entrant version, you need to declare your persistent
+ * variables between `ccrBeginContext' and `ccrEndContext'. These
+ * will be members of a structure whose name you specify in the
+ * parameter to `ccrEndContext'.
+ * 
+ * The re-entrant macros will malloc() the state structure on first
+ * call, and free() it when `ccrFinish' is reached. If you want to
+ * abort in the middle, you can use `ccrStop' to free the state
+ * structure immediately (equivalent to an explicit return() in a
+ * caller-type routine).
+ * 
+ * A coroutine returning void type may call `ccrReturnV',
+ * `ccrFinishV' and `ccrStopV', or `scrReturnV', to avoid having to
+ * specify an empty parameter to the ordinary return macros.
+ * 
+ * Ground rules:
+ *  - never put `ccrReturn' or `scrReturn' within an explicit `switch'.
+ *  - never put two `ccrReturn' or `scrReturn' statements on the same
+ *    source line.
+ * 
+ * The caller of a static coroutine calls it just as if it were an
+ * ordinary function:
+ * 
+ * void main(void) {
+ *    int i;
+ *    do {
+ *       i = ascending();
+ *       printf("got number %d\n", i);
+ *    } while (i != -1);
+ * }
+ * 
+ * The caller of a re-entrant coroutine must provide a context
+ * variable:
+ * 
+ * void main(void) {
+ *    ccrContext z = 0;
+ *    do {
+ *       printf("got number %d\n", ascending (&z));
+ *    } while (z);
+ * }
+ * 
+ * Note that the context variable is set back to zero when the
+ * coroutine terminates (by crStop, or by control reaching
+ * crFinish). This can make the re-entrant coroutines more useful
+ * than the static ones, because you can tell when they have
+ * finished.
+ * 
+ * If you need to dispose of a crContext when it is non-zero (that
+ * is, if you want to stop calling a coroutine without suffering a
+ * memory leak), the caller should call `ccrAbort(ctx)' where `ctx'
+ * is the context variable.
+ * 
+ * This mechanism could have been better implemented using GNU C
+ * and its ability to store pointers to labels, but sadly this is
+ * not part of the ANSI C standard and so the mechanism is done by
+ * case statements instead. That's why you can't put a crReturn()
+ * inside a switch() statement.
+ */
+
+/*
+ * coroutine.h is copyright 1995,2000 Simon Tatham.
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ * $Id$
+ */
+
+#ifndef COROUTINE_H
+#define COROUTINE_H
+
+#include <stdlib.h>
+
+/*
+ * `scr' macros for static coroutines.
+ */
+
+#define scrBegin         static int scrLine = 0; switch(scrLine) { case 0:;
+#define scrFinish(z)     } return (z)
+#define scrFinishV       } return
+
+#define scrReturn(z)     \
+        do {\
+            scrLine=__LINE__;\
+            return (z); case __LINE__:;\
+        } while (0)
+#define scrReturnV       \
+        do {\
+            scrLine=__LINE__;\
+            return; case __LINE__:;\
+        } while (0)
+
+/*
+ * `ccr' macros for re-entrant coroutines.
+ */
+
+#define ccrContParam     void **ccrParam
+
+#define ccrBeginContext  struct ccrContextTag { int ccrLine
+#define ccrEndContext(x) } *x = (struct ccrContextTag *)*ccrParam
+
+#define ccrBegin(x)      if(!x) {x= *ccrParam=malloc(sizeof(*x)); x->ccrLine=0;}\
+                         if (x) switch(x->ccrLine) { case 0:;
+#define ccrFinish(z)     } free(*ccrParam); *ccrParam=0; return (z)
+#define ccrFinishV       } free(*ccrParam); *ccrParam=0; return
+
+#define ccrReturn(z)     \
+        do {\
+            ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\
+            return (z); case __LINE__:;\
+        } while (0)
+#define ccrReturnV       \
+        do {\
+            ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\
+            return; case __LINE__:;\
+        } while (0)
+
+#define ccrStop(z)       do{ free(*ccrParam); *ccrParam=0; return (z); }while(0)
+#define ccrStopV         do{ free(*ccrParam); *ccrParam=0; return; }while(0)
+
+#define ccrContext       void *
+#define ccrAbort(ctx)    do { free (ctx); ctx = 0; } while (0)
+
+#endif /* COROUTINE_H */
diff --git a/src/arch/sdl/emscripten/sdl_emscripten.h b/src/arch/sdl/emscripten/sdl_emscripten.h
new file mode 100644
index 0000000..ad444d4
--- /dev/null
+++ b/src/arch/sdl/emscripten/sdl_emscripten.h
@@ -0,0 +1,3 @@
+#define EMSCRIPTEN_SYNC 0
+
+extern void vice_blocking_delay(Uint32 delay);
diff --git a/src/arch/sdl/kbd.c b/src/arch/sdl/kbd.c
index ecf4335..9efc01c 100644
--- a/src/arch/sdl/kbd.c
+++ b/src/arch/sdl/kbd.c
@@ -61,7 +61,7 @@ int sdl_ui_menukeys[MENU_ACTION_NUM];
 
 /* UI hotkeys: index is the key(combo), value is a pointer to the menu item.
    4 is the number of the supported modifiers: shift, alt, control, meta. */
-#define SDLKBD_UI_HOTKEYS_MAX (SDLK_LAST * (1 << 4))
+#define SDLKBD_UI_HOTKEYS_MAX (SDL_NUM_SCANCODES * (1 << 4))
 ui_menu_entry_t *sdlkbd_ui_hotkeys[SDLKBD_UI_HOTKEYS_MAX];
 
 /* ------------------------------------------------------------------------ */
@@ -130,7 +130,7 @@ static inline int sdlkbd_key_mod_to_index(SDLKey key, SDLMod mod)
             i |= (1 << 3);
         }
     }
-    return i * SDLK_LAST + key;
+    return i * SDL_NUM_SCANCODES + key;
 }
 
 ui_menu_entry_t *sdlkbd_get_hotkey(SDLKey key, SDLMod mod)
diff --git a/src/arch/sdl/menu_help.c b/src/arch/sdl/menu_help.c
index 1d12a05..2b2a986 100644
--- a/src/arch/sdl/menu_help.c
+++ b/src/arch/sdl/menu_help.c
@@ -424,11 +424,11 @@ static UI_MENU_CALLBACK(license_callback)
 #endif
         } else {
 #ifdef WINMIPS
-            new_text = concat_all(info_license_text40);
+            new_text = concat_all(info_license_text);
             show_text(new_text);
             lib_free(new_text);
 #else
-            show_text(info_license_text40);
+            show_text(info_license_text);
 #endif
         }
     }
@@ -444,7 +444,7 @@ static UI_MENU_CALLBACK(warranty_callback)
         if (menu_draw->max_text_x > 60) {
             show_text(info_warranty_text);
         } else {
-            show_text(info_warranty_text40);
+            show_text(info_warranty_text);
         }
     }
     return NULL;
diff --git a/src/arch/sdl/ui.c b/src/arch/sdl/ui.c
index c7a05d7..87e17c3 100644
--- a/src/arch/sdl/ui.c
+++ b/src/arch/sdl/ui.c
@@ -440,9 +440,9 @@ ui_menu_action_t ui_dispatch_events(void)
                 }
                 break;
             default:
-                SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
+//                SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
                 ui_handle_misc_sdl_event(e);
-                SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
+//                SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
                 break;
         }
         /* When using the menu or vkbd, pass every meaningful event to the caller */
diff --git a/src/arch/sdl/video.c b/src/arch/sdl/video.c
index 49802f5..fc24dcf 100644
--- a/src/arch/sdl/video.c
+++ b/src/arch/sdl/video.c
@@ -615,7 +615,7 @@ static video_canvas_t *sdl_canvas_create(video_canvas_t *canvas, unsigned int *w
 
     if (canvas == sdl_active_canvas) {
 #ifndef ANDROID_COMPILE
-        SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
+//        SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
 #endif
 #ifndef HAVE_HWSCALE
         new_screen = SDL_SetVideoMode(actual_width, actual_height, sdl_bitdepth, flags);
@@ -654,9 +654,7 @@ static video_canvas_t *sdl_canvas_create(video_canvas_t *canvas, unsigned int *w
             }
         }
 #endif
-#ifndef ANDROID_COMPILE
-        SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
-#endif
+//        SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
     } else {
 #ifdef HAVE_HWSCALE
         /* free the old hwscale screen when hwscaled screen is switched away */
@@ -927,11 +925,11 @@ static void sdl_video_resize(unsigned int w, unsigned int h)
         }
 
 #ifndef ANDROID_COMPILE
-        SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
+//        SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
 #endif
         sdl_active_canvas->hwscale_screen = SDL_SetVideoMode((int)w, (int)h, sdl_bitdepth, flags);
 #ifndef ANDROID_COMPILE
-        SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
+//        SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
 #endif
 
 #ifdef SDL_DEBUG
diff --git a/src/arch/sdl/vsyncarch.c b/src/arch/sdl/vsyncarch.c
index 3de9de6..a8b6308 100644
--- a/src/arch/sdl/vsyncarch.c
+++ b/src/arch/sdl/vsyncarch.c
@@ -43,6 +43,11 @@
 
 #include "vice_sdl.h"
 
+#ifdef EMSCRIPTEN
+    #include <emscripten.h>
+    #include "emscripten/sdl_emscripten.h"
+#endif
+
 /* ------------------------------------------------------------------------- */
 
 /* SDL_Delay & GetTicks have 1ms resolution, while VICE needs 1us */
@@ -74,10 +79,27 @@ void vsyncarch_display_speed(double speed, double frame_rate, int warp_enabled)
     ui_display_speed((float)speed, (float)frame_rate, warp_enabled);
 }
 
+#ifdef EMSCRIPTEN
+/* Wrap the resume main loop function to prevent a pointer cast making it safe for asm.js */
+void emscripten_resume_main_loop_wrapper(void *arg) 
+{
+    emscripten_resume_main_loop();
+}
+#endif
+
 /* Sleep a number of timer units. */
 void vsyncarch_sleep(signed long delay)
 {
-    SDL_Delay(delay / VICE_SDL_TICKS_SCALE);
+#ifdef EMSCRIPTEN
+# if EMSCRIPTEN_SYNC
+    vice_blocking_delay(delay/VICE_SDL_TICKS_SCALE);
+# else    
+    emscripten_pause_main_loop();
+    emscripten_async_call(emscripten_resume_main_loop_wrapper, NULL, delay/VICE_SDL_TICKS_SCALE);
+# endif
+#else    
+    SDL_Delay(delay/VICE_SDL_TICKS_SCALE);
+#endif
 }
 
 void vsyncarch_presync(void)
diff --git a/src/main.c b/src/main.c
index 5e33fc9..4d9ebd4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -73,6 +73,9 @@
 #include "svnversion.h"
 #endif
 
+#ifdef EMSCRIPTEN
+    #include <emscripten.h>
+#endif
 #ifdef DEBUG_MAIN
 #define DBG(x)  printf x
 #else
@@ -250,7 +253,12 @@ int main_program(int argc, char **argv)
 
     /* Let's go...  */
     log_message(LOG_DEFAULT, "Main CPU: starting at ($FFFC).");
+
+#ifdef EMSCRIPTEN
+    emscripten_set_main_loop(maincpu_mainloop, 0, 0);
+#else
     maincpu_mainloop();
+#endif    
 
     log_error(LOG_DEFAULT, "perkele!");
 
diff --git a/src/maincpu.c b/src/maincpu.c
index 02e3c24..026e3aa 100644
--- a/src/maincpu.c
+++ b/src/maincpu.c
@@ -48,6 +48,12 @@
 #include "traps.h"
 #include "types.h"
 
+#ifdef EMSCRIPTEN
+    #include "arch/sdl/emscripten/coroutine.h"
+    #include "vsync.h"
+#endif
+
+
 /* MACHINE_STUFF should define/undef
 
  - NEED_REG_PC
@@ -393,8 +399,6 @@ void maincpu_resync_limits(void)
     }
 }
 
-void maincpu_mainloop(void)
-{
 #ifndef C64DTV
     /* Notice that using a struct for these would make it a lot slower (at
        least, on gcc 2.7.2.x).  */
@@ -444,6 +448,12 @@ void maincpu_mainloop(void)
     int bank_start = 0;
     int bank_limit = 0;
 
+void maincpu_mainloop(void)
+{
+#ifdef EMSCRIPTEN
+    scrBegin;
+#endif    
+    
     o_bank_base = &bank_base;
     o_bank_start = &bank_start;
     o_bank_limit = &bank_limit;
@@ -451,6 +461,14 @@ void maincpu_mainloop(void)
     machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
 
     while (1) {
+
+#ifdef EMSCRIPTEN    
+        /* Loop until next frame */
+        int startFrame = vsync_frame_counter;
+        while (vsync_frame_counter == startFrame) {
+#endif
+
+
 #define CLK maincpu_clk
 #define RMW_FLAG maincpu_rmw_flag
 #define LAST_OPCODE_INFO last_opcode_info
@@ -504,9 +522,17 @@ void maincpu_mainloop(void)
 #if 0
         if (CLK > 246171754) {
             debug.maincpu_traceflg = 1;
+#endif
+
+#ifdef EMSCRIPTEN    
         }
+    scrReturnV;
 #endif
     }
+
+#ifdef EMSCRIPTEN    
+    scrFinishV;
+#endif    
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/src/opencbm.h b/src/opencbm.h
index dda9b3c..7422608 100644
--- a/src/opencbm.h
+++ b/src/opencbm.h
@@ -116,6 +116,11 @@ typedef unsigned char __u_char;
 #ifdef __CYGWIN32__
 typedef unsigned char __u_char;
 #endif
+
+#ifdef EMSCRIPTEN
+typedef unsigned char __u_char;
+#endif
+
 #endif
 
 /* specifiers for the IEC bus lines */
diff --git a/src/vice_sdl.h b/src/vice_sdl.h
index b66b369..dff728e 100644
--- a/src/vice_sdl.h
+++ b/src/vice_sdl.h
@@ -57,7 +57,7 @@
 #  endif
 #else
 #  include <SDL.h>
-#  include <SDL_keysym.h>
+#  include <SDL_keycode.h>
 #  ifdef INCLUDE_SDL_SYSWM_H
 #    include <SDL_syswm.h>
 #  endif
-- 
1.8.3.msysgit.0

