# 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](https://github.com/danoon2/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 /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 -zip TinyCore15Wine11.0.zip \ -env WINEDLLOVERRIDES=mscoree,mshtml= -mount /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` → `std::shared_ptr(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).