Files
llamamod/notes/dev/browser-boxedwine.md

9.2 KiB
Raw Permalink Blame History

Browser feasibility: Boxedwine (2026-11-07)

Question: can The Emperor's New Groove (groove.exe, D3D7/DirectDraw, DirectInput, DirectSound) run in a web browser through Boxedwine (Wine + x86 emulator, also built to WebAssembly)?

Verdict

Not with today's Boxedwine web build: Direct3D is missing in the browser.

  • Web (Emscripten) build 26R1: the game starts and shows Wine dialogs, then stops with the game's own message "Direct Draw kann nicht gestartet werden." ("Direct Draw cannot be started"). The web build has no OpenGL bridge: the Emscripten makefile defines none of the BOXEDWINE_OPENGL_* switches, the stripped file system has no libGL.so.1 (Wine logs Failed to load libGL … OpenGL support is disabled), and the release readme says "OpenGL and Direct3D are not supported in the Web/Emscripten build because they can not currently be converted to WebGL." Without OpenGL, wined3d has no D3D device, so groove.exe finds no 3D device.
  • Native Linux build (same emulator, x86 JIT), Wine 11 file system: works. After three small Boxedwine fixes (see below) it reaches the intro, the main menu, the save slot screen, the map and in-game Village chapter 1 at ~30 fps (llvmpipe on Xvfb, load average ~15). Keyboard input works. One visible problem: in-game the camera seems to sit at Kuzco's position (the llama is not visible, the view pitches up/down with Up/Down); in the attract-mode demo Kuzco is drawn normally. Not investigated. With the Wine 6 file system it hangs on the loading screen (emulator livelock, see below).
  • Software renderer (plan B) does not help: no own rasterizer found in groove.exe. FUN_0040ffd0 chooses a DirectDraw device + Direct3D device by name (DisplayDevice/D3DDevice). The "software" flag (SoftwareScreenBPP/W/H, device record +0x10) is derived from the enumerated D3D device description (FUN_00412a10: (desc+0xf4 >> 3) & 1), most likely D3D's own software device (RGB/MMX emulation) – in any case a device the game gets from Direct3D enumeration, not an own rasterizer (no other draw path was found by grep). In Wine that device is wined3d too, which needs OpenGL (or Vulkan). Wine has no GL-free D3D rasterizer, so the software path also needs a GL bridge in the browser.
  • Path in Boxedwine: yes, D3D7 → Wine ddraw → wined3d → OpenGL. Natively, Boxedwine passes the emulated GL calls to the host GL through SDL (source/opengl/sdl). In the browser that bridge would have to become WebGL (GL ES 2/3), which Boxedwine does not do. The source has an unused ES path (source/opengl/es: glshim/esopengl) that is not part of the Emscripten build.

