The Makefile's platform=emscripten target has been broken for years but is structurally intact. I got it building and running as a libretro core inside EmulatorJS — first known working Flycast WASM build.
Demo video: https://www.youtube.com/watch?v=VAGoy-kjqYA
Repo with all patches and full build guide: https://github.com/nasomers/flycast-wasm
Makefile issues
HOST_CPU_FLAGS override fails — GNU Make $(filter) returns empty when HOST_CPU_FLAGS is unset, causing the conditional to fall through. The emscripten block never sets HOST_CPU_FLAGS, so TARGET_NO_REC and HAVE_GENERIC_JIT are never applied.
- Missing
-s USE_ZLIB=1 — Emscripten provides zlib via ports, but the emscripten block doesn't enable it.
-fexceptions needed — Flycast uses C++ exceptions but the emscripten block doesn't enable them.
- OpenMP flags leak into emscripten builds (not supported by Emscripten).
Source issues
core/rend/gles/gles.cpp — glGetString(GL_VERSION) returns garbage in WASM (browser returns WebGL version string, not GLES). Flycast parses this to detect GLES3 and falls back to desktop GL #version 130 shaders, which fail in WebGL2. Fix: #ifdef __EMSCRIPTEN__ to force GLES3 code path.
core/hw/sh4/sh4_core_regs.cpp — Missing CPU_GENERIC case in floating-point rounding mode switch. Build fails without TARGET_NO_REC.
Runtime issues (JavaScript/WebGL2 layer)
Three runtime patches are required for gameplay:
getParameter(GL_VERSION) override — return proper GLES3 string for RetroArch's GL driver detection
getError() suppression — GL_INVALID_ENUM from WebGL2 causes RetroArch to abort video driver init
texParameteri/f guard — calls on unbound textures cause massive console spam and lag
All patches documented with rationale in the technical writeup.
Current limitations
- SH4 interpreter only (no dynarec in WASM) — CPU-bound games are slow
- Single-threaded (pthreads disabled for stability)
- Built with emsdk 3.1.74 on the deprecated libretro/flycast fork
Performance optimization roadmap: https://github.com/nasomers/flycast-wasm/blob/main/PERFORMANCE.md
The Makefile's
platform=emscriptentarget has been broken for years but is structurally intact. I got it building and running as a libretro core inside EmulatorJS — first known working Flycast WASM build.Demo video: https://www.youtube.com/watch?v=VAGoy-kjqYA
Repo with all patches and full build guide: https://github.com/nasomers/flycast-wasm
Makefile issues
HOST_CPU_FLAGSoverride fails — GNU Make$(filter)returns empty whenHOST_CPU_FLAGSis unset, causing the conditional to fall through. The emscripten block never setsHOST_CPU_FLAGS, soTARGET_NO_RECandHAVE_GENERIC_JITare never applied.-s USE_ZLIB=1— Emscripten provides zlib via ports, but the emscripten block doesn't enable it.-fexceptionsneeded — Flycast uses C++ exceptions but the emscripten block doesn't enable them.Source issues
core/rend/gles/gles.cpp—glGetString(GL_VERSION)returns garbage in WASM (browser returns WebGL version string, not GLES). Flycast parses this to detect GLES3 and falls back to desktop GL#version 130shaders, which fail in WebGL2. Fix:#ifdef __EMSCRIPTEN__to force GLES3 code path.core/hw/sh4/sh4_core_regs.cpp— MissingCPU_GENERICcase in floating-point rounding mode switch. Build fails withoutTARGET_NO_REC.Runtime issues (JavaScript/WebGL2 layer)
Three runtime patches are required for gameplay:
getParameter(GL_VERSION)override — return proper GLES3 string for RetroArch's GL driver detectiongetError()suppression —GL_INVALID_ENUMfrom WebGL2 causes RetroArch to abort video driver inittexParameteri/fguard — calls on unbound textures cause massive console spam and lagAll patches documented with rationale in the technical writeup.
Current limitations
Performance optimization roadmap: https://github.com/nasomers/flycast-wasm/blob/main/PERFORMANCE.md