This repository is the functional 2D demonstration and starter project for CNA-Rust. It runs its lifecycle and drawing through CNA C++; it does not use a fake Rust frame loop.
The demo:
- initializes and shuts down a native CNA game;
- composes the durable per-game state and verifies retained, instance-local
GameServiceContaineridentity; - receives XNA-shaped
GameTimeupdate/draw callbacks; - obtains the native game graphics device;
- decodes
Content/logo.pnginto a real nativeTexture2D; - clears and draws through a real
SpriteBatch; - applies XNA's real
BlendState::AlphaBlendthrough CNA's state-bearingSpriteBatch::Beginroute; - captures native keyboard, mouse, and player-one gamepad snapshots (
Escapeexits where input is available); - moves and bounds the logo using the current viewport;
- prints renderer name/capabilities queried from CNA; and
- explicitly disposes resources, with
Dropsafely following.
There is no cube, fake supports_3d, fabricated renderer name, fake texture, or
XNB template claim. This canary deliberately keeps Texture2D::FromStream as
the raw encoded-image route. CNA-Rust now has a separate real uncompressed XNB
ContentManager pipeline, but the template does not claim to exercise it.
| Platform | Status |
|---|---|
| Linux x86-64 / CNA HEADLESS | Experimental runtime verified on ABI 0.21: 60 and 600 frames |
| Linux windowed/GPU | Planned |
| Windows | Planned |
| macOS | Planned |
| WebAssembly | Blocked by the toolchain: CNA's WebAssembly C ABI exists, and the binding now has a direct-linkage mode, but no wasm Rust target is installed here |
| Android | Unsupported: no native CNA app integration verified |
The 2026-08-31 headless test used CNA ABI 0.21.0 against an out-of-tree build
of an unmodified canonical CNA checkout; the build-only corrections the
earlier ABI-0.7 run needed are no longer required, because ABI 0.20.0 is the
version that repaired the renderer-table mismatch behind them, and 0.21.0 is
purely additive on top of it. See the CNA-Rust
docs/abi-migration-evidence.md for the exact evidence.
This development checkout intentionally uses an exact sibling path dependency:
cna = { package = "cna-rust", path = "../cna-rust/crates/cna" }Neither crate is published yet. Supply an ABI 0.21 native library:
CNA_NATIVE_LIBRARY=/absolute/path/to/libcna_c_api.so cargo runThe current CNA-Rust loader supports Unix. A missing or mismatched library is a clear error; the demo never falls back to fake behavior.
CNA_NATIVE_LIBRARY=/absolute/path/to/libcna_c_api.so \
cargo run -- --smoke-test # 60 successful draw frames
CNA_NATIVE_LIBRARY=/absolute/path/to/libcna_c_api.so \
cargo run -- --stability-test # 600 successful draw frames
CNA_NATIVE_LIBRARY=/absolute/path/to/libcna_c_api.so \
cargo run -- --frames 120A success message means CNA initialized, content loaded, Update and Draw
completed for the requested count, child resources were disposed, CNA shut
down, and the process exited zero.
CNA_NATIVE_LIBRARY=/absolute/path/to/libcna_c_api.so \
cargo run -- --extensions-smokeThe game itself is deliberately pure XNA. This opt-in route is the other half
of the binding: CNA's own runtime identity and renderer registry, which XNA 4.0
has no counterpart for. It also builds a GraphicsDevice with no Game
anywhere, and authors and reads back a compiled .cnb model -- two things a
CNA-Rust program could not do at all before ABI 0.21, and each about one screen
of code, which is the only reason they are here. This stays a starter template,
not an engine demo.
It prints the platform, the running renderer with its
backend category and maturity, whether the renderer selection has latched, and
every renderer identity compiled into the library. It then round-trips a
texture through CNA's own .cnb content container -- build, encode, parse,
decode, compare -- which needs no asset on disk because the document is built
in the process. All of it comes from cna::extensions, never from
cna::Microsoft::Xna::Framework.
The checked-in canary stays directly buildable. The generator parameterizes the project directory, crate/package metadata, and binary name, and vendors a supplied CNA-Rust checkout so the result has no developer absolute paths or sibling-repository dependencies:
python3 tools/generate.py \
--output /tmp \
--project-name asteroid-demo \
--crate-name asteroid-game \
--binary-name asteroids \
--author "Example Developer" \
--description "A native CNA asteroid demo" \
--cna-root ../cna-rustThe destination must not already exist; the generator refuses to overwrite it. The vendored binding targets CNA ABI 0.21 and Rust 1.74.
- Rust 1.74 or newer;
- a CNA C API library matching experimental ABI 0.21;
- the native dependencies of that CNA build; and
- a display only when the selected CNA platform/renderer requires one.
This template is licensed under the MIT License.