Files
llamamod/notes/testharness.md
T

148 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Test harness `tools/lamatest.py`
Starts "Ein Königreich für ein Lama" unattended and invisibly (Xvfb :5,
sound into a null sink), loads TestLevel chapter 1 (T1L9M001.wad) and takes screenshots.
Tested on 2026-11-06 with Wine 6.0.3, llvmpipe.
## Commands
```
lamatest.py run <wad> <outdir> [n] # all in one: install, start, tolevel, tour, stop
lamatest.py start # Xvfb :5 + null sink lama_stumm + groove.exe
lamatest.py tolevel # menu -> slot with TestLevel -> chapter 1 -> gameplay
lamatest.py tour <outdir> [n] # n camera shots (look around) + n walking shots + llama view
lamatest.py shot out.png # full screen 1920x1080
lamatest.py key <xdotool-key> [s] # hold key for s seconds (default 0.12)
lamatest.py keys Up:1.5 a:0.5 x # sequence, name[:hold time], also sleep=2
lamatest.py seq <outdir> "TOKENS" # --seq tokens (shot:, run:, rj: …) in the running game
lamatest.py status | stop | restore-wad
```
### `run` options (added 2026-11-06)
```
lamatest.py run <wad> <outdir> [n] [--seq "TOKENS"] [--tour] [--keep]
```
* **WAD restore**: `run` remembers the *previously installed*
`T1L9M001.wad` (`$LAMATEST_DIR/vorher_T1L9M001.wad`) and restores it after the run –
i.e. not `.orig`. With `--keep` the tested WAD stays installed.
(`restore-wad` still explicitly restores `.orig`.)
* `--seq` replaces the default tour with a key sequence (with `--tour` the tour runs as well):
* `Up:1.5`, `a:0.5`, `x` … key[:hold time] as with `keys`; `sleep=1`
* `shot:NAME` → `seq_NN_NAME.jpg`, `fp:NAME` → shot in llama view (Return held)
* `dialog` → click away dialog/letterbox
* `Up+x:0.8` → hold keys simultaneously
* `rj:T1:T2` → running jump (hold Up, X after T1 s, Up for another T2 s)
* `dj:T` → double X with run-up, `hop:N:T` → hold Up, jump N× every T s
* `run:T:x@1.3,x@2.9,shot@5.0,Left@3.0-3.4` → hold Up for T s, following a schedule (s from start)
tap X / take a shot (`seq_NN_runT.jpg`) / hold a key from–to; `run/Left:T:…` holds
another key instead of Up. Real time: a shot blocks ~0.4 s (delays subsequent events
and slows the game down) → no shots shortly before jumps.
* Controls are **camera-relative** (Up = in the camera's view direction, Left/Right sideways).
A/S rotate the camera, S:0.45 ≈ look 90° to the left.
* Measurements (llama): ~1.1 units/s walking, jump 0.35 high, ~1.3 far with run-up – see
levelbau.md. Timed runs scatter by ~0.3 units (start delay, frame rate);
longer distances need "stops" (a wall/step where the llama comes to a halt).
* Camera: after running into a wall or a fall the camera rotates unpredictably →
Up then walks in a different direction. A/S rotation (S:0.45) is only roughly 90°.
* Complete test world parkour as a script: `levels/testwelt_parkour.seq` (levelbau.md).
* `LAMATEST_SHOT=1280` (environment): `shot:`/`fp:` shots at 1280×720, quality 85 instead of 960×540 (preview images).
* "EINGEFROREN?" (frozen?) for a `--seq` without movement (e.g. only `sleep=3 shot:x`) is a false alarm –
the standing llama does not change the image; with camera rotation/walking you get "OK".
* Good viewing angles in the game are hard: the camera hangs low behind the llama; elevated
start points (pedestal, parkour checkpoint `pk2` + `A:0.6`) show several areas.
Helper script for series: `$CLAUDE_JOB_DIR/tmp/lb_run.sh WAD NAME "SEQ"` (montage `lb_mNAME.jpg`,
WAD path absolute!), `rs.sh NAME "SEQ"` (restart with installed WAD + `seq`, montage `i/NAME.jpg`).
**Caution**: no `pgrep -f groove.exe` in wait loops – it matches your own shell
(the command line contains "groove.exe") and lamatest takes it for a foreign instance.
State/PIDs/wine.log: `$LAMATEST_DIR` (default `/tmp/lamatest-$USER`). Game: `$LAMA_WINEPREFIX` (default `~/.wine-lama`),
`lama-mod`: `$LAMA_MOD` (see [docs/tools.md](../docs/tools.md#paths)).
`run` exit codes: 0 OK, 3 crash, 4 timeout/hang, 5 image frozen.
Output in `<outdir>`: `report.txt`, `wine.log` (stderr, truncated to 2 MB),
`00_geladen.png` (full) + `.jpg`, `tour_*.jpg` (960x540, ~30 KB), on failure
`zz_absturz.jpg` / `zz_timeout.jpg`. One run ≈ 75 s, ≈ 1.2 MB.
## Safety rules (implemented in the script)
- Aborts if a groove.exe with a different DISPLAY is running (the user's own instance).
- xdotool only with DISPLAY=:5.
- Sound: own null sink, the app is never muted; `stop` unloads the sink.
- Save games (`*.ksv` in the game folder) are backed up on `start` and restored
on `stop` if changed (newly created ones are deleted).
- `stop`: `wineserver -k` only if no foreign groove.exe is running, otherwise only own PIDs.
- The test world exit saves progress (chapter 2 unlocked) – restored on `stop` together with the
save games.
- WAD: the first `run` backs up the original as `mods/testlevel/wads/T1L9M001.wad.orig`;
`restore-wad` restores it. The overlay (`lama-mod an`) consists of
**symlinks** to the mod files → overwriting
`~/.wine-lama/mods/testlevel/wads/T1L9M001.wad` takes effect immediately; `lama-mod an` is
only called if the overlay link is missing.
## `tolevel` sequence (measured)
| Step | Key | Detection | t (from start) |
|---|---|---|---|
| Logo → main menu | – | OCR crop 700x300+1150+650, threshold 75 % → only the highlighted item "Spiel starten" is readable | ~6 s |
| "Spiel starten" (start game) | Return | – | |
| Save slot selection (carousel, starts at slot 2, **no** wrap) | Left ×3, then Right until "TestLevel" | OCR crop 1600x280+160+740 (fuzzy, 2 thresholds) | ~20 s |
| Load slot 3 | Return | selection map = >75 % beige pixels | ~25 s |
| Activate chapter 1 (cursor from KSV +4/+5) | Return | | |
| Camera fly-through (letterbox: top+bottom row black) | Return skips | | +1.5 s |
| Gameplay | – | bright, no letterbox, golden HUD top left (or >25 s) 3× in a row | ~29 s total, loading ~4 s |
Without skipping, the camera fly-through in the village takes ~20 s.
Loading screen = T191.COR ("TestLevel Kapitel 1 … LADEVORGANG").
Fallback: if no menu is detected, Return after 40 s (skips the demo). Caution:
Return on a misdetected screen can start a different game –
but save games are restored at the end.
## PC controls (keyboard, from "Optionen → Tastatur konfigurieren", verified)
| Action | Key |
|---|---|
| Up / Down (walk forward / backward) | Up / Down |
| Left / Right (turn) | Left / Right |
| Jump (also advances dialog) | X |
| Action | Z |
| Power | Space |
| Llama view (first person, hold) | Return |
| Rotate camera left / right | A / S (hold 0.5 s ≈ 90°) |
| Pause menu | Escape |
Registry `HKCU\Software\Disney Interactive\Emperors New Groove\1.0`,
`"InputDevice Wine Keyboard"` = 14 DIK codes (4 hex digits each):
CB Left, CD Right, C8 Up, D0 Down, 1E A, 1F S, 39 Space, 2D X, 1C Return,
19 P, C9 PgUp, D1 PgDn, 2C Z, 18 O. The registry order ≠ menu order;
P/PgUp/PgDn/O probably pause/inventory (according to exe strings: PAUSE GAME, CYCLE
INVENTORY UP/DOWN, USE AN ITEM, TURN 180, SELECT) – not verified.
Other values there: CameraMode, ControlType, ScreenW/H (1920x1142), CDPath=L:\.
Pause menu (Escape): graphics/sound options, configure keyboard/joystick,
more options, continue, "Beenden und zur Auswahlkarte wechseln" (quit to selection map; confirmation
Ja/Nein, default Nein → Up, Return), quit game. Main menu submenus: Escape = back.
## Observations on the village 1 copy
- Walking forward in the village immediately starts the Pacha dialog (letterbox with
subtitles, ~9× X to click through). `tour` detects this, photographs the
dialog once and clicks it away.
- The llama can fall off the cliff during the tour (respawn) – irrelevant for visual checks.
## Crash detection
Per poll: groove.exe process on :5 gone / window "Groove" gone / window with
"Programmfehler", "error", "exception" … (Wine crash dialog). The report contains the
line `wine: Unhandled page fault … at address XXXXXXXX` (look up the address in Ghidra).
Tested: WAD truncated to 300 KB and WAD with 2000 random
bytes → both crash during the loading screen, detected after ~5 s (exit 3).
Harmless log noise (gstreamer/MPEG-1 missing, ole, ChangeDisplaySettings,
MIDIMAP) is filtered out of the report.
## Dependencies
Xvfb, xdotool, ImageMagick (import/convert), tesseract with `deu`, pactl, wine.