# zaparoo-update
Rust and QML update UI package for Zaparoo Frontend hosts.
## Package layout
The root package keeps the public `zaparoo-update` crate name and only contains
the frontend-facing facade API. It never includes or compiles
`private/zaparoo-update-impl/`.
The implementation source lives in `private/zaparoo-update-impl/` as a separate
private crate. Local runtime builders compile that crate into binary/QML
artifacts, and the public facade plus runtime crates consume those artifacts in
the same shape production consumers use.
Runtime packages are scaffolded under `runtime/`. They contain only package
metadata and an `artifacts/` layout for compiled shared libraries/QML plugin
files; they must not contain the private implementation source.
Current runtime package crates:
- `zaparoo-update-runtime-linux-armv7`
- `zaparoo-update-runtime-linux-x86_64`
- `zaparoo-update-runtime-windows-x86_64`
Publish runtime crates before publishing the root facade crate. The root crate
declares runtime crates as target-specific dependencies, so Cargo package
verification for the facade expects the matching runtime package to be
available from the registry for each published target.
With the private implementation source or binary runtime present, the crate
provides the `Zaparoo.Update.Native` CXX-Qt singletons plus packaged QML/CMake
assets for embedding the update screens into a host frontend. Hosts must
provide the documented QML host APIs, including `Zaparoo.Update.Host` and
`Zaparoo.Theme.Sizing`.
## Host integration entrypoints
- Rust: call `zaparoo_update::init_runtime(tokio_handle)` before showing the
update QML.
- QML: embed `Zaparoo.Update.UpdateScreen` and provide the host modules
`Zaparoo.Update.Host` and `Zaparoo.Theme`.
- CMake: include `cmake/ZaparooUpdate.cmake` and call
`zaparoo_update_add_qml_module()` from the host build.
See `examples/minimal-frontend` for a small host with one Update button,
screensaver handling, CRT preview aliases, and launchers for mock and real
Downloader runs.
## Local run entrypoints
Run these from the package root (`../zaparoo-update`) unless noted otherwise.
### Mock Downloader UI run
```sh
./examples/minimal-frontend/run-mock.sh
```
Builds local desktop runtime artifacts, builds the desktop minimal frontend
against those artifacts, and runs it against `./mock-downloader.py`. Useful for
UI work without touching real Downloader files.
CRT preview aliases are accepted:
```sh
./examples/minimal-frontend/run-mock.sh --crt ntsc-320b
./examples/minimal-frontend/run-mock.sh --resolution pal-640
```
### Real Downloader local run
```sh
./examples/minimal-frontend/run-real-downloader.sh
```
Builds the desktop minimal frontend and runs it against a local
`../Downloader_MiSTer` checkout. It creates `./.local_drv/`, copies
`../Downloader_MiSTer/downloader.ini` there on first run, and points Downloader
at that directory for install state, downloaded files, and logs. This mirrors
Downloader's `./src/debug.py local_run` setup.
Override paths when needed:
```sh
./examples/minimal-frontend/run-real-downloader.sh --downloader-root ../Downloader_MiSTer
./examples/minimal-frontend/run-real-downloader.sh --local-dir ./.local_drv
```
`./.local_drv/` is git-ignored.
## Local dylib runtime targets
These targets build dynamic runtime artifacts from the private source tree for
desktop development. They are non-default and write to `build/` by default.
```sh
make dylib-local-linux
make dylib-local-win
```
`dylib-local-linux` is intended to run on a Linux host. `dylib-local-win` is
intended to run on a Windows host with Rust, CMake, Ninja, and Qt available in
the environment. The default outputs are:
```txt
build/runtime-local-dylib/linux/artifacts
build/runtime-local-dylib/windows/artifacts
```
Common overrides:
```sh
make dylib-local-linux BUILD_PROFILE=debug
make dylib-local-linux OUTPUT_DIR=/tmp/zaparoo-update-runtime
```
## Run the production-like frontend from WSL
```sh
./run-frontend-wsl-prod.sh
```
This stages `../zaparoo-frontend` under `build/frontend-wsl-prod/`, stages this
package as a facade-only `zaparoo-update` dependency, configures a Release
frontend build with `ZAPAROO_DEV=OFF`, and runs it against the platform
`zaparoo-update-runtime-*` crate resolved through Cargo/CMake.
The staged checkout is reused by default so Cargo/CMake incremental outputs are
kept between runs. Use `--fresh-stage` when you need to copy fresh changes from
`../zaparoo-frontend` or restage this facade package from scratch.
By default the script starts the frontend mock core and uses this repo's mock
downloader so it can run locally in WSL. To keep the core endpoint untouched or
use a local Downloader_MiSTer checkout:
```sh
./run-frontend-wsl-prod.sh --real-core
./run-frontend-wsl-prod.sh --real-downloader ../Downloader_MiSTer
```
Useful local checks:
```sh
./run-frontend-wsl-prod.sh --build-only
./run-frontend-wsl-prod.sh --fresh-stage --build-only
./run-frontend-wsl-prod.sh --play-events /tmp/events.ltsv
./run-frontend-wsl-prod.sh --record-events /tmp/events.ltsv
```
## MiSTer ARM32 entrypoints
### Build the production frontend with this package
```sh
./build-frontend-armv7.sh
```
Builds `../zaparoo-frontend` through its ARMv7/MiSTer Dockerfile while staging
this checkout as the `zaparoo-update` dependency. The default mode stages the
public facade files plus the runtime crate manifests/artifacts needed by Cargo,
while keeping `private/` out of the Docker build context. That mode requires the
ARMv7 runtime crate artifacts to be populated first.
To explicitly build local ARMv7 runtime artifacts from the private source tree and
then build the frontend through the facade-only context:
```sh
./build-frontend-armv7.sh --build-local-runtime
```
### Deploy the production-like frontend to MiSTer
```sh
./deploy-frontend-mister-prod.sh
```
This runs the same facade/runtime-crate build as
`./build-frontend-armv7.sh --build-local-runtime`, then copies
`build/frontend-mister-prod/output/frontend` to
`/media/fat/zaparoo/frontend` and lets `MiSTer_Zaparoo` respawn it. Use
`--build-only` to stop before SSH deployment, or `--skip-build` to deploy an
already built binary.
This deploy helper defaults to the local MiSTer toolchain image and stable
staged Docker contexts under `build/frontend-mister-prod/stage/`, so repeated
runs can reuse Docker/Cargo build state. Use `--fresh-stage` to restage those
contexts, or `--official-toolchain` to use the GHCR toolchain image instead.
That path is intentionally non-default. It writes generated files into
`runtime/zaparoo-update-runtime-linux-armv7/artifacts/`.
### Build minimal frontend for MiSTer
```sh
./examples/minimal-frontend/build-arm32.sh
```
Uses the local Docker toolchain image
`zaparoo/qt6-arm32-mister:<version>` and writes:
```txt
examples/minimal-frontend/output/minimal_update_frontend
```
### Deploy and run minimal frontend on MiSTer
```sh
./examples/minimal-frontend/deploy-mister.sh
```
Reads `MISTER_IP` and optional `MISTER_PW` from `./.env`, deploys to
`/tmp/zaparoo-update-minimal`, stops the normal frontend wrapper while the
example runs, and starts the wrapper again on exit when available.
Common options:
```sh
./examples/minimal-frontend/deploy-mister.sh --skip-build
./examples/minimal-frontend/deploy-mister.sh --no-run
./examples/minimal-frontend/deploy-mister.sh --crt ntsc-320b --apply-vmode
```
By default deploy leaves the current MiSTer framebuffer/video mode unchanged.
Use `--crt` and `--apply-vmode` only when explicitly testing the CRT/native
writer path.
## Direct mock stream entrypoint
```sh
./mock-downloader.py
```
Emits a DLP1 LTSV update stream for development and tests. The minimal mock
launcher wires this up automatically, so most UI work should use
`run-mock.sh` instead.
## Event stream recording and playback
These debug hooks are inactive unless the env vars are explicitly set.
```sh
RECORD_EVENTS=/tmp/events.ltsv ./examples/minimal-frontend/run-real-downloader.sh
PLAY_EVENTS=/tmp/events.ltsv ./examples/minimal-frontend/run-mock.sh
```
`RECORD_EVENTS` writes the raw update event stream to the target file, creating
or truncating it for each run. `PLAY_EVENTS` reads that stream back instead of
starting the downloader.