CNA vs Alternatives
Documented snapshot: CNA c1c316b9 (branch apple/m4-stabilization, 9 October 2026), a development snapshot 3,687 commits after v0.1.0-alpha.1; its product version string is still 0.1.0-alpha.1. CNA represents the public XNA 4.0 runtime API in full — all 331 documented types and all 3,627 documented members have a matching C++ declaration, including the Framework.Design converters (representation, not behaviour; the census is a manual script, not a CI gate). Compile-time signature-freeze tests cover the Input namespace only, and CNA_STRICT_XNA_API is a compile definition that makes non-XNA (CNAEXT) declarations deprecated where you define it. The snapshot contains 813 C++ test sources and 11,380 statically discoverable GoogleTest-family definitions (the site's counting method), plus a 39-scene XNA oracle corpus whose reference images come from the real XNA 4.0 runtime under Wine and DXVK on Linux; the DIRECTX9 renderer is recorded in the repository as matching all 39 at zero tolerance through that same stack (not run in CI). XACT and the XNB loader are real, and a build-time content pipeline now exists. XNA/FNA compiled Effect Framework binaries work only on qualified renderer builds; HLSL .fx source is not compiled at run time.
Maturity, honestly. FNA and MonoGame have shipped commercial games for over a decade. CNA's only tagged release is explicitly an alpha, and this development snapshot is not a new release: its APIs and experimental native C ABI may change, renderer capabilities vary widely, and the 20-workflow CI inventory does not prove every renderer, driver and platform combination. If you are shipping a commercial title on a deadline, weigh that maturity difference first.
Overview
The XNA 4.0 API has three meaningful successors: FNA, MonoGame, and now CNA. All three preserve the familiar XNA programming model, but each occupies a different niche. FNA is the most faithful managed reimplementation and the right choice for shipping existing C# XNA games. MonoGame extends XNA toward modern commercial development with broad console support and a large community. CNA is the only C++ reimplementation — it targets developers who want the XNA design without a managed runtime, who need a native foundation for an engine, or who are building Linux-first and WASM-first projects.
The original XNA 4.0 is discontinued (last update 2014) and runs only on Windows with .NET 4.0. It remains relevant only for projects still in maintenance on that exact stack.
Feature comparison
| Feature | CNA | FNA | MonoGame | XNA 4.0 |
|---|---|---|---|---|
| Language | C++23 | C# (.NET) | C# (.NET) | C# (.NET) |
| Runtime | Native (no GC) | Mono / .NET | Mono / .NET | .NET 4.0 |
| API model | XNA 4.0 compatible | XNA 4.0.4 binary compatible | XNA-inspired | Original |
| Renderers | 14 public identities across 12 implementation families, spanning native GPU APIs, the browser (WebGL 2 and WebGPU), a CPU rasterizer and no-output harnesses. They are not equally complete. | FNA3D (OpenGL, Vulkan, Metal, DX11) | OpenGL, DX11, Metal, Vulkan | DirectX |
| Renderer selection | Single-renderer by default; opt-in multi-renderer builds select before the first device and can enable explicit fallback | Runtime | Runtime | Runtime |
| Platforms | Linux, Windows, macOS, Emscripten and Android source/build paths; experimental iOS (SDL_RENDERER and METAL) with final-link and simulator-smoke evidence. Three platform implementations (SDL3, which reaches Windows, X11, Wayland and macOS through its own video drivers, plus Headless and Terminal) are independently selectable. | Windows, Linux, macOS, iOS, Android, Switch | Windows, Linux, macOS, iOS, Android, Switch, consoles | Windows, Xbox 360, Windows Phone |
| API coverage | All 331 documented XNA runtime types and 3,627 members represented (including Framework.Design); signature-freeze tests for Input only. Representation, not behaviour: effect bytecode and graphics-format behavior remain renderer-qualified. |
XNA 4.0.4 binary compatible | XNA-inspired; broad but not identical | Reference |
| XACT audio | Implemented, with named codec/listener limits | Implemented | Via XACT or custom | Full |
| XNB content pipeline | Loader plus build-time tool 61 built-in readers (60 without native 128-bit integers), real LZX, typed external references and compiled effects, registered automatically by Game; cna-content writes .xnb and .cnb; no reflective discovery and no .mgcb route |
Yes | Yes (via MGCB) | Yes |
Compiled .fx bytecode |
Renderer-qualified XNA/FNA D3D9 Effect Framework binaries on FNA3D always and on 10 more renderer identities behind default-off build options (11 of 14); not HLSL source, DXBC or MGFX at run time | Yes (MojoShader) | Yes | Yes |
| Custom shaders | Hand-written GLSL or SPIR-V through the CNA-only ShaderEffect, per renderer |
GLSL / HLSL via FNA3D | GLSL / HLSL / Metal / SPIR-V | HLSL |
| Surface formats | Renderer-dependent Query and test the active renderer | Full set | Full set | Full set |
| Test suite | 813 C++ test sources; 11,380 statically discoverable GoogleTest-family definitions; configuration-scoped CTest registration; 39-scene XNA oracle corpus (reference images from real XNA under Wine + DXVK) | – | Some | – |
| Continuous integration | Growing 18 workflow files including Linux, Apple, Emscripten, platform, multi-renderer and C API gate workflows; the Direct3D Windows lanes are manual and coverage is not exhaustive | Established | Established | – |
| Memory model | RAII, no GC | Managed GC | Managed GC | Managed GC |
| License | Ms-PL | Ms-PL | Ms-PL | Proprietary / discontinued |
| Status | Pre-release (version string 0.1.0-alpha.1; snapshot c1c316b9) | Stable / active | Stable / active | Discontinued 2014 |
When to choose each
Choose CNA when…
- Your codebase is in C++ and you want XNA-style structure without switching languages.
- You need a native binary with no managed runtime, GC pauses, or JIT warm-up.
- You are doing engine research or building a higher-level engine on a stable XNA-shaped API.
- Linux-first or Web (WASM) deployment is a primary goal.
- You are already familiar with XNA and want that API in C++23.
- You value a large source-auditable test inventory and are prepared to run the exact renderer/platform configuration you ship.
- Your content and graphics needs fit the capability boundaries of a renderer you have verified.
Do not choose CNA when…
- You are shipping a commercial title on a schedule — FNA and MonoGame have a decade of production use behind them and CNA does not.
- Your game ships effects in a format the selected renderer cannot consume and you cannot migrate or rebuild them.
- You need a platform or graphics capability that this snapshot does not verify for your chosen configuration.
- You need stable pre-1.0 API/ABI guarantees or production support today.
Choose FNA when…
- You have an existing C# game that shipped on XNA and need the closest drop-in replacement.
- Binary compatibility with XNA 4.0.4 assemblies is required.
- You want the most complete and battle-tested managed XNA reimplementation available.
- You need XNB content pipeline compatibility for existing asset workflows.
Choose MonoGame when…
- You are starting a new commercial C# game and want a large, active community behind you.
- Broad console support (Switch, PlayStation, Xbox) is on your roadmap.
- You want to use the MGCB content build pipeline and the MonoGame ecosystem of tools.
- Long-term community maintenance and third-party tutorials matter to your team.
Stick with original XNA 4.0 when…
- You are maintaining a very old project that must stay on .NET 4.0 on Windows.
- Migrating to any other framework is out of scope.
- Note: no new projects should target original XNA. Microsoft discontinued it in 2014 and it is not available for modern Windows without compatibility shims.
C++ vs C# API differences
CNA maps the XNA 4.0 API as faithfully as C++23 allows. The core patterns are the same, but C++ syntax requires some adjustments.
| XNA / C# pattern | CNA / C++ equivalent |
|---|---|
Property texture.Width |
Getter method texture.getWidthProperty() (vector and matrix components such as v.X stay plain fields) |
Property setter effect.World = m; |
Setter method effect->setWorldProperty(m); |
using (var x = new T()) { ... } |
RAII: { auto x = std::make_unique<T>(...); ... } (destructor called on scope exit) |
| C# delegates / events | C++ virtual method overrides or sharp-runtime event wrappers |
Content.Load<T>("name") |
getContentProperty().Load<T>("name") — same generic call, returns T by value |
Namespace Microsoft.Xna.Framework |
Namespace Microsoft::Xna::Framework |
new Texture2D(device, w, h) |
Texture2D tex(device, w, h); as a value, or std::make_unique<Texture2D>(device, w, h) when you need a pointer |
Color.CornflowerBlue |
Color::CornflowerBlue |
Vector2(1f, 2f) |
Vector2(1.0f, 2.0f) |
Code comparison: LoadContent and Draw
The following side-by-side example shows the same LoadContent + Draw pattern in XNA C# and in CNA C++23. The structure is deliberately identical; only language-level syntax differs.
| XNA / MonoGame / FNA — C# | CNA — C++23 |
|---|---|
|
|
Key differences to note: std::unique_ptr replaces new for owned resources, while assets from Load<T> arrive by value (held here in a std::optional, because textures and fonts have no default-state constructor to leave empty); *playerTexture dereferences the optional when passing a const Texture2D&; the graphics device and content manager are reached with getGraphicsDeviceProperty() and getContentProperty(); Game::Draw(gameTime) is the C++ equivalent of base.Draw(gameTime); and static colour / vector constants use :: instead of ..
Migration note
If you are considering porting an existing MonoGame or FNA project to CNA, see the dedicated Migration from MonoGame / FNA guide. It covers content loading (CNA reads .xnb through the built-in readers a Game registers, then .cnb, and falls back to loose files otherwise), property-to-method renaming, and ownership patterns. For the full per-namespace picture of what will and will not work, start at XNA Compatibility.
Deep dives on this topic
Long-form pages that explain the exact semantics, invariants and evidence behind this subject.
- CNA and XNA 4.0: what the compatibility promise covers — What CNA translates and cannot load, which reference settles a disputed XNA question, what CNA deliberately is not at snapshot c1c316b9, and its Ms-PL licence and FNA provenance.
- From C# to C++: CNA's translation conventions — How CNA represents C# XNA concepts in C++ so that code stays diffable against the reference: names, properties, aliases, events, interfaces, disposal, visibility, layout and the porting checklist.