What it would take to ship

  1. A GL → WebGL bridge for the Emscripten build (upstream work in Boxedwine: wined3d needs desktop GL 2.1+ features; a translation layer like gl4es/glshim or a WebGL2 backend for the marshalled GL calls). This is the blocker, weeks of emulator work at least, not something LlamaMod can patch around.
  2. Speed: the web build has no JIT (wasm interpreter, TOTAL_MEMORY 512 MB). Native JIT gives ~30 fps with 1.2 cores; the interpreter is typically several times slower, so even with WebGL the 3D game would likely be far below playable on average hardware. Unmeasured.
  3. Distribution page: a static page where the user drops their own ISO/folder; JS builds the app zip in memory (game folder + CD data, ~400 MB without movies) plus a root zip with the registry values, never uploaded anywhere. Never host game data. Needs COOP/COEP headers for the multi-threaded build.
  4. Sound and movies: DirectSound opened 17 SDL audio streams natively (silent dummy driver here, audibility not checked). Intro movies (movies/*.dat) do not play in Wine 11 under Boxedwine (quartz: Failed to create filter … hr 0x8007000e); the game skips them.

Alternatives that do not need a GL bridge are out of scope here (e.g. a native port, or a WebGL renderer re-implementation of the engine's D3D7 calls).

Versions

Item Version / source
Boxedwine 26R1.0 (2026-04-22). GitHub releases have Windows, Mac and Web builds, no Linux build → built from the source tarball
Linux build GCC 11.4 (Mint 21.3). Official requirement is GCC 12; one fix needed (below). libminizip-dev missing → linked against the installed libminizip.so.1 via a local symlink (no system packages installed)
File systems from Boxedwine's own list http://www.boxedwine.org/v2/26R1/filesV2.xml: TinyCore15Wine6.0.zip, TinyCore15Wine11.0.zip; web: boxedwine.zip (stripped Wine 6) from Boxedwine26R1Web.zip
Browser Chromium (/usr/bin/chromium, own profile) on Xvfb :26, page served by a local Python server with COOP/COEP headers on 127.0.0.1, MultiThreaded web build
Game German CD via tools/apptest.py setup boxedwine; LlamaMod's patched game/groove.exe (HKCU registry)

Procedure (native)

Xvfb :26 -screen 0 1920x1080x24 -nolisten tcp +extension GLX
# prefix: copy user.reg out of the file-system zip into <root>/home/username/.wine/, append
#   [Software\\Disney Interactive\\Emperors New Groove\\1.0]  CDPath="Z:\\mnt\\lama\\cd-active\\"  HDPath=".\\"
#   ScreenW=dword:280 ScreenH=dword:1e0
# and write "disable" into .update-timestamp (otherwise wineboot updates the prefix: >15 min and it hung)
SDL_AUDIODRIVER=dummy DISPLAY=:26 boxedwine -root <root> -zip TinyCore15Wine11.0.zip \
   -env WINEDLLOVERRIDES=mscoree,mshtml= -mount <apptest>/data /mnt/lama -w /mnt/lama/game /bin/wine groove.exe

Keys via xdotool keydown/keyup with the pointer over the window (X focus follows the pointer, no WM). The game renders 640x480 into the top-left of the 800x600 Boxedwine window.

Boxedwine fixes needed (patch: $CLAUDE_JOB_DIR/tmp/boxedwine/results/boxedwine-26R1-linux-xvfb.patch, not upstreamed):

  1. readIcons.cpp: std::make_shared<U8[]> → std::shared_ptr<U8[]>(new U8[n]()) (GCC 11).
  2. platform/linux/platformOpenGL.cpp: skip GLX fbconfigs with GLX_SLOW_CONFIG caveat and without GLX_WINDOW_BIT. Under Xvfb/llvmpipe, Wine otherwise picks an accum-buffer config (SDL refuses it as "accelerated") or a non-window config (set_pixel_format … not compatible for window rendering) and wined3d reports Failed to get a GL context. Probably Xvfb-specific; real GPUs may not need it.
  3. KMemory::mapNativeMemory: when no free pages are left above 0xD0000000, reserve in the user area instead. Without it the first glMapBufferRange of wined3d (Wine 6) fails → Failed to map bo → page fault. Not checked whether Wine 11 still needs it.

Wine 6 file system with these fixes: loading screen drawn through D3D7, ~10–25 presents/s for ~30 s, then every emulated thread waits for the JIT memory mutex (JitCodeGen::doJIT) while one thread spins — the game never leaves the loading screen. Not investigated further; Wine 11 does not show it.

Procedure (web)

Web page = release MultiThreaded/ folder plus lamaroot.zip (= boxedwine.zip with the user.reg above, CDPath C:\\files\\lama\\cd\\) and lama.zip (lama/ = game folder + lama/cd/ = CD data without movies, stored, 415 MB). URL: boxedwine.html?root=lamaroot&app=lama&p=groove.exe&sound=false. The overlay= parameter did not override user.reg of the root zip (game asked for the CD), a modified root zip did. Loading 415 MB into the page took a few seconds locally.

Screenshots

  • ../img/dev/boxedwine-native-menu.jpg – main menu (native Boxedwine, Wine 11)
  • ../img/dev/boxedwine-native-demo.jpg – attract-mode demo in 3D (the right/bottom strips are a stale frame outside the 640x480 game area)
  • ../img/dev/boxedwine-native-village.jpg – Village chapter 1 in game (Kuzco not visible, see above)
  • ../img/dev/boxedwine-web-ddraw-error.jpg – web build in Chromium: "Direct Draw kann nicht gestartet werden."

Running it locally

A durable native setup lives in ~/opt/boxedwine-26R1/ (rebuilt 2026-11-07 from the procedure above):

Path Content
bin/boxedwine Boxedwine 26R1.0 built from dl-src/ (GitHub tag tarball) with boxedwine-26R1-linux-xvfb.patch, GCC 11.4. The sources are CRLF: convert the five patched files to LF (sed -i 's/\r$//') before patch -p1; project/linux/linux_build/lib/libminizip.so → system libminizip.so.1
dl-fs/TinyCore15Wine11.0.zip Wine 11 file system (+ filesV2.xml)
root/home/username/.wine/ user.reg from the zip + the game's HKCU key, .update-timestamp = disable
apptest/lama/data/ APPTEST_ROOT=~/opt/boxedwine-26R1/apptest tools/apptest.py setup lama: game/ (patched groove.exe), cd-active/; mounted as /mnt/lama

Start: lama-boxedwine (~/.local/bin, bash) on the current $DISPLAY, normal sound (SDL_AUDIODRIVER=dummy lama-boxedwine for silence). Log: ~/opt/boxedwine-26R1/last-run.log; PID file ~/opt/boxedwine-26R1/boxedwine.pid blocks a second instance. Known issues: in-game camera at Kuzco's position, no intro movies (see above).

Real screen (AMD RX 480, Mesa radeonsi): the window stayed black and the game hung after the movie attempts; with LIBGL_ALWAYS_SOFTWARE=1 (llvmpipe) it shows the title and runs. lama-boxedwine therefore defaults to the software renderer (LAMA_BW_GPU=1 to try the GPU).