Replace the legacy script interface with an editable uv application, log-driven flows, reliable button commands, and directory-backed SD imports.
xteink QEMU fork
Espressif's QEMU fork carrying the xteink X3/X4 (ESP32-C3) machine model and a wasm32 TCG backend (ported from ktock/qemu-wasm), used by xteink-web-emulator to run CrossPoint firmware in the browser.
Branch
main— the working branch. Base is Espressif'sesp-develop-9.2.2-20260417(40edccac).
Remotes
origin— https://ssh.gitea.va.reichard.io/evan/qemu-xteinkupstream— https://github.com/espressif/qemuqemu-wasm— https://github.com/ktock/qemu-wasm (source of the wasm32 backend)
Building
Native (parity check — authoritative)
nix develop
./configure --target-list=riscv32-softmmu --with-devices-riscv32=xteink --enable-gcrypt
ninja -C build qemu-system-riscv32
Install the emulator controller as an editable global tool:
uv tool install -e tools/xteink-emu-cli
xteink-emu --help
Its first boot builds .#qemu-native-xteink with Nix when dist/qemu-native is missing. Run make xteink when you want to build ahead of time.
Agent emulator
nix run .#xteink-emu -- boot firmware.bin
nix run .#xteink-emu -- boot firmware.bin --sdcard sdcard.img
nix run .#xteink-emu -- boot firmware.bin --sdcard test-library/ --fresh-sd
nix run .#xteink-emu -- wait-log 'ready' --timeout 30
nix run .#xteink-emu -- press bottom-4 bottom-4 bottom-2
nix run .#xteink-emu -- wait-frame 2
nix run .#xteink-emu -- capture screen.png
nix run .#xteink-emu -- memory
nix run .#xteink-emu -- stop
Use one state for a complete flow:
nix run .#xteink-emu -- --state /tmp/reader-test run flow.xteink
# Omit flow.xteink to read command lines from stdin.
boot replaces the emulator already running in that state. Without --sdcard, it creates or reuses $STATE/sdcard.img. An image path is used directly; a directory is merged into the state image before every boot, with host files winning conflicts and other image files preserved. --fresh-sd recreates a state-owned image before importing the directory. The source directory is never modified.
The installable application lives in tools/xteink-emu-cli/; uv tool install -e tools/xteink-emu-cli exposes the global xteink-emu command and reflects checkout edits immediately. press waits for debounced guest ADC reads, so multiple presses do not need display waits. wait-log advances a persistent cursor and fails on timeout; use wait-frame only when visible rendering is itself under test. capture records the current panel without a static delay.
web serves a browser UI for firmware, SD images, controls, screen, logs, and SD files. memory reports RAM high-water marks; QEMU zeroes RAM at reset, so firmware heap logs remain authoritative for live usage. State defaults to /tmp/xteink-emu-$UID. interactive opens a native window and maps Left/Right, 1–4, and P to device buttons. The emulator exposes the open Wi-Fi network qemu through QEMU user-mode NAT.
WebAssembly
Driven by the parent repo, not here:
cd ../xteink-web-emulator
make web-dev # incremental build straight from this tree
The parent's scripts/build-qemu-wasm.sh compiles this checkout inside the
emsdk Docker image defined in xteink-web-emulator/qemu/wasm/Dockerfile.