Chapter 1 CNA and XNA 4.0
1.1 The one-sentence version
CNA is a native C++ reimplementation of the XNA 4.0 programming model, compiled with a C++23 toolchain floor but written in a disciplined C++17/20 idiom. It reimplements the game framework Microsoft shipped for the Xbox 360 and Windows from roughly 2006 to 2013. CNA’s default platform and audio implementations use SDL3, but those are independent configuration axes. Rendering is delegated to one of 50 public identities mapped to 46 implementation families; an opt-in build may compile several families and select one at runtime.
That description contains three separate engineering problems which organize the rest of the book:
CNA is a translation target, not a loader or binary compatibility layer. It cannot run an existing C# assembly. Porting translates the source to C++; even a property access becomes a getXProperty() or setXProperty(value) call. Names and observable contracts can remain XNA-shaped while the source language and ownership model cannot.
-
1.
Reproduce an API. XNA’s public surface — Microsoft.Xna.Framework and its sub-namespaces — has to exist in C++, with the same class names, method signatures, namespaces, and observable behavior, so that code written against real XNA (or against FNA, the open-source XNA reimplementation in C# that this project treats as its primary behavioral reference) has somewhere to go.
-
2.
Reproduce a runtime. XNA is a managed-code API. It assumes things a bare C++ program does not have for free: garbage-collected System.Object, events and delegates, exceptions with a .NET-shaped hierarchy, TimeSpan, collections. CNA does not reimplement the CLR — instead it depends on a sibling project, sharp-runtime, which provides a deliberately partial C++ subset of the .NET base class library, just deep enough to make the XNA API’s vocabulary make sense in C++.
-
3.
Reproduce a GPU. XNA only had to run against Direct3D 9 (Xbox 360’s own GPU API is Direct3D-shaped too). CNA has to make the same GraphicsDevice /SpriteBatch / Effect surface available while pixels are produced by SDL’s 2D renderer, OpenGL, Vulkan, BGFX, WebGPU, Direct3D 9/11/12 under Wine, an HTML <canvas> under Emscripten, or a from-scratch DirectDraw reimplementation. Identical API presence does not imply identical behavior or evidence; Part IV records those distinctions.
From the project’s own README (2026-07-11 snapshot): “CNA is a C++ reimplementation of the XNA 4.0 programming model, built on SDL3 and a pluggable graphics renderer layer. It is a framework/runtime and abstraction layer—not a game—designed to preserve XNA-style APIs (Microsoft::Xna::Framework) while using modern C++ internals.”
1.2 Why XNA, and why now
XNA Game Studio was Microsoft’s managed-code (C#) game development framework, built around a small, coherent Game / GraphicsDevice / SpriteBatch / Effect vocabulary that a whole generation of independent and student developers learned game programming on. Microsoft discontinued active XNA development years ago; the community response was FNA, a faithful open-source reimplementation of the XNA 4.0 API in C#. The pinned local reference selects its SDL3 platform implementation by default and retains SDL2 as an explicit compatibility choice through FNA_PLATFORM_BACKEND=SDL2; describing FNA simply as an SDL2 runtime is therefore historical shorthand, not its current default.
CNA asks a different question than FNA does. FNA asks: how do we keep running C# XNA code forever, on modern platforms, without Microsoft? CNA asks: what if the code itself did not have to be C#? A native C++ implementation of the same API gives a team that likes the XNA/MonoGame mental model — a thin, explicit, immediate-mode-ish 2D/3D API without an editor or a scene graph imposed on you — a path that does not require a managed runtime or GC pauses, and that a build system and toolchain of your choosing can own end to end. CNA’s own README states this directly: it is meant to “provide a native C++ path for teams that like the XNA/MonoGame model but need non-managed runtime/toolchain control.”
This is also, not incidentally, why CNA is useful as a target for porting existing XNA/FNA games rather than only for writing new ones from scratch — a use case this book returns to in this book’s migration and case-study chapters, using the real ports of Speedy Blupi and Planet Blupi (via the free-direct sibling project) as worked examples.
“Why now” is not merely an argument from intent. At the pin, CNA has fifteen physical framework modules, an optional native C API source module (whose alpha.1 final target is compile-blocked), 50 public renderer identities over 46 implementation families, an XNB reader stack, its own CNJ format, a shared runtime/offline glTF importer, and implemented Media types backed by file parsing, FFmpeg and SDL3_mixer. Those facts establish breadth; they do not establish uniform parity. Later chapters therefore report each route’s behavior, host and oracle separately instead of reviving a fragile percentage of “types present.”
1.3 Design goals, in the project’s own words
CNA’s own README states six goals directly, worth quoting in full since every one of them recurs as a concrete design decision somewhere later in this book, not just as an aspiration: “recreate the XNA developer experience in native C++”; “provide a native C++ path for teams that like the XNA/MonoGame model but need non-managed runtime/toolchain control”; “mirror core XNA namespaces and API patterns while implementing them incrementally”; “decouple gameplay-facing API from renderer implementation details”; “enable one high-level API surface across different rendering technologies”; and “keep SDL/OpenGL/Vulkan-level concerns behind framework abstractions.” The middle four of these six are really one idea stated four ways — the renderer-abstraction goal — and Chapter 19 is where that idea becomes a concrete IGraphicsRenderer contract rather than a design principle; the first two are the “why native C++, why not just use FNA” argument already made above.
1.4 Verification is a vector, not a leaderboard
There is no honest one-number answer to “how tested is CNA?” A source tree can contain a test definition without registering it in a selected build; CTest can register a command that the host cannot execute; a renderer can return success without consuming effect state; and a pixel can be correct on one translated runtime without proving another host.
The book therefore records a claim as a vector: public identity and implementation family, configuration, execution host, driver or translation layer, oracle, and unavailable branches. Examples deliberately occupy different tiers:
-
•
the 50-identity / 46-family registry is strong structural evidence, not rendering proof;
-
•
the Direct3D 9 corpus compares 39 scenes with real XNA output, but runs through Wine and DXVK rather than native period hardware;
-
•
HTML_DOM has HTTP-served Chromium execution and compositor samples, while a successful build of another Web identity proves less;
-
•
recorded Vulkan and BGFX pass fractions belong to their named campaigns and configured populations, not to a universal current suite total.
1.5 What CNA is not
It is worth being precise about the negative space, because CNA’s own documentation is:
-
•
Not a game. There is no bundled playable demo executable shipped as the project’s flagship artifact — the README states this is a deliberate priority of framework/runtime development over a shipping game demo. What ships instead is a test suite (thousands of GoogleTest cases across the unit and GPU pixel-test suites) and a set of minimal verification executables like hello-triangle-sdl.
-
•
Not an XNA content builder. CNA has a substantial runtime XNB reader, but no MGCB-style import/process/write toolchain and no automatic reader bootstrap. A game must register the built-in readers before loading XNB; CNJ, loose files, and glTF are separate routes. Chapters 34–36 define those boundaries.
-
•
Not universally compiled-shader compatible. CNA has distinct answers to XNA effects: renderer-owned stock effects; compiled XNA/FNA D3D9 Effect Framework bytecode accepted by the public Effect constructor on qualified renderers; and renderer-specific custom source or program forms through ShaderEffect. .fx or HLSL source, DXBC and MGFX are not interchangeable with that compiled Effect Framework format. No one route works identically on all 46 families; Chapter 17 separates those contracts.
-
•
Not binary-compatible with real Xbox Live. The GamerServices namespace (Chapter 49) reimplements the public API shape with local/synthetic semantics, matching how FNA itself already handles this namespace — there is no real Xbox Live behind it, by design.
-
•
Not a drop-in Microsoft DirectX runtime. The free-direct sibling implements a game-driven subset of DirectDraw, DirectSound, and DirectPlay over SDL3 and free-api. Its default DirectPlay transport is in-process; ENet networking is opt-in and speaks to the same reimplementation, not Microsoft’s historical service. Chapter 60 gives the per-method status census.
1.6 Auditability as a framework property
The single most distinctive thing about how this project is run — and the reason this book can make specific, checkable claims instead of vague ones — is its verification methodology. Three mechanisms recur throughout the codebase and throughout this book:
- Differential testing against a real reference implementation.
-
tools/fna-reference/ runs a genuine, live FNA.dll and compares CNA’s behavior against it call-for-call, rather than against a written specification of what FNA is supposed to do. Disputed behavior that differential testing cannot settle is checked against real XNA 4.0 running in a Windows 7 virtual machine.
- A compile-time purity check.
-
A dedicated build define, CNA_STRICT_XNA_API, turns the otherwise-inert CNAEXT marker macro into a real [[deprecated]] attribute, checked under -Werror=deprecated-declarations by two small standalone CMake targets built specifically for this purpose. Because every CNA extension beyond the real XNA 4.0 API must be wrapped in the CNAEXT marker macro (Chapter 3 explains the convention, and the self-verifying pair of targets that checks it, in full), this gives the project a mechanical — not just documented — guarantee that the public Microsoft::Xna::Framework surface has not silently grown project-specific extensions.
- Pixel-level oracle corpora, not just “it compiles.”
-
The D3D9 renderer in particular ships an oracle corpus that diffs CNA’s own render output against the real XNA 4.0 runtime’s own render of the same scene. The checked-in corpus contains 39 declarative scenes and the same number of matching reference PNGs. Its registered D3D9 gate runs the full corpus through the absolute per-channel comparator at tolerance zero; that wiring is an enforceable contract, while a pass count still requires an identified run. Chapter 28 covers what that verification pipeline (MinGW-w64 cross-compilation, Wine, DXVK, a real GPU) actually looks like.
Why “differential testing against FNA” is not by itself enough — a real finding. CNA’s own CHECKLIST.md names FNA as authoritative for behavior but the original Microsoft XNA 4.0 reference assemblies as authoritative for API surface, and explains why with a genuine near-miss: FNA is itself a reimplementation, and its own src/Media/Song.cs quietly omits three public XNA 4.0 members — Song.Album, Song.Artist, and Song.Genre — along with Song.ToString(). Because CNA’s Media namespace (Chapter 46) was itself audited against FNA across eight consecutive adversarial review passes, every one of those eight passes came back clean — CNA had faithfully reproduced FNA’s own incompleteness, not merely failed to find a bug that was there to find. The gap was only caught on a ninth pass, once the audit method itself changed to a member-level diff against the real Microsoft reference XML rather than another comparison against FNA. The fix (tracked as MEDIA-174 through MEDIA-180 in plan_media.md) added non-owning Album* / Artist* / Genre* back-pointers to Song, populated by MediaLibrary and nullptr for a song outside any library — mirroring an ownership pattern the surrounding Media types already used. The methodological lesson the project drew from this, stated directly in its own checklist, is the one this chapter opened with: “FNA doesn’t have it either” is not a justification, because that is exactly the reasoning that let this specific gap survive eight reviews.
This matters for how you should read the rest of this book. Where a claim in the chapters ahead is stated as a fact about CNA’s behavior, it is because the project’s own test suite, documentation, or source comments state it as a verified fact, generally with a specific mechanism (a CTest binary, a doc file, a task number) behind it — and where the project’s own documentation flags something as a dated snapshot, an estimate, or a known open gap, this book preserves that qualification rather than erasing it for a cleaner sentence.
1.7 The first tagged release and the continuing phase workflow
CNA developed continuously from 2025-02-22 without conventional releases while numbered phases and tasks carried engineering state. On 2026-08-20 the annotated v0.1.0-alpha.1 tag established the first Semantic Versioning release. The product version is assembled from CMake’s numeric 0.1.0 project version and the separate alpha.1 prerelease field. CMake prints the complete version during configuration, cmake/Version.cmake generates CNA/Version.hpp, Doxygen uses the same product version, and the changelog and release procedure name the tag spelling with its leading v.
The leading zero and alpha qualifier matter. The release policy permits compatibility-breaking changes before 1.0 when the minor or prerelease version advances; alpha.1 should not be read as a stable 1.0-quality API promise. The native C ABI has its own experimental version, 0.7.0, described in Appendix I; product and ABI versions answer different questions.
SemVer did not replace the project’s strictly incrementing Phase counter. Phases in CHECKLIST.md and the per-subsystem plan_*.md files still name bounded work, split it into numbered tasks, and retain closure evidence. They are an engineering workflow; tags identify publishable source states. Chapter 78 covers how the two now coexist.
This phase-based, task-tracked structure supplies valuable historical evidence, but a closing count remains a snapshot of one configuration. This edition preserves such a number only with its campaign and verdict channel; current source definitions, CTest registrations, executed cases, and oracle scenes are never silently combined into one total.
1.8 CNA’s software license
CNA is licensed under the Microsoft Public License (Ms-PL), the same permissive-but-not-MIT license FNA itself uses — a deliberate choice, not a coincidence: portions of CNA are directly derived from or based on FNA’s own source (most visibly the D3D9 renderer’s vendored Stock Effects HLSL sources, discussed in Part IV), and matching FNA’s license keeps that derivation legally uncomplicated. Ms-PL permits commercial use, modification, and redistribution, but — unlike MIT or the 2-clause BSD license — includes an explicit patent grant limited to contributions and a reciprocal “if you sue over patents, your license ends” clause; it is not a copyleft license, so a game built against CNA is not obligated to publish its own source.
1.9 Reading map for the rest of this book
Chapter 2 draws the full dependency graph between CNA and its sibling repositories. Chapter 3 is the “house style” chapter — the concrete rules (API mirroring, namespace discipline, the CNAEXT tag, the getXProperty / setXProperty convention, the porting checklist) that every other chapter’s code examples silently assume. Part II gets you from a clean checkout to a running triangle and then through the core framework types. Parts III and IV are the graphics machine, first as an API and then as 46 implementation factories serving 50 public renderer identities.