From af3aef21555dd8099b1d2665e143bf5a21c10f13 Mon Sep 17 00:00:00 2001 From: Boris Gjenero Date: Tue, 6 Dec 2022 00:47:40 -0500 Subject: [PATCH] Use Asyncify by default, as replacement for Emterpreter Sync Emterpreter was removed in Emscripten 1.39.17. The Emterpreter code can run using Asyncify with trivial changes. Since this works well and creates a more fully functioning DOSBox, it is now the default. Use ./configure --disable-asyncify if you don't want it. --- configure.ac | 9 +++++++++ include/dosbox.h | 2 +- src/Makefile.am | 3 +++ src/debug/debug.cpp | 4 +++- src/dos/dos_programs.cpp | 17 +++++++++++------ src/dosbox.cpp | 18 +++++++++++++----- src/gui/sdlmain.cpp | 12 ++++++++---- src/shell/shell_misc.cpp | 2 +- 8 files changed, 49 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index 9faa60415..97593da34 100644 --- a/configure.ac +++ b/configure.ac @@ -630,6 +630,14 @@ AC_ARG_ENABLE( [], [enable_sync=no]) AM_CONDITIONAL([EMTERPRETER], [test "x$enable_sync" != "xno"]) +AH_TEMPLATE([EM_ASYNCIFY],[Compile using Emscripten asyncify.]) +AC_ARG_ENABLE( + [asyncify], + [AC_HELP_STRING([--disable-asyncify], + [Disable Emscripten asyncify])], + [], [enable_asyncify=yes]) +AM_CONDITIONAL([ASYNCIFY], [test "x$enable_asyncify" != "xno"]) + AC_ARG_ENABLE( [wasm], [AC_HELP_STRING([--disable-wasm], @@ -641,6 +649,7 @@ AM_CONDITIONAL([WEBASSEMBLY], [test "x$enable_wasm" == "xyes"]) # host compiler, so those flags are set at the end. AS_IF([test "x$enable_emscripten" = "xyes"],[ AS_IF([test "x$enable_sync" != "xno"], [AC_DEFINE([EMTERPRETER_SYNC],[1])]) + AS_IF([test "x$enable_asyncify" != "xno"], [AC_DEFINE([EM_ASYNCIFY],[1])]) AS_IF([test "x$with_sdl2" != "xno"],[ AS_IF([test "x$with_sdl2" = "xyes"], [CXXFLAGS="$CXXFLAGS -s USE_SDL=2"], diff --git a/include/dosbox.h b/include/dosbox.h index ed3aa33a2..ee5c847b8 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -36,7 +36,7 @@ class Section; typedef Bitu (LoopHandler)(void); void DOSBOX_RunMachine(); -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) /* This is for cases where RunMachine is called from code not using * emterpreter. There, emscripten_sleep() is prohibited and emulation * will be aborted with a timeout error if this takes too long. diff --git a/src/Makefile.am b/src/Makefile.am index 1b0077121..6f1dcd5c3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,9 @@ else # Memory init file is huge and it doesn't save bandwith even if using gzip. # It is only required when using emterpreter. dosbox_LDFLAGS+=--memory-init-file 0 +if ASYNCIFY +dosbox_LDFLAGS+=-s ASYNCIFY=1 -s FETCH=1 +endif endif if WEBASSEMBLY dosbox_LDFLAGS+=-s WASM=1 diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index fd488603f..7bbeff2b3 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -27,7 +27,7 @@ #include #include #include -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) #include #endif using namespace std; @@ -1826,6 +1826,8 @@ Bitu DEBUG_Loop(void) { #if defined(EMSCRIPTEN) #if defined(EMTERPRETER_SYNC) emscripten_sleep_with_yield(1); +#elif defined(EM_ASYNCIFY) + emscripten_sleep(1); #endif #else SDL_Delay(1); diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 9245ae15c..eaeeaa230 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -23,7 +23,7 @@ #include #include #include -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) #include #include #include "dos_inc.h" @@ -1535,7 +1535,7 @@ static void KEYB_ProgramStart(Program * * make) { *make=new KEYB; } -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) class WGET : public Program { public: void Run(void); @@ -1598,7 +1598,12 @@ void WGET::Run(void) { attr.onerror = downloadFailed; fetchdone = false; emscripten_fetch_t *fetch = emscripten_fetch(&attr, url.c_str()); - while (!fetchdone) emscripten_sleep_with_yield(10); + while (!fetchdone) +#ifdef EMTERPRETER_SYNC + emscripten_sleep_with_yield(10); +#elif defined(EM_ASYNCIFY) + emscripten_sleep(10); +#endif if (fetchsuccess) { Bit16u fhandle; if (!DOS_CreateFile(outname.c_str(),OPEN_WRITE,&fhandle)) { @@ -1640,7 +1645,7 @@ void WGET::Run(void) { static void WGET_ProgramStart(Program * * make) { *make=new WGET; } -#endif // defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#endif // defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) void DOS_SetupPrograms(void) { /*Add Messages */ @@ -1863,7 +1868,7 @@ void DOS_SetupPrograms(void) { MSG_Add("PROGRAM_KEYB_INVALIDFILE","Keyboard file %s invalid\n"); MSG_Add("PROGRAM_KEYB_LAYOUTNOTFOUND","No layout in %s for codepage %i\n"); MSG_Add("PROGRAM_KEYB_INVCPFILE","None or invalid codepage file for layout %s\n\n"); -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) MSG_Add("PROGRAM_WGET_SHOWHELP", "\033[32;1mWGET\033[0m [-o FILENAME] URL\n\n" "Downloads file from URL and saves it to the file system.\n" @@ -1887,7 +1892,7 @@ void DOS_SetupPrograms(void) { PROGRAMS_MakeFile("LOADROM.COM", LOADROM_ProgramStart); PROGRAMS_MakeFile("IMGMOUNT.COM", IMGMOUNT_ProgramStart); PROGRAMS_MakeFile("KEYB.COM", KEYB_ProgramStart); -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && (defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY)) PROGRAMS_MakeFile("WGET.COM", WGET_ProgramStart); #endif } diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 328ab36c2..f18f99fd3 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -137,7 +137,7 @@ Bit32u ticksScheduled; bool ticksLocked; #ifdef EMSCRIPTEN -#ifdef EMTERPRETER_SYNC +#if defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) int nosleep_lock = 0; #else static int runcount = 0; @@ -148,7 +148,7 @@ static Bitu Normal_Loop(void) { Bits ret; #ifdef EMSCRIPTEN int ticksEntry = GetTicks(); -#ifdef EMTERPRETER_SYNC +#if defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) /* Normal DOSBox is free to use up all available host CPU time, but * in a browser, sleep has to happen regularly so the screen is updated, * sound isn't interrupted, and the script does not appear to hang. @@ -158,7 +158,11 @@ static Bitu Normal_Loop(void) { if (SDL_TICKS_PASSED(ticksEntry, last_sleep + 10)) { if (nosleep_lock == 0) { last_sleep = ticksEntry; +#ifdef EMTERPRETER_SYNC emscripten_sleep_with_yield(1); +#elif defined(EM_ASYNCIFY) + emscripten_sleep(1); +#endif ticksEntry = GetTicks(); } else if (SDL_TICKS_PASSED(ticksEntry, last_sleep + 2000) && !SDL_TICKS_PASSED(ticksEntry, last_loop + 200)) { @@ -360,10 +364,14 @@ static Bitu Normal_Loop(void) { ticksAdded = 0; #ifndef EMSCRIPTEN SDL_Delay(1); -#elif defined(EMTERPRETER_SYNC) +#elif defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) if (nosleep_lock == 0) { last_sleep = ticksNew; +#ifdef EMTERPRETER_SYNC emscripten_sleep_with_yield(1); +#elif defined(EM_ASYNCIFY) + emscripten_sleep(1); +#endif } #endif ticksDone -= GetTicks() - ticksNew; @@ -417,7 +425,7 @@ static void em_main_loop(void) { #endif void DOSBOX_RunMachine(void){ -#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) && !defined(EM_ASYNCIFY) if (runcount == 0) { runcount = 1; } else if (runcount == 1) { @@ -434,7 +442,7 @@ void DOSBOX_RunMachine(void){ Bitu ret; do { ret=(*loop)(); -#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) && !defined(EM_ASYNCIFY) /* These should be very short operations, like interrupts. * Anything taking a long time will probably run indefinitely, * making DOSBox appear to hang. diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 88d888756..9bfa968bb 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -427,7 +427,7 @@ static Bitu Pause_Loop(void) { } } } -#ifdef EMTERPRETER_SYNC +#if defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) emscripten_sleep(10); #endif return 0; @@ -2027,7 +2027,7 @@ static void GUI_StartUp(Section * sec) { * The splash screen requires emterpreter sync. * Creating a 2D context prevents subsequent creation of a 3D context. */ -#if !defined(EMSCRIPTEN) || defined(EMTERPRETER_SYNC) +#if !defined(EMSCRIPTEN) || defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) /* Please leave the Splash screen stuff in working order in DOSBox. We spend a lot of time making DOSBox. */ SDL_Surface* splash_surf = NULL; #ifdef EMSCRIPTEN @@ -2080,8 +2080,12 @@ static void GUI_StartUp(Section * sec) { } } if (exit_splash) break; -#if defined(EMSCRIPTEN) && defined(EMTERPRETER_SYNC) +#ifdef EMSCRIPTEN +#ifdef EMTERPRETER_SYNC emscripten_sleep_with_yield(1); +#elif defined(EM_ASYNCIFY) + emscripten_sleep(1); +#endif #endif if (ct<1) { @@ -2136,7 +2140,7 @@ static void GUI_StartUp(Section * sec) { delete [] tmpbufp; } -#endif // !defined(EMSCRIPTEN) || defined(EMTERPRETER_SYNC) +#endif // !defined(EMSCRIPTEN) || defined(EMTERPRETER_SYNC) || defined(EM_ASYNCIFY) /* Get some Event handlers */ MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown"); MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse"); diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 8111438cd..dc312fb33 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -40,7 +40,7 @@ static void outc(Bit8u c) { } void DOS_Shell::InputCommand(char * line) { -#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) +#if defined(EMSCRIPTEN) && !defined(EMTERPRETER_SYNC) && !defined(EM_ASYNCIFY) if (!strcmp(Files[input_handle]->name, "CON")) { // This can be called during startup, before main loop being used. LOG_MSG("Emulation ended because interactive shell is not supported.");