The Legend of Edgar 1.38 (94d76eb) for fredygames.com (GPL-2.0-or-later, like the game). Every change is active only when building with Emscripten (__EMSCRIPTEN__): - init.c: the game never goes fullscreen (the page has its own fullscreen button), so the option and the fullscreen key do nothing; - draw.c: delay() hands the turn back to the browser (emscripten_sleep(0)) when a frame is late; the build uses Asyncify and SDL_Delay already yields otherwise; - main.c: fredygames_save(), which the page calls when the tab is hidden or closed: the settings (volumes, controls) are only written when the game exits; - system/error.c: the error screen is drawn once and the runtime stops (it cannot sleep in a loop); - system/load_save.c: the browser has no user database, so the saves directory is /home/web_user/.parallelrealities (the page keeps it in IndexedDB). diff -ruN a/src/draw.c b/src/draw.c --- a/src/draw.c 2026-02-09 19:38:22.000000000 -0300 +++ b/src/draw.c 2026-11-01 19:23:13.063741886 -0300 @@ -19,6 +19,10 @@ #include "headers.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "credits.h" #include "dialog.h" #include "entity.h" @@ -231,6 +235,10 @@ if (frameLimit < ticks) { +#ifdef __EMSCRIPTEN__ + /* Late frame: still give the browser a turn (the build uses Asyncify) */ + emscripten_sleep(0); +#endif return; } diff -ruN a/src/init.c b/src/init.c --- a/src/init.c 2026-02-09 19:38:22.000000000 -0300 +++ b/src/init.c 2026-11-01 19:22:57.318568550 -0300 @@ -29,6 +29,10 @@ #include "system/record.h" #include "system/resources.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + extern Game game; void init(char *title, int joystickNum) @@ -66,6 +70,11 @@ loadConfig(); +#ifdef __EMSCRIPTEN__ + /* The page has its own fullscreen button */ + game.fullscreen = FALSE; +#endif + if (game.fullscreen == TRUE) { windowFlags |= SDL_WINDOW_FULLSCREEN; @@ -148,6 +157,9 @@ void toggleFullScreen() { +#ifdef __EMSCRIPTEN__ + return; +#endif long fullScreen = SDL_GetWindowFlags(game.window) & SDL_WINDOW_FULLSCREEN; fullScreen ^= SDL_WINDOW_FULLSCREEN; diff -ruN a/src/main.c b/src/main.c --- a/src/main.c 2026-02-09 19:38:22.000000000 -0300 +++ b/src/main.c 2026-11-01 20:08:53.755376406 -0300 @@ -45,6 +45,17 @@ #include "system/resources.h" #include "title.h" +#ifdef __EMSCRIPTEN__ +#include + +/* Called by the page when the tab is hidden or closed: the settings (volumes, controls) are only + written when the game exits */ +EMSCRIPTEN_KEEPALIVE void fredygames_save(void) +{ + saveConfig(); +} +#endif + Input input, menuInput; Entity *self; Game game; diff -ruN a/src/system/error.c b/src/system/error.c --- a/src/system/error.c 2026-02-09 19:38:22.000000000 -0300 +++ b/src/system/error.c 2026-11-01 19:24:50.618037207 -0300 @@ -19,6 +19,10 @@ #include "../headers.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "../audio/music.h" #include "../graphics/font.h" #include "../graphics/graphics.h" @@ -144,6 +148,14 @@ static void drawError() { +#ifdef __EMSCRIPTEN__ + /* Show the error screen once and stop: the page keeps the last frame (Asyncify cannot sleep here) */ + clearScreen(0, 0, 0); + SDL_RenderCopy(game.renderer, game.tempSurface->texture, NULL, NULL); + SDL_RenderPresent(game.renderer); + emscripten_exit_with_live_runtime(); +#endif + do { getInput(game.gameType); diff -ruN a/src/system/load_save.c b/src/system/load_save.c --- a/src/system/load_save.c 2026-02-09 19:38:22.000000000 -0300 +++ b/src/system/load_save.c 2026-11-01 20:00:52.960731185 -0300 @@ -67,6 +67,11 @@ #endif struct passwd *pass; +#ifdef __EMSCRIPTEN__ + /* The browser has no user database: the page mounts the saves under this directory */ + (void)pass; + userHome = "/home/web_user"; +#else pass = getpwuid(geteuid()); if (pass == NULL) @@ -77,6 +82,7 @@ } userHome = pass->pw_dir; +#endif #if MACOS == 1 SNPRINTF(dir, sizeof(dir), "%s/Library/Application Support", userHome);