Motocross Madness demo

Test route

The browser build can reach a live race without Wine. With a persisted profile, the reliable 640x480 guest-coordinate route is:

  1. (310,441) captures the mouse over the existing-profile screen.
  2. (445,45) twice enters the main menu and Single Player Event.
  3. (350,442) advances through track selection, rider selection, and Start.

The CLI-driven Puppeteer probe used during the 2026-08-30 investigation waited 45 seconds after Start in cooperative mode and 60 seconds in true browser Worker mode. Both reached UI id 104 and rendered the quarry, rider, HUD, and attached 16-bit Z surface. The Worker run was served with COOP/COEP isolation and reported hasWorker:true; its loading phase is substantially slower but is not stuck.

Headless route (CLI, 2026-09-18)

A fresh profile reaches the race in the CLI with no browser. Batch numbers are at the default --batch-size/--tick-ms-per-batch:

  1. 200:dlg-cmd:1 answers the "test your video memory" MessageBox (it appears near batch 57; a dlg-cmd sent earlier finds no dialog).
  2. The Enter Name box is up by batch 10000. Type with keydown + keypress + keyup per character. keydown alone types nothing: TranslateMessage does not synthesize WM_CHAR (the browser queues it from the keypress event), and MCM's edit field reads only WM_CHAR.
  3. OK (221,236), then Single Player Event (445,45), pressed twice. Event Options is up by batch 22000.
  4. Next (338,442) shows Select Stunt Quarry ("T-rific"), Next again shows rider/bike, then Start (338,442).
  5. Loading takes about 150000 batches: quarry01.trn (6.3 MB) is decoded in 4 KB reads, then a terrain-grid visibility pass at 0x48c290 runs for about 30000 batches with no file I/O. The race renders by batch 180000. Holding Up (keydown:38 + di-keydown:38) drives the bike.

Use mousedown/mouseup a few dozen batches apart, and --stuck-after large: the app parks in blocking waits that the default detector reads as a hang. --control=PORT --frozen with tools/ctl.js step N / png drives it without re-running the long boot for every click.

File layout (why the manifest looks like this)

MCM opens media two ways: relative to the working directory (ui\cursor.tga, sbike\*.vub, ui\profile\*.*) and rooted at the registry's HardDriveRootPath (<root>\ui\global.dat, <root>\audio\*.wav). A real install keeps the working directory and that root in one Program Files directory. The registry entry therefore mounts every asset under C:\Program Files\Microsoft Games\Motocross Madness Trial\ and sets workingDirectory to that directory. run.js takes the same default when --cwd is absent.

Rendering findings

Both D3DIM backends reach the race (2026-09-20)

The headless route above works verbatim on the WebGL D3DIM executor too — add --headless-gl --d3dim-gpu (and hold the display awake with nohup caffeinate -d -u -t 2400 &, or GLFW reports zero displays and D3DIMGpu._target throws "WebGL is unavailable"). Both arms race; the batch-60000 loading screen is bit-identical between them, and the batch-185000 race frames differ by 1.39% of pixels at --tolerance=32 — the software arm's terrain texture is blocky and dithered where the GPU arm's is filtered.

This corrects the mcm NODRAW row in docs/d3dim-gl-sweep-2026-09-19.md: MCM was not failing to draw, it was parked behind the video-memory MessageBox that a startup slice never answers. Captures and the full command are in docs/d3d-backend-coverage.md.

The focused coverage is in test/test-d3dim-indexed-texture.js and test/test-directdraw-cursor-background-restore.js. The verified final race screenshots from the investigation were /private/tmp/mcm-fixed-coop2-final-wait-45000.png and /private/tmp/mcm-fixed-worker-final-wait-60000.png